LifeV
FSIMonolithic.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 monolithic.hpp
29  * @author Paolo Crosetto
30  * @date 13-09-2008
31  * Class handling the monolithic solver for FSI problems. The block structure of the matrix can be
32  \f$\left(\begin{array}{cc}
33  C&B\\
34  D&N
35  \end{array}\right)\f$
36  if the time discretization at hand is the Geometry-Explicit one (implemented in monolithicGE.hpp), or
37  \f$\left(\begin{array}{ccc}
38  C&B&D\\
39  D&N&0\\
40  0&I&H
41  \end{array}\right)\f$
42  if the time discretization at hand is the Geometry-Implicit one (implemented in monolithicGI.hpp)
43 */
44 #ifndef _MONOLITHIC_HPP
45 #define _MONOLITHIC_HPP
46 
47 #include <EpetraExt_MatrixMatrix.h>
48 //#include <EpetraExt_Reindex_MultiVector.h>
49 //#include <EpetraExt_Reindex_CrsMatrix.h>
50 
51 #include <lifev/core/util/LifeChrono.hpp>
52 #include <lifev/core/fem/FESpace.hpp>
53 #include <lifev/fsi/solver/FSIOperator.hpp>
54 
55 #include <lifev/core/algorithm/PreconditionerComposed.hpp>
56 #include <lifev/core/algorithm/ComposedOperator.hpp>
57 #ifdef HAVE_TRILINOS_ANASAZI
58 #include <lifev/core/algorithm/EigenSolver.hpp>
59 #endif
60 
61 #include <lifev/fsi/solver/MonolithicBlockMatrix.hpp>
62 #include <lifev/fsi/solver/MonolithicBlockComposed.hpp>
63 #ifdef HAVE_NS_PREC
64 #include <life/lifealg/PreconditionerPCD.hpp>
65 #endif
66 
67 //To handle ET for FSI
68 #include <lifev/core/array/MatrixEpetraStructured.hpp>
69 #include <lifev/core/array/MatrixEpetraStructuredUtility.hpp>
70 #include <lifev/core/array/MatrixEpetraStructuredView.hpp>
71 #include <lifev/core/array/VectorEpetraStructured.hpp>
72 #include <lifev/core/array/VectorEpetraStructuredView.hpp>
73 
74 
75 namespace LifeV
76 {
77 
78 class WRONG_PREC_EXCEPTION;
79 
80 //! FSIMonolithic.hpp pure virtual class containing the core methods of the FSIMonolithic FSI solver
81 /*!
82  * Class handling the monolithic solver for FSI problems. The block structure of the matrix can be
83  \f$\left(\begin{array}{cc}
84  C&B\\
85  D&N
86  \end{array}\right)\f$
87  if the time discretization at hand is the Geometry-Explicit one (implemented in monolithicGE.hpp), or
88  \f$\left(\begin{array}{ccc}
89  C&B&D\\
90  D&N&0\\
91  0&I&H
92  \end{array}\right)\f$
93  if the time discretization at hand is the Geometry-Implicit one (implemented in monolithicGI.hpp),
94  * where \f$N\f$ represents the solid block, \f$C\f$ the fluid block, \f$H\f$ the harmonic extension block, while the extra
95  * diagonal blocks represent the coupling. The implementation of the stress continuity coupling condition
96  * is obtained by means of an augmented formulation.
97  * Different possible preconditioners are implemented.
98  * The flag semiImplicit in the data file is used to distinguish between the GCE and CE (with quasi Newton) time discretizations.
99  * Exact Newton method and full implicit time discretization are implemented in the FSIMonolithicGI class.
100  */
101 
102 class FSIMonolithic : public FSIOperator
103 {
104 public:
105 
106  //!@name Typedefs
107  //@{
108 
109  typedef FSIOperator super_Type;
110  typedef FSIOperator::fluid_Type::matrix_Type matrix_Type;
111  typedef std::shared_ptr<matrix_Type> matrixPtr_Type;
112  typedef super_Type::solution_Type solution_Type;
113  typedef super_Type::solutionPtr_Type solutionPtr_Type;
114  typedef MonolithicBlock prec_Type;
115  typedef std::shared_ptr<prec_Type> precPtr_Type;
116  typedef MonolithicBlockMatrix blockMatrix_Type;
117  typedef std::shared_ptr<blockMatrix_Type> blockMatrixPtr_Type;
118  typedef FactorySingleton< Factory< FSIMonolithic, std::string > > factory_Type;
119  typedef SolverAztecOO solver_Type;
120 
121  // Added due to ET
122  typedef MatrixEpetraStructured<Real> matrixBlock_Type;
123  typedef MatrixEpetraStructuredView<Real> matrixBlockView_Type;
124  typedef std::shared_ptr<matrixBlock_Type> matrixBlockPtr_Type;
125  //@}
126 
127  // constructors
128 
129  //!@name Constructors, Destructor
130  //!@{
131  FSIMonolithic();
132 
133  ~FSIMonolithic();
134  //!@}
135 
136  //!@name Public Setup Methods
137  //!@{
138 
139  /**
140  create FEspace
141  */
142  void setupFEspace();
143 
144 
145  /**
146  sets the interface map between the fluid and solid meshes
147  (non scalable, do not use for massively parallel simulations)
148  */
149  virtual void setupDOF ( void );
150 
151 #ifdef HAVE_HDF5
152  /**
153  reads the interface map between the fluid and solid meshes from file.
154  */
155  void setupDOF ( meshFilter_Type& filterMesh );
156 #endif
157 
158  //! sets the parameters from data file
159  /**
160  Calls the setup of the fluid problem and the setUp method.
161  */
162  virtual void setupSystem( );
163 
164  // /** stores the data file into a member */
165  // virtual void setDataFile( const GetPot& dataFile );
166 
167  //! setup method for the FSIMonolithic solver
168  /**
169  sets some parameters specific to the FSIMonolithic class
170  */
171  virtual void setup ( const GetPot& dataFile );
172 
173  //! builds the global Epetra map
174  /**
175  assigns each mesh partition to the corresponding processor, builds the monolithic map
176  */
177  virtual void setupFluidSolid();
178 
179  //! builds the global Epetra map
180  /**
181  assigns each mesh partition to the corresponding processor, builds the monolithic map with a number of fluxes
182  specified from input
183  */
184  virtual void setupFluidSolid ( UInt const fluxes );
185 
186  //!@}
187 
188  //!@name Public Methods
189  //!@{
190 
191  //! Transfers a vector to the interface
192  /**
193  restricts a vector with a monolithic map on the solid interface map
194  \param lambdaSolid: vector on the solid interface
195  \param disp: monolithic vector
196  */
197  void monolithicToInterface ( vector_Type& lambdaSolid, const vector_Type& sol) ;
198 
199 
200  //!Transfers a vector to a subdomain
201  /**
202  restricts a vector with a monolithic map on another map that must
203  have a sequential numbering (not the interface map)
204  \param disp: monolithic vector
205  \param dispFluid: vector on the fluid domain
206  \param map: MapEpetra of the part of vector that we want to transfer
207  \param offset: offset for the monolithic vector (also alpplied to the input map)
208  */
209  void monolithicToX (const vector_Type& disp, vector_Type& dispFluid, MapEpetra& map, UInt offset = (UInt) 0);
210 
211 
212  /**
213  builds the constant part of the monolithic matrix
214  */
215  void buildSystem();
216 
217 
218  //! Merges the flux boundary conditions into the fluid BCHandler
219  /*!two separate BCHandlers are initially created for the flux-type boundary conditions, these are later merged with the fluid BCHandler
220  automatically, using this method
221  */
222  void mergeBCHandlers()
223  {
224  if (M_BCh_u.get() )
225  {
226  M_BCh_u->merge (*M_BCh_flux);
227  }
228  else // in this case only fluxes are imposed on the fluid
229  {
230  M_BCh_u = M_BCh_flux;
231  }
232  M_BCh_flux.reset();
233 
234 
235  }
236 
237 #ifdef HAVE_TRILINOS_ANASAZI
238  //! Computes the maximum singular value
239  /**
240  \small Computes the maximum singular value of the preconditioned system \f$P^{-1}A\f$ where \f$P\f$ is an
241  instance of ComposedOperator and \f$A\f$ is the system matrix.
242  */
243  LifeV::Real& computeMaxSingularValue();
244 #endif
245  //! Computes the normals to the fluid domain
246  /**
247  \small Computes the normals to the fluid domain in the nodes. It is an example of how
248  to use the boundary conditions methods to compute the normal field on
249  a surface.
250  */
251  void computeFluidNormals ( vector_Type& normals);
252 
253 
254  //!Evaluates the nonlinear residual
255  /**
256  This class is pure virtual, it depends on which type of monolithic solver is used
257  \param res: output
258  \param _sol: monolithic solution
259  \param iter: current NonLinearRichardson (Newton) iteration
260  */
261  virtual void evalResidual (vector_Type& res,
262  const vector_Type& sol,
263  const UInt iter) = 0 ;
264 
265  /**
266  solves the Jacobian system
267  \param muk: output, solution at the current Newton step
268  \param res: nonlinear residual
269  \param linearRelTol: not used
270 
271  \small The preconditioner type is usually an algebraic additive Schwarz. The following values
272  assigned to the field DDBlockPrec in the data file correspond to different variants:
273 
274  Only for the FSIMonolithic Geometry Explicit:
275  - DDBlockPrec = AdditiveSchwarz is AAS on a the system matrix
276  - DDBlockPrec = MonolithicBlockComposedDN is AAS on a Dirichlet-Neumann preconditioner using the ComposedOperator strategy
277  - DDBlockPrec = ComposedDN2 is AAS on an alternative Dirichlet-Neumann preconditioner using the ComposedOperator strategy
278  - DDBlockPrec = MonolithicBlockComposedNN is AAS on a Neumann-Neumann preconditioner using the ComposedOperator strategy
279  - DDBlockPrec = MonolithicBlockComposedDNND is AAS on a Dirichler-Neumamm -- Neumann-Dirichlet preconditioner using the ComposedOperator strategy
280 
281  Only for the Geometry Implicit:
282  - DDBlockPrec = AdditiveSchwarzGI is AAS on the whole matrix.
283  - DDBlockPrec = MonolithicBlockComposedDNDGI is AAS on the quasi-newton matrix obtained with the ComposedOperator strategy. Split in 3 factors.
284  - DDBlockPrec = ComposedDND2GI is AAS on the quasi-newton matrix obtained with the ComposedOperator strategy. Split in 3 factors.
285  - DDBlockPrec = MonolithicBlockComposedDNGI is AAS on the full Jacobian matrix obtained with the ComposedOperator strategy by neglecting part
286  of the fluid--structure coupling, split in 3 factors
287  - DDBlockPrec = MonolithicBlockComposedDN2GI is AAS on an alternative matrix obtained with the previous strategy
288  */
289  virtual void solveJac (vector_Type& muk,
290  const vector_Type& res,
291  const Real linearRelTol);
292 
293  /**
294  updates the meshmotion, advances of a time step
295  \param _sol: solution
296  */
297  virtual void updateSystem();
298 
299  //! activates the computation of the wall stress on the boundary with a specified flag.
300  /**
301  Notice that the specified flag must be in the coupling fluid-structure interface
302  */
303  void enableStressComputation (UInt flag);
304 
305  /**
306  Computes the stress on the coupling boundary (the traction vector)
307  */
308  vectorPtr_Type computeStress();
309 
310 
311  //@}
312 
313  //!@name Set Methods
314  //@{
315 
316  //! returns a non-const pointer to the preconditioner. Can be used either as a setter or a getter.
317  precPtr_Type& precPtrView()
318  {
319  return M_precPtr;
320  }
321 
322  //! returns a non-const pointer to the preconditioner. Can be used either as a setter or a getter.
323  blockMatrixPtr_Type& operatorPtrView()
324  {
325  return M_monolithicMatrix;
326  }
327 
328  /**
329  \small sets the solid BCHandle
330  */
331  virtual void setSolidBC ( const fluidBchandlerPtr_Type& bc_solid )
332  {
333  super_Type::setSolidBC (bc_solid);
334  //bc_solid->merge(*M_BCh_Robin);
335  }
336 
337  //! initializes the solution by reference (through a shared_ptr)
338  /*!
339  \param sol: input pointer
340  */
341 
342  void setFluidBC ( const fluidBchandlerPtr_Type& bc_fluid )
343  {
344  super_Type::setFluidBC (bc_fluid);
345 
346  if (M_BChs.size() )
347  {
348  UInt nfluxes (M_BChs[1]->numberOfBCWithType (Flux) );
349  //M_substituteFlux.reset(new std::vector<bool>(nfluxes))
350  M_fluxOffset.resize (nfluxes);
351  M_BCFluxNames = M_BChs[1]->findAllBCWithType (Flux);
352  for (UInt i = 0; i < nfluxes; ++i)
353  {
354  const BCBase* bc = M_BChs[1]->findBCWithName (M_BCFluxNames[i]);
355  M_fluxOffset[i] = bc->offset();
356  }
357  M_BChs[1] = bc_fluid;
358  M_monolithicMatrix->setConditions (M_BChs);
359  M_precPtr->setConditions (M_BChs);
360  }
361 
362  }
363 
364 
365  //!get the total dimension of the FS interface
366  UInt dimInterface() const
367  {
368  return nDimensions * M_monolithicMatrix->interface();
369  }
370 
371  //! Returns true if CE of FI methods are used, false otherwise (GCE)
372  //bool const isFullMonolithic(){return M_fullMonolithic;}
373 
374  //! Returns the offset assigned to the solid block
375  UInt offset() const
376  {
377  return M_offset;
378  }
379 
380  //!Get the solid displacement from the solution
381  /*!
382  \param solidDisplacement: input vector
383  */
384  void exportSolidDisplacement ( vector_Type& solidDisplacement )
385  {
386  solidDisplacement.subset ( M_fluidTimeAdvance->singleElement (0), M_offset );
387  solidDisplacement *= M_solid->rescaleFactor();
388  }
389 
390  //!Get the solid velocity
391  /*!
392  fills an input vector with the solid displacement from the solution.
393  \param solidVelocity: input vector (output solid velocity)
394  */
395  void exportSolidVelocity ( vector_Type& solidVelocity )
396  {
397  solidVelocity.subset ( M_solidTimeAdvance->firstDerivative(), M_offset );
398  solidVelocity *= M_solid->rescaleFactor();
399  }
400 
401  //!Get the solid accelration
402  /*!
403  fills an input vector with the solid displacement from the solution.
404  \param solidVelocity: input vector (output solid acceleration)
405  */
406  void exportSolidAcceleration ( vector_Type& solidAcceleration )
407  {
408  solidAcceleration.subset ( M_solidTimeAdvance->secondDerivative(), M_offset );
409  solidAcceleration *= M_solid->rescaleFactor();
410  }
411 
412  //! Export the fluid velocity by copying it to an external vector
413  /*!
414  * @param fluidVelocity vector to be filled with the fluid velocity
415  */
416  void exportFluidVelocity ( vector_Type& fluidVelocity )
417  {
418  fluidVelocity.subset ( M_fluidTimeAdvance->singleElement (0), 0 );
419  }
420 
421  //! Export the fluid pressure by copying it to an external vector
422  /*!
423  * @param fluidPressure vector to be filled with the fluid pressure
424  */
425  void exportFluidPressure ( vector_Type& fluidPressure )
426  {
427  fluidPressure.subset ( M_fluidTimeAdvance->singleElement (0), static_cast<UInt> (3 * M_uFESpace->dof().numTotalDof() ) );
428  }
429 
430  //! Gets the fluid and pressure
431  /**
432  fills an input vector with the fluid and pressure from the solution M_un.
433  It performs a trilinos import. Thus it works also for the velocity, depending on the map of the input vector
434  \param fluidVelocityandPressure: input vector
435  */
436  void exportFluidVelocityAndPressure ( vector_Type& fluidVelocityAndPressure )
437  {
438  fluidVelocityAndPressure = M_fluidTimeAdvance->singleElement (0);
439  }
440 
441  //! Returns the monolithic map
442  virtual std::shared_ptr<MapEpetra>& couplingVariableMap()
443  {
444  return M_monolithicMap;
445  }
446 
447  //! get the solution vector
448  virtual const vector_Type& solution() const = 0;
449 
450  //! Update the solution after NonLinearRichardson is called.
451  /*!
452  * Here it is used also to update the velocity for the post-processing.
453  */
454  virtual void updateSolution ( const vector_Type& solution )
455  {
456  this->M_fluidTimeAdvance->shiftRight (solution);
457  if (M_data->dataFluid()->conservativeFormulation() )
458  {
459  this->M_fluidMassTimeAdvance->shiftRight (M_fluid->matrixMass() *solution);
460  }
461  this->M_solidTimeAdvance->shiftRight (solution);
462  }
463 
464  //! Updates the right hand side
465  /**
466  Adds to the rhs the fluid time discretization terms
467  \todo this should be handled externally
468  */
469  void updateRHS();
470 
471  //! Set vectors for restart
472  /*!
473  * Set vectors for restart
474  */
475  void setVectorInStencils ( const vectorPtr_Type& vel,
476  const vectorPtr_Type& pressure,
477  const vectorPtr_Type& solidDisp,
478  //const vectorPtr_Type& fluidDisp,
479  const UInt iter);
480 
481  void setFluidVectorInStencil ( const vectorPtr_Type& vel, const vectorPtr_Type& pressure, const UInt iter);
482 
483  void setSolidVectorInStencil ( const vectorPtr_Type& solidDisp, const UInt iter);
484 
485  virtual void setALEVectorInStencil ( const vectorPtr_Type& fluidDisp, const UInt iter, const bool lastVector) = 0;
486 
487  void finalizeRestart();
488 
489  void initializeMonolithicOperator ( std::vector< vectorPtr_Type> u0, std::vector< vectorPtr_Type> ds0, std::vector< vectorPtr_Type> df0);
490 
491  //@}
492 
493 
494 protected:
495 
496 
497  //!@name Protected methods
498  //!@{
499 
500  //! pure virtual: creates the operator (either of type FSIMonolithicGI or FSIMonolithicGE)
501  virtual void createOperator ( std::string& operType ) = 0;
502 
503  /**
504  \small solves the monolithic system, once a solver, a preconditioner and a rhs have been defined.
505  */
506  void iterateMonolithic (const vector_Type& rhs, vector_Type& step);
507 
508  /**
509  \small adds the part due to coupling to the rhs
510  \param rhs: right hand side
511  \param un: current solution
512  */
513  void couplingRhs ( vectorPtr_Type rhs);
514 
515 
516  /**\small evaluates the linear residual
517  \param sol: solution vector
518  \param rhs: right-hand side
519  \param res: the output residual
520  \param diagonalScaling: flag stating wether to perform diagonal scaling
521  */
522  void evalResidual ( const vector_Type& sol, const vectorPtr_Type& rhs, vector_Type& res, bool diagonalScaling = false);
523 
524  //!\small says if the preconditioner will be recomputed
525  bool recomputePrec()
526  {
527  return (!M_reusePrec || M_resetPrec);
528  }
529 
530  //!\small updates the rhs of the solid block.
531  void updateSolidSystem (vectorPtr_Type& rhsFluidCoupling);
532 
533  /**\small scales matrix and rhs
534  \param rhs: the output rhs
535  \param matrFull: the output matrix*/
536  void diagonalScale (vector_Type& rhs, matrixPtr_Type matrFull);
537 
538 
539  //! Constructs the solid FESpace
540  /**
541  Creates the solid FESpace with an unpartitioned mesh, necessary step to create the dof interconnections
542  at the interface. The solid FESpace will be reset in variablesInit using the partitioned mesh.export
543  If the interface map is created offline this method is never called.
544  \param dOrder: discretization order
545  */
546  void solidInit (std::string const& dOrder);
547 
548  //! Constructs the solid FESpace and initializes the coupling variables at the interface
549  /**
550  If the mesh is partitioned online the previous FESpace constructed with the unpartitioned mesh is discarded and
551  replaced with one using a partitioned mesh.
552  */
553  void variablesInit (std::string const& dOrder);
554 
555  //!
556  virtual void setupBlockPrec();
557 
558 
559  //! assembles the solid problem (the matrix and the rhs due to the time derivative)
560  /*
561  \param iter: current nonlinear iteration: used as flag to distinguish the first nonlinear iteration from the others
562  \param solution: current solution, used for the time advance implementation, and thus for the update of the right hand side
563  */
564  void assembleSolidBlock (UInt iter, const vector_Type& solution);
565 
566 
567  //! assembles the fluid problem (the matrix and the rhs due to the time derivative)
568  /*
569  \param iter: current nonlinear iteration: used as flag to distinguish the first nonlinear iteration from the others
570  \param solution: current solution, used for the time advance implementation, and thus for the update of the right hand side
571  */
572  void assembleFluidBlock (UInt iter, const vector_Type& solution);
573 
574  //! Checks if the flux bcs changed during the simulation, e.g. if a flux b.c. has been changed to Natural
575  //! (this can be useful when modeling valves)
576  /**
577  When the fluxes bcs changed a '1' is added in the line corresponding to the Lagrange multiplier. This method must
578  be called for both operator and preconditioner
579  */
580  void checkIfChangedFluxBC ( precPtr_Type oper );
581 
582  //!@}
583 
584 
585  //!@name Protected attributes
586  //@{
587  std::shared_ptr<MapEpetra> M_monolithicMap;
588  std::shared_ptr< MapEpetra > M_interfaceMap;///the solid interface map
589  std::shared_ptr<vector_Type> M_beta;
590  std::shared_ptr<MonolithicBlockMatrix > M_monolithicMatrix;
591  precPtr_Type M_precPtr;
592  std::shared_ptr<vector_Type> M_rhsFull;
593 
594  fluidBchandlerPtr_Type M_BCh_flux;
595  solidBchandlerPtr_Type M_BChWS;
596  BCFunctionRobin M_bcfWs;
597  UInt M_offset;
598  UInt M_solidAndFluidDim;
599  FSIOperator::fluid_Type::matrixPtr_Type M_fluidBlock;
600  matrixPtr_Type M_solidBlockPrec;
601  matrixPtr_Type M_robinCoupling; //uninitialized if not needed
602  matrixPtr_Type M_boundaryMass;
603  std::shared_ptr<solver_Type> M_linearSolver;
604  std::shared_ptr<vector_Type> M_numerationInterface;
605  std::vector<fluidBchandlerPtr_Type> M_BChs;
606  std::vector<std::shared_ptr<FESpace<mesh_Type, MapEpetra> > > M_FESpaces;
607  bool M_diagonalScale;
608  bool M_reusePrec;//!\todo to move to private
609  bool M_resetPrec;//!\todo to move to private
610  Int M_maxIterSolver;//!\todo to move to private
611  bool M_restarts;
612  //@}
613 
614 private:
615  //!@name Private attributes
616  //!@{
617  //! operator \f$P^{-1}AA^TP^{-T}\f$, where P is the preconditioner and A is the monolithic matrix
618  std::shared_ptr<ComposedOperator<Epetra_Operator> > M_preconditionedSymmetrizedMatrix;
619  std::shared_ptr<vector_Type> M_stress;
620  UInt M_fluxes;
621  std::vector<bcName_Type> M_BCFluxNames;
622  std::vector<UInt> M_fluxOffset;
623 
624  //@}
625 };
626 
627 class WRONG_PREC_EXCEPTION
628 {
629 public:
630 
631  //! Exception thrown when a wrong preconditioning strategy is set
632  WRONG_PREC_EXCEPTION() {}
633  virtual ~WRONG_PREC_EXCEPTION() {}
634 
635 };
636 
637 }
638 
639 
640 #endif
void assignFunction(bcBase_Type &base)
Assign the function to the base of the BCHandler.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
double Real
Generic real data.
Definition: LifeV.hpp:175
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191