MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
ode.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_ODE
13#define MFEM_ODE
14
16#include "../config/config.hpp"
17#include "operator.hpp"
18#include <vector>
19#include <memory>
20
21namespace mfem
22{
23
24/// An interface for storing state of previous timesteps
26{
27public:
28 /// Get the maximum number of stored stages
29 virtual int MaxSize() const = 0;
30
31 /// Get the current number of stored stages
32 virtual int Size() const = 0;
33
34 /// Get the ith state vector
35 virtual const Vector &Get(int i) const = 0;
36
37 /// Get the ith state vector - non-const version
38 virtual Vector &Get(int i) = 0;
39
40 /// Get the ith state vector - with a copy
41 virtual void Get(int i, Vector &vec) const = 0;
42
43 /// Set the ith state vector
44 virtual void Set(int i, Vector &state) = 0;
45
46 /// Add state vector and increment state size
47 virtual void Append(Vector &state) = 0;
48
49 /// Virtual destructor
50 virtual ~ODEStateData() = default;
51};
52
53/// An implementation of ODEStateData that stores states in an std::vector<Vector>
55{
56private:
57 MemoryType mem_type;
58 int ss, smax;
59 std::vector<Vector> data;
60 Array<int> idx;
61
62public:
63 ODEStateDataVector (int smax): smax(smax)
64 {
65 data.resize(smax);
66 idx.SetSize(smax);
67 ss = 0;
68 };
69
70 /// Set the number of stages and the size of the vectors
71 void SetSize(int vsize, MemoryType mem_type);
72
73 /// Shift the stage counter for the next timestep
74 inline void ShiftStages()
75 {
76 for (int i = 0; i < smax; i++) { idx[i] = (++idx[i])%smax; }
77 };
78
79 /// Increment the stage counter
80 void Increment() { ss++; ss = std::min(ss,smax); };
81
82 /// Reset the stage counter
83 void Reset() { ss = 0; };
84
85 /// Reference access to the ith vector.
86 inline Vector & operator[](int i) { return data[idx[i]]; };
87
88 /// Const reference access to the ith vector.
89 inline const Vector &operator[](int i) const { return data[idx[i]]; };
90
91 /// Print state data
92 void Print(std::ostream &os = mfem::out) const ;
93
94 int MaxSize() const override { return smax; };
95
96 int Size() const override { return ss; };
97
98 const Vector &Get(int i) const override;
99 Vector &Get(int i) override;
100 void Get(int i, Vector &vec) const override;
101
102 void Set(int i, Vector &state) override;
103
104 void Append(Vector &state) override;
105};
106
107
108/// Abstract class for solving systems of ODEs: dx/dt = f(x,t)
109/** For systems of split ODEs:
110 $$ M dx/dt = f_1(x,t) + f_2(x,t) $$
111 where $ M^{-1} f_1 $ and $ M^{-1} f_2 $ are treated differently (e.g.,
112 explicitly and implicitly), the solver class expects a
113 TimeDependentOperator with split functionality. Setting
114 TimeDependentOperator::EvalMode = TimeDependentOperator::ADDITIVE_TERM_1
115 and calling TimeDependentOperator::Mult() should return
116 $ k_1=M^{-1} f_1(x,t) $. Setting TimeDependentOperator::EvalMode =
117 TimeDependentOperator::ADDITIVE_TERM_2 and calling
118 TimeDependentOperator::ImplicitSolve() should solve
119 $ M k_2 = f_2(x+\gamma k_2,t) $. */
121{
122protected:
123 /// Pointer to the associated TimeDependentOperator.
124 TimeDependentOperator *f; // f(.,t) : R^n --> R^n
126
127public:
129
130 /// Associate a TimeDependentOperator with the ODE solver.
131 /** This method has to be called:
132 - Before the first call to Step().
133 - When the dimensions of the associated TimeDependentOperator change.
134 - When a time stepping sequence has to be restarted.
135 - To change the associated TimeDependentOperator. */
136 virtual void Init(TimeDependentOperator &f_);
137
138 /** @brief Perform a time step from time @a t [in] to time @a t [out] based
139 on the requested step size @a dt [in]. */
140 /** @param[in,out] x Approximate solution.
141 @param[in,out] t Time associated with the approximate solution @a x.
142 @param[in,out] dt Time step size.
143
144 The following rules describe the common behavior of the method:
145 - The input @a x [in] is the approximate solution for the input time
146 @a t [in].
147 - The input @a dt [in] is the desired time step size, defining the desired
148 target time: t [target] = @a t [in] + @a dt [in].
149 - The output @a x [out] is the approximate solution for the output time
150 @a t [out].
151 - The output @a dt [out] is the last time step taken by the method which
152 may be smaller or larger than the input @a dt [in] value, e.g. because
153 of time step control.
154 - The method may perform more than one time step internally; in this case
155 @a dt [out] is the last internal time step size.
156 - The output value of @a t [out] may be smaller or larger than
157 t [target], however, it is not smaller than @a t [in] + @a dt [out], if
158 at least one internal time step was performed.
159 - The value @a x [out] may be obtained by interpolation using internally
160 stored data.
161 - In some cases, the contents of @a x [in] may not be used, e.g. when
162 @a x [out] from a previous Step() call was obtained by interpolation.
163 - In consecutive calls to this method, the output @a t [out] of one
164 Step() call has to be the same as the input @a t [in] to the next
165 Step() call.
166 - If the previous rule has to be broken, e.g. to restart a time stepping
167 sequence, then the ODE solver must be re-initialized by calling Init()
168 between the two Step() calls. */
169 virtual void Step(Vector &x, real_t &t, real_t &dt) = 0;
170
171 /// Perform time integration from time @a t [in] to time @a tf [in].
172 /** @param[in,out] x Approximate solution.
173 @param[in,out] t Time associated with the approximate solution @a x.
174 @param[in,out] dt Time step size.
175 @param[in] tf Requested final time.
176
177 The default implementation makes consecutive calls to Step() until
178 reaching @a tf.
179 The following rules describe the common behavior of the method:
180 - The input @a x [in] is the approximate solution for the input time
181 @a t [in].
182 - The input @a dt [in] is the initial time step size.
183 - The output @a dt [out] is the last time step taken by the method which
184 may be smaller or larger than the input @a dt [in] value, e.g. because
185 of time step control.
186 - The output value of @a t [out] is not smaller than @a tf [in]. */
187 virtual void Run(Vector &x, real_t &t, real_t &dt, real_t tf)
188 {
189 while (t < tf) { Step(x, t, dt); }
190 }
191
192 /// Returns how many State vectors the ODE requires
193 virtual int GetStateSize() { return 0; };
194
195 // Help info for ODESolver options
196 static MFEM_EXPORT std::string ExplicitTypes;
197 static MFEM_EXPORT std::string ImplicitTypes;
198 static MFEM_EXPORT std::string IMEXTypes;
199 static MFEM_EXPORT std::string Types;
200
201 /// Function for selecting the desired ODESolver (Explicit and Implicit)
202 /// Returns an ODESolver pointer based on an type
203 /// Caller gets ownership of the object and is responsible for its deletion
204 static MFEM_EXPORT std::unique_ptr<ODESolver> Select(const int ode_solver_type);
205
206 /// Function for selecting the desired Explicit ODESolver
207 /// Returns an ODESolver pointer based on an type
208 /// Caller gets ownership of the object and is responsible for its deletion
209 static MFEM_EXPORT std::unique_ptr<ODESolver> SelectExplicit(
210 const int ode_solver_type);
211
212 /// Function for selecting the desired Implicit ODESolver
213 /// Returns an ODESolver pointer based on an type
214 /// Caller gets ownership of the object and is responsible for its deletion
215 static MFEM_EXPORT std::unique_ptr<ODESolver> SelectImplicit(
216 const int ode_solver_type);
217
218
219 /// Function for selecting the desired IMEX ODESolver
220 /// Returns an ODESolver pointer based on an type
221 /// Caller gets ownership of the object and is responsible for its deletion
222 static MFEM_EXPORT std::unique_ptr<ODESolver> SelectIMEX(
223 const int ode_solver_type);
224
225 virtual ~ODESolver() { }
226};
227
228/// Abstract class for an ODESolver that has state history implemented as ODEStateData
230{
231public:
232 /// Returns the StateData
233 virtual ODEStateData& GetState() = 0;
234
235 /// Returns the StateData
236 virtual const ODEStateData& GetState() const = 0;
237
238 /// Returns how many State vectors the ODE requires
239 virtual int GetStateSize() { return GetState().MaxSize(); };
240};
241
242
243/// The classical forward Euler method
245{
246private:
247 Vector dxdt;
248
249public:
250 void Init(TimeDependentOperator &f_) override;
251
252 void Step(Vector &x, real_t &t, real_t &dt) override;
253};
254
255
256/** A family of explicit second-order RK2 methods. Some choices for the
257 parameter 'a' are:
258 a = 1/2 - the midpoint method
259 a = 1 - Heun's method
260 a = 2/3 - default, has minimal truncation error. */
261class RK2Solver : public ODESolver
262{
263private:
264 real_t a;
265 Vector dxdt, x1;
266
267public:
268 RK2Solver(const real_t a_ = 2./3.) : a(a_) { }
269
270 void Init(TimeDependentOperator &f_) override;
271
272 void Step(Vector &x, real_t &t, real_t &dt) override;
273};
274
275
276/// Third-order, strong stability preserving (SSP) Runge-Kutta method
278{
279private:
280 Vector y, k;
281
282public:
283 void Init(TimeDependentOperator &f_) override;
284
285 void Step(Vector &x, real_t &t, real_t &dt) override;
286};
287
288
289/// The classical explicit forth-order Runge-Kutta method, RK4
290class RK4Solver : public ODESolver
291{
292private:
293 Vector y, k, z;
294
295public:
296 void Init(TimeDependentOperator &f_) override;
297
298 void Step(Vector &x, real_t &t, real_t &dt) override;
299};
300
301
302/** An explicit Runge-Kutta method corresponding to a general Butcher tableau
303 +--------+----------------------+
304 | c[0] | a[0] |
305 | c[1] | a[1] a[2] |
306 | ... | ... |
307 | c[s-2] | ... a[s(s-1)/2-1] |
308 +--------+----------------------+
309 | | b[0] b[1] ... b[s-1] |
310 +--------+----------------------+ */
312{
313private:
314 int s;
315 const real_t *a, *b, *c;
316 Vector y, *k;
317
318public:
319 ExplicitRKSolver(int s_, const real_t *a_, const real_t *b_,
320 const real_t *c_);
321
322 void Init(TimeDependentOperator &f_) override;
323
324 void Step(Vector &x, real_t &t, real_t &dt) override;
325
326 virtual ~ExplicitRKSolver();
327};
328
329
330/** An 8-stage, 6th order RK method. From Verner's "efficient" 9-stage 6(5)
331 pair. */
333{
334private:
335 static MFEM_EXPORT const real_t a[28], b[8], c[7];
336
337public:
339};
340
341
342/** A 12-stage, 8th order RK method. From Verner's "efficient" 13-stage 8(7)
343 pair. */
345{
346private:
347 static MFEM_EXPORT const real_t a[66], b[12], c[11];
348
349public:
350 RK8Solver() : ExplicitRKSolver(12, a, b, c) { }
351};
352
353
354/// Backward Euler ODE solver. L-stable.
356{
357protected:
359
360public:
361 void Init(TimeDependentOperator &f_) override;
362
363 void Step(Vector &x, real_t &t, real_t &dt) override;
364};
365
366
367/// Implicit midpoint method. A-stable, not L-stable.
369{
370protected:
372
373public:
374 void Init(TimeDependentOperator &f_) override;
375
376 void Step(Vector &x, real_t &t, real_t &dt) override;
377};
378
379
380/** Two stage, singly diagonal implicit Runge-Kutta (SDIRK) methods;
381 the choices for gamma_opt are:
382 0 - 3rd order method, not A-stable
383 1 - 3rd order method, A-stable, not L-stable (default)
384 2 - 2nd order method, L-stable
385 3 - 2nd order method, L-stable (has solves outside [t,t+dt]). */
387{
388protected:
391
392public:
393 SDIRK23Solver(int gamma_opt = 1);
394
395 void Init(TimeDependentOperator &f_) override;
396
397 void Step(Vector &x, real_t &t, real_t &dt) override;
398};
399
400
401/** Three stage, singly diagonal implicit Runge-Kutta (SDIRK) method of
402 order 4. A-stable, not L-stable. */
404{
405protected:
407
408public:
409 void Init(TimeDependentOperator &f_) override;
410
411 void Step(Vector &x, real_t &t, real_t &dt) override;
412};
413
414
415/** Three stage, singly diagonal implicit Runge-Kutta (SDIRK) method of
416 order 3. L-stable. */
418{
419protected:
421
422public:
423 void Init(TimeDependentOperator &f_) override;
424
425 void Step(Vector &x, real_t &t, real_t &dt) override;
426};
427
428
429/** Two stage, explicit singly diagonal implicit Runge-Kutta (ESDIRK) method
430 of order 2. A-stable. */
432{
433protected:
435
436public:
437 void Init(TimeDependentOperator &f_) override;
438
439 void Step(Vector &x, real_t &t, real_t &dt) override;
440};
441
442
443/** Three stage, explicit singly diagonal implicit Runge-Kutta (ESDIRK) method
444 of order 2. L-stable. */
446{
447protected:
449
450public:
451 void Init(TimeDependentOperator &f_) override;
452
453 void Step(Vector &x, real_t &t, real_t &dt) override;
454};
455
456
457/** Three stage, explicit singly diagonal implicit Runge-Kutta (ESDIRK) method
458 of order 3. A-stable. */
460{
461protected:
463
464public:
465 void Init(TimeDependentOperator &f_) override;
466
467 void Step(Vector &x, real_t &t, real_t &dt) override;
468};
469
470
471/// Generalized-alpha ODE solver from "A generalized-α method for integrating
472/// the filtered Navier-Stokes equations with a stabilized finite element
473/// method" by K.E. Jansen, C.H. Whiting and G.M. Hulbert.
475{
476 ODEStateDataVector state;
477
478protected:
479
480 mutable Vector k,y;
482
483 void SetRhoInf(real_t rho_inf);
484 void PrintProperties(std::ostream &os = mfem::out);
485public:
486
487 GeneralizedAlphaSolver(real_t rho = 1.0) : state(1) { SetRhoInf(rho); };
488 void Init(TimeDependentOperator &f_) override;
489 void Step(Vector &x, real_t &t, real_t &dt) override;
490
491 ODEStateData& GetState() override { return state; }
492 const ODEStateData& GetState() const override { return state; }
493};
494
495
496/** An explicit Adams-Bashforth method. */
498{
499private:
500 const real_t *a;
501 const int stages;
502 real_t dt_;
503 ODEStateDataVector state;
504
505protected:
506 std::unique_ptr<ODESolver> RKsolver;
507
508 inline bool print()
509 {
510#ifdef MFEM_USE_MPI
511 return Mpi::IsInitialized() ? Mpi::Root() : true;
512#else
513 return true;
514#endif
515 }
516
517 void CheckTimestep(real_t dt);
518
519public:
520 AdamsBashforthSolver(int s_, const real_t *a_);
521 void Init(TimeDependentOperator &f_) override;
522 void Step(Vector &x, real_t &t, real_t &dt) override;
523
524 ODEStateData& GetState() override { return state; }
525 const ODEStateData& GetState() const override { return state; }
526};
527
528/** A 1-stage, 1st order AB method. */
530{
531private:
532 static MFEM_EXPORT const real_t a[1];
533
534public:
536};
537
538/** A 2-stage, 2nd order AB method. */
540{
541private:
542 static MFEM_EXPORT const real_t a[2];
543
544public:
546};
547
548/** A 3-stage, 3rd order AB method. */
550{
551private:
552 static MFEM_EXPORT const real_t a[3];
553
554public:
556};
557
558/** A 4-stage, 4th order AB method. */
560{
561private:
562 static MFEM_EXPORT const real_t a[4];
563
564public:
566};
567
568/** A 5-stage, 5th order AB method. */
570{
571private:
572 static MFEM_EXPORT const real_t a[5];
573
574public:
576};
577
578
579/** An implicit Adams-Moulton method. */
581{
582private:
583 const real_t *a;
584 const int stages;
585 real_t dt_;
586 ODEStateDataVector state;
587
588protected:
589 std::unique_ptr<ODESolver> RKsolver;
590
591 inline bool print()
592 {
593#ifdef MFEM_USE_MPI
594 return Mpi::IsInitialized() ? Mpi::Root() : true;
595#else
596 return true;
597#endif
598 }
599
601
602public:
603 AdamsMoultonSolver(int s_, const real_t *a_);
604 void Init(TimeDependentOperator &f_) override;
605 void Step(Vector &x, real_t &t, real_t &dt) override;
606
607 ODEStateData& GetState() override { return state; }
608 const ODEStateData& GetState() const override { return state; }
609};
610
611/** A 1-stage, 2nd order AM method. */
613{
614private:
615 static MFEM_EXPORT const real_t a[2];
616
617public:
619};
620
621/** A 2-stage, 3rd order AM method. */
623{
624private:
625 static MFEM_EXPORT const real_t a[3];
626
627public:
629};
630
631/** A 3-stage, 4th order AM method. */
633{
634private:
635 static MFEM_EXPORT const real_t a[4];
636
637public:
639};
640
641/** A 4-stage, 5th order AM method. */
643{
644private:
645 static MFEM_EXPORT const real_t a[5];
646
647public:
649};
650
651/// The SIASolver class is based on the Symplectic Integration Algorithm
652/// described in "A Symplectic Integration Algorithm for Separable Hamiltonian
653/// Functions" by J. Candy and W. Rozmus, Journal of Computational Physics,
654/// Vol. 92, pages 230-256 (1991).
655
656/** The Symplectic Integration Algorithm (SIA) is designed for systems of first
657 order ODEs derived from a Hamiltonian.
658 H(q,p,t) = T(p) + V(q,t)
659 Which leads to the equations:
660 dq/dt = dT/dp
661 dp/dt = -dV/dq
662 In the integrator the operators P and F are defined to be:
663 P = dT/dp
664 F = -dV/dq
665 */
667{
668public:
669 SIASolver() : F_(NULL), P_(NULL) {}
670
671 virtual void Init(Operator &P, TimeDependentOperator & F);
672
673 virtual void Step(Vector &q, Vector &p, real_t &t, real_t &dt) = 0;
674
675 virtual void Run(Vector &q, Vector &p, real_t &t, real_t &dt, real_t tf)
676 {
677 while (t < tf) { Step(q, p, t, dt); }
678 }
679
680 virtual ~SIASolver() {}
681
682protected:
683 TimeDependentOperator * F_; // p_{i+1} = p_{i} + dt F(q_{i})
684 Operator * P_; // q_{i+1} = q_{i} + dt P(p_{i+1})
685
686 mutable Vector dp_;
687 mutable Vector dq_;
688};
689
690/// First Order Symplectic Integration Algorithm
691class SIA1Solver : public SIASolver
692{
693public:
695 void Step(Vector &q, Vector &p, real_t &t, real_t &dt) override;
696};
697
698/// Second Order Symplectic Integration Algorithm
699class SIA2Solver : public SIASolver
700{
701public:
703 void Step(Vector &q, Vector &p, real_t &t, real_t &dt) override;
704};
705
706/// Variable order Symplectic Integration Algorithm (orders 1-4)
707class SIAVSolver : public SIASolver
708{
709public:
710 SIAVSolver(int order);
711 void Step(Vector &q, Vector &p, real_t &t, real_t &dt) override;
712
713private:
714 int order_;
715
716 Array<real_t> a_;
717 Array<real_t> b_;
718};
719
720
721
722/// Abstract class for solving systems of ODEs: d2x/dt2 = f(x,dx/dt,t)
724{
725protected:
726 /// Pointer to the associated TimeDependentOperator.
727 SecondOrderTimeDependentOperator *f; // f(.,.,t) : R^n x R^n --> R^n
730
731public:
733
734 /// Associate a TimeDependentOperator with the ODE solver.
735 /** This method has to be called:
736 - Before the first call to Step().
737 - When the dimensions of the associated TimeDependentOperator change.
738 - When a time stepping sequence has to be restarted.
739 - To change the associated TimeDependentOperator. */
741
742 /** @brief Perform a time step from time @a t [in] to time @a t [out] based
743 on the requested step size @a dt [in]. */
744 /** @param[in,out] x Approximate solution.
745 @param[in,out] dxdt Approximate rate.
746 @param[in,out] t Time associated with the
747 approximate solution @a x and rate @ dxdt
748 @param[in,out] dt Time step size.
749
750 The following rules describe the common behavior of the method:
751 - The input @a x [in] is the approximate solution for the input time
752 @a t [in].
753 - The input @a dxdt [in] is the approximate rate for the input time
754 @a t [in].
755 - The input @a dt [in] is the desired time step size, defining the desired
756 target time: t [target] = @a t [in] + @a dt [in].
757 - The output @a x [out] is the approximate solution for the output time
758 @a t [out].
759 - The output @a dxdt [out] is the approximate rate for the output time
760 @a t [out].
761 - The output @a dt [out] is the last time step taken by the method which
762 may be smaller or larger than the input @a dt [in] value, e.g. because
763 of time step control.
764 - The method may perform more than one time step internally; in this case
765 @a dt [out] is the last internal time step size.
766 - The output value of @a t [out] may be smaller or larger than
767 t [target], however, it is not smaller than @a t [in] + @a dt [out], if
768 at least one internal time step was performed.
769 - The value @a x [out] may be obtained by interpolation using internally
770 stored data.
771 - In some cases, the contents of @a x [in] may not be used, e.g. when
772 @a x [out] from a previous Step() call was obtained by interpolation.
773 - In consecutive calls to this method, the output @a t [out] of one
774 Step() call has to be the same as the input @a t [in] to the next
775 Step() call.
776 - If the previous rule has to be broken, e.g. to restart a time stepping
777 sequence, then the ODE solver must be re-initialized by calling Init()
778 between the two Step() calls. */
779 virtual void Step(Vector &x, Vector &dxdt, real_t &t, real_t &dt) = 0;
780 void EulerStep(Vector &x, Vector &dxdt, real_t &t, real_t &dt);
781 void MidPointStep(Vector &x, Vector &dxdt, real_t &t, real_t &dt);
782
783 /// Perform time integration from time @a t [in] to time @a tf [in].
784 /** @param[in,out] x Approximate solution.
785 @param[in,out] dxdt Approximate rate.
786 @param[in,out] t Time associated with the approximate solution @a x.
787 @param[in,out] dt Time step size.
788 @param[in] tf Requested final time.
789
790 The default implementation makes consecutive calls to Step() until
791 reaching @a tf.
792 The following rules describe the common behavior of the method:
793 - The input @a x [in] is the approximate solution for the input time
794 @a t [in].
795 - The input @a dxdt [in] is the approximate rate for the input time
796 @a t [in].
797 - The input @a dt [in] is the initial time step size.
798 - The output @a dt [out] is the last time step taken by the method which
799 may be smaller or larger than the input @a dt [in] value, e.g. because
800 of time step control.
801 - The output value of @a t [out] is not smaller than @a tf [in]. */
802 virtual void Run(Vector &x, Vector &dxdt, real_t &t, real_t &dt, real_t tf)
803 {
804 while (t < tf) { Step(x, dxdt, t, dt); }
805 }
806
807 /// Functions for getting the state vectors
809 const ODEStateData& GetState() const { return state; }
810
811 /// Returns how many State vectors the ODE requires
812 int GetStateSize() { return GetState().MaxSize(); };
813
814 /// Help info for SecondOrderODESolver options
815 static MFEM_EXPORT std::string Types;
816
817 /// Function selecting the desired SecondOrderODESolver
818 static MFEM_EXPORT SecondOrderODESolver *Select(const int ode_solver_type);
819
821};
822
823/// The classical newmark method.
824/// Newmark, N. M. (1959) A method of computation for structural dynamics.
825/// Journal of Engineering Mechanics, ASCE, 85 (EM3) 67-94.
827{
828private:
829 real_t beta, gamma;
830 bool no_mult;
831
832public:
833 NewmarkSolver(real_t beta_ = 0.25, real_t gamma_ = 0.5, bool no_mult_ = false)
834 {
835 beta = beta_;
836 gamma = gamma_;
837 no_mult = no_mult_;
838 };
839
840 void PrintProperties(std::ostream &os = mfem::out);
841
842 void Step(Vector &x, Vector &dxdt, real_t &t, real_t &dt) override;
843};
844
846{
847public:
849};
850
852{
853public:
855};
856
858{
859public:
860 FoxGoodwinSolver() : NewmarkSolver(1.0/12.0, 0.5) { };
861};
862
863/// Generalized-alpha ODE solver
864/// A Time Integration Algorithm for Structural Dynamics With Improved
865/// Numerical Dissipation: The Generalized-α Method
866/// J.Chung and G.M. Hulbert, J. Appl. Mech 60(2), 371-375, 1993
867/// https://doi.org/10.1115/1.2900803
868/// rho_inf in [0,1]
870{
871protected:
875
876public:
877 GeneralizedAlpha2Solver(real_t rho_inf = 1.0, bool no_mult_ = false)
878 {
879 no_mult = no_mult_;
880 rho_inf = (rho_inf > 1.0) ? 1.0 : rho_inf;
881 rho_inf = (rho_inf < 0.0) ? 0.0 : rho_inf;
882
883 alpha_m = (2.0 - rho_inf)/(1.0 + rho_inf);
884 alpha_f = 1.0/(1.0 + rho_inf);
885 beta = 0.25*pow(1.0 + alpha_m - alpha_f,2);
886 gamma = 0.5 + alpha_m - alpha_f;
887 };
888
889 void PrintProperties(std::ostream &os = mfem::out);
890
891 void Init(SecondOrderTimeDependentOperator &f_) override;
892
893 void Step(Vector &x, Vector &dxdt, real_t &t, real_t &dt) override;
894
895};
896
897/// The classical midpoint method.
899{
900public:
902 {
903 alpha_m = 0.5;
904 alpha_f = 0.5;
905 beta = 0.25;
906 gamma = 0.5;
907 };
908};
909
910/// HHT-alpha ODE solver
911/// Improved numerical dissipation for time integration algorithms
912/// in structural dynamics
913/// H.M. Hilber, T.J.R. Hughes and R.L. Taylor 1977
914/// https://doi.org/10.1002/eqe.4290050306
915/// alpha in [2/3,1] --> Defined differently than in paper.
917{
918public:
920 {
921 alpha = (alpha > 1.0) ? 1.0 : alpha;
922 alpha = (alpha < 2.0/3.0) ? 2.0/3.0 : alpha;
923
924 alpha_m = 1.0;
925 alpha_f = alpha;
926 beta = (2-alpha)*(2-alpha)/4;
927 gamma = 0.5 + alpha_m - alpha_f;
928 };
929
930};
931
932/// WBZ-alpha ODE solver
933/// An alpha modification of Newmark's method
934/// W.L. Wood, M. Bossak and O.C. Zienkiewicz 1980
935/// https://doi.org/10.1002/nme.1620151011
936/// rho_inf in [0,1]
938{
939public:
940 WBZAlphaSolver(real_t rho_inf = 1.0)
941 {
942 rho_inf = (rho_inf > 1.0) ? 1.0 : rho_inf;
943 rho_inf = (rho_inf < 0.0) ? 0.0 : rho_inf;
944
945 alpha_f = 1.0;
946 alpha_m = 2.0/(1.0 + rho_inf);
947 beta = 0.25*pow(1.0 + alpha_m - alpha_f,2);
948 gamma = 0.5 + alpha_m - alpha_f;
949 };
950
951};
952
953/// Forward-backward Euler method
955{
956private:
957 Vector k1; Vector k2;
958public:
959 void Init(TimeDependentOperator &f_) override;
960
961 void Step(Vector &x, real_t &t, real_t &dt) override;
962};
963
964/// Second order, two-stage implicit-explicit (IMEX) Runge-Kutta (RK) method
965/** L-stable IMEX RK2 method adopted from "On the Stability of IMEX Upwind gSBP
966 Schemes for 1D Linear Advection‑Difusion Equations" by Sigrun Ortleb. Same
967 as (2,2,2) from "Implicit-explicit Runge-Kutta methods for time-dependent
968 partial differential equations" by Ascher, Ruuth and Spiteri, Applied
969 Numerical Mathematics (1997). */
970class IMEXRK2 : public ODESolver
971{
972private:
973 Vector k1_exp; Vector k2_exp; Vector k_imp;
974 //helper vector
975 Vector y;
976public:
977 void Init(TimeDependentOperator &f_) override;
978
979 void Step(Vector &x, real_t &t, real_t &dt) override;
980};
981
982/// Second order, 2/3-stage implicit-explicit (IMEX) Runge-Kutta (RK) method
983/** L-stable method (2,3,2) from "Implicit-explicit Runge-Kutta methods for
984 time-dependent partial differential equations" by Ascher, Ruuth and
985 Spiteri, Applied Numerical Mathematics (1997). */
987{
988private:
989 Vector k1_exp; Vector k2_exp; Vector k3_exp;
990 Vector k_imp;
991 //helper vectors
992 Vector y;
993public:
994 void Init(TimeDependentOperator &f_) override;
995
996 void Step(Vector &x, real_t &t, real_t &dt) override;
997};
998
999/// Third order, 3/4-stage implicit-explicit (IMEX) Runge-Kutta (RK) method
1000/** L-stable method (3,4,3) from "Implicit-explicit Runge-Kutta methods for
1001 time-dependent partial differential equations" by Ascher, Ruuth and
1002 Spiteri, Applied Numerical Mathematics (1997). */
1004{
1005private:
1006 Vector k1_exp; Vector k2_exp; Vector k3_exp; Vector k4_exp;
1007 Vector k2_imp; Vector k3_imp;
1008 //helper vectors
1009 Vector y;
1010public:
1011 void Init(TimeDependentOperator &f_) override;
1012
1013 void Step(Vector &x, real_t &t, real_t &dt) override;
1014};
1015
1016
1017}
1018
1019#endif
ODEStateData & GetState() override
Returns the StateData.
Definition ode.hpp:524
const ODEStateData & GetState() const override
Returns the StateData.
Definition ode.hpp:525
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:516
void CheckTimestep(real_t dt)
Definition ode.cpp:549
AdamsBashforthSolver(int s_, const real_t *a_)
Definition ode.cpp:510
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:524
std::unique_ptr< ODESolver > RKsolver
Definition ode.hpp:506
const ODEStateData & GetState() const override
Returns the StateData.
Definition ode.hpp:608
std::unique_ptr< ODESolver > RKsolver
Definition ode.hpp:589
ODEStateData & GetState() override
Returns the StateData.
Definition ode.hpp:607
void CheckTimestep(real_t dt)
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:597
AdamsMoultonSolver(int s_, const real_t *a_)
Definition ode.cpp:583
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:589
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:840
The classical midpoint method.
Definition ode.hpp:899
Backward Euler ODE solver. L-stable.
Definition ode.hpp:356
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:654
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:660
static MemoryType GetHostMemoryType()
Get the current Host MemoryType. This is the MemoryType used by most MFEM classes when allocating mem...
Definition device.hpp:268
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:825
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:833
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:860
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:868
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:322
virtual ~ExplicitRKSolver()
Definition ode.cpp:352
ExplicitRKSolver(int s_, const real_t *a_, const real_t *b_, const real_t *c_)
Definition ode.cpp:301
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:311
The classical forward Euler method.
Definition ode.hpp:245
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:193
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:187
void PrintProperties(std::ostream &os=mfem::out)
Definition ode.cpp:1219
void Init(SecondOrderTimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:1211
void Step(Vector &x, Vector &dxdt, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:1249
GeneralizedAlpha2Solver(real_t rho_inf=1.0, bool no_mult_=false)
Definition ode.hpp:877
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:897
void SetRhoInf(real_t rho_inf)
Definition ode.cpp:905
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:943
GeneralizedAlphaSolver(real_t rho=1.0)
Definition ode.hpp:487
ODEStateData & GetState() override
Returns the StateData.
Definition ode.hpp:491
void PrintProperties(std::ostream &os=mfem::out)
Definition ode.cpp:916
const ODEStateData & GetState() const override
Returns the StateData.
Definition ode.hpp:492
HHTAlphaSolver(real_t alpha=1.0)
Definition ode.hpp:919
Forward-backward Euler method.
Definition ode.hpp:955
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:1300
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:1308
Second order, 2/3-stage implicit-explicit (IMEX) Runge-Kutta (RK) method.
Definition ode.hpp:987
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:1374
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:1385
Second order, two-stage implicit-explicit (IMEX) Runge-Kutta (RK) method.
Definition ode.hpp:971
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:1324
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:1334
Third order, 3/4-stage implicit-explicit (IMEX) Runge-Kutta (RK) method.
Definition ode.hpp:1004
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:1431
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:1444
Implicit midpoint method. A-stable, not L-stable.
Definition ode.hpp:369
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:675
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:669
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
static bool IsInitialized()
Return true if MPI has been initialized.
NewmarkSolver(real_t beta_=0.25, real_t gamma_=0.5, bool no_mult_=false)
Definition ode.hpp:833
void Step(Vector &x, Vector &dxdt, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:1176
void PrintProperties(std::ostream &os=mfem::out)
Definition ode.cpp:1146
Abstract class for an ODESolver that has state history implemented as ODEStateData.
Definition ode.hpp:230
virtual const ODEStateData & GetState() const =0
Returns the StateData.
virtual int GetStateSize()
Returns how many State vectors the ODE requires.
Definition ode.hpp:239
virtual ODEStateData & GetState()=0
Returns the StateData.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
Definition ode.hpp:121
TimeDependentOperator * f
Pointer to the associated TimeDependentOperator.
Definition ode.hpp:124
virtual void Init(TimeDependentOperator &f_)
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:181
virtual void Step(Vector &x, real_t &t, real_t &dt)=0
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
virtual ~ODESolver()
Definition ode.hpp:225
static MFEM_EXPORT std::unique_ptr< ODESolver > SelectImplicit(const int ode_solver_type)
Definition ode.cpp:76
static MFEM_EXPORT std::string Types
Definition ode.hpp:199
static MFEM_EXPORT std::unique_ptr< ODESolver > Select(const int ode_solver_type)
Definition ode.cpp:40
MemoryType mem_type
Definition ode.hpp:125
static MFEM_EXPORT std::string ImplicitTypes
Definition ode.hpp:197
static MFEM_EXPORT std::unique_ptr< ODESolver > SelectIMEX(const int ode_solver_type)
Definition ode.cpp:115
virtual void Run(Vector &x, real_t &t, real_t &dt, real_t tf)
Perform time integration from time t [in] to time tf [in].
Definition ode.hpp:187
static MFEM_EXPORT std::string ExplicitTypes
Definition ode.hpp:196
virtual int GetStateSize()
Returns how many State vectors the ODE requires.
Definition ode.hpp:193
static MFEM_EXPORT std::unique_ptr< ODESolver > SelectExplicit(const int ode_solver_type)
Definition ode.cpp:52
static MFEM_EXPORT std::string IMEXTypes
Definition ode.hpp:198
An implementation of ODEStateData that stores states in an std::vector<Vector>
Definition ode.hpp:55
void Increment()
Increment the stage counter.
Definition ode.hpp:80
const Vector & Get(int i) const override
Get the ith state vector.
Definition ode.cpp:142
void Set(int i, Vector &state) override
Set the ith state vector.
Definition ode.cpp:160
void SetSize(int vsize, MemoryType mem_type)
Set the number of stages and the size of the vectors.
Definition ode.cpp:130
ODEStateDataVector(int smax)
Definition ode.hpp:63
void Append(Vector &state) override
Add state vector and increment state size.
Definition ode.cpp:166
void ShiftStages()
Shift the stage counter for the next timestep.
Definition ode.hpp:74
void Print(std::ostream &os=mfem::out) const
Print state data.
Definition ode.cpp:173
Vector & operator[](int i)
Reference access to the ith vector.
Definition ode.hpp:86
const Vector & operator[](int i) const
Const reference access to the ith vector.
Definition ode.hpp:89
int Size() const override
Get the current number of stored stages.
Definition ode.hpp:96
int MaxSize() const override
Get the maximum number of stored stages.
Definition ode.hpp:94
void Reset()
Reset the stage counter.
Definition ode.hpp:83
An interface for storing state of previous timesteps.
Definition ode.hpp:26
virtual void Get(int i, Vector &vec) const =0
Get the ith state vector - with a copy.
virtual int MaxSize() const =0
Get the maximum number of stored stages.
virtual Vector & Get(int i)=0
Get the ith state vector - non-const version.
virtual const Vector & Get(int i) const =0
Get the ith state vector.
virtual void Set(int i, Vector &state)=0
Set the ith state vector.
virtual void Append(Vector &state)=0
Add state vector and increment state size.
virtual int Size() const =0
Get the current number of stored stages.
virtual ~ODEStateData()=default
Virtual destructor.
Abstract operator.
Definition operator.hpp:25
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:202
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:210
RK2Solver(const real_t a_=2./3.)
Definition ode.hpp:268
Third-order, strong stability preserving (SSP) Runge-Kutta method.
Definition ode.hpp:278
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:231
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:239
The classical explicit forth-order Runge-Kutta method, RK4.
Definition ode.hpp:291
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:263
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:272
SDIRK23Solver(int gamma_opt=1)
Definition ode.cpp:684
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:711
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:704
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:775
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:768
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:739
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:731
First Order Symplectic Integration Algorithm.
Definition ode.hpp:692
void Step(Vector &q, Vector &p, real_t &t, real_t &dt) override
Definition ode.cpp:980
Second Order Symplectic Integration Algorithm.
Definition ode.hpp:700
void Step(Vector &q, Vector &p, real_t &t, real_t &dt) override
Definition ode.cpp:993
TimeDependentOperator * F_
Definition ode.hpp:683
Vector dq_
Definition ode.hpp:687
Vector dp_
Definition ode.hpp:686
virtual void Init(Operator &P, TimeDependentOperator &F)
Definition ode.cpp:971
virtual void Step(Vector &q, Vector &p, real_t &t, real_t &dt)=0
virtual ~SIASolver()
Definition ode.hpp:680
virtual void Run(Vector &q, Vector &p, real_t &t, real_t &dt, real_t tf)
Definition ode.hpp:675
Operator * P_
Definition ode.hpp:684
Variable order Symplectic Integration Algorithm (orders 1-4)
Definition ode.hpp:708
void Step(Vector &q, Vector &p, real_t &t, real_t &dt) override
Definition ode.cpp:1050
SIAVSolver(int order)
Definition ode.cpp:1008
Abstract class for solving systems of ODEs: d2x/dt2 = f(x,dx/dt,t)
Definition ode.hpp:724
SecondOrderTimeDependentOperator * f
Pointer to the associated TimeDependentOperator.
Definition ode.hpp:727
ODEStateData & GetState()
Functions for getting the state vectors.
Definition ode.hpp:808
void MidPointStep(Vector &x, Vector &dxdt, real_t &t, real_t &dt)
Definition ode.cpp:1125
virtual ~SecondOrderODESolver()
Definition ode.hpp:820
const ODEStateData & GetState() const
Definition ode.hpp:809
ODEStateDataVector state
Definition ode.hpp:729
int GetStateSize()
Returns how many State vectors the ODE requires.
Definition ode.hpp:812
static MFEM_EXPORT std::string Types
Help info for SecondOrderODESolver options.
Definition ode.hpp:815
void EulerStep(Vector &x, Vector &dxdt, real_t &t, real_t &dt)
Definition ode.cpp:1111
static MFEM_EXPORT SecondOrderODESolver * Select(const int ode_solver_type)
Function selecting the desired SecondOrderODESolver.
Definition ode.cpp:1081
virtual void Run(Vector &x, Vector &dxdt, real_t &t, real_t &dt, real_t tf)
Perform time integration from time t [in] to time tf [in].
Definition ode.hpp:802
virtual void Init(SecondOrderTimeDependentOperator &f)
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:1139
virtual void Step(Vector &x, Vector &dxdt, real_t &t, real_t &dt)=0
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Base abstract class for second order time dependent operators.
Definition operator.hpp:744
Base abstract class for first order time dependent operators.
Definition operator.hpp:344
void Step(Vector &x, real_t &t, real_t &dt) override
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
Definition ode.cpp:808
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:801
Vector data type.
Definition vector.hpp:82
WBZAlphaSolver(real_t rho_inf=1.0)
Definition ode.hpp:940
Vector beta_
const real_t alpha
Definition ex15.cpp:369
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
float real_t
Definition config.hpp:46
MemoryType
Memory types supported by MFEM.
@ HOST
Host memory; using new[] and delete[].
real_t p(const Vector &x, real_t t)