203 [[maybe_unused]]
const double t,
const double dt,
204 std::vector<GlobalVector*>
const& x,
205 std::vector<GlobalVector*>
const& x_prev,
int const process_id,
213 "The current parallel implementation of flux corrected transport "
214 "supports only one MPI rank, but the simulation uses {} ranks",
219 PetscCallAbort(PETSC_COMM_WORLD,
220 MatDuplicate(K_raw, MAT_DO_NOT_COPY_VALUES, &D));
221 PetscCallAbort(PETSC_COMM_WORLD, MatZeroEntries(D));
224 PetscCallAbort(PETSC_COMM_WORLD,
227 PetscCallAbort(PETSC_COMM_WORLD, MatScale(K_raw, -1.0));
228 K.finalizeAssembly();
230 for (PetscInt i = start; i < end; ++i)
232 PetscInt number_of_columns;
233 PetscInt
const* columns;
234 PetscScalar
const* values;
236 PetscCallAbort(PETSC_COMM_WORLD, MatGetRow(K_raw, i, &number_of_columns,
239 auto const columns_span =
240 std::span<PetscInt const>(columns, number_of_columns);
241 auto const values_span =
242 std::span<PetscScalar const>(values, number_of_columns);
243 for (
auto const [j, kij] : std::views::zip(columns_span, values_span))
251 PetscCallAbort(PETSC_COMM_WORLD, MatGetValue(K_raw, j, i, &kji));
252 PetscScalar dij = std::max({-kij, 0.0, -kji});
253 PetscCallAbort(PETSC_COMM_WORLD,
254 MatSetValue(D, i, j, dij, INSERT_VALUES));
259 MatRestoreRow(K_raw, i, &number_of_columns, &columns, &values));
263 Vec row_sums_raw = row_sums->getRawVector();
264 PetscCallAbort(PETSC_COMM_WORLD, MatGetRowSum(D, row_sums_raw));
265 PetscCallAbort(PETSC_COMM_WORLD, VecScale(row_sums_raw, -1.0));
266 PetscCallAbort(PETSC_COMM_WORLD, VecAssemblyBegin(row_sums_raw));
267 PetscCallAbort(PETSC_COMM_WORLD, VecAssemblyEnd(row_sums_raw));
268 PetscCallAbort(PETSC_COMM_WORLD,
269 MatDiagonalSet(D, row_sums_raw, ADD_VALUES));
272 x[process_id]->setLocalAccessibleVector();
273 x_prev[process_id]->setLocalAccessibleVector();
277 PetscCallAbort(PETSC_COMM_WORLD,
278 MatDuplicate(K.
getRawMatrix(), MAT_DO_NOT_COPY_VALUES, &F));
279 PetscCallAbort(PETSC_COMM_WORLD, MatZeroEntries(F));
280 for (PetscInt i = start; i < end; ++i)
283 const PetscInt* col_indices;
284 const PetscScalar* values;
286 PetscCallAbort(PETSC_COMM_WORLD,
287 MatGetRow(D, i, &cols, &col_indices, &values));
289 auto const columns = std::span<PetscInt const>(col_indices, cols);
290 auto const values_D = std::span<PetscScalar const>(values, cols);
292 for (
auto const [j, dij] : std::views::zip(columns, values_D))
294 PetscScalar
const xi = x[process_id]->get(i);
295 PetscScalar
const xj = x[process_id]->get(j);
296 PetscScalar
const fij = -dij * (xj - xi);
297 PetscCallAbort(PETSC_COMM_WORLD,
298 MatSetValue(F, i, j, fij, INSERT_VALUES));
300 PetscCallAbort(PETSC_COMM_WORLD,
301 MatRestoreRow(D, i, &cols, &col_indices, &values));
307 xdot->setLocalAccessibleVector();
308 for (PetscInt i = start; i < end; ++i)
310 xdot->add(i, (x[process_id]->get(i) - x_prev[process_id]->get(i)) / dt);
312 xdot->finalizeAssembly();
313 xdot->setLocalAccessibleVector();
315 for (PetscInt i = start; i < end; ++i)
318 PetscInt
const* col_indices;
319 PetscScalar
const* values;
321 PetscCallAbort(PETSC_COMM_WORLD,
322 MatGetRow(M_raw, i, &cols, &col_indices, &values));
324 auto const columns = std::span<PetscInt const>(col_indices, cols);
325 auto const values_M = std::span<PetscScalar const>(values, cols);
327 for (
auto const [j, mij] : std::views::zip(columns, values_M))
329 PetscScalar
const fij = -mij * (xdot->get(j) - xdot->get(i));
330 PetscCallAbort(PETSC_COMM_WORLD,
331 MatSetValue(F, i, j, fij, ADD_VALUES));
333 PetscCallAbort(PETSC_COMM_WORLD,
334 MatRestoreRow(M_raw, i, &cols, &col_indices, &values));
340 P_plus->setLocalAccessibleVector();
341 P_minus->setLocalAccessibleVector();
343 for (PetscInt i = start; i < end; ++i)
346 PetscInt
const* col_indices;
347 PetscScalar
const* values;
349 PetscCallAbort(PETSC_COMM_WORLD,
350 MatGetRow(F, i, &cols, &col_indices, &values));
352 auto const column_indices =
353 std::span<PetscInt const>(col_indices, cols);
354 auto const values_span = std::span<PetscScalar const>(values, cols);
355 for (
auto const [j, fij] : std::views::zip(column_indices, values_span))
362 P_plus->add(i, std::max(0., fij));
363 P_minus->add(i, std::min(0., fij));
365 PetscCallAbort(PETSC_COMM_WORLD,
366 MatRestoreRow(F, i, &cols, &col_indices, &values));
368 P_plus->finalizeAssembly();
369 P_plus->setLocalAccessibleVector();
370 P_minus->finalizeAssembly();
371 P_minus->setLocalAccessibleVector();
374 Q_plus->setLocalAccessibleVector();
375 Q_minus->setLocalAccessibleVector();
377 for (PetscInt i = start; i < end; ++i)
380 PetscInt
const* col_indices;
382 PetscScalar Q_plus_i = 0.0;
383 PetscScalar Q_minus_i = 0.0;
385 PetscCallAbort(PETSC_COMM_WORLD,
386 MatGetRow(F, i, &cols, &col_indices,
nullptr));
387 auto const column_indices =
388 std::span<PetscInt const>(col_indices, cols);
389 for (
auto const j : column_indices)
396 PetscScalar
const x_prev_i = x_prev[process_id]->get(i);
397 PetscScalar
const x_prev_j = x_prev[process_id]->get(j);
399 Q_plus_i = std::max({Q_plus_i, 0., x_prev_j - x_prev_i});
400 Q_minus_i = std::min({Q_minus_i, 0., x_prev_j - x_prev_i});
402 Q_plus->set(i, Q_plus_i);
403 Q_minus->set(i, Q_minus_i);
404 PetscCallAbort(PETSC_COMM_WORLD,
405 MatRestoreRow(F, i, &cols, &col_indices,
nullptr));
407 Q_plus->finalizeAssembly();
408 Q_plus->setLocalAccessibleVector();
409 Q_minus->finalizeAssembly();
410 Q_minus->setLocalAccessibleVector();
413 R_plus->setLocalAccessibleVector();
416 Vec M_L = row_sums_M->getRawVector();
417 PetscCallAbort(PETSC_COMM_WORLD, MatGetRowSum(M_raw, M_L));
418 row_sums_M->finalizeAssembly();
419 row_sums_M->setLocalAccessibleVector();
421 for (
auto k = R_plus->getRangeBegin(); k < R_plus->getRangeEnd(); ++k)
423 PetscScalar
const P_plus_i = P_plus->get(k);
428 PetscScalar
const mi = row_sums_M->get(k);
429 PetscScalar
const Q_plus_i = Q_plus->get(k);
430 R_plus->set(k, std::min(1.0, mi * Q_plus_i / dt / P_plus_i));
432 R_plus->finalizeAssembly();
433 R_plus->setLocalAccessibleVector();
435 R_minus->setLocalAccessibleVector();
437 for (
auto k = R_minus->getRangeBegin(); k < R_minus->getRangeEnd(); ++k)
439 PetscScalar
const P_minus_i = P_minus->get(k);
440 if (P_minus_i == 0.0)
444 PetscScalar
const mi = row_sums_M->get(k);
445 PetscScalar
const Q_minus_i = Q_minus->get(k);
446 R_minus->set(k, std::min(1.0, mi * Q_minus_i / dt / P_minus_i));
448 R_minus->finalizeAssembly();
449 R_minus->setLocalAccessibleVector();
452 for (PetscInt i = start; i < end; ++i)
455 PetscInt
const* col_indices;
456 PetscScalar
const* values;
458 PetscCallAbort(PETSC_COMM_WORLD,
459 MatGetRow(F, i, &cols, &col_indices, &values));
461 auto col_indices_span = std::span<PetscInt const>(col_indices, cols);
462 auto values_span = std::span<PetscScalar const>(values, cols);
466 for (
auto [j, fij] : std::views::zip(col_indices_span, values_span))
474 alpha_ij = std::min(R_plus->get(i), R_minus->get(j));
478 alpha_ij = std::min(R_minus->get(i), R_plus->get(j));
480 b.
add(i, alpha_ij * fij);
482 PetscCallAbort(PETSC_COMM_WORLD,
483 MatRestoreRow(F, i, &cols, &col_indices, &values));
488 for (PetscInt i = start; i < end; ++i)
491 PetscInt
const* col_indices_D;
492 PetscScalar
const* values_D;
493 PetscCallAbort(PETSC_COMM_WORLD,
494 MatGetRow(D, i, &cols_D, &col_indices_D, &values_D));
496 auto const column_indices =
497 std::span<PetscInt const>(col_indices_D, cols_D);
498 auto const values = std::span<PetscScalar const>(values_D, cols_D);
499 for (
auto [j, Dij] : std::views::zip(column_indices, values))
501 PetscCallAbort(PETSC_COMM_WORLD,
502 MatSetValues(K_raw, 1, &i, 1, &j, &Dij, ADD_VALUES));
504 PetscCallAbort(PETSC_COMM_WORLD,
505 MatRestoreRow(D, i, &cols_D, &col_indices_D, &values_D));
508 PetscCallAbort(PETSC_COMM_WORLD, MatScale(K_raw, -1.0));
509 K.finalizeAssembly();
511 for (PetscInt i = start; i < end; ++i)
513 PetscScalar
const row_sum_M_i = row_sums_M->get(i);
514 MatSetValues(M.
getRawMatrix(), 1, &i, 1, &i, &row_sum_M_i,
517 M.finalizeAssembly();