Skip to content

Commit b51d0c4

Browse files
committed
Add advance_postprocessing_timestep declarations and implementations for 1st order fixed timestep solvers.
1 parent 112b78c commit b51d0c4

File tree

5 files changed

+72
-0
lines changed

5 files changed

+72
-0
lines changed

include/solvers/euler2_solver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class Euler2Solver : public FirstOrderUnsteadySolver
8787
virtual void integrate_adjoint_refinement_error_estimate(AdjointRefinementEstimator & adjoint_refinement_error_estimator, ErrorVector & QoI_elementwise_error) override;
8888
#endif // LIBMESH_ENABLE_AMR
8989

90+
virtual void advance_postprocessing_timestep(std::vector<std::function<void(Real, System &)>> integration_operations) override;
91+
9092
/**
9193
* This method uses the DifferentiablePhysics'
9294
* element_time_derivative() and element_constraint()

include/solvers/euler_solver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class EulerSolver : public FirstOrderUnsteadySolver
109109
virtual void integrate_adjoint_refinement_error_estimate(AdjointRefinementEstimator & adjoint_refinement_error_estimator, ErrorVector & QoI_elementwise_error) override;
110110
#endif // LIBMESH_ENABLE_AMR
111111

112+
virtual void advance_postprocessing_timestep(std::vector<std::function<void(Real, System &)>> integration_operations) override;
113+
112114
/**
113115
* The value for the theta method to employ: 1.0 corresponds
114116
* to backwards Euler, 0.0 corresponds to forwards Euler,

include/solvers/first_order_unsteady_solver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ class FirstOrderUnsteadySolver : public UnsteadySolver
9696
virtual void integrate_adjoint_refinement_error_estimate(AdjointRefinementEstimator & adjoint_refinement_error_estimator, ErrorVector & QoI_elementwise_error) override = 0;
9797
#endif // LIBMESH_ENABLE_AMR
9898

99+
virtual void advance_postprocessing_timestep(std::vector<std::function<void(Real, System &)>> integration_operations) override = 0;
100+
99101
protected:
100102

101103
/**

src/solvers/euler2_solver.C

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,4 +482,31 @@ void Euler2Solver::integrate_adjoint_refinement_error_estimate(AdjointRefinement
482482
}
483483
#endif // LIBMESH_ENABLE_AMR
484484

485+
void Euler2Solver::advance_postprocessing_timestep(std::vector<std::function<void(Real, System &)>> integration_operations)
486+
{
487+
// Enables the user to evaluate (1 - theta)*f(u_i-1) + theta*f(u_i)
488+
489+
// For correctness and adjoint consistency reasons we currently only support Backward Euler
490+
if(theta != 0)
491+
libmesh_not_implemented();
492+
493+
// The mesh and solutions (primal, adjoint) are already read in.
494+
// So we are ready to call the user's integration operations.
495+
for (auto integration_operations_iterator:integration_operations)
496+
integration_operations_iterator(1.0 - theta, dynamic_cast<System&>(_system));
497+
498+
// Advance to t_j+1
499+
_system.time = _system.time + _system.deltat;
500+
501+
// Retrieve the state and adjoint vectors for the next time instant
502+
retrieve_timestep();
503+
504+
// Mesh and solution read in. Ready to call the user's integration operations.
505+
for (auto integration_operations_iterator:integration_operations)
506+
integration_operations_iterator(theta, dynamic_cast<System&>(_system));
507+
508+
return;
509+
510+
}
511+
485512
} // namespace libMesh

src/solvers/euler_solver.C

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,4 +415,43 @@ void EulerSolver::integrate_adjoint_refinement_error_estimate(AdjointRefinementE
415415
}
416416
#endif // LIBMESH_ENABLE_AMR
417417

418+
void EulerSolver::advance_postprocessing_timestep(std::vector<std::function<void(Real, System &)>> integration_operations)
419+
{
420+
// // For EulerSolver: \int_{t_i}^{t_(i+1)} f(u(t)) dt \approx f(theta u_i + (1-theta)u_i+1) (t_i+1 - t_i)
421+
422+
// Currently, we only support this functionality when Backward-Euler time integration is used.
423+
if (theta != 1.0)
424+
libmesh_not_implemented();
425+
426+
// u_i will be provided by the old nonlinear solution after we advance to the next time instant.
427+
428+
// Advance to t_j+1
429+
_system.time = _system.time + _system.deltat;
430+
431+
// Retrieve the state and adjoint vectors for the next time instant
432+
retrieve_timestep();
433+
434+
// Create a new weighted solution vector (1 - theta)*u_i-1 + theta*u_i
435+
std::unique_ptr<NumericVector<Number>> weighted_vector = NumericVector<Number>::build(_system.comm());
436+
weighted_vector->init(_system.get_vector("_old_nonlinear_solution"));
437+
438+
weighted_vector->add(1.0 - theta, _system.get_vector("_old_nonlinear_solution"));
439+
440+
weighted_vector->add(theta, *(_system.solution));
441+
442+
_system.solution->swap(*weighted_vector);
443+
444+
// Mesh and solution read in. Ready to call the user's integration operations.
445+
// Since we have already weighted the solution and old solution, we just pass 1.0
446+
// as the time quadrature weight.
447+
for (auto integration_operations_iterator:integration_operations)
448+
integration_operations_iterator(1.0, dynamic_cast<System&>(_system));
449+
450+
// Swap back
451+
_system.solution->swap(*weighted_vector);
452+
453+
return;
454+
}
455+
456+
418457
} // namespace libMesh

0 commit comments

Comments
 (0)