Nektar++
DIRKTimeIntegrationSchemes.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: DIRKTimeIntegrationSchemes.h
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2018 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Combined header file for all basic DIRK based time integration
33 // schemes.
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 
37 // Note : If adding a new integrator be sure to register the
38 // integrator with the Time Integration Scheme Facatory in
39 // SchemeInitializor.cpp.
40 
41 #ifndef NEKTAR_LIB_UTILITIES_TIME_INTEGRATION_DIRK_TIME_INTEGRATION_SCHEME
42 #define NEKTAR_LIB_UTILITIES_TIME_INTEGRATION_DIRK_TIME_INTEGRATION_SCHEME
43 
44 #define LUE LIB_UTILITIES_EXPORT
45 using namespace std;
46 
49 
50 namespace Nektar
51 {
52 namespace LibUtilities
53 {
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 // DIRK Order N
58 {
59 public:
60  DIRKTimeIntegrationScheme(std::string variant, unsigned int order,
61  std::vector<NekDouble> freeParams)
62  : TimeIntegrationSchemeGLM(variant, order, freeParams)
63  {
64  // Currently 2nd and 3rd order are implemented.
65  ASSERTL1(2 <= order && order <= 4,
66  "Diagonally Implicit Runge Kutta integration scheme bad order "
67  "(2-4): " +
68  std::to_string(order));
69 
70  m_integration_phases = TimeIntegrationAlgorithmGLMVector(1);
71  m_integration_phases[0] = TimeIntegrationAlgorithmGLMSharedPtr(
72  new TimeIntegrationAlgorithmGLM(this));
73 
74  ASSERTL1((variant == "" || variant == "ES5" || variant == "ES6"),
75  "DIRK Time integration scheme bad variant: "
76  + variant + ". "
77  "Must blank, 'ES5', or 'ES6'");
78 
79  if ("" == variant)
80  {
81  DIRKTimeIntegrationScheme::SetupSchemeData( m_integration_phases[0],
82  order);
83  }
84  else
85  {
86  DIRKTimeIntegrationScheme::SetupSchemeDataESDIRK(
87  m_integration_phases[0], variant, order, freeParams);
88  }
89  }
90 
92  {
93  }
94 
96  std::string variant, unsigned int order,
97  std::vector<NekDouble> freeParams)
98  {
101  variant, order, freeParams);
102  return p;
103  }
104 
105  static std::string className;
106 
107  LUE virtual std::string GetName() const
108  {
109  return std::string("DIRK");
110  }
111 
113  {
114  return 1.0;
115  }
116 
118  unsigned int order)
119  {
120  phase->m_schemeType = eDiagonallyImplicit;
121  phase->m_order = order;
122  phase->m_name =
123  std::string("DIRKOrder" + std::to_string(phase->m_order));
124 
125  phase->m_numsteps = 1;
126  phase->m_numstages = phase->m_order;
127 
128  phase->m_A = Array<OneD, Array<TwoD, NekDouble>>(1);
129  phase->m_B = Array<OneD, Array<TwoD, NekDouble>>(1);
130 
131  phase->m_A[0] =
132  Array<TwoD, NekDouble>(phase->m_numstages, phase->m_numstages, 0.0);
133  phase->m_B[0] =
134  Array<TwoD, NekDouble>(phase->m_numsteps, phase->m_numstages, 0.0);
135  phase->m_U =
136  Array<TwoD, NekDouble>(phase->m_numstages, phase->m_numsteps, 1.0);
137  phase->m_V =
138  Array<TwoD, NekDouble>(phase->m_numsteps, phase->m_numsteps, 1.0);
139 
140  switch (phase->m_order)
141  {
142  case 2:
143  {
144  // Two-stage, 2nd order Diagonally Implicit Runge
145  // Kutta method. It is A-stable if and only if x ≥ 1/4
146  // and is L-stable if and only if x equals one of the
147  // roots of the polynomial x^2 - 2x + 1/2, i.e. if
148  // x = 1 ± sqrt(2)/2.
149  NekDouble lambda = (2.0 - sqrt(2.0)) / 2.0;
150 
151  phase->m_A[0][0][0] = lambda;
152  phase->m_A[0][1][0] = 1.0 - lambda;
153  phase->m_A[0][1][1] = lambda;
154 
155  phase->m_B[0][0][0] = 1.0 - lambda;
156  phase->m_B[0][0][1] = lambda;
157  }
158  break;
159 
160  case 3:
161  {
162  // Three-stage, 3rd order, L-stable Diagonally Implicit
163  // Runge Kutta method:
164  NekDouble lambda = 0.4358665215;
165 
166  phase->m_A[0][0][0] = lambda;
167  phase->m_A[0][1][0] = 0.5 * (1.0 - lambda);
168  phase->m_A[0][2][0] =
169  0.25 * (-6.0 * lambda * lambda + 16.0 * lambda - 1.0);
170 
171  phase->m_A[0][1][1] = lambda;
172 
173  phase->m_A[0][2][1] =
174  0.25 * (6.0 * lambda * lambda - 20.0 * lambda + 5.0);
175  phase->m_A[0][2][2] = lambda;
176 
177  phase->m_B[0][0][0] =
178  0.25 * (-6.0 * lambda * lambda + 16.0 * lambda - 1.0);
179  phase->m_B[0][0][1] =
180  0.25 * (6.0 * lambda * lambda - 20.0 * lambda + 5.0);
181  phase->m_B[0][0][2] = lambda;
182  }
183  break;
184  }
185 
186  phase->m_numMultiStepValues = 1;
187  phase->m_numMultiStepDerivs = 0;
188  phase->m_timeLevelOffset = Array<OneD, unsigned int>(phase->m_numsteps);
189  phase->m_timeLevelOffset[0] = 0;
190 
191  phase->CheckAndVerify();
192  }
193 
196  std::string variant,
197  unsigned int order,
198  std::vector<NekDouble> freeParams)
199  {
200  phase->m_schemeType = eDiagonallyImplicit;
201  phase->m_order = order;
202  phase->m_name = std::string("DIRKOrder" +
203  std::to_string(phase->m_order)
204  + variant);
205 
206  phase->m_numsteps = 1;
207  char const &stage = variant.back();
208  phase->m_numstages = std::atoi(&stage);
209 
210  phase->m_A = Array<OneD, Array<TwoD, NekDouble>>(1);
211  phase->m_B = Array<OneD, Array<TwoD, NekDouble>>(1);
212 
213  phase->m_A[0] =
214  Array<TwoD, NekDouble>(phase->m_numstages, phase->m_numstages, 0.0);
215  phase->m_B[0] =
216  Array<TwoD, NekDouble>(phase->m_numsteps, phase->m_numstages, 0.0);
217  phase->m_U =
218  Array<TwoD, NekDouble>(phase->m_numstages, phase->m_numsteps, 1.0);
219  phase->m_V =
220  Array<TwoD, NekDouble>(phase->m_numsteps, phase->m_numsteps, 1.0);
221 
222  const NekDouble ConstSqrt2 = sqrt(2.0);
223  switch( phase->m_order )
224  {
225  case 3:
226  {
227  ASSERTL0(5==phase->m_numstages,
228  std::string("DIRKOrder3_ES" +
229  std::to_string(phase->m_numstages)+
230  " not defined"));
231  NekDouble lambda;
232  if(freeParams.size())
233  {
234  lambda = freeParams[0];
235  }
236  else
237  {
238  lambda = 9.0/40.0;
239  }
240 
241  phase->m_A[0][0][0] = 0.0;
242  phase->m_A[0][1][0] = lambda;
243  phase->m_A[0][2][0] = 9.0 * (1.0 + ConstSqrt2) / 80.0;
244  phase->m_A[0][3][0] = (22.0 + 15.0 * ConstSqrt2) /
245  (80.0 * (1 + ConstSqrt2));
246  phase->m_A[0][4][0] = (2398.0 + 1205.0 * ConstSqrt2) /
247  (2835.0 * (4 + 3.0 * ConstSqrt2));
248 
249  phase->m_A[0][1][1] = phase->m_A[0][1][0];
250  phase->m_A[0][2][1] = phase->m_A[0][2][0];
251  phase->m_A[0][3][1] = phase->m_A[0][3][0];
252  phase->m_A[0][4][1] = phase->m_A[0][4][0];
253 
254  phase->m_A[0][2][2] = lambda;
255  phase->m_A[0][3][2] = -7.0 / (40.0 * (1.0 + ConstSqrt2));
256  phase->m_A[0][4][2] = -2374 * (2.0 + ConstSqrt2)/
257  (2835.0 * (4.0 + 3.0 * ConstSqrt2));
258 
259  phase->m_A[0][3][3] = lambda;
260  phase->m_A[0][4][3] = 5827.0 / 7560.0;
261 
262  phase->m_A[0][4][4] = lambda;
263 
264  phase->m_B[0][0][0] = phase->m_A[0][4][0];
265  phase->m_B[0][0][1] = phase->m_A[0][4][1];
266  phase->m_B[0][0][2] = phase->m_A[0][4][2];
267  phase->m_B[0][0][3] = phase->m_A[0][4][3];
268  phase->m_B[0][0][4] = phase->m_A[0][4][4];
269  }
270  break;
271 
272  case 4:
273  {
274  ASSERTL0(6 == phase->m_numstages,
275  std::string("DIRKOrder4_ES" +
276  std::to_string(phase->m_numstages)+
277  " not defined"));
278  NekDouble lambda;
279  if (freeParams.size())
280  {
281  lambda = freeParams[0];
282  }
283  else
284  {
285  lambda = 1.0 / 4.0;
286  }
287 
288  const NekDouble ConstSqrt2 = sqrt(2.0);
289 
290  phase->m_A[0][0][0] = 0.0;
291  phase->m_A[0][1][0] = lambda;
292  phase->m_A[0][2][0] = (1.0 - ConstSqrt2) / 8.0;
293  phase->m_A[0][3][0] = (5.0 - 7.0 * ConstSqrt2) / 64.0;
294  phase->m_A[0][4][0] = (-13796.0 - 54539 * ConstSqrt2) /
295  125000.0;
296  phase->m_A[0][5][0] = (1181.0 - 987.0 * ConstSqrt2) /
297  13782.0;
298 
299  phase->m_A[0][1][1] = phase->m_A[0][1][0];
300  phase->m_A[0][2][1] = phase->m_A[0][2][0];
301  phase->m_A[0][3][1] = phase->m_A[0][3][0];
302  phase->m_A[0][4][1] = phase->m_A[0][4][0];
303  phase->m_A[0][5][1] = phase->m_A[0][5][0];
304 
305  phase->m_A[0][2][2] = lambda;
306  phase->m_A[0][3][2] = 7.0 * (1.0 + ConstSqrt2) /
307  32.0;
308  phase->m_A[0][4][2] = (506605.0 + 132109.0 * ConstSqrt2) /
309  437500.0;
310  phase->m_A[0][5][2] = 47.0 * (-267.0 + 1783.0 * ConstSqrt2) /
311  273343.0;
312 
313  phase->m_A[0][3][3] = lambda;
314  phase->m_A[0][4][3] = 166.0 * (-97.0 + 376.0 * ConstSqrt2) /
315  109375.0;
316  phase->m_A[0][5][3] = -16.0 * (-22922.0 + 3525.0 * ConstSqrt2) /
317  571953.0;
318 
319  phase->m_A[0][4][4] = lambda;
320  phase->m_A[0][5][4] = -15625.0 * (97.0 + 376.0 * ConstSqrt2) /
321  90749876.0;
322 
323  phase->m_A[0][5][5] = lambda;
324  }
325  break;
326  default:
327  {
328  ASSERTL0(false, std::string("ESDIRK of order" +
329  std::to_string(phase->m_order)+
330  " not defined"));
331  break;
332  }
333  }
334 
335  phase->m_numMultiStepValues = 1;
336  phase->m_numMultiStepDerivs = 0;
337  phase->m_timeLevelOffset = Array<OneD, unsigned int>(phase->m_numsteps);
338  phase->m_timeLevelOffset[0] = 0;
339 
340  phase->CheckAndVerify();
341  }
342 
343 }; // end class DIRKTimeIntegrationScheme
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 // Backwards compatibility
348 {
349 public:
350  DIRKOrder2TimeIntegrationScheme(std::string variant, unsigned int order,
351  std::vector<NekDouble> freeParams)
352  : DIRKTimeIntegrationScheme("", 2, freeParams)
353  {
354  boost::ignore_unused(variant);
355  boost::ignore_unused(order);
356  }
357 
359  std::string variant, unsigned int order,
360  std::vector<NekDouble> freeParams)
361  {
362  boost::ignore_unused(variant);
363  boost::ignore_unused(order);
364 
367  "", 2, freeParams);
368 
369  return p;
370  }
371 
372  static std::string className;
373 
374 }; // end class DIRKOrder2TimeIntegrationScheme
375 
377 {
378 public:
379  DIRKOrder3TimeIntegrationScheme(std::string variant, unsigned int order,
380  std::vector<NekDouble> freeParams)
381  : DIRKTimeIntegrationScheme("", 3, freeParams)
382  {
383  boost::ignore_unused(variant);
384  boost::ignore_unused(order);
385  }
386 
388  std::string variant, unsigned int order,
389  std::vector<NekDouble> freeParams)
390  {
391  boost::ignore_unused(variant);
392  boost::ignore_unused(order);
393 
396  "", 3, freeParams);
397 
398  return p;
399  }
400 
401  static std::string className;
402 
403 }; // end class DIRKOrder3TimeIntegrationScheme
404 
407 {
408 public:
409  DIRKOrder3_ES5TimeIntegrationScheme(std::string variant, unsigned int order,
410  std::vector<NekDouble> freeParams) :
411  DIRKTimeIntegrationScheme("ES5", 3, freeParams)
412  {
413  boost::ignore_unused(variant);
414  boost::ignore_unused(order);
415  }
416 
418  std::string variant, unsigned int order,
419  std::vector<NekDouble> freeParams)
420  {
421  boost::ignore_unused(variant);
422  boost::ignore_unused(order);
423 
425  DIRKTimeIntegrationScheme>::AllocateSharedPtr("ES5", 3, freeParams);
426 
427  return p;
428  }
429 
430  static std::string className;
431 
432 }; // end class DIRKOrder3_ES5TimeIntegrationScheme
433 
436 {
437 public:
438  DIRKOrder4_ES6TimeIntegrationScheme(std::string variant, unsigned int order,
439  std::vector<NekDouble> freeParams) :
440  DIRKTimeIntegrationScheme("ES6", 4, freeParams)
441  {
442  boost::ignore_unused(variant);
443  boost::ignore_unused(order);
444  }
445 
447  std::string variant, unsigned int order,
448  std::vector<NekDouble> freeParams)
449  {
450  boost::ignore_unused(variant);
451  boost::ignore_unused(order);
452 
454  DIRKTimeIntegrationScheme>::AllocateSharedPtr("ES6", 4, freeParams);
455 
456  return p;
457  }
458 
459  static std::string className;
460 
461 };
462 
463 } // end namespace LibUtilities
464 } // end namespace Nektar
465 
466 #endif
#define LUE
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:250
DIRKOrder2TimeIntegrationScheme(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static TimeIntegrationSchemeSharedPtr create(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
DIRKOrder3_ES5TimeIntegrationScheme(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static TimeIntegrationSchemeSharedPtr create(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static TimeIntegrationSchemeSharedPtr create(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
DIRKOrder3TimeIntegrationScheme(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static TimeIntegrationSchemeSharedPtr create(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
DIRKOrder4_ES6TimeIntegrationScheme(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static LUE void SetupSchemeDataESDIRK(TimeIntegrationAlgorithmGLMSharedPtr &phase, std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static TimeIntegrationSchemeSharedPtr create(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
static LUE void SetupSchemeData(TimeIntegrationAlgorithmGLMSharedPtr &phase, unsigned int order)
DIRKTimeIntegrationScheme(std::string variant, unsigned int order, std::vector< NekDouble > freeParams)
Base class for GLM time integration schemes.
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
std::shared_ptr< TimeIntegrationAlgorithmGLM > TimeIntegrationAlgorithmGLMSharedPtr
@ eDiagonallyImplicit
Diagonally implicit scheme (e.g. the DIRK schemes)
std::vector< TimeIntegrationAlgorithmGLMSharedPtr > TimeIntegrationAlgorithmGLMVector
std::shared_ptr< TimeIntegrationScheme > TimeIntegrationSchemeSharedPtr
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
double NekDouble
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267