9 namespace serac::mfem_ext {
12 : mfem::SecondOrderTimeDependentOperator(n, 0.0), state_(std::move(state)), solver_(solver), bcs_(bcs), zero_(n)
24 timestepper_ = timestepper;
26 switch (timestepper) {
28 second_order_ode_solver_ = std::make_unique<mfem::NewmarkSolver>();
31 second_order_ode_solver_ = std::make_unique<mfem::HHTAlphaSolver>();
34 second_order_ode_solver_ = std::make_unique<mfem::WBZAlphaSolver>();
46 "Cannot guarantee stability for AverageAcceleration with time-dependent Dirichlet Boundary Conditions");
47 second_order_ode_solver_ = std::make_unique<mfem::AverageAccelerationSolver>();
50 second_order_ode_solver_ = std::make_unique<mfem::LinearAccelerationSolver>();
53 second_order_ode_solver_ = std::make_unique<mfem::CentralDifferenceSolver>();
56 second_order_ode_solver_ = std::make_unique<mfem::FoxGoodwinSolver>();
59 first_order_system_ode_solver_ = std::make_unique<mfem::BackwardEulerSolver>();
62 SLIC_ERROR_ROOT(
"Timestep method was not a supported second-order ODE method");
65 if (second_order_ode_solver_) {
66 second_order_ode_solver_->Init(*
this);
67 }
else if (first_order_system_ode_solver_) {
70 first_order_system_ode_solver_->Init(*
this);
73 SLIC_ERROR(
"Neither second_order_ode_solver_ nor first_order_system_ode_solver_ specified");
79 if (second_order_ode_solver_) {
81 second_order_ode_solver_->Step(x, dxdt, time, dt);
88 bc.setDofs(U_minus_, t -
epsilon);
90 bc.setDofs(U_plus_, t +
epsilon);
94 for (
int i = 0; i < constrained_dofs.Size(); i++) {
96 dxdt[i] = (U_plus_[i] - U_minus_[i]) / (2.0 *
epsilon);
100 }
else if (first_order_system_ode_solver_) {
102 mfem::Array<int> boffsets(3);
104 boffsets[1] = x.Size();
105 boffsets[2] = x.Size() + dxdt.Size();
106 mfem::BlockVector bx(boffsets);
108 bx.GetBlock(1) = dxdt;
110 first_order_system_ode_solver_->Step(bx, time, dt);
114 dxdt = bx.GetBlock(1);
116 SLIC_ERROR_ROOT(
"Neither second_order_ode_solver_ nor first_order_system_ode_solver_ specified");
132 mfem::Array<int> boffsets(3);
134 boffsets[1] = u.Size() / 2;
135 boffsets[2] = u.Size();
137 const mfem::BlockVector bu(u.GetData(), boffsets);
139 mfem::BlockVector bdu_dt(du_dt.GetData(), boffsets);
141 mfem::Vector u_next(bu.GetBlock(0));
142 u_next.Add(dt, bu.GetBlock(1));
144 Solve(t, dt * dt, dt, u_next,
148 bdu_dt.GetBlock(0) = bu.GetBlock(1);
149 bdu_dt.GetBlock(0).Add(dt, bdu_dt.GetBlock(1));
152 void SecondOrderODE::Solve(
const double time,
const double c0,
const double c1,
const mfem::Vector& u,
153 const mfem::Vector& du_dt, mfem::Vector& d2u_dt2)
const
161 state_.
du_dt = du_dt;
171 bc.setDofs(U_minus_, time -
epsilon);
172 bc.setDofs(U_, time);
173 bc.setDofs(U_plus_, time +
epsilon);
176 bool implicit = (c0 != 0.0 || c1 != 0.0);
182 subtract(1.0 / c0, U_, u, d2U_dt2_);
189 subtract(U_plus_, U_minus_, d2U_dt2_);
200 add(1.0, U_minus_, -2.0, U_, d2U_dt2_);
205 subtract(U_plus_, U_minus_, d2U_dt2_);
211 subtract(U_plus_, U_minus_, dU_dt_);
213 dU_dt_.Add(-1.0 * c1, d2U_dt2_);
216 U_.Add(-1.0 * c0, d2U_dt2_);
220 add(1.0, U_minus_, -2.0, U_, d2U_dt2_);
225 subtract(U_plus_, U_minus_, dU_dt_);
230 state_.
u.SetSubVector(constrained_dofs, 0.0);
231 U_.SetSubVectorComplement(constrained_dofs, 0.0);
234 state_.
du_dt.SetSubVector(constrained_dofs, 0.0);
235 dU_dt_.SetSubVectorComplement(constrained_dofs, 0.0);
236 state_.
du_dt += dU_dt_;
240 d2u_dt2.SetSubVector(constrained_dofs, 0.0);
241 d2U_dt2_.SetSubVectorComplement(constrained_dofs, 0.0);
244 solver_.
solve(d2u_dt2);
245 SLIC_WARNING_ROOT_IF(!solver_.
nonlinearSolver().GetConverged(),
"Newton Solver did not converge.");
252 : mfem::TimeDependentOperator(n, 0.0), state_(std::move(state)), solver_(solver), bcs_(bcs), zero_(n)
263 timestepper_ = timestepper;
265 switch (timestepper) {
267 ode_solver_ = std::make_unique<mfem::BackwardEulerSolver>();
270 ode_solver_ = std::make_unique<mfem::SDIRK33Solver>();
273 ode_solver_ = std::make_unique<mfem::ForwardEulerSolver>();
276 ode_solver_ = std::make_unique<mfem::RK2Solver>(0.5);
279 ode_solver_ = std::make_unique<mfem::RK3SSPSolver>();
282 ode_solver_ = std::make_unique<mfem::RK4Solver>();
285 ode_solver_ = std::make_unique<mfem::GeneralizedAlphaSolver>(0.5);
288 ode_solver_ = std::make_unique<mfem::ImplicitMidpointSolver>();
291 ode_solver_ = std::make_unique<mfem::SDIRK23Solver>();
294 ode_solver_ = std::make_unique<mfem::SDIRK34Solver>();
297 SLIC_ERROR_ROOT(
"Timestep method was not a supported first-order ODE method");
299 ode_solver_->Init(*
this);
302 void FirstOrderODE::Solve(
const double time,
const double dt,
const mfem::Vector& u, mfem::Vector& du_dt)
const
318 bc.setDofs(U_minus_, time -
epsilon);
319 bc.setDofs(U_, time);
320 bc.setDofs(U_plus_, time +
epsilon);
323 bool implicit = (dt != 0.0);
329 subtract(1.0 / dt, U_, u, dU_dt_);
335 subtract(1.0 / (2.0 *
epsilon), U_plus_, U_minus_, dU_dt_);
341 subtract(1.0 / (2.0 *
epsilon), U_plus_, U_minus_, dU_dt_);
343 U_.Add(-1.0 * dt, dU_dt_);
347 subtract(1.0 / (2.0 *
epsilon), U_plus_, U_minus_, dU_dt_);
351 state_.
u.SetSubVector(constrained_dofs, 0.0);
352 U_.SetSubVectorComplement(constrained_dofs, 0.0);
355 du_dt = state_.
du_dt;
356 du_dt.SetSubVector(constrained_dofs, 0.0);
357 dU_dt_.SetSubVectorComplement(constrained_dofs, 0.0);
360 solver_.
solve(du_dt);
361 SLIC_WARNING_ROOT_IF(!solver_.
nonlinearSolver().GetConverged(),
"Newton Solver did not converge.");
363 state_.
du_dt = du_dt;
A container for the boundary condition information relating to a specific physics module.
std::vector< BoundaryCondition > & essentials()
Accessor for the essential BC objects.
const mfem::Array< int > & allEssentialTrueDofs() const
Returns all the true degrees of freedom associated with all the essential BCs.
This class manages the objects typically required to solve a nonlinear set of equations arising from ...
mfem::NewtonSolver & nonlinearSolver()
void solve(mfem::Vector &x) const
void SetTimestepper(const serac::TimestepMethod timestepper)
Set the time integration method.
FirstOrderODE(int n, FirstOrderODE::State &&state, const EquationSolver &solver, const BoundaryConditionManager &bcs)
Constructor defining the size and specific system of ordinary differential equations to be solved.
static constexpr double epsilon
a small number used to compute finite difference approximations to time derivatives of boundary condi...
void Step(mfem::Vector &x, mfem::Vector &dxdt, double &time, double &dt)
Performs a time step.
void ImplicitSolve(const double c0, const double c1, const mfem::Vector &u, const mfem::Vector &du_dt, mfem::Vector &d2u_dt2) override
Solves the equation d2u_dt2 = f(u + c0 * d2u_dt2, du_dt + c1 * d2u_dt2, t)
static constexpr double epsilon
a small number used to compute finite difference approximations to time derivatives of boundary condi...
void SetTimestepper(const serac::TimestepMethod timestepper)
Set the time integration method.
SecondOrderODE(int n, State &&state, const EquationSolver &solver, const BoundaryConditionManager &bcs)
Constructor defining the size and specific system of ordinary differential equations to be solved.
TimestepMethod
Timestep method of a solver.
Wrapper classes for using MFEM's ODE solver objects.
A set of references to physics-module-owned variables used by the residual operator.
double & dt
Current time step.
mfem::Vector & u
Predicted true DOFs.
double & time
Time value at which the ODE solver wants to compute a residual.
mfem::Vector & du_dt
Previous value of du_dt.
double & previous_dt
Previous value of dt.
A set of references to physics-module-owned variables used by the residual operator.
double & time
Time value at which the ODE solver wants to compute a residual.
double & c0
coefficient used to calculate updated displacement: u_{n + 1} := u + c0 * d2u_dt2
mfem::Vector & du_dt
Predicted du_dt.
double & c1
coefficient used to calculate updated velocity: du_dt_{n+1} := du_dt + c1 * d2u_dt2
mfem::Vector & u
Predicted true DOFs.
mfem::Vector & d2u_dt2
Previous value of d^2u_dt^2.