LifeV
TimeAdvance.hpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  @file
29  @brief File containing a class to deal the time advancing scheme
30 
31  @date 09-2010
32 
33  @author Matteo Pozzoli <matteo1.pozzoli@mail.polimi.it>
34  @contributor Matteo Pozzoli <matteo1.pozzoli@mail.polimi.it>
35  @maintainer Matteo Pozzoli <matteo1.pozzoli@mail.polimi.it>
36 */
37 
38 #ifndef TIMEADVANCE_H
39 #define TIMEADVANCE_H 1
40 
41 
42 #include <stdexcept>
43 #include <sstream>
44 
45 
46 #include <lifev/core/LifeV.hpp>
47 #include <lifev/core/util/Factory.hpp>
48 #include <lifev/core/util/FactorySingleton.hpp>
49 #include <lifev/core/array/VectorEpetra.hpp>
50 
51 namespace LifeV
52 {
53 typedef boost::numeric::ublas::vector<Real> ScalarVector;
54 
55 //! timeAdvance_template - File containing a class to deal the time advancing scheme
56 /*!
57  @author Matteo Pozzoli <matteo1.pozzoli@mail.polimi.it>
58 
59  This class define an abstract method to build temporal discretization schemes.
60  In particular we consider problems of the first order and the second order in time;
61  that after space and time discretization, and suitable linearisation of non linear operator,
62  we obtain a linear system to solve at each time step (or each iteration ):
63 
64  \f[ K U^{n+1} =F^{n+1}\f]
65 
66  where \f$K\f$ is an opportune matrix, \f$ U^{n+1}\f$ is the unknown vector and \f$F^{n+1}\f$ is the
67  right hand side vector at the time \f$t^{n+1}\f$ .
68  To determine \f$F^{n+1}\f$ we define the state vector \f$X^{n+1}\f$ that contained the informations
69  about previous solutions.
70  <ol>
71  <li> First order problems:
72 
73  \f[ M \frac{\partial u}{\partial t} + L( u) = f ,\f]
74 
75  where L is a generic nonlinear operator.
76  We define U an approximation of u and the velocity vector \f$V\f$ an approximation of \f$\dot{u}\f$
77  at the time step \f$n+1\f$ as
78 
79  \f[ V^{n+1}=\frac{\alpha_0}{\Delta t} U^{n+1}- f_V^{n+1}, \f]
80 
81  where \f$\alpha_0\f$ is a suitable coefficient and \f$f_V\f$ is a linear combination of the previous solutions
82  \f$X^{n+1}\f$ with coefficients \f$\alpha_i\f$, that will be specified in the following.
83 
84 
85  Then the time discrete version is
86  \f[ \frac{\alpha_0}{\Delta t}M U^{n+1} +A (U^{n+1})= f^{n+1}+ M f_V^{n+1} \f],
87  that can be solved by any non-linear iterative solver (fixed point, Newton, ....).
88  This class provides also a suitable extrapolation \f$ U^*\f$ of \f$U^{n+1}\f$, given by a linear
89  combination of previous solutions and of order consistent with the time discretization formula.
90  </li>
91  <li> In this part we want to extend the previous approach to second order
92  problems in time.
93 
94  Second order problems:
95 
96  \f[ \ddot{ u} + L( \dot{u}, u) = f \f]
97  where \f$L\f$ is non linear operator.
98 
99  We consider the following semidiscrete problem
100 
101  \f[ M \frac{d^2 U}{d t^2} + D ( U, \frac{d U}{d t} ) + A ( U ) = f \f]
102 
103  where \f$M\f$ is the mass matrix, \f$f_V\f$ the forcing term
104  and \f$U\f$ is the vector of unknowns.
105 
106  We define the following quantities
107 
108  \f[ V :=\frac{d U}{d t }\qquad W := \frac{d^2 U} {d t^2}, \f]
109  where \f$V\f$ and \f$W\f$ are the velocity and the acceleration vectors, respectively.
110 
111  At the time step \f$n+1\f$, we consider the following approximations of \f$V\f$ and \f$W\f$:
112 
113  \f[ V^{n+1}=\frac{\alpha_0}{\Delta t} U^{n+1}- f_V^{n+1}, \f]
114 
115  and
116 
117  \f[ W^{n+1}=\frac{\xi_0}{\Delta t^2} U^{n+1} - f_W^{n+1}, \f]
118 
119  where \f$f_V^{n+1}\f$ and \f$f_W^{n+1}\f$ are linear combinations of the previous solutions with
120  suitable coefficients \f$\alpha_i\f$ and \f$\xi_i\f$, respectively.
121  If \f$A\f$ and \f$D\f$ depend on \f$U\f$ and \f$V\f$ we can linearise the
122  problem using suitable extrapolations \f$U^*\f$ \f$V^*\f$ obtained by linear combinations
123  of previous solutions with coefficients \f$\beta_i\f$ and \f$\beta_i^V\f$ respectively.
124  </li>
125  </ol>
126 */
127 
128 template<typename feVectorType = VectorEpetra >
129 
130 class TimeAdvance
131 {
132 public:
133 
134  //! @name Public Types
135  //@{
136  // type of template
137  typedef feVectorType feVector_Type;
138 
139  // container of real number;
140  typedef ScalarVector container_Type;
141 
142  // container of feVector;
143  typedef std::vector<feVector_Type> feVectorContainer_Type;
144 
145  // container of pointer of feVector;
146  typedef std::vector<feVector_Type*> feVectorContainerPtr_Type;
147 
148  // iterator
149  typedef typename feVectorContainerPtr_Type::iterator feVectorContainerPtrIterate_Type;
150 
151  //container of shared pointer;
152  typedef std::vector<std::shared_ptr<feVector_Type> > feVectorSharedPtrContainer_Type;
153  //@}
154 
155  //! @name Constructor & Destructor
156  //@{
157 
158  //! Empty Constructor
159  TimeAdvance();
160 
161  //! Destructor
162  virtual ~TimeAdvance();
163 
164  //@}
165 
166  //! @name Methods
167  //@{
168 
169  //!Update the vectors of the previous time steps by shifting on the right
170  /*!
171  Update the vectors of the previous time steps by shifting on the right
172  the old values.
173  @param solution is a (new) value of the state vector
174  */
175  virtual void shiftRight (const feVector_Type& solution ) = 0;
176 
177  //!Update the right hand side
178  /*!
179  update rhs contributions: \f$f_V\f$ and \$f_W\f$
180  */
181  void updateRHSContribution ( const Real& timeStep);
182 
183  //! Update the right hand side \f$ f_V \f$ of the time derivative formula
184  /*!
185  Returns the right hand side \f$ f_V \f$ of the time derivative formula
186  @param timeStep defines the time step
187  @param rhsContribution on input: a copy the first vector for the RHS contribution,
188  usually M_unknown[0].
189  On output: the new RHS contribution
190  @param shift how much shift the stored solutions. usually zero, but can be 1.
191  @return rhsV the first order Rhs
192  */
193  virtual void RHSFirstDerivative (const Real& timeStep, feVectorType& rhsContribution ) const = 0;
194 
195  //! Update the right hand side \f$ f_V \f$ of the time derivative formula
196  /*!
197  Sets the right hand side \f$ f_V \f$ of the time derivative formula
198  @param timeStep defined the time step need to compute the
199  @return rhsV the first order Rhs
200  */
201  void updateRHSFirstDerivative (const Real& timeStep = 1 );
202 
203  //! Update the right hand side \f$ f_W \f$ of the time derivative formula
204  /*!
205  Sets and Returns the right hand side \f$ f_W \f$ of the time derivative formula
206  @param timeStep defined the time step need to compute the \f$ f_W \f$
207  @return rhsW the fsecond order Rhs
208  */
209  virtual void updateRHSSecondDerivative (const Real& timeStep = 1 ) = 0;
210 
211  //!Show the properties of temporal scheme
212  /*!
213  Show the properties of temporal scheme
214  */
215  virtual void showMe (std::ostream& output = std::cout) const = 0;
216 
217  //! Spy state vector
218  /*!
219  Spy of stateVector;
220  this method saves n-vectors ( unknownsIJ.m)
221  containing the each element of state vector;
222  the index J defines the J-element of StateVector;
223  the index I defines the I-th time that this method is called;
224  */
225  void spyStateVector();
226 
227  //! Spy rhs vector
228  /*!
229  Spy of rhsVector;
230  this method saves n-vectors (rhsIJ.m) containing the each element of rhs vector;
231  the index J defines the J-element of rhsVector;
232  the index I defines the I-th time that this method is called;
233  */
234  void spyRHS();
235 
236  //@}
237 
238  //! @name Set Methods
239  //@{
240 
241  //!Initialize parameters of time advance scheme;
242  /*!
243  Initialize parameters of time advance scheme;
244  @param orderDerivative define the maximum order of derivative
245  */
246  void setup ( const UInt& orderDerivative )
247  {
248  M_orderDerivative = orderDerivative;
249  }
250 
251  //! Initialize the parameters of time advance scheme
252  /*!
253  @param order define the order of BDF;
254  @param orderDerivatve define the order of derivative;
255  */
256  virtual void setup ( const UInt& order, const UInt& orderDerivative ) = 0;
257 
258  //! Initialize the parameters of time advance scheme
259  /*!
260  @param coefficients define the TimeAdvanceNewmark's coefficients (\theta, \gamma);
261  @param orderDerivative define the order of derivative;
262  */
263  virtual void setup ( const std::vector<Real>& coefficients, const UInt& orderDerivative ) = 0;
264 
265  //! Initialize the State Vector
266  /*!
267  Initialize all the entries of the unknown vector to be derived with the vector x0 (duplicated).
268  this class is virtual because used in bdf;
269  @param x0 is the initial unk;
270  */
271  virtual void setInitialCondition ( const feVector_Type& x0) = 0;
272 
273  //! initialize the State Vector
274  /*!
275  Initialize all the entries of the unknown vector to be derived with the vector x0, v0 (duplicated).
276  this class is virtual because used in \f$\theta\f$-method scheme;
277  @param x0 is the initial unk;
278  @param v0 is the initial velocity
279  */
280  virtual void setInitialCondition ( const feVector_Type& x0, const feVector_Type& v0) = 0;
281 
282  //! initialize the StateVector
283  /*!
284  Initialize all the entries of the unknown vector to be derived with the vector x0, v0,w0 (duplicated).
285  this class is virtual because used in Newamrk scheme;
286  @param x0 is the initial unk;
287  @param v0 is the initial velocity
288  @param w0 is the initial accelerate
289  */
290  virtual void setInitialCondition ( const feVector_Type& x0, const feVector_Type& v0, const feVector_Type& w0) = 0;
291 
292  //! initialize the StateVector
293  /*!
294  Initialize all the entries of the unknown vector to be derived with the vector x0.
295  this class is virtual because used in TimeAdvanceNewmark scheme;
296  @param x0 is a vector of feVector_Type containing the state vector;
297  */
298  virtual void setInitialCondition ( const feVectorSharedPtrContainer_Type& /*x0*/)
299  {
300  ERROR_MSG ("this method is not implemented.");
301  }
302 
303  //!Initialize the RhsVector:
304  /*!
305  Initialize all the entries of the unknown vector to be derived with the vector x0.
306  this class is virtual because used in Newamrk scheme;
307  @param rhs0 is a vector of feVector_Type containing the state vector;
308  */
309  void setInitialRHS (const feVector_Type& rhs0 ) ;
310 
311  //! Set time step
312  /*!
313  @param timeStep is time step
314  */
315  void setTimeStep (const Real& timeStep)
316  {
317  M_timeStep = timeStep;
318  }
319 
320  //@}
321 
322  //!@name Get Methods
323  //@{
324 
325  //! Return the i-th coefficient of the first time derivative
326  /*!
327  @param i index of coefficient alpha
328  @returns the i-th coefficient of the time derivative alpha_i
329  */
330  Real coefficientFirstDerivative (const UInt& i) const;
331 
332  //!Return the \f$i-\f$th coefficient of the second time derivative
333  /*
334  @param \f$i\f$ index of coefficient \f$xi\f$
335  @returns the i-th coefficient of the second time derivative \f$xi_i\f$
336  */
337  inline Real coefficientSecondDerivative (const UInt& i) const;
338 
339  //!Return the\f$ i-\f$th coefficient of the solution's extrapolation
340  /*!
341  @param \f$i\f$ index of extrapolation coefficient
342  @returns the \f$i-\f$th coefficient of the extrapolation of the first order derivative
343  */
344  virtual Real coefficientExtrapolation (const UInt& i ) const = 0;
345 
346  //!Returns the \f$i-\f$th coefficient of the velocity's extrap
347  /*!
348  @param i index of velocity's extrapolation coefficient
349  @returns the \f$i-\f$th coefficient of the velocity's extrapolation
350  */
351 
352  virtual Real coefficientExtrapolationFirstDerivative (const UInt& i ) const = 0;
353 
354  //! Compute the polynomial extrapolation of solution
355  /*!
356  Compute the polynomial extrapolation approximation of order \f$n-1\f$ of
357  \f$u^{n+1}\f$ defined by the n stored state vectors
358  @returns extrapolation of state vector u^*
359  */
360  virtual void extrapolation (feVector_Type& extrapolation) const = 0;
361 
362  //! Compute the polynomial extrapolation of solution
363  /*!
364  Compute the polynomial extrapolation approximation of order \f$n-1\f$ of
365  \f$u^{n+1}\f$ defined by the n stored state vectors
366  @returns extrapolation of state vector u^*
367  */
368  virtual void extrapolationFirstDerivative (feVector_Type& extrapolation) const = 0;
369 
370  //! Return the \f$i-\f$th element of state vector
371  /*!
372  @param \f$i\f$ index of element
373  @returns the i-th element of state vector
374  */
375  inline const feVector_Type& singleElement (const UInt& i) const;
376 
377  //! Return the last solution (the first element of state vector)
378  inline const feVector_Type& solution() const;
379 
380  void setSolution ( const feVector_Type& solution )
381  {
382  // why don't we just do
383  if (M_unknowns[0] != NULL )
384  {
385  *M_unknowns[0] = solution;
386  }
387  else
388  {
389  M_unknowns[0] = new feVector_Type (solution);
390  }
391  //delete M_unknowns[0];
392  //M_unknowns[0]= new feVector_Type(solution);
393  }
394 
395 
396  //! Return the current velocity
397  virtual feVectorType firstDerivative() const = 0;
398 
399  //!Return the velocity
400  /*!
401  @param u unk to compute the current velocity;
402  @returns the velocity associated to \f$u\f$
403  this method is used for example in FSI to return the value of solid
404  in the internal loop
405  */
406  feVectorType firstDerivative (const feVector_Type& u) const;
407 
408  //!Return the current acceleration
409  virtual feVectorType secondDerivative() const = 0;
410 
411  //! Return the accelerate
412  /*!
413  @param \f$u\f$ is necessary to compute wnk;
414  @return the accelerate associated to \f$u\f$;
415  this method is used for example in FSI to return the value of solid in the internal loop;
416  */
417  feVector_Type acceleration (feVector_Type& u) const;
418 
419  //!Return velocity's right hand side
420  /*!
421  @returns velocity's right hand side
422  */
423  const feVector_Type& rhsContributionFirstDerivative() const
424  {
425  return *M_rhsContribution[0];
426  }
427 
428  //! Return accelerate's right hand side
429  /*!
430  @return accelerate's right hand side
431  */
432  const feVector_Type& rhsContributionSecondDerivative() const
433  {
434  return *M_rhsContribution[1];
435  }
436 
437  //! Return order of accuracy of the scheme
438  /*!
439  @returns the order of accuracy of the scheme
440  */
441  UInt order() const
442  {
443  return M_order;
444  }
445 
446  //! Returns size of the stencil used by time integration scheme
447  /*!
448  @returns the size of the stencil
449  */
450  UInt size() const
451  {
452  return M_size;
453  }
454 
455  /*!Returns a pointer to the vector of solutions stored in M_unknowns
456  */
457  feVectorContainerPtr_Type& stencil()
458  {
459  return M_unknowns;
460  }
461  //@}
462 
463 protected:
464 
465  //! Order of the BDF derivative/extrapolation: the time-derivative
466  //! coefficients vector has size \f$n+1\f$, the extrapolation vector has size \f$n\f$
467  UInt M_order;
468 
469  //! Order of temporal derivative: the time-derivative
470  //! coefficients vector has size \f$n+1\f$, the extrapolation vector has size \f$n\f$
471  UInt M_orderDerivative;
472 
473  //! time step
474  Real M_timeStep;
475 
476  //! Size of the unknown vector
477  UInt M_size;
478 
479  //! Size for firstOrderDerivative loop (for bdf equal M_order, for TimeAdvanceNewmark equal M_size/2)
480  UInt M_firstOrderDerivativeSize;
481 
482  //! Size for setSecondOrderDerivatve loop (for bdf equal M_order, for TimeAdvanceNewmark equal M_size/2)
483  UInt M_secondOrderDerivativeSize;
484 
485  //!Size of coefficients (for bdf equal M_order + M_orderDerivative, for theta-method is 3, and TimeAdvanceNewmark is 4)
486  UInt M_coefficientsSize;
487 
488  //! Coefficients \f$ \alpha_i \f$ of the time advance discretization
489  container_Type M_xi;
490 
491  //! Coefficients \f$ \alpha_i \f$ of the time advance discretization
492  container_Type M_alpha;
493 
494  //! Coefficients \f$ \beta_i \f$ of the extrapolation
495  container_Type M_beta;
496 
497  //! Coefficients \f$ \beta^V_i \f$ of the velocity's extrapolation
498  container_Type M_betaFirstDerivative;
499 
500  //! Last n state vectors
501  feVectorContainerPtr_Type M_unknowns;
502 
503  //! Vector of rhs (rhsV and rhsW)
504  feVectorContainerPtr_Type M_rhsContribution;
505 };
506 
507 // ===================================================
508 // Constructors & Destructor
509 // ===================================================
510 
511 //! Empty Constructor
512 template<typename feVectorType>
513 TimeAdvance<feVectorType>::TimeAdvance()
514  :
515  M_unknowns(),
516  M_rhsContribution()
517 {
518  M_unknowns.reserve ( 1 );
519  M_rhsContribution.reserve (2);
520 }
521 
522 //! Destructor
523 template<typename feVectorType>
524 TimeAdvance<feVectorType>::~TimeAdvance()
525 {
526  feVectorContainerPtrIterate_Type iter = M_unknowns.begin();
527  feVectorContainerPtrIterate_Type iter_end = M_unknowns.end();
528 
529  for ( ; iter != iter_end; iter++ )
530  {
531  delete *iter;
532  }
533 }
534 
535 // ===================================================
536 // Methods
537 // ===================================================
538 
539 template<typename feVectorType>
540 void
541 TimeAdvance<feVectorType>::
542 updateRHSContribution (const Real& timeStep )
543 {
544  //! update rhsContribution of the first Derivative
545  this->updateRHSFirstDerivative ( timeStep );
546 
547  //! update rhsContribution of the second Derivative
548  if ( M_orderDerivative == 2 )
549  {
550  this->updateRHSSecondDerivative ( timeStep );
551  }
552 }
553 
554 
555 template<typename feVectorType>
556 void
557 TimeAdvance<feVectorType>::updateRHSFirstDerivative (const Real& timeStep )
558 {
559  feVectorContainerPtrIterate_Type it = this->M_rhsContribution.begin();
560 
561  //feVector_Type fv ( *this->M_unknowns[ 0 ] );
562  if (*it == NULL)
563  {
564  *it = new feVector_Type (*this->M_unknowns[ 0 ]);
565  }
566  else
567  {
568  **it = *this->M_unknowns[ 0 ];
569  }
570 
571  this->RHSFirstDerivative ( timeStep, **it );
572 
573 }
574 
575 template<typename feVectorType>
576 void
577 TimeAdvance<feVectorType>::
578 spyStateVector()
579 {
580  static UInt saveUnknowns = 0;
581  std::string unknowns = "unknowns";
582 
583  for ( UInt i = 0 ; i < M_size ; i++ )
584  {
585  std::ostringstream j;
586  j << saveUnknowns;
587  j << i;
588 
589  unknowns + j.str();
590 
591  M_unknowns[i]->spy (unknowns + j.str() );
592  }
593  saveUnknowns++;
594 }
595 
596 template<typename feVectorType>
597 void
598 TimeAdvance<feVectorType>::
599 spyRHS()
600 {
601  static UInt saveRhs = 0;
602  std::string rhs = "rhs";
603  for ( UInt i = 0 ; i < 2 ; ++i )
604  {
605  std::ostringstream j;
606  j << saveRhs;
607  j << i;
608 
609  rhs + j.str();
610  M_rhsContribution[i]->spy (rhs + j.str() );
611  }
612  saveRhs++;
613 }
614 
615 // ===================================================
616 // Set Methods
617 // ===================================================
618 
619 template<typename feVectorType>
620 void
621 TimeAdvance<feVectorType>::setInitialRHS (const feVector_Type& rhs )
622 {
623  for (UInt i = 0; i < 2; ++i )
624  {
625  M_rhsContribution.push_back (new feVector_Type (rhs) );
626  }
627 }
628 
629 // ===================================================
630 // Get Methods
631 // ===================================================
632 template<typename feVectorType>
633 Real
634 TimeAdvance<feVectorType>::coefficientFirstDerivative (const UInt& i) const
635 {
636  // Pay attention: i is c-based indexed
637  ASSERT ( i < M_coefficientsSize,
638  "Error in specification of the time derivative coefficient for the time scheme" );
639  return M_alpha[ i ];
640 }
641 
642 template<typename feVectorType>
643 Real
644 TimeAdvance<feVectorType>::coefficientSecondDerivative ( const UInt& i ) const
645 {
646  // Pay attention: i is c-based indexed
647  ASSERT ( i < M_coefficientsSize,
648  "Error in specification of the time derivative coefficient for the time scheme" );
649  return M_xi[ i ];
650 }
651 
652 template<typename feVectorType>
653 inline const feVectorType&
654 TimeAdvance<feVectorType>::solution() const
655 {
656  return *M_unknowns[0];
657 }
658 
659 
660 template<typename feVectorType>
661 inline const feVectorType&
662 TimeAdvance<feVectorType>::singleElement ( const UInt& i) const
663 {
664  ASSERT ( i < M_size,
665  "Error there isn't unk(i), i must be shorter than M_size" );
666 
667  return *M_unknowns[i];
668 }
669 
670 template<typename feVectorType>
671 feVectorType
672 TimeAdvance<feVectorType>::firstDerivative ( const feVector_Type& u ) const
673 {
674  feVector_Type vel ( u );
675  vel *= M_alpha[ 0 ] / M_timeStep;
676  vel -= (*this->M_rhsContribution[ 0 ]);
677  return vel;
678 }
679 
680 
681 template<typename feVectorType>
682 feVectorType
683 TimeAdvance<feVectorType>::acceleration (feVector_Type& u) const
684 {
685  feVector_Type accelerate (u);
686  accelerate *= M_xi[ 0 ] / (M_timeStep * M_timeStep );
687  accelerate -= (*this->M_rhsContribution[1]);
688  return accelerate;
689 }
690 // ===================================================
691 // Macros
692 // ===================================================
693 
694 //! create factory for timeAdvance; this class runs only the default template parameter.
695 
696 typedef FactorySingleton< Factory < TimeAdvance<>, std::string> > TimeAdvanceFactory;
697 
698 }
699 #endif /* TIMEADVANCE_H */
#define ERROR_MSG(A)
Definition: LifeAssert.hpp:69
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
double Real
Generic real data.
Definition: LifeV.hpp:175
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191