Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TimeIntegrationScheme.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: TimeIntegrationScheme.h
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 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: Header file of time integration scheme base class
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NEKTAR_LIB_UTILITIES_FOUNDATIONS_TIMEINTEGRATIONSCHEME_H
37 #define NEKTAR_LIB_UTILITIES_FOUNDATIONS_TIMEINTEGRATIONSCHEME_H
38 
44 
45 namespace Nektar
46 {
47  namespace LibUtilities
48  {
49  // Forward declaration of all classes in this file
50  class TimeIntegrationScheme;
52 
53  // typedefs
54  typedef boost::shared_ptr<TimeIntegrationScheme> TimeIntegrationSchemeSharedPtr;
55  typedef std::vector<TimeIntegrationSchemeSharedPtr> TimeIntegrationSchemeVector;
57  typedef boost::shared_ptr<TimeIntegrationSolution> TimeIntegrationSolutionSharedPtr;
58  typedef std::vector<TimeIntegrationSolutionSharedPtr> TimeIntegrationSolutionVector;
60 
61  // =========================================================================
62  // ==== ENUM LIST OF ALL SUPPORTED INTEGRATION SCHEMES
63  // =========================================================================
65  {
67  eAdamsBashforthOrder1, //!< Adams-Bashforth Forward multi-step scheme of order 1
68  eAdamsBashforthOrder2, //!< Adams-Bashforth Forward multi-step scheme of order 2
69  eAdamsBashforthOrder3, //!< Adams-Bashforth Forward multi-step scheme of order 3
70  eAdamsMoultonOrder1, //!< Adams-Moulton Forward multi-step scheme of order 1
71  eAdamsMoultonOrder2, //!< Adams-Moulton Forward multi-step scheme of order 2
72  eBDFImplicitOrder1, //!< BDF multi-step scheme of order 1 (implicit)
73  eBDFImplicitOrder2, //!< BDF multi-step scheme of order 2 (implicit)
74  eClassicalRungeKutta4, //!< Runge-Kutta multi-stage scheme 4th order explicit
75  eRungeKutta2_ModifiedEuler, //!< Runge-Kutta multi-stage scheme 2nd order explicit
76  eRungeKutta2_ImprovedEuler, //!< Runge-Kutta multi-stage scheme 2nd order explicit
77  eForwardEuler, //!< Forward euler scheme
78  eBackwardEuler, //!< Backward euler scheme
79  eIMEXOrder1, //!< IMEX 1st order scheme using Euler Backwards/Euler Forwards
80  eIMEXOrder2, //!< IMEX 2nd order scheme using Backward Different Formula & Extrapolation
81  eIMEXOrder3, //!< IMEX 3rd order scheme using Backward Different Formula & Extrapolation
82  eMidpoint, //!< midpoint method
83  eDIRKOrder2, //!< Diagonally Implicit Runge Kutta scheme of order 3
84  eDIRKOrder3, //!< Diagonally Implicit Runge Kutta scheme of order 3
85  eCNAB, //!< Crank-Nicolson/Adams-Bashforth Order 2 (CNAB)
86  eIMEXGear, //!< IMEX Gear Order 2
87  eMCNAB, //!< Modified Crank-Nicolson/Adams-Bashforth Order 2 (MCNAB)
88  eIMEXdirk_1_1_1, //!< Forward-Backward Euler IMEX DIRK(1,1,1)
89  eIMEXdirk_1_2_1, //!< Forward-Backward Euler IMEX DIRK(1,2,1)
90  eIMEXdirk_1_2_2, //!< Implicit-Explicit Midpoint IMEX DIRK(1,2,2)
91  eIMEXdirk_2_2_2, //!< L-stable, two stage, second order IMEX DIRK(2,2,2)
92  eIMEXdirk_2_3_2, //!< L-stable, three stage, third order IMEX DIRK(3,4,3)
93  eIMEXdirk_2_3_3, //!< L-stable, two stage, third order IMEX DIRK(2,3,3)
94  eIMEXdirk_3_4_3, //!< L-stable, three stage, third order IMEX DIRK(3,4,3)
95  eIMEXdirk_4_4_3, //!< L-stable, four stage, third order IMEX DIRK(4,4,3)
96  SIZE_TimeIntegrationMethod //!< Length of enum list
97  };
98 
99  const char* const TimeIntegrationMethodMap[] =
100  {
101  "NoTimeIntegrationMethod",
102  "AdamsBashforthOrder1",
103  "AdamsBashforthOrder2",
104  "AdamsBashforthOrder3",
105  "AdamsMoultonOrder1",
106  "AdamsMoultonOrder2",
107  "BDFImplicitOrder1",
108  "BDFImplicitOrder2",
109  "ClassicalRungeKutta4",
110  "RungeKutta2_ModifiedEuler",
111  "RungeKutta2_ImprovedEuler",
112  "ForwardEuler",
113  "BackwardEuler",
114  "IMEXOrder1",
115  "IMEXOrder2",
116  "IMEXOrder3",
117  "Midpoint",
118  "DIRKOrder2",
119  "DIRKOrder3",
120  "CNAB",
121  "IMEXGear",
122  "MCNAB",
123  "IMEXdirk_1_1_1",
124  "IMEXdirk_1_2_1",
125  "IMEXdirk_1_2_2",
126  "IMEXdirk_2_2_2",
127  "IMEXdirk_2_3_2",
128  "IMEXdirk_2_3_3",
129  "IMEXdirk_3_4_3",
130  "IMEXdirk_4_4_3",
131  };
132 
134  {
136  eExplicit, //!< Formally explicit scheme
137  eDiagonallyImplicit, //!< Diagonally implicit scheme (e.g. the DIRK schemes)
138  eIMEX, //!< Implicit Explicit General Linear Method
139  eImplicit, //!< Fully implicit scheme
140  };
141 
142  const char* const TimeIntegrationSchemeTypeMap[] =
143  {
144  "NoTimeIntegrationSchemeType",
145  "Explicit",
146  "DiagonallyImplicit",
147  "IMEX",
148  "Implicit"
149  };
150 
151  // =====================================================================
152 
153  // =====================================================================
154  // ==== DEFINITION OF THE CLASS TimeIntegrationSchemeOperators
155  // =====================================================================
157  {
158  public:
159  typedef const Array<OneD, const Array<OneD, NekDouble> > InArrayType;
160  typedef Array<OneD, Array<OneD, NekDouble> > OutArrayType;
161 
162  typedef boost::function< void (InArrayType&, OutArrayType&, const NekDouble) > FunctorType1;
163  typedef boost::function< void (InArrayType&, OutArrayType&, const NekDouble, const NekDouble) > FunctorType2;
164 
167 
168  typedef Array<OneD, FunctorType1> FunctorType1Array;
169  typedef Array<OneD, FunctorType2> FunctorType2Array;
170 
172  m_functors1(4),
173  m_functors2(1)
174  {
175  }
176 
177  template<typename FuncPointerT, typename ObjectPointerT>
178  void DefineOdeRhs(FuncPointerT func, ObjectPointerT obj)
179  {
180  m_functors1[0] = boost::bind(func, obj, _1, _2, _3);
181  }
182 
183  template<typename FuncPointerT, typename ObjectPointerT>
184  void DefineOdeExplicitRhs(FuncPointerT func, ObjectPointerT obj)
185  {
186  m_functors1[1] = boost::bind(func, obj, _1, _2, _3);
187  }
188 
189  template<typename FuncPointerT, typename ObjectPointerT>
190  void DefineOdeImplicitRhs(FuncPointerT func, ObjectPointerT obj)
191  {
192  m_functors1[2] = boost::bind(func, obj, _1, _2, _3);
193  }
194 
195  template<typename FuncPointerT, typename ObjectPointerT>
196  void DefineProjection(FuncPointerT func, ObjectPointerT obj)
197  {
198  m_functors1[3] = boost::bind(func, obj, _1, _2, _3);
199  }
200 
201  template<typename FuncPointerT, typename ObjectPointerT>
202  void DefineImplicitSolve(FuncPointerT func, ObjectPointerT obj)
203  {
204  m_functors2[0] = boost::bind(func, obj, _1, _2, _3, _4);
205  }
206 
207 
208  inline void DoOdeRhs(InArrayType &inarray,
209  OutArrayType &outarray,
210  const NekDouble time) const
211  {
212  ASSERTL1(!(m_functors1[0].empty()),"OdeRhs should be defined for this time integration scheme");
213  m_functors1[0](inarray,outarray,time);
214  }
215 
216  inline void DoOdeExplicitRhs(InArrayType &inarray,
217  OutArrayType &outarray,
218  const NekDouble time) const
219  {
220  ASSERTL1(!(m_functors1[1].empty()),"OdeExplicitRhs should be defined for this time integration scheme");
221  m_functors1[1](inarray,outarray,time);
222  }
223 
224  inline void DoOdeImplicitRhs(InArrayType &inarray,
225  OutArrayType &outarray,
226  const NekDouble time) const
227  {
228  ASSERTL1(!(m_functors1[2].empty()),"OdeImplictRhs should be defined for this time integration scheme");
229  m_functors1[2](inarray,outarray,time);
230  }
231 
232  inline void DoProjection(InArrayType &inarray,
233  OutArrayType &outarray,
234  const NekDouble time) const
235  {
236  ASSERTL1(!(m_functors1[3].empty()),"Projection operation should be defined for this time integration scheme");
237  m_functors1[3](inarray,outarray,time);
238  }
239 
240  inline void DoImplicitSolve(InArrayType &inarray,
241  OutArrayType &outarray,
242  const NekDouble time,
243  const NekDouble lambda) const
244  {
245  ASSERTL1(!(m_functors2[0].empty()),"ImplicitSolve should be defined for this time integration scheme");
246  m_functors2[0](inarray,outarray,time,lambda);
247  }
248 
249 
250  protected:
253 
254  private:
255 
256  };
257 
258  // =========================================================================
259  // ==== DEFINITION OF THE CLASS TimeIntegrationSchemeKey
260  // =========================================================================
262  {
263  public:
264 
265  struct opLess
266  {
268  };
269 
271  m_method(method)
272  {
273  }
274 
276  {
277  }
278 
280  {
281  *this = key; // defer to assignment operator
282  }
283 
285  {
286  m_method = key.m_method;
287 
288  return *this;
289  }
290 
292  {
293  return m_method;
294  }
295 
296  inline bool operator==(const TimeIntegrationSchemeKey &key)
297  {
298  return (m_method == key.m_method);
299  }
300 
301  inline bool operator== (const TimeIntegrationSchemeKey *y)
302  {
303  return (*this == *y);
304  }
305 
307  {
308  return (!(*this == y));
309  }
310 
312  {
313  return (!(*this == *y));
314  }
315 
319 
320  protected:
321  TimeIntegrationMethod m_method; //!< integration method
322 
323  private:
324  // This should never be called
326  {
327  NEKERROR(ErrorUtil::efatal,"Default Constructor for the TimeIntegrationSchemeKey class should not be called");
328  }
329  };
330 
331  static const TimeIntegrationSchemeKey NullTimeIntegrationSchemeKey(eNoTimeIntegrationMethod);
332  LIB_UTILITIES_EXPORT bool operator==(const TimeIntegrationSchemeKey &lhs, const TimeIntegrationSchemeKey &rhs);
333  LIB_UTILITIES_EXPORT bool operator<(const TimeIntegrationSchemeKey &lhs, const TimeIntegrationSchemeKey &rhs);
334  LIB_UTILITIES_EXPORT std::ostream& operator<<(std::ostream& os, const TimeIntegrationSchemeKey& rhs);
335 
336  // =====================================================================
337 
338 
339  // =====================================================================
340  // ==== DEFINITION OF THE FUNCTION TimeIntegrationSolution
341  // =====================================================================
342  // This is the interface the user can use to get hold of the different
343  // time integration schemes. It returns you the NekManager
344  // singleton which manages all the time integration schemes...
345  //
346  typedef NekManager<TimeIntegrationSchemeKey,
347  TimeIntegrationScheme,
350  // =====================================================================
351 
352  // =====================================================================
353  // ==== DEFINITION OF THE CLASS TimeIntegrationScheme
354  // =====================================================================
356  {
357  public:
358 
359  typedef const Array<OneD, const Array<OneD, Array<OneD, NekDouble> > > ConstTripleArray;
360  typedef Array<OneD, Array<OneD, Array<OneD, NekDouble> > > TripleArray;
361  typedef const Array<OneD, const Array<OneD, NekDouble> > ConstDoubleArray;
362  typedef Array<OneD, Array<OneD, NekDouble> > DoubleArray;
363  typedef const Array<OneD, const NekDouble > ConstSingleArray;
364  typedef Array<OneD, NekDouble > SingleArray;
365  typedef boost::function< void (ConstDoubleArray&, DoubleArray&, const NekDouble) > FunctorType1;
366  typedef boost::function< void (ConstDoubleArray&, DoubleArray&, const NekDouble, const NekDouble) > FunctorType2;
367 
368  public:
369 
371  {
372  }
373 
375  {
376  return m_schemeKey;
377  }
378 
380  {
382  }
383 
385  {
386  return m_schemeType;
387  }
388 
389  inline NekDouble A(const unsigned int i, const unsigned int j) const
390  {
391  return m_A[0][i][j];
392  }
393 
394  inline NekDouble B(const unsigned int i, const unsigned int j) const
395  {
396  return m_B[0][i][j];
397  }
398 
399  inline NekDouble U(const unsigned int i, const unsigned int j) const
400  {
401  return m_U[i][j];
402  }
403 
404  inline NekDouble V(const unsigned int i, const unsigned int j) const
405  {
406  return m_V[i][j];
407  }
408 
409  inline NekDouble A_IMEX(const unsigned int i, const unsigned int j) const
410  {
411  return m_A[1][i][j];
412  }
413 
414  inline NekDouble B_IMEX(const unsigned int i, const unsigned int j) const
415  {
416  return m_B[1][i][j];
417  }
418 
419  inline unsigned int GetNsteps(void) const
420  {
421  return m_numsteps;
422  }
423 
424  inline unsigned int GetNstages(void) const
425  {
426  return m_numstages;
427  }
428 
429  inline unsigned int GetNmultiStepValues(void) const
430  {
431  return m_numMultiStepValues;
432  }
433 
434  inline unsigned int GetNmultiStepDerivs(void) const
435  {
436  return m_numMultiStepDerivs;
437  }
438 
439  /**
440  * \brief This function initialises the time integration
441  * scheme
442  *
443  * Given the solution at the initial time level
444  * \f$\boldsymbol{y}(t_0)\f$, this function generates the
445  * vectors \f$\boldsymbol{y}^{[n]}\f$ and \f$t^{[n]}\f$
446  * needed to evaluate the time integration scheme
447  * formulated as a General Linear Method. These vectors
448  * are embedded in an object of the class
449  * TimeIntegrationSolution. This class is the abstraction
450  * of the input and output vectors of the General Linear
451  * Method.
452  *
453  * For single-step methods, this function is trivial as it
454  * just wraps a TimeIntegrationSolution object around the
455  * given initial values and initial time. However, for
456  * multistep methods, actual time stepping is being done
457  * to evaluate the necessary parameters at multiple time
458  * levels needed to start the actual integration.
459  *
460  * \param timestep The size of the timestep, i.e. \f$\Delta t\f$.
461  * \param time on input: the initial time, i.e. \f$t_0\f$.
462  * \param time on output: the new time-level after initialisation, in general this yields
463  * \f$t = t_0 + (r-1)\Delta t\f$ where \f$r\f$ is the number of steps of the multi-step method.
464  * \param nsteps on output: he number of initialisation steps required. In general this corresponds to \f$r-1\f$
465  * where \f$r\f$ is the number of steps of the multi-step method.
466  * \param f an object of the class FuncType, where FuncType should have a method FuncType::ODEforcing
467  * to evaluate the right hand side \f$f(t,\boldsymbol{y})\f$ of the ODE.
468  * \param y_0 the initial value \f$\boldsymbol{y}(t_0)\f$
469  * \return An object of the class TimeIntegrationSolution which represents the vectors \f$\boldsymbol{y}^{[n]}\f$ and \f$t^{[n]}\f$
470  * that can be used to start the actual integration.
471  */
473  ConstDoubleArray &y_0 ,
474  const NekDouble time ,
475  const TimeIntegrationSchemeOperators &op );
476 
477  /**
478  * \brief Explicit integration of an ODE.
479  *
480  * This function explicitely perfroms a signle integration step of the ODE system:
481  * \f[
482  * \frac{d\boldsymbol{y}}{dt}=\boldsymbol{f}(t,\boldsymbol{y})
483  * \f]
484  *
485  * \param timestep The size of the timestep, i.e. \f$\Delta t\f$.
486  * \param f an object of the class FuncType, where FuncType should have a method FuncType::ODEforcing
487  * to evaluate the right hand side \f$f(t,\boldsymbol{y})\f$ of the ODE.
488  * \param y on input: the vectors \f$\boldsymbol{y}^{[n-1]}\f$ and \f$t^{[n-1]}\f$ (which corresponds to the
489  * solution at the old time level)
490  * \param y on output: the vectors \f$\boldsymbol{y}^{[n]}\f$ and \f$t^{[n]}\f$ (which corresponds to the
491  * solution at the old new level)
492  * \return The actual solution \f$\boldsymbol{y}^{n}\f$ at the new time level
493  * (which in fact is also embedded in the argument y).
494  */
497  const TimeIntegrationSchemeOperators &op );
498 
499  inline const Array<OneD, const unsigned int>& GetTimeLevelOffset()
500  {
501  return m_timeLevelOffset;
502  }
503 
504 
505  protected:
508  unsigned int m_numsteps; //< Number of steps in multi-step component.
509  unsigned int m_numstages; //< Number of stages in multi-stage component.
510 
511  bool m_firstStageEqualsOldSolution; //< Optimisation-flag
512  bool m_lastStageEqualsNewSolution; //< Optimisation-flag
513 
514  unsigned int m_numMultiStepValues; // number of entries in input and output vector that correspond
515  // to VALUES at previous time levels
516  unsigned int m_numMultiStepDerivs; // number of entries in input and output vector that correspond
517  // to DERIVATIVES at previous time levels
518  Array<OneD,unsigned int> m_timeLevelOffset; // denotes to which time-level the entries in both
519  // input and output vector correspond, e.g.
520  // INPUT VECTOR --------> m_inputTimeLevelOffset
521  // _ _ _ _
522  // | u^n | | 0 |
523  // | u^{n-1} | | 1 |
524  // | u^{n-2} | -----> | 2 |
525  // | dt f(u^{n-1})| | 1 |
526  // | dt f(u^{n-2})| | 2 |
527  // - - - -
528 
529  Array<OneD, Array<TwoD,NekDouble> > m_A;
530  Array<OneD, Array<TwoD,NekDouble> > m_B;
531  Array<TwoD,NekDouble> m_U;
532  Array<TwoD,NekDouble> m_V;
533 
534  private:
535  bool m_initialised; /// bool to identify if array has been initialised
536  int m_nvar; /// The number of variables in integration scheme.
537  int m_npoints; /// The size of inner data which is stored for reuse.
538  DoubleArray m_Y; /// Array containing the stage values
539  DoubleArray m_tmp; /// explicit right hand side of each stage equation
540 
541  TripleArray m_F; /// Array corresponding to the stage Derivatives
542  TripleArray m_F_IMEX; /// Used to store the Explicit stage derivative of IMEX schemes
543 
544  NekDouble m_T; /// Time at the different stages
545 
546  template <typename> friend class Nektar::MemoryManager;
548 
549  LIB_UTILITIES_EXPORT static boost::shared_ptr<TimeIntegrationScheme> Create(const TimeIntegrationSchemeKey &key);
550 
552 
553  // These should never be called
555  {
556  NEKERROR(ErrorUtil::efatal,"Default Constructor for the TimeIntegrationScheme class should not be called");
557  }
558 
560  {
561  NEKERROR(ErrorUtil::efatal,"Copy Constructor for the TimeIntegrationScheme class should not be called");
562  }
563 
565  const Array<OneD, const Array<TwoD, NekDouble> >& A,
566  const Array<OneD, const Array<TwoD, NekDouble> >& B,
567  const Array<TwoD, const NekDouble>& U,
568  const Array<TwoD, const NekDouble>& V) const;
569 
570  LIB_UTILITIES_EXPORT void TimeIntegrate(const NekDouble timestep,
571  ConstTripleArray &y_old ,
572  ConstSingleArray &t_old ,
573  TripleArray &y_new ,
574  SingleArray &t_new ,
575  const TimeIntegrationSchemeOperators &op );
576 
577 
578  inline int GetFirstDim(ConstTripleArray &y) const
579  {
580  return y[0].num_elements();
581  }
582 
583  inline int GetSecondDim(ConstTripleArray &y) const
584  {
585  return y[0][0].num_elements();
586  }
587 
589  ConstTripleArray &y_old ,
590  ConstSingleArray &t_old ,
591  TripleArray &y_new ,
592  SingleArray &t_new ,
593  const TimeIntegrationSchemeOperators &op) const;
594 
595  LIB_UTILITIES_EXPORT bool CheckIfFirstStageEqualsOldSolution(const Array<OneD, const Array<TwoD, NekDouble> >& A,
596  const Array<OneD, const Array<TwoD, NekDouble> >& B,
597  const Array<TwoD, const NekDouble>& U,
598  const Array<TwoD, const NekDouble>& V) const;
599 
600  LIB_UTILITIES_EXPORT bool CheckIfLastStageEqualsNewSolution(const Array<OneD, const Array<TwoD, NekDouble> >& A,
601  const Array<OneD, const Array<TwoD, NekDouble> >& B,
602  const Array<TwoD, const NekDouble>& U,
603  const Array<TwoD, const NekDouble>& V) const;
604 
605 
606 
607  };
608 
609 
610  // =========================================================================
611  // ==== DEFINITION OF THE CLASS TimeIntegrationSolution
612  // =========================================================================
614  {
615  public:
616  typedef Array<OneD, Array<OneD, Array<OneD, NekDouble> > > TripleArray;
617  typedef Array<OneD, Array<OneD, NekDouble> > DoubleArray;
618 
619  // Constructor for single step methods
621  const DoubleArray& y,
622  const NekDouble time,
623  const NekDouble timestep);
624  // Constructor for multi-step methods
626  const TripleArray& y,
627  const Array<OneD, NekDouble>& t);
629  unsigned int nvar,
630  unsigned int npoints);
632 
634  {
635  return m_scheme;
636  }
637 
639  {
640  return m_scheme->GetIntegrationSchemeKey();
641  }
642 
644  {
645  return m_scheme->GetIntegrationMethod();
646  }
647 
648  inline const TripleArray& GetSolutionVector() const
649  {
650  return m_solVector;
651  }
652 
654  {
655  return m_solVector;
656  }
657 
658  inline const DoubleArray& GetSolution() const
659  {
660  return m_solVector[0];
661  }
662 
664  {
665  return m_solVector[0];
666  }
667 
668  inline const Array<OneD, const NekDouble>& GetTimeVector() const
669  {
670  return m_t;
671  }
672 
673  inline Array<OneD, NekDouble>& UpdateTimeVector()
674  {
675  return m_t;
676  }
677 
678  inline NekDouble GetTime() const
679  {
680  return m_t[0];
681  }
682 
683  inline int GetNsteps()
684  {
685  return m_scheme->GetNsteps();
686  }
687 
688  inline int GetFirstDim() const
689  {
690  return m_solVector[0].num_elements();
691  }
692 
693  inline int GetSecondDim() const
694  {
695  return m_solVector[0][0].num_elements();
696  }
697 
698  // Return the number of entries in the solution vector that correspond
699  // to (multi-step) values
700  inline unsigned int GetNvalues(void) const
701  {
702  return m_scheme->GetNmultiStepValues();
703  }
704 
705  // Return the number of entries in the solution vector that correspond
706  // to (multi-step) derivatives
707  inline unsigned int GetNderivs(void) const
708  {
709  return m_scheme->GetNmultiStepDerivs();
710  }
711 
712  // Returns an array which indicates to which time-level the entries in the
713  // solution vector correspond
714  inline const Array<OneD, const unsigned int>& GetTimeLevelOffset()
715  {
716  return m_scheme->GetTimeLevelOffset();
717  }
718 
719  // returns the entry in the solution vector which corresponds to
720  // the (multi-step) value at the time-level with specified offset
721  inline DoubleArray& GetValue(const unsigned int timeLevelOffset)
722  {
723  int nMultiStepVals = m_scheme->GetNmultiStepValues();
724  const Array<OneD, const unsigned int>& offsetvec = GetTimeLevelOffset();
725 
726  for(int i = 0; i < nMultiStepVals; i++)
727  {
728  if( timeLevelOffset == offsetvec[i] )
729  {
730  return m_solVector[i];
731  }
732  }
733  ASSERTL1(false,"The solution vector of this scheme does not contain a value at the requested time-level");
734  return m_solVector[0];
735  }
736 
737  // returns the entry in the solution vector which corresponds to
738  // the (multi-step) derivative at the time-level with specified offset
739  inline DoubleArray& GetDerivative(const unsigned int timeLevelOffset)
740  {
741  int nMultiStepVals = m_scheme->GetNmultiStepValues();
742  int size = m_scheme->GetNsteps();
743  const Array<OneD, const unsigned int>& offsetvec = GetTimeLevelOffset();
744 
745  for(int i = nMultiStepVals; i < size; i++)
746  {
747  if( timeLevelOffset == offsetvec[i] )
748  {
749  return m_solVector[i];
750  }
751  }
752  ASSERTL1(false,"The solution vector of this scheme does not contain a derivative at the requested time-level");
753  return m_solVector[0];
754  }
755 
756  // returns the time associated with the (multi-step) value at the time-level with the
757  // given offset
758  inline NekDouble GetValueTime(const unsigned int timeLevelOffset)
759  {
760  int nMultiStepVals = m_scheme->GetNmultiStepValues();
761  const Array<OneD, const unsigned int>& offsetvec = GetTimeLevelOffset();
762 
763  for(int i = 0; i < nMultiStepVals; i++)
764  {
765  if( timeLevelOffset == offsetvec[i] )
766  {
767  return m_t[i];
768  }
769  }
770  ASSERTL1(false,"The solution vector of this scheme does not contain a value at the requested time-level");
771  return m_t[0];
772  }
773 
774  // sets the (multi-step) value and time in the solution
775  // vector which corresponds to
776  // the value at the time-level with specified offset
777  inline void SetValue(const unsigned int timeLevelOffset, const DoubleArray& y, const NekDouble t)
778  {
779  int nMultiStepVals = m_scheme->GetNmultiStepValues();
780  const Array<OneD, const unsigned int>& offsetvec = GetTimeLevelOffset();
781 
782  for(int i = 0; i < nMultiStepVals; i++)
783  {
784  if( timeLevelOffset == offsetvec[i] )
785  {
786  m_solVector[i] = y;
787  m_t[i] = t;
788  return;
789  }
790  }
791  }
792 
793  // sets the (multi-step) derivative and time in the
794  // solution vector which corresponds to
795  // the derivative at the time-level with specified offset
796  inline void SetDerivative(const unsigned int timeLevelOffset, const DoubleArray& y, const NekDouble timestep)
797  {
798  int nMultiStepVals = m_scheme->GetNmultiStepValues();
799  int size = m_scheme->GetNsteps();
800  const Array<OneD, const unsigned int>& offsetvec = GetTimeLevelOffset();
801 
802  for(int i = nMultiStepVals; i < size; i++)
803  {
804  if( timeLevelOffset == offsetvec[i] )
805  {
806  m_solVector[i] = y;
807  m_t[i] = timestep;
808  return;
809  }
810  }
811  }
812 
813  // sets the soln Vector
814  inline void SetSolVector(const int Offset, const DoubleArray& y)
815  {
816  m_solVector[Offset] = y;
817  }
818 
819  // Rotate the solution vector
820  // (i.e. updating without calculating/inserting new values)
821  inline void RotateSolutionVector()
822  {
823  int i;
824  int nMultiStepVals = m_scheme->GetNmultiStepValues();
825  int size = m_scheme->GetNsteps();
826  for(i = (nMultiStepVals-1); i > 0; i--)
827  {
828  m_solVector[i] = m_solVector[i-1];
829  }
830 
831  for(i = (size-1); i > nMultiStepVals; i--)
832  {
833  m_solVector[i] = m_solVector[i-1];
834  }
835  }
836 
837 
838  private:
841  Array<OneD,NekDouble> m_t;
842  };
843  // =========================================================================
844 
845 
846  LIB_UTILITIES_EXPORT std::ostream& operator<<(std::ostream& os, const TimeIntegrationScheme& rhs);
847  LIB_UTILITIES_EXPORT std::ostream& operator<<(std::ostream& os, const TimeIntegrationSchemeSharedPtr& rhs);
848 
849  // =========================================================================
850 
851  }; // end of namespace
852 } // end of namespace
853 
854 #endif //NEKTAR_LIB_UTILITIES_FOUNDATIONS_TIMEINTEGRATIONSCHEME_H