209 [[maybe_unused]]
const double t,
const double dt,
210 std::vector<GlobalVector*>
const& x,
211 std::vector<GlobalVector*>
const& x_prev,
int const process_id,
219 "The current parallel implementation of flux corrected transport "
220 "supports only one MPI rank, but the simulation uses {} ranks",
225 PetscCallAbort(PETSC_COMM_WORLD,
226 MatDuplicate(K_raw, MAT_DO_NOT_COPY_VALUES, &D));
227 PetscCallAbort(PETSC_COMM_WORLD, MatZeroEntries(D));
230 PetscCallAbort(PETSC_COMM_WORLD,
233 PetscCallAbort(PETSC_COMM_WORLD, MatScale(K_raw, -1.0));
234 K.finalizeAssembly();
236 for (PetscInt i = start; i < end; ++i)
238 PetscInt number_of_columns;
239 PetscInt
const* columns;
240 PetscScalar
const* values;
242 PetscCallAbort(PETSC_COMM_WORLD, MatGetRow(K_raw, i, &number_of_columns,
245 auto const columns_span =
246 std::span<PetscInt const>(columns, number_of_columns);
247 auto const values_span =
248 std::span<PetscScalar const>(values, number_of_columns);
249 for (
auto const [j, kij] : std::views::zip(columns_span, values_span))
257 PetscCallAbort(PETSC_COMM_WORLD, MatGetValue(K_raw, j, i, &kji));
258 PetscScalar dij = std::max({-kij, 0.0, -kji});
259 PetscCallAbort(PETSC_COMM_WORLD,
260 MatSetValue(D, i, j, dij, INSERT_VALUES));
265 MatRestoreRow(K_raw, i, &number_of_columns, &columns, &values));
269 Vec row_sums_raw = row_sums->getRawVector();
270 PetscCallAbort(PETSC_COMM_WORLD, MatGetRowSum(D, row_sums_raw));
271 PetscCallAbort(PETSC_COMM_WORLD, VecScale(row_sums_raw, -1.0));
272 PetscCallAbort(PETSC_COMM_WORLD, VecAssemblyBegin(row_sums_raw));
273 PetscCallAbort(PETSC_COMM_WORLD, VecAssemblyEnd(row_sums_raw));
274 PetscCallAbort(PETSC_COMM_WORLD,
275 MatDiagonalSet(D, row_sums_raw, ADD_VALUES));
278 x[process_id]->setLocalAccessibleVector();
279 x_prev[process_id]->setLocalAccessibleVector();
283 PetscCallAbort(PETSC_COMM_WORLD,
284 MatDuplicate(K.
getRawMatrix(), MAT_DO_NOT_COPY_VALUES, &F));
285 PetscCallAbort(PETSC_COMM_WORLD, MatZeroEntries(F));
286 for (PetscInt i = start; i < end; ++i)
289 const PetscInt* col_indices;
290 const PetscScalar* values;
292 PetscCallAbort(PETSC_COMM_WORLD,
293 MatGetRow(D, i, &cols, &col_indices, &values));
295 auto const columns = std::span<PetscInt const>(col_indices, cols);
296 auto const values_D = std::span<PetscScalar const>(values, cols);
298 for (
auto const [j, dij] : std::views::zip(columns, values_D))
300 PetscScalar
const xi = x[process_id]->get(i);
301 PetscScalar
const xj = x[process_id]->get(j);
302 PetscScalar
const fij = -dij * (xj - xi);
303 PetscCallAbort(PETSC_COMM_WORLD,
304 MatSetValue(F, i, j, fij, INSERT_VALUES));
306 PetscCallAbort(PETSC_COMM_WORLD,
307 MatRestoreRow(D, i, &cols, &col_indices, &values));
313 xdot->setLocalAccessibleVector();
314 for (PetscInt i = start; i < end; ++i)
316 xdot->add(i, (x[process_id]->get(i) - x_prev[process_id]->get(i)) / dt);
318 xdot->finalizeAssembly();
319 xdot->setLocalAccessibleVector();
321 for (PetscInt i = start; i < end; ++i)
324 PetscInt
const* col_indices;
325 PetscScalar
const* values;
327 PetscCallAbort(PETSC_COMM_WORLD,
328 MatGetRow(M_raw, i, &cols, &col_indices, &values));
330 auto const columns = std::span<PetscInt const>(col_indices, cols);
331 auto const values_M = std::span<PetscScalar const>(values, cols);
333 for (
auto const [j, mij] : std::views::zip(columns, values_M))
335 PetscScalar
const fij = -mij * (xdot->get(j) - xdot->get(i));
336 PetscCallAbort(PETSC_COMM_WORLD,
337 MatSetValue(F, i, j, fij, ADD_VALUES));
339 PetscCallAbort(PETSC_COMM_WORLD,
340 MatRestoreRow(M_raw, i, &cols, &col_indices, &values));
346 P_plus->setLocalAccessibleVector();
347 P_minus->setLocalAccessibleVector();
349 for (PetscInt i = start; i < end; ++i)
352 PetscInt
const* col_indices;
353 PetscScalar
const* values;
355 PetscCallAbort(PETSC_COMM_WORLD,
356 MatGetRow(F, i, &cols, &col_indices, &values));
358 auto const column_indices =
359 std::span<PetscInt const>(col_indices, cols);
360 auto const values_span = std::span<PetscScalar const>(values, cols);
361 for (
auto const [j, fij] : std::views::zip(column_indices, values_span))
368 P_plus->add(i, std::max(0., fij));
369 P_minus->add(i, std::min(0., fij));
371 PetscCallAbort(PETSC_COMM_WORLD,
372 MatRestoreRow(F, i, &cols, &col_indices, &values));
374 P_plus->finalizeAssembly();
375 P_plus->setLocalAccessibleVector();
376 P_minus->finalizeAssembly();
377 P_minus->setLocalAccessibleVector();
380 Q_plus->setLocalAccessibleVector();
381 Q_minus->setLocalAccessibleVector();
383 for (PetscInt i = start; i < end; ++i)
386 PetscInt
const* col_indices;
388 PetscScalar Q_plus_i = 0.0;
389 PetscScalar Q_minus_i = 0.0;
391 PetscCallAbort(PETSC_COMM_WORLD,
392 MatGetRow(F, i, &cols, &col_indices,
nullptr));
393 auto const column_indices =
394 std::span<PetscInt const>(col_indices, cols);
395 for (
auto const j : column_indices)
402 PetscScalar
const x_prev_i = x_prev[process_id]->get(i);
403 PetscScalar
const x_prev_j = x_prev[process_id]->get(j);
405 Q_plus_i = std::max({Q_plus_i, 0., x_prev_j - x_prev_i});
406 Q_minus_i = std::min({Q_minus_i, 0., x_prev_j - x_prev_i});
408 Q_plus->set(i, Q_plus_i);
409 Q_minus->set(i, Q_minus_i);
410 PetscCallAbort(PETSC_COMM_WORLD,
411 MatRestoreRow(F, i, &cols, &col_indices,
nullptr));
413 Q_plus->finalizeAssembly();
414 Q_plus->setLocalAccessibleVector();
415 Q_minus->finalizeAssembly();
416 Q_minus->setLocalAccessibleVector();
419 R_plus->setLocalAccessibleVector();
422 Vec M_L = row_sums_M->getRawVector();
423 PetscCallAbort(PETSC_COMM_WORLD, MatGetRowSum(M_raw, M_L));
424 row_sums_M->finalizeAssembly();
425 row_sums_M->setLocalAccessibleVector();
427 for (
auto k = R_plus->getRangeBegin(); k < R_plus->getRangeEnd(); ++k)
429 PetscScalar
const P_plus_i = P_plus->get(k);
434 PetscScalar
const mi = row_sums_M->get(k);
435 PetscScalar
const Q_plus_i = Q_plus->get(k);
436 R_plus->set(k, std::min(1.0, mi * Q_plus_i / dt / P_plus_i));
438 R_plus->finalizeAssembly();
439 R_plus->setLocalAccessibleVector();
441 R_minus->setLocalAccessibleVector();
443 for (
auto k = R_minus->getRangeBegin(); k < R_minus->getRangeEnd(); ++k)
445 PetscScalar
const P_minus_i = P_minus->get(k);
446 if (P_minus_i == 0.0)
450 PetscScalar
const mi = row_sums_M->get(k);
451 PetscScalar
const Q_minus_i = Q_minus->get(k);
452 R_minus->set(k, std::min(1.0, mi * Q_minus_i / dt / P_minus_i));
454 R_minus->finalizeAssembly();
455 R_minus->setLocalAccessibleVector();
458 for (PetscInt i = start; i < end; ++i)
461 PetscInt
const* col_indices;
462 PetscScalar
const* values;
464 PetscCallAbort(PETSC_COMM_WORLD,
465 MatGetRow(F, i, &cols, &col_indices, &values));
467 auto col_indices_span = std::span<PetscInt const>(col_indices, cols);
468 auto values_span = std::span<PetscScalar const>(values, cols);
472 for (
auto [j, fij] : std::views::zip(col_indices_span, values_span))
480 alpha_ij = std::min(R_plus->get(i), R_minus->get(j));
484 alpha_ij = std::min(R_minus->get(i), R_plus->get(j));
486 b.
add(i, alpha_ij * fij);
488 PetscCallAbort(PETSC_COMM_WORLD,
489 MatRestoreRow(F, i, &cols, &col_indices, &values));
494 for (PetscInt i = start; i < end; ++i)
497 PetscInt
const* col_indices_D;
498 PetscScalar
const* values_D;
499 PetscCallAbort(PETSC_COMM_WORLD,
500 MatGetRow(D, i, &cols_D, &col_indices_D, &values_D));
502 auto const column_indices =
503 std::span<PetscInt const>(col_indices_D, cols_D);
504 auto const values = std::span<PetscScalar const>(values_D, cols_D);
505 for (
auto [j, Dij] : std::views::zip(column_indices, values))
507 PetscCallAbort(PETSC_COMM_WORLD,
508 MatSetValues(K_raw, 1, &i, 1, &j, &Dij, ADD_VALUES));
510 PetscCallAbort(PETSC_COMM_WORLD,
511 MatRestoreRow(D, i, &cols_D, &col_indices_D, &values_D));
514 PetscCallAbort(PETSC_COMM_WORLD, MatScale(K_raw, -1.0));
515 K.finalizeAssembly();
517 for (PetscInt i = start; i < end; ++i)
519 PetscScalar
const row_sum_M_i = row_sums_M->get(i);
520 MatSetValues(M.
getRawMatrix(), 1, &i, 1, &i, &row_sum_M_i,
523 M.finalizeAssembly();