LifeV
StructuralOperator.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 This file contains solvers for different materials.
30  * @warning: This is the most important issue related with this class.
31  * At the moment, the BC are applied on the matrix and on rhsNoBc for VK models
32  * but for NH and EXP they are applied on the residual directly. This does
33  * not work for nonhomogeneus Dirichlet conditions!!
34  *
35  * @version 1.0
36  * @date 01-01-2010
37  * @author Paolo Tricerri
38  *
39  * @maintainer Paolo Tricerri <paolo.tricerri@epfl.ch>
40 */
41 
42 #ifndef _STRUCTURALOPERATOR_H_
43 #define _STRUCTURALOPERATOR_H_ 1
44 
45 
46 #include <Epetra_Vector.h>
47 #include <EpetraExt_MatrixMatrix.h>
48 
49 
50 #include <lifev/core/util/LifeChrono.hpp>
51 #include <lifev/core/util/Displayer.hpp>
52 
53 #include <lifev/core/array/MatrixElemental.hpp>
54 #include <lifev/core/array/VectorElemental.hpp>
55 #include <lifev/core/array/MatrixEpetra.hpp>
56 #include <lifev/core/array/VectorEpetra.hpp>
57 
58 #include <lifev/core/fem/AssemblyElemental.hpp>
59 #include <lifev/structure/fem/AssemblyElementalStructure.hpp>
60 #include <lifev/core/fem/Assembly.hpp>
61 #include <lifev/core/fem/BCManage.hpp>
62 #include <lifev/core/fem/FESpace.hpp>
63 
64 #include <lifev/core/mesh/MeshEntityContainer.hpp>
65 
66 #include <lifev/core/algorithm/NonLinearRichardson.hpp>
67 
68 #include <lifev/structure/solver/StructuralConstitutiveLawData.hpp>
69 #include <lifev/structure/solver/StructuralConstitutiveLaw.hpp>
70 
71 #include <Epetra_SerialDenseMatrix.h>
72 
73 
74 //Linear Solver includes
75 #include <Teuchos_ParameterList.hpp>
76 #include <Teuchos_XMLParameterListHelpers.hpp>
77 #include <Teuchos_RCP.hpp>
78 #include <lifev/core/algorithm/PreconditionerIfpack.hpp>
79 #include <lifev/core/algorithm/PreconditionerML.hpp>
80 #include <lifev/core/algorithm/LinearSolver.hpp>
81 
82 
83 //ET includes
84 #include <lifev/eta/fem/ETFESpace.hpp>
85 #include <lifev/eta/expression/Integrate.hpp>
86 #include <lifev/eta/expression/Evaluate.hpp>
87 
88 // Time Advance includes
89 #include <lifev/core/fem/TimeAdvance.hpp>
90 #include <lifev/core/fem/TimeAdvanceNewmark.hpp>
91 #include <lifev/core/fem/TimeAdvanceBDF.hpp>
92 
93 // To sort vectors
94 #include <algorithm>
95 
96 namespace LifeV
97 {
98 
99 using namespace ExpressionAssembly;
100 
101 template < typename MeshEntityType,
102  typename ComparisonPolicyType = std::function < bool (
103  const UInt,
104  const UInt ) > >
105 class MarkerSelector
106 {
107 public:
108  typedef MeshEntityType meshEntity_Type;
109  typedef ComparisonPolicyType comparisonPolicy_Type;
110 
111  MarkerSelector ( const UInt materialFlagReference,
112  comparisonPolicy_Type const& policy = std::equal_to<UInt>() )
113  : M_reference ( materialFlagReference ),
114  M_policy ( policy ) {}
115 
116  bool operator() ( const meshEntity_Type& entity ) const
117  {
118  //Extract the flag from the mesh entity
119  UInt flagChecked = entity.markerID();
120 
121  return M_policy ( flagChecked, M_reference );
122  }
123 
124 private:
125  const UInt M_reference;
126  const comparisonPolicy_Type M_policy;
127 
128 }; // Marker selector
129 
130 
131 // Note that the functor is specialized for 3D problems.
132 class sourceVectorialFunctor
133 {
134 public:
135  typedef std::function<VectorSmall<3> ( Real const&, Real const&, Real const&, Real const& ) > volumeForce_Type;
136  typedef std::shared_ptr<volumeForce_Type > volumeForcePtr_Type;
137  typedef VectorSmall<3> return_Type;
138 
139  sourceVectorialFunctor ( const volumeForcePtr_Type volumeSource )
140  : M_volumeSource ( volumeSource ), M_currentTime( 0.0 )
141  {}
142 
143  void setCurrentTime( const Real time )
144  {
145  M_currentTime = time;
146  }
147 
148  return_Type operator() ( const VectorSmall<3> spaceCoordinates )
149  {
150  //Extract the flag from the mesh entity
151  return (*M_volumeSource)( M_currentTime, spaceCoordinates[0], spaceCoordinates[1], spaceCoordinates[2] );
152  }
153 
154 private:
155  volumeForcePtr_Type M_volumeSource;
156  Real M_currentTime;
157 }; // sourceFunctor
158 
159 /*!
160  \class StructuralSolver
161  \brief
162  This class solves the linear elastodynamics equations for different kinds of materials
163  (St. Venant-Kirchoff materials right now)
164 
165 */
166 template <typename Mesh>
167 class StructuralOperator
168 {
169 public:
170 
171  //!@name Type definitions
172  //@{
173  typedef Real ( *function ) ( const Real&, const Real&, const Real&, const Real&, const ID& );
174  typedef std::function<Real ( Real const&, Real const&, Real const&, Real const&, ID const& ) > source_Type;
175 
176  typedef StructuralConstitutiveLaw<Mesh> material_Type;
177  typedef std::shared_ptr<material_Type> materialPtr_Type;
178 
179  typedef BCHandler bcHandlerRaw_Type;
180  typedef std::shared_ptr<bcHandlerRaw_Type> bcHandler_Type;
181 
182  typedef LinearSolver solver_Type;
183 
184  typedef typename solver_Type::matrix_Type matrix_Type;
185  typedef std::shared_ptr<matrix_Type> matrixPtr_Type;
186  typedef typename solver_Type::vector_Type vector_Type;
187  typedef std::shared_ptr<vector_Type> vectorPtr_Type;
188  typedef vector_Type solution_Type;
189  typedef std::shared_ptr<solution_Type> solutionPtr_Type;
190 
191  typedef StructuralConstitutiveLawData data_Type;
192 
193  typedef RegionMesh<LinearTetra > mesh_Type;
194  typedef std::vector< mesh_Type::element_Type* > vectorVolumes_Type;
195  typedef std::vector< UInt > vectorIndexes_Type;
196 
197  typedef std::map< UInt, vectorVolumes_Type> mapMarkerVolumes_Type;
198  typedef std::map< UInt, vectorIndexes_Type> mapMarkerIndexes_Type;
199  typedef std::shared_ptr<mapMarkerVolumes_Type> mapMarkerVolumesPtr_Type;
200  typedef std::shared_ptr<mapMarkerIndexes_Type> mapMarkerIndexesPtr_Type;
201  typedef mapMarkerVolumes_Type::const_iterator mapIterator_Type;
202 
203  typedef typename mesh_Type::element_Type meshEntity_Type;
204 
205  typedef typename std::function<bool (const UInt, const UInt) > comparisonPolicy_Type;
206 
207  typedef MarkerSelector<meshEntity_Type, comparisonPolicy_Type> markerSelector_Type;
208  typedef std::unique_ptr<markerSelector_Type> markerSelectorPtr_Type;
209 
210  typedef ETFESpace< RegionMesh<LinearTetra>, MapEpetra, 3, 3 > ETFESpace_Type;
211  typedef std::shared_ptr<ETFESpace_Type> ETFESpacePtr_Type;
212 
213  typedef FESpace< RegionMesh<LinearTetra>, MapEpetra > FESpace_Type;
214  typedef std::shared_ptr<FESpace_Type> FESpacePtr_Type;
215 
216  //Preconditioners typedef
217  typedef LifeV::Preconditioner basePrec_Type;
218  typedef std::shared_ptr<basePrec_Type> basePrecPtr_Type;
219  typedef LifeV::PreconditionerIfpack precIfpack_Type;
220  typedef std::shared_ptr<precIfpack_Type> precIfpackPtr_Type;
221  typedef LifeV::PreconditionerML precML_Type;
222  typedef std::shared_ptr<precML_Type> precMLPtr_Type;
223 
224  // Time advance
225  typedef TimeAdvance< vector_Type > timeAdvance_Type;
226  typedef std::shared_ptr< timeAdvance_Type > timeAdvancePtr_Type;
227 
228  typedef Epetra_SerialDenseMatrix matrixSerialDense_Type;
229  typedef std::shared_ptr<matrixSerialDense_Type> matrixSerialDensePtr_Type;
230  typedef std::vector<LifeV::Real> vectorInvariants_Type;
231 
232  typedef std::shared_ptr<vectorInvariants_Type> vectorInvariantsPtr_Type;
233 
234 
235  // Source term
236  typedef std::function<VectorSmall<3> ( Real const&, const Real&, const Real&, const Real& ) > volumeForce_Type;
237  typedef std::shared_ptr<volumeForce_Type> volumeForcePtr_Type;
238  typedef sourceVectorialFunctor sourceFunctor_Type;
239  typedef std::shared_ptr<sourceFunctor_Type> sourceFunctorPtr_Type;
240 
241  //@}
242 
243  //! @name Constructor & Destructor
244  //@{
245 
246  StructuralOperator();
247 
248  virtual ~StructuralOperator() {};
249 
250  //@}
251 
252  //!@name Methods
253  //@{
254 
255  //! Setup the created object of the class Venantkirchhof
256  /*!
257  \param data_file GetPot data file
258  \param refFE reference FE for the displacement
259  \param BCh boundary conditions for the displacement
260  \param comm the Epetra Comunicator
261  */
262  void setup ( std::shared_ptr<data_Type> data,
263  const FESpacePtr_Type& dFESpace,
264  const ETFESpacePtr_Type& dETFESpace,
265  bcHandler_Type& BCh,
266  std::shared_ptr<Epetra_Comm>& comm
267  );
268 
269  /*!
270  \param data_file GetPot data file
271  \param refFE reference FE for the displacement
272  \param comm the Epetra Comunicator
273  */
274  void setup ( std::shared_ptr<data_Type> data,
275  const FESpacePtr_Type& dFESpace,
276  const ETFESpacePtr_Type& dETFESpace,
277  std::shared_ptr<Epetra_Comm>& comm
278  );
279 
280  /*!
281  \param data_file GetPot data file
282  \param refFE reference FE for the displacement
283  \param comm the comunicator parameter
284  \param monolithicMap the MapEpetra
285  \param offset the offset parameter
286  */
287  void setup ( std::shared_ptr<data_Type> data,
288  const FESpacePtr_Type& dFESpace,
289  const ETFESpacePtr_Type& dETFESpace,
290  std::shared_ptr<Epetra_Comm>& comm,
291  const std::shared_ptr<const MapEpetra>& monolithicMap,
292  UInt offset = 0
293  );
294 
295 
296  //! Updates the system at the end of each time step
297  void updateSystem ( void );
298 
299  //! Updates the system at the end of each time step when the matrix is passed from outside
300  /*!
301  \param stiff stiffness matrix provided from outside
302  */
303  void updateSystem ( matrixPtr_Type& mat_stiff);
304 
305  //! Updates the system at the end of each time step given a source term
306  /*!
307  \param rhsTimeAdvance the portion of the rhs of the discrete equation which comes from TA.
308  */
309  void updateRightHandSideWithBodyForce ( const Real currentTime, const vector_Type& rhsTimeAdvance );
310 
311  //! Updates the rhs at the start of each time step
312  /*!
313  \param rhs: solid right hand side
314  !*/
315  void setRightHandSide (const vector_Type& rightHandSide)
316  {
317  *M_rhsNoBC = rightHandSide;
318  };
319 
320  //! Comuptes the right hand side in the updateSystem methods
321  void computeRHSNoBC ( void );
322 
323  //! Compute the mass matrix and it calls the method to build the linear part of the stiffness matrix of the material class
324  void buildSystem ( const Real coefficient );
325 
326  //void buildSystem(matrix_Type & bigMatrixStokes, const Real& timeAdvanceCoefficient, const Real& factor); // used for monolithic
327 
328  //! Compute the mass matrix and the linear part of the stiffness matrix
329  /*!
330  \param matrix the matrix containing the mass matrix and the linear part of he stiffness matrix
331  \param rescale factor for FSI problems
332  */
333  void computeMassMatrix ( const Real factor = 1.);
334 
335  //! Solve the non-linear system
336  /*!
337  \param bch BCHander object containing the boundary conditions
338  */
339  void iterate ( const bcHandler_Type& bch );
340 
341  //! Solve the linearized problem. Used in FSI segregated in ExactJacobian
342  /*!
343  \param bch BCHander object containing the boundary conditions
344  */
345  void iterateLin ( bcHandler_Type& bch );
346 
347 
348  //! Output
349  /*!
350  \param c output file
351  */
352  void showMe ( std::ostream& c = std::cout ) const;
353 
354  //! Update the Jacobian Matrix at each iteration of the nonLinearRichardson method
355  /*!
356  \param solution the current solution at each iteration of the nonLinearRichardson method
357  \param jacobian the Jacobian matrix that must be updated
358  */
359  void updateJacobian ( const vector_Type& solution, matrixPtr_Type& jacobian );
360 
361  //! Update the Jacobian Matrix at each iteration of the nonLinearRichardson method
362  /*! Note: this method is used in FSIExactJacobian
363  \param solution the current solution at each iteration of the nonLinearRichardson method
364  */
365  void updateJacobian (const vector_Type& solution );
366 
367  //! Solves the tangent problem for newton iterations
368  /*!
369  \param step the vector containing the solution of the sistem J*step=-Res
370  \param res the vector conteining the residual
371  \param lin_res_tol linear_rel_tol send for the relative tolerance to the linear solver is therefore eta.
372  eta is determined by the modified Eisenstat-Walker formula
373  */
374  void solveJac ( vector_Type& step,
375  const vector_Type& residual,
376  Real& linear_rel_tol ) ;
377  // void solveJac( const Vector& res, Real& linear_rel_tol, Vector &step);
378 
379  //! Solves the tangent problem with custom BC
380  /*!
381  \param step the vector containing the solution of the sistem J*step=-Res
382  \param res the vector conteining the residual
383  \param lin_res_tol linear_rel_tol send for the relative tolerance to the linear solver is therefore eta.
384  eta is determined by the modified Eisenstat-Walker formula
385  \param BCd BCHandler object containing the boundary condition
386  */
387  void solveJacobian ( vector_Type& step,
388  const vector_Type& residual,
389  Real& linear_rel_tol,
390  bcHandler_Type& BCd ) ;
391 
392 
393  //! Evaluates residual for newton interations
394  /*!
395  \param res residal vector that is update every time the method is called
396  \param sol solution vector from which the residual is computed
397  \param iter iteration of the nonLinearRichardson method
398  */
399  void evalResidual ( vector_Type& residual, const vector_Type& solution, Int iter);
400 
401  //! Evaluates residual of the displacement for FSI problems
402  /*!
403  \param sol, the current displacement of he sturcture
404  */
405  void evalResidualDisplacement ( const vector_Type& solution );
406 
407  //! Evaluates residual of the displacement in the Linearized problem of ExactJcobian. FSI problems
408  /*!
409  \param sol, the current displacement of he sturcture
410  */
411  void evalResidualDisplacementLin ( const vector_Type& solution );
412 
413  //! Sets the initial displacement, velocity, acceleration
414  /*!
415  \param d0 space function describing the initial displacement
416  \param w0 space function describing the initial velocity
417  \param a0 space function describing the initial acceleration
418  */
419  void initialize ( const function& d0 );
420 
421  //! Sets the initial displacement, velocity, acceleration
422  /*!
423  \param d0 space function describing the initial displacement
424  \param w0 empty vector
425  \param a0 empty vector
426  */
427  void initialize ( vectorPtr_Type d0 );
428 
429  //! Computes the velocity and acceleration vector at the n-th time step
430  //void updateVelAndAcceleration();
431 
432  //! Reduce the complete solution to the solution on the pocessor with rank 0
433  /*!
434  \param disp displacement solution
435  \param vel velocity solution
436  */
437  void reduceSolution ( Vector& displacement, Vector& velocity );
438 
439  //! Multiply the mass matrix and the linear stiffness matrix by the rescaleFactor
440  // void rescaleMatrices(); // used for monolithic
441 
442  /**
443  in the linear case the solid matrix is constant, thus it does not need to be recomputed.
444  */
445 
446  //! Update (in the case of nonlinear material) the solid matrix
447  /*!
448  \param stiff stiffness matrix
449  \param sol the current solution
450  \param factor the rescaleFactor
451  */
452  void computeMatrix ( matrixPtr_Type& stiff, const vector_Type& sol, Real const& factor, const UInt iter );
453 
454  //! compute the value of the determinant of F in all the volumes of the mesh
455  /*!
456  \param displacement the solution at a certain time
457  \return the vector with the values for J
458  */
459  void jacobianDistribution ( vectorPtr_Type displacement, vector_Type& jacobianDistribution );
460 
461 
462  //! compute the value of the determinant of F in all the volumes of the mesh
463  /*!
464  \param displacement the solution at a certain time
465  \return the vector with the values for J
466  */
467  void colorMesh ( vector_Type& meshColors );
468 
469  //! Compute the three columns of the Cauchy stress tensor
470  /*!
471  \param displacement at a certain time
472  \return fills the three columns
473  */
474  void computeCauchyStressTensor ( const vectorPtr_Type disp, const QuadratureRule& evalQuad,
475  vectorPtr_Type sigma_1, vectorPtr_Type sigma_2, vectorPtr_Type sigma_3);
476 
477 
478  //! Compute the nodal principal tensions given the cauchy stress tensor
479  /*!
480  \param The three vectors of the three columns of the Cauchy stress tensor
481  \return fills the vector of the eigenvalues
482  */
483  void computePrincipalTensions ( vectorPtr_Type sigma_1, vectorPtr_Type sigma_2,
484  vectorPtr_Type sigma_3, vectorPtr_Type vectorEigenvalue);
485 
486  //void updateMatrix(matrix_Type & bigMatrixStokes);// used for monolithic
487  //void updateCoupling(matrix_Type couplingMatrix);// used for monolithic
488 
489  //@}
490 
491  //! @name Set Methods
492  //@{
493 
494  //!Setters
495  //! Set the BCHandler object
496  void setBC (const bcHandler_Type& BCd)
497  {
498  M_BCh = BCd;
499  }
500 
501  // Paolo Tricerri May, 5th 2013
502  // This version of the method is to make FSI compile
503  // It is not used at the moment and that is why it is commented inside
504 
505  //! Set the source object
506  void setSourceTerm ( source_Type const& /*s*/ )
507  {
508  //M_source = s;
509  }
510 
511  //! Set the source object
512  void setSourceTerm ( const volumeForcePtr_Type s )
513  {
514  M_source.reset( new sourceFunctor_Type( s ) );
515  }
516 
517  //! Set the source object
518  void setHavingSourceTerm ( const bool havingSource )
519  {
520  M_havingSource = havingSource;
521  }
522 
523  // //! Set the preconditioner
524  // void resetPrec(bool reset = true) { if (reset) M_linearSolver.precReset(); }
525 
526  // //! Set the displacement
527  // virtual void setDisp(const vector_Type& disp) {*M_disp = disp;} // used for monolithic
528 
529  //! Set the recur parameter
530  void setRecur (UInt recur)
531  {
532  M_recur = recur;
533  }
534 
535  //! Set the data fields with the Getpot data file for preconditioners and solver
536  void setDataFromGetPot ( const GetPot& dataFile );
537 
538  void setTimeAdvance ( const timeAdvancePtr_Type& timeAdvancePtr )
539  {
540  M_timeAdvance = timeAdvancePtr;
541  }
542 
543  //! constructPatchAreaVector: This method build the patch area vector used in the reconstruction process
544  /*!
545  \param NONE
546  */
547  void constructPatchAreaVector ( vector_Type& patchArea, const vector_Type& solution );
548 
549 
550  //! reconstructElementaryVector: This method applies a reconstruction procedure on the elvec that is passed
551  /*!
552  \param elvecTens VectorElemental over which the reconstruction is applied
553  */
554  void reconstructElementaryVector ( VectorElemental& elVecSigma, vector_Type& patchArea, UInt nVol );
555 
556  //@}
557 
558 
559  //! @name Get Methods
560  //@{
561 
562  //! Getters
563  //! Get the Epetramap
564  MapEpetra const& map() const
565  {
566  return *M_localMap;
567  }
568 
569  //! Get the Displayer object
570  Displayer const& displayer() const
571  {
572  return *M_Displayer;
573  }
574 
575  std::shared_ptr<const Displayer> const& displayerPtr() const
576  {
577  return M_Displayer;
578  }
579 
580  //! Get the matrix containing the mass mtrix and the linear part of the stiffness matrix
581  //matrixPtr_Type const MassStiff() const {return M_massStiff; }
582 
583  //! Get the mass matrix
584  matrixPtr_Type const massMatrix() const
585  {
586  return M_massMatrix;
587  }
588 
589  //! Get the FESpace object
590  FESpace_Type& dispFESpace()
591  {
592  return *M_dispFESpace;
593  }
594 
595  //! Get the ETFESpace object
596  ETFESpace_Type& dispETFESpace()
597  {
598  return *M_dispETFESpace;
599  }
600 
601  //! Get the bCHandler object
602  bcHandler_Type const& bcHandler() const
603  {
604  return M_BCh;
605  }
606 
607  //! Get the residual
608  vector_Type& residual()
609  {
610  return *M_residual_d;
611  }
612 
613  //! Get the source term
614  const bool havingSourceTerm() const
615  {
616  return M_havingSource;
617  }
618 
619 
620  //! Get the displacement
621  vector_Type& displacement()
622  {
623  return *M_disp;
624  }
625 
626  vectorPtr_Type displacementPtr()
627  {
628  return M_disp;
629  }
630 
631  //! Get the right hand sde without BC
632  vectorPtr_Type& rhsWithoutBC()
633  {
634  return M_rhsNoBC;
635  }
636 
637  solver_Type& linearSolver()
638  {
639  return *M_linearSolver;
640  }
641 
642  //! Get the right hand. The member rhsCopy is used for Debug purposes!
643  vector_Type& rhsCopy()
644  {
645  return *M_rhsCopy;
646  }
647  vector_Type& residualCopy()
648  {
649  return *M_residualCopy;
650  }
651 
652  vector_Type& bodyForce()
653  {
654  return *M_bodyForceVector;
655  }
656 
657  //! Get the comunicator object
658  std::shared_ptr<Epetra_Comm> const& comunicator() const
659  {
660  return M_Displayer->comm();
661  }
662 
663  //! Get the rescaleFactor
664  Real rescaleFactor()
665  {
666  return M_rescaleFactor;
667  }
668 
669  /*! Get the offset parameter. It is taken into account when the boundary conditions
670  are applied and the matrices are assembled.
671  */
672  const UInt& offset() const
673  {
674  return M_offset;
675  }
676 
677  /*! Get the offset parameter. It is taken into account when the boundary conditions
678  are applied and the matrices are assembled.
679  */
680  const materialPtr_Type& material() const
681  {
682  return M_material;
683  }
684 
685  /**
686  Do nothing in the linear case: the matrix remains constant. Otherwise substitute the matrix with an updated one
687  */
688  //! Get the Solid Matrix
689  void solidMatrix ( matrixPtr_Type& /*matrix*/ )
690  {
691  }
692 
693  // Physic constant
694  //! Get the thickness
695  Real thickness() const
696  {
697  return M_data->thickness();
698  }
699 
700  //! Get the Young modulus
701  Real young ( UInt material = 1) const
702  {
703  return M_data->young ( material );
704  }
705 
706  //! Get the Poisson coefficient
707  Real poisson ( UInt material = 1 ) const
708  {
709  return M_data->poisson ( material );
710  }
711 
712  //! Get the density
713  Real rho() const
714  {
715  return M_data->rho();
716  }
717 
718  //! Get the data container
719  const std::shared_ptr<data_Type>& data() const
720  {
721  return M_data;
722  }
723 
724  void apply ( const vector_Type& sol, vector_Type& res) const;
725 
726  //! Get the density
727  mapMarkerVolumesPtr_Type mapMarkersVolumes() const
728  {
729  return M_mapMarkersVolumes;
730  }
731 
732  //! Get the density
733  mapMarkerIndexesPtr_Type mapMarkersIndexes() const
734  {
735  return M_mapMarkersIndexes;
736  }
737 
738  const timeAdvancePtr_Type& timeAdvancePtr() const
739  {
740  return M_timeAdvance;
741  }
742 
743  //@}
744 
745 protected:
746 
747  //! Apply boundary condition
748  /*!
749  \param matrix the matrix of the system
750  \param rhs the right hand side of the system
751  \param BCh BCHandler object
752  \param offset the offset parameter
753  */
754  void applyBoundaryConditions (matrix_Type& matrix,
755  vector_Type& rhs,
756  bcHandler_Type& BCh,
757  UInt offset = 0);
758 
759 
760  UInt dim() const
761  {
762  return M_dispFESpace->dim();
763  }
764 
765 
766  //! construct the map between the markers and the volumes
767  /*!
768  \param VOID
769  \return VOID
770  */
771  void setupMapMarkersVolumes ( void );
772 
773  //!Protected Members
774 
775 
776  std::shared_ptr<data_Type> M_data;
777 
778  FESpacePtr_Type M_dispFESpace;
779 
780  ETFESpacePtr_Type M_dispETFESpace;
781 
782  std::shared_ptr<const Displayer> M_Displayer;
783 
784  Int M_me;
785 
786  //! data for solving tangent problem with aztec + preconditioner
787  std::shared_ptr<solver_Type> M_linearSolver;
788  basePrecPtr_Type M_preconditioner;
789 
790  //! Elementary matrices and vectors
791  std::shared_ptr<MatrixElemental> M_elmatM;
792 
793  //! linearized velocity
794  vectorPtr_Type M_disp;
795 
796  //! right hand side displacement
797  vectorPtr_Type M_rhs;
798 
799  vectorPtr_Type M_rhsCopy;
800  vectorPtr_Type M_residualCopy;
801 
802  //! right hand side
803  vectorPtr_Type M_rhsNoBC;
804 
805  vectorPtr_Type M_bodyForceVector;
806  //! right hand side
807  //std::shared_ptr<vector_Type> M_f;
808 
809  //! residual
810  std::shared_ptr<vector_Type> M_residual_d;
811 
812  //! files for lists of iterations and residuals per timestep
813  std::ofstream M_out_iter;
814  std::ofstream M_out_res;
815 
816  //! BCHandler object
817  bcHandler_Type M_BCh;
818 
819  //! Map Epetra
820  std::shared_ptr<const MapEpetra> M_localMap;
821 
822  //! Matrix M: mass
823  matrixPtr_Type M_massMatrix;
824 
825  //! Matrix Temp: Temporary matrix to compute residuals or rhs
826  matrixPtr_Type M_systemMatrix;
827 
828 
829  //! Jacobian Matrix: Matrix to store the jacobian of the newton method
830  matrixPtr_Type M_jacobian;
831 
832 
833  //! level of recursion for Aztec (has a sens with FSI coupling)
834  UInt M_recur;
835 
836  bool M_havingSource;
837  sourceFunctorPtr_Type M_source;
838 
839  UInt M_offset;
840  Real M_rescaleFactor;
841  // Real M_zeta;
842  // Real M_theta;
843 
844  //! Material class
845  materialPtr_Type M_material;
846 
847  //! Map between markers and volumes on the mesh
848  mapMarkerVolumesPtr_Type M_mapMarkersVolumes;
849 
850  //! Map between markers and volumes on the mesh
851  mapMarkerIndexesPtr_Type M_mapMarkersIndexes;
852 
853  //! Elementary matrix for the tensor F
854  matrixSerialDensePtr_Type M_deformationF;
855  vectorInvariants_Type M_invariants;
856 
857 
858  timeAdvancePtr_Type M_timeAdvance;
859 };
860 
861 //====================================
862 // Constructor
863 //=====================================
864 
865 template <typename Mesh>
866 StructuralOperator<Mesh>::StructuralOperator( ) :
867  M_data ( ),
868  M_dispFESpace ( ),
869  M_dispETFESpace ( ),
870  M_Displayer ( ),
871  M_me ( 0 ),
872  M_linearSolver ( ),
873  M_preconditioner ( ),
874  M_elmatM ( ),
875  M_disp ( ),
876  M_rhsNoBC ( ),
877  M_bodyForceVector ( ),
878  M_rhsCopy ( ),
879  M_residualCopy ( ),
880  M_residual_d ( ),
881  M_out_iter ( ),
882  M_out_res ( ),
883  M_BCh ( ),
884  M_localMap ( ),
885  M_massMatrix ( ),
886  M_systemMatrix ( ),
887  M_jacobian ( ),
888  M_recur ( ),
889  M_havingSource ( false ),
890  M_source ( ),
891  M_offset ( 0 ),
892  M_rescaleFactor ( 1. ),
893  M_material ( ),
894  M_deformationF ( ),
895  M_invariants ( ),
896  M_mapMarkersVolumes ( ),
897  M_mapMarkersIndexes ( ),
898  M_timeAdvance ( )
899 {
900 
901  // M_Displayer->leaderPrint("I am in the constructor for the solver");
902 }
903 
904 template <typename Mesh>
905 void
906 StructuralOperator<Mesh>::setup (std::shared_ptr<data_Type> data,
907  const FESpacePtr_Type& dFESpace,
908  const ETFESpacePtr_Type& dETFESpace,
909  bcHandler_Type& BCh,
910  std::shared_ptr<Epetra_Comm>& comm)
911 {
912  setup (data, dFESpace, dETFESpace, comm);
913  M_BCh = BCh;
914 }
915 
916 template <typename Mesh>
917 void
918 StructuralOperator<Mesh>::setup (std::shared_ptr<data_Type> data,
919  const FESpacePtr_Type& dFESpace,
920  const ETFESpacePtr_Type& dETFESpace,
921  std::shared_ptr<Epetra_Comm>& comm)
922 {
923  setup ( data, dFESpace, dETFESpace, comm, dFESpace->mapPtr(), (UInt) 0 );
924 
925  M_rhs.reset ( new vector_Type (*M_localMap) );
926 
927  M_rhsCopy.reset ( new vector_Type (*M_localMap) );
928  M_residualCopy.reset ( new vector_Type (*M_localMap) );
929 
930  M_rhsNoBC.reset ( new vector_Type (*M_localMap) );
931  M_bodyForceVector.reset ( new vector_Type (*M_localMap) );
932  M_linearSolver.reset ( new LinearSolver ( comm ) );
933  M_disp.reset ( new vector_Type (*M_localMap) );
934 }
935 
936 template <typename Mesh>
937 void
938 StructuralOperator<Mesh>::setup (std::shared_ptr<data_Type> data,
939  const FESpacePtr_Type& dFESpace,
940  const ETFESpacePtr_Type& dETFESpace,
941  std::shared_ptr<Epetra_Comm>& comm,
942  const std::shared_ptr<const MapEpetra>& monolithicMap,
943  UInt offset)
944 {
945  M_data = data;
946  M_dispFESpace = dFESpace;
947  M_dispETFESpace = dETFESpace;
948  M_Displayer.reset (new Displayer (comm) );
949  M_me = comm->MyPID();
950  M_elmatM.reset ( new MatrixElemental ( M_dispFESpace->fe().nbFEDof(), nDimensions, nDimensions ) );
951  M_localMap = monolithicMap;
952  M_massMatrix.reset (new matrix_Type (*M_localMap) );
953  M_systemMatrix.reset (new matrix_Type (*M_localMap) );
954  M_jacobian.reset (new matrix_Type (*M_localMap) );
955 
956  M_offset = offset;
957 
958  M_material.reset( new material_Type() );
959  M_material->setup ( dFESpace, dETFESpace, M_localMap, M_offset, M_data, M_Displayer );
960 
961  if ( M_data->verbose() )
962  {
963  M_out_iter.open ( "out_iter_solid" );
964  M_out_res.open ( "out_res_solid" );
965  }
966  M_mapMarkersVolumes.reset ( new mapMarkerVolumes_Type() );
967  M_mapMarkersIndexes.reset ( new mapMarkerIndexes_Type() );
968 
969  this->setupMapMarkersVolumes();
970 }
971 
972 
973 template <typename Mesh>
974 void StructuralOperator<Mesh>::setupMapMarkersVolumes ( void )
975 {
976 
977  LifeChrono time;
978 
979  this->M_Displayer->leaderPrint (" S- Starting the time: \n");
980 
981  time.start();
982 
983 
984  this->M_Displayer->leaderPrint (" S- Building the map between volumesMarkers <--> volumes \n");
985 
986  //We first loop over the vector of the material_flags
987  for ( UInt i (0); i < M_data->vectorFlags().size(); i++ )
988  {
989 
990  //Create the functor to extract volumes
991  markerSelectorPtr_Type ref ( new markerSelector_Type (M_data->vectorFlags() [i]) );
992 
993  //Number of volumes with the current marker
994  UInt numExtractedVolumes = this->M_dispFESpace->mesh()->elementList().countAccordingToPredicate ( *ref );
995 
996  this->M_Displayer->leaderPrint (" Current marker: ", M_data->vectorFlags() [i]);
997  this->M_Displayer->leaderPrint (" \n");
998  this->M_Displayer->leaderPrint (" Number of volumes:", numExtractedVolumes);
999  this->M_Displayer->leaderPrint (" \n");
1000 
1001  //Vector large enough to contain the number of volumes with the current marker
1002  vectorVolumes_Type extractedVolumes ( numExtractedVolumes );
1003  vectorIndexes_Type extractedIndexes;
1004 
1005  //Extracting the volumes and the corresponding position
1006  extractedVolumes = this->M_dispFESpace->mesh()->elementList().extractAccordingToPredicateNonConstElement ( *ref, extractedIndexes );
1007 
1008  //Insert the correspondande Marker <--> List of Volumes inside the map
1009  M_mapMarkersVolumes->insert ( std::pair<UInt, vectorVolumes_Type> (M_data->vectorFlags() [i], extractedVolumes) ) ;
1010  M_mapMarkersIndexes->insert ( std::pair<UInt, vectorIndexes_Type> (M_data->vectorFlags() [i], extractedIndexes) ) ;
1011 
1012  // for( UInt i(0); i<extractedIndexes.size(); i++ )
1013  // std::cout << "Element: " << extractedIndexes[i] << std::endl;
1014 
1015  //Cleaning the vector
1016  extractedVolumes.clear();
1017  extractedIndexes.clear();
1018 
1019  }
1020 
1021  time.stop();
1022 
1023  this->M_Displayer->leaderPrint (" S- Time to build the map:", time.diff() );
1024 }
1025 
1026 template <typename Mesh>
1027 void StructuralOperator<Mesh>::updateSystem ( void )
1028 {
1029  updateSystem (M_systemMatrix);
1030 }
1031 
1032 template <typename Mesh>
1033 void StructuralOperator<Mesh>::updateSystem ( matrixPtr_Type& mat_stiff)
1034 {
1035  M_Displayer->leaderPrint (" S- Updating mass term on right hand side... ");
1036 
1037  LifeChrono chrono;
1038  chrono.start();
1039 
1040  if ( M_data->lawType() == "linear" )
1041  {
1042  *mat_stiff += *M_material->stiffMatrix();
1043  mat_stiff->globalAssemble();
1044  }
1045  else
1046  {
1047  //Compute the new Stiffness Matrix
1048  // The method computeStiffness is done inside the nonlinear case. In the linear case it is empty
1049  // The int parameter iter is equal to zero to let the user treat implicitly the multi-mechanism
1050  M_material->computeStiffness (*M_disp, 0 , M_rescaleFactor, M_data, M_mapMarkersVolumes, M_mapMarkersIndexes, M_Displayer);
1051  }
1052 
1053  chrono.stop();
1054  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1055 
1056 }
1057 
1058 template <typename Mesh>
1059 void StructuralOperator<Mesh>::updateRightHandSideWithBodyForce ( const Real currentTime, const vector_Type& rhsTimeAdvance )
1060 {
1061  using namespace ExpressionAssembly;
1062 
1063  M_source->setCurrentTime( currentTime );
1064 
1065  vectorPtr_Type rhs ( new vector_Type (*M_localMap) );
1066 
1067  integrate ( elements ( this->M_dispETFESpace->mesh() ) ,
1068  this->M_dispFESpace->qr(),
1069  this->M_dispETFESpace,
1070  value ( M_data->rho() ) * dot ( eval( M_source, X ), phi_i )
1071  ) >> rhs;
1072 
1073  M_bodyForceVector = rhs;
1074 
1075  *rhs += rhsTimeAdvance;
1076 
1077  *M_rhsNoBC += *rhs;
1078 
1079 }
1080 
1081 template <typename Mesh>
1082 void StructuralOperator<Mesh>::buildSystem ( const Real coefficient )
1083 {
1084  M_Displayer->leaderPrint (" S- Computing constant matrices ... ");
1085  LifeChrono chrono;
1086  chrono.start();
1087 
1088  computeMassMatrix ( coefficient );
1089  M_material->computeLinearStiff (M_data, M_mapMarkersVolumes, M_mapMarkersIndexes);
1090 
1091  chrono.stop();
1092  M_Displayer->leaderPrintMax ( "done in ", chrono.diff() );
1093 
1094 }
1095 
1096 template <typename Mesh>
1097 void
1098 StructuralOperator<Mesh>::computeMassMatrix ( const Real factor)
1099 {
1100  using namespace ExpressionAssembly;
1101 
1102  //UInt totalDof = M_dispFESpace->dof().numTotalDof();
1103 
1104  //! Number of displacement components
1105  /*UInt nc = nDimensions;*/
1106  const Real factorMassMatrix = factor * M_data->rho();
1107 
1108  //Assembling using the Expression Template
1109  //At the moment, that the ET is not the standard, when the integration is
1110  //performed the quadrature rule set in FESpace is used.
1111  //Otherwhise, one can set his preferred quadrature rule for the integrals.
1112 
1113  integrate ( elements (M_dispETFESpace->mesh() ),
1114  M_dispFESpace->qr(),
1115  M_dispETFESpace,
1116  M_dispETFESpace,
1117  value (factorMassMatrix) * dot ( phi_j , phi_i ) ) >> M_massMatrix;
1118 
1119  M_massMatrix->globalAssemble();
1120 
1121  //M_massMatrix->spy("massMatrixStructure.m");
1122 
1123  //*massStiff *= factor; //M_data.dataTime()->timeStep() * M_rescaleFactor;
1124 
1125  // UInt totalDof = M_dispFESpace->dof().numTotalDof();
1126 
1127  // //! Number of displacement components
1128  // UInt nc = nDimensions;
1129  // const Real factorMassMatrix = factor * M_data->rho();
1130 
1131  // //! Elementary computation and matrix assembling
1132  // //! Loop on elements
1133  // for ( UInt i = 0; i < M_dispFESpace->mesh()->numVolumes(); i++ )
1134  // {
1135 
1136  // M_dispFESpace->fe().updateFirstDerivQuadPt ( M_dispFESpace->mesh()->volumeList ( i ) );
1137 
1138  // M_elmatM->zero();
1139 
1140  // // mass
1141  // // The method mass is implemented in AssemblyElemental.cpp
1142  // mass ( factorMassMatrix , *M_elmatM, M_dispFESpace->fe(), 0, 0, nDimensions );
1143 
1144  // //! assembling
1145  // for ( UInt ic = 0; ic < nc; ic++ )
1146  // {
1147  // //mass
1148  // assembleMatrix ( *M_massMatrix, *M_elmatM, M_dispFESpace->fe(), M_dispFESpace->dof(), ic, ic, M_offset + ic * totalDof, M_offset + ic * totalDof);
1149  // }
1150  // }
1151 
1152 }
1153 
1154 template <typename Mesh>
1155 void
1156 StructuralOperator<Mesh>::iterate ( const bcHandler_Type& bch )
1157 {
1158  LifeChrono chrono;
1159 
1160  // matrix and vector assembling communication
1161  M_Displayer->leaderPrint (" S- Solving the system ... \n");
1162 
1163  M_BCh = bch;
1164 
1165  Real abstol = M_data->absoluteTolerance();
1166  Real reltol = M_data->relativeTolerance();
1167  UInt maxiter = M_data->maxSubIterationNumber();
1168  Real etamax = M_data->errorTolerance();
1169  Int NonLinearLineSearch = M_data->NonLinearLineSearch();
1170 
1171  Real time = M_data->dataTime()->time();
1172 
1173  Int status = 0;
1174 
1175  if ( M_data->verbose() )
1176  {
1177  status = NonLinearRichardson ( *M_disp, *this, abstol, reltol, maxiter, etamax, NonLinearLineSearch, 0, 2, M_out_res, M_data->dataTime()->time() );
1178  }
1179  else
1180  {
1181  status = NonLinearRichardson ( *M_disp, *this, abstol, reltol, maxiter, etamax, NonLinearLineSearch );
1182  }
1183 
1184 
1185  if ( status == 1 )
1186  {
1187  std::ostringstream ex;
1188  ex << "StructuralOperator::iterate() Inners nonLinearRichardson iterations failed to converge\n";
1189  throw std::logic_error ( ex.str() );
1190  }
1191  else // if status == 0 NonLinearrRichardson converges
1192  {
1193  // std::cout << std::endl;
1194 
1195  // std::cout <<" Number of inner iterations : " << maxiter << std::endl;
1196 
1197  // std::cout <<" We are at the time step : " << M_data->dataTime()->time() << std::endl;
1198  if ( M_data->verbose() )
1199  {
1200  M_out_iter << time << " " << maxiter << std::endl;
1201  }
1202  }
1203 
1204  // std::cout << "iterate: d norm = " << M_disp->norm2() << std::endl;
1205 
1206  //These two lines mut be checked fo FSI. With the linear solver, they have a totally
1207  //different expression. For structural problems it is not used.
1208  evalResidualDisplacement (*M_disp); //\todo related to FSI. Should be caled from outside
1209 }
1210 
1211 template <typename Mesh>
1212 void
1213 StructuralOperator<Mesh>::iterateLin ( bcHandler_Type& bch )
1214 {
1215  vector_Type rhsFull (M_rhsNoBC->map() );
1216  Real zero (0.);
1217  if ( !bch->bcUpdateDone() )
1218  {
1219  bch->bcUpdate ( *M_dispFESpace->mesh(), M_dispFESpace->feBd(), M_dispFESpace->dof() );
1220  }
1221  bcManageVector ( rhsFull, *M_dispFESpace->mesh(), M_dispFESpace->dof(), *bch, M_dispFESpace->feBd(), M_data->dataTime()->time(), 1.0 );
1222  solveJacobian (*M_disp, rhsFull, zero, bch);
1223  evalResidualDisplacementLin (*M_disp);
1224 }
1225 
1226 
1227 template <typename Mesh>
1228 void
1229 StructuralOperator<Mesh>::showMe ( std::ostream& c ) const
1230 {
1231  c << "\n*** StructuralOperator::showMe method" << std::endl;
1232 
1233  M_data->showMe ( c );
1234 
1235 }
1236 
1237 template <typename Mesh>
1238 void StructuralOperator<Mesh>::computeMatrix ( matrixPtr_Type& stiff, const vector_Type& sol,
1239  Real const& /*factor*/, const UInt iter)
1240 {
1241  M_Displayer->leaderPrint ( " Computing residual ... \t\t\t");
1242 
1243  LifeChrono chrono;
1244  chrono.start();
1245 
1246  if ( M_data->lawType() == "linear" )
1247  {
1248  *stiff = *M_material->stiffMatrix();
1249  *stiff += *M_massMatrix;
1250  stiff->globalAssemble();
1251  }
1252  else
1253  {
1254  //! It is right to do globalAssemble() inside the M_material class
1255  // The method computeStiffness is done inside the nonlinear case. In the linear case it is empty
1256  M_material->computeStiffness ( sol, iter, 1., M_data, M_mapMarkersVolumes, M_mapMarkersIndexes, M_Displayer);
1257  }
1258  chrono.stop();
1259  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1260 }
1261 
1262 
1263 
1264 template <typename Mesh>
1265 void StructuralOperator<Mesh>::jacobianDistribution ( vectorPtr_Type displacement, vector_Type& jacobianDistribution )
1266 {
1267  M_Displayer->leaderPrint ( " Computing the jacobian for all the volumes ... \t\t\t");
1268 
1269  //Initialization of the deformationF matrix
1270  M_deformationF.reset ( new matrixSerialDense_Type ( M_dispFESpace->fieldDim(), M_dispFESpace->fieldDim() ) );
1271 
1272  vector_Type vectorJacobian ( jacobianDistribution );
1273  vectorJacobian *= 0.0;
1274 
1275  LifeChrono chrono;
1276  chrono.start();
1277 
1278  //construct a vector to store the are
1279  vector_Type patchArea (*displacement, Unique, Add);
1280  patchArea *= 0.0;
1281 
1282  constructPatchAreaVector ( patchArea, *displacement );
1283 
1284  //Before assembling the reconstruction process is done
1285  vector_Type patchAreaR (patchArea, Repeated);
1286 
1287 
1288  //Loop over the volumes to compute J = det(F)
1289  //Inside the loop, the determinant is store in the appropriate positions
1290  vector_Type dRep (*displacement, Repeated);
1291  UInt totalDof = M_dispFESpace->dof().numTotalDof();
1292  VectorElemental dk_loc ( M_dispFESpace->fe().nbFEDof(), this->M_dispFESpace->fieldDim() );
1293  VectorElemental elVecDet ( M_dispFESpace->fe().nbFEDof(), this->M_dispFESpace->fieldDim() );
1294 
1295  //Building fake quadrature rules to compute the deformation gradient F at the nodes
1296  QuadratureRule fakeQuadratureRule;
1297 
1298  Real refElemArea (0); //area of reference element
1299  //compute the area of reference element
1300  for (UInt iq = 0; iq < M_dispFESpace->qr().nbQuadPt(); iq++)
1301  {
1302  refElemArea += M_dispFESpace->qr().weight (iq);
1303  }
1304 
1305  Real wQuad (refElemArea / M_dispFESpace->refFE().nbDof() );
1306 
1307  //Setting the quadrature Points = DOFs of the element and weight = 1
1308  std::vector<GeoVector> coords = M_dispFESpace->refFE().refCoor();
1309  std::vector<Real> weights (M_dispFESpace->fe().nbFEDof(), wQuad);
1310  fakeQuadratureRule.setDimensionShape ( shapeDimension (M_dispFESpace->refFE().shape() ), M_dispFESpace->refFE().shape() );
1311  fakeQuadratureRule.setPoints (coords, weights);
1312 
1313  //Set the new quadrature rule
1314  M_dispFESpace->setQuadRule (fakeQuadratureRule);
1315 
1316 
1317  //Loop over the volumes. No markerIDs are necessary on this loop for J = det(F)
1318  for ( UInt i = 0; i < M_dispFESpace->mesh()->numVolumes(); ++i )
1319  {
1320 
1321  //Vectors for the deformation tensor
1322  std::vector<matrixSerialDense_Type> vectorDeformationF (M_dispFESpace->fe().nbFEDof(), *M_deformationF);
1323  M_invariants.resize ( M_dispFESpace->fieldDim() + 1 );
1324 
1325 
1326  M_dispFESpace->fe().updateFirstDerivQuadPt ( M_dispFESpace->mesh()->volumeList ( i ) );
1327 
1328  UInt eleID = M_dispFESpace->fe().currentLocalId();
1329 
1330  //Extracting the local displacement
1331  for ( UInt iNode = 0; iNode < ( UInt ) M_dispFESpace->fe().nbFEDof(); iNode++ )
1332  {
1333  UInt iloc = M_dispFESpace->fe().patternFirst ( iNode );
1334 
1335  for ( UInt iComp = 0; iComp < this->M_dispFESpace->fieldDim(); ++iComp )
1336  {
1337  UInt ig = M_dispFESpace->dof().localToGlobalMap ( eleID, iloc ) + iComp * M_dispFESpace->dim() + this->M_offset;
1338  dk_loc[iloc + iComp * M_dispFESpace->fe().nbFEDof()] = dRep[ig];
1339  }
1340  }
1341 
1342  //computing the tensor F
1343  AssemblyElementalStructure::computeLocalDeformationGradient ( dk_loc, vectorDeformationF, M_dispFESpace->fe() );
1344 
1345 
1346  //Cycle over the nDofs/element
1347  for ( UInt nDOF = 0; nDOF < ( UInt ) M_dispFESpace->fe().nbFEDof(); nDOF++ )
1348  {
1349  UInt iloc = M_dispFESpace->fe().patternFirst ( nDOF );
1350 
1351  //computing the determinant
1352  AssemblyElementalStructure::computeInvariantsRightCauchyGreenTensor ( M_invariants, vectorDeformationF[nDOF] );
1353 
1354  //Assembling elemental vector
1355  (elVecDet) [ iloc ] = M_invariants[3];
1356  (elVecDet) [ iloc + M_dispFESpace->fe().nbFEDof() ] = 0.0;
1357  (elVecDet) [ iloc + 2 * M_dispFESpace->fe().nbFEDof() ] = 0.0;
1358 
1359  }
1360 
1361  //multiplying it for the patch area
1362  reconstructElementaryVector ( elVecDet, patchAreaR, i );
1363 
1364  //assembling it into the global vector
1365  for ( UInt ic = 0; ic < this->M_dispFESpace->fieldDim(); ++ic )
1366  {
1367  assembleVector (vectorJacobian, elVecDet, M_dispFESpace->fe(), M_dispFESpace->dof(), ic, this->M_offset + ic * totalDof );
1368  }
1369 
1370  vectorDeformationF.clear();
1371  M_invariants.clear();
1372 
1373  }
1374 
1375  vectorJacobian.globalAssemble();
1376 
1377  chrono.stop();
1378  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1379 
1380  jacobianDistribution = vectorJacobian;
1381 }
1382 
1383 
1384 template <typename Mesh>
1385 void StructuralOperator<Mesh >::constructPatchAreaVector ( vector_Type& patchArea,
1386  const vector_Type& solution )
1387 {
1388 
1389  vector_Type patchAreaR (solution, Repeated);
1390  patchAreaR *= 0.0;
1391 
1392  Real refElemArea (0); //area of reference element
1393  UInt totalDof = M_dispFESpace->dof().numTotalDof();
1394  //compute the area of reference element
1395  for (UInt iq = 0; iq < M_dispFESpace->qr().nbQuadPt(); iq++)
1396  {
1397  refElemArea += M_dispFESpace->qr().weight (iq);
1398  }
1399 
1400  // Define a special quadrature rule for the interpolation
1401  QuadratureRule interpQuad;
1402  interpQuad.setDimensionShape (shapeDimension (M_dispFESpace->refFE().shape() ), M_dispFESpace->refFE().shape() );
1403  Real wQuad (refElemArea / M_dispFESpace->refFE().nbDof() );
1404 
1405  for (UInt i (0); i < M_dispFESpace->refFE().nbDof(); ++i) //nbRefCoor
1406  {
1407  interpQuad.addPoint (QuadraturePoint (M_dispFESpace->refFE().xi (i), M_dispFESpace->refFE().eta (i), M_dispFESpace->refFE().zeta (i), wQuad) );
1408  }
1409 
1410  UInt totalNumberVolumes (M_dispFESpace->mesh()->numVolumes() );
1411  UInt numberLocalDof (M_dispFESpace->dof().numLocalDof() );
1412 
1413  CurrentFE interpCFE (M_dispFESpace->refFE(), getGeometricMap (* (M_dispFESpace->mesh() ) ), interpQuad);
1414 
1415  // Loop over the cells
1416  for (UInt iterElement (0); iterElement < totalNumberVolumes; iterElement++)
1417  {
1418  interpCFE.update (M_dispFESpace->mesh()->volumeList ( iterElement ), UPDATE_WDET );
1419 
1420  for (UInt iterDof (0); iterDof < numberLocalDof; iterDof++)
1421  {
1422  for (UInt iDim (0); iDim < M_dispFESpace->fieldDim(); ++iDim)
1423  {
1424  ID globalDofID (M_dispFESpace->dof().localToGlobalMap (iterElement, iterDof) + iDim * totalDof);
1425  patchAreaR[globalDofID] += interpCFE.measure();
1426  }
1427  }
1428  }
1429 
1430  vector_Type final (patchAreaR, Unique, Add);
1431 
1432  patchArea.add (final);
1433 }
1434 
1435 template <typename Mesh>
1436 void
1437 StructuralOperator<Mesh >::reconstructElementaryVector ( VectorElemental& elVecDet,
1438  vector_Type& patchArea,
1439  UInt nVol )
1440 {
1441  //UpdateElement Infos
1442  //M_dispFESpace->fe().updateFirstDerivQuadPt( M_dispFESpace->mesh()->volumeList( nVol ) );
1443 
1444  Real measure = M_dispFESpace->fe().measure();
1445  UInt eleID = M_dispFESpace->fe().currentLocalId();
1446 
1447  for (UInt iDof = 0; iDof < M_dispFESpace->fe().nbFEDof(); iDof++)
1448  {
1449  UInt iloc = M_dispFESpace->fe().patternFirst ( iDof );
1450 
1451  for ( UInt icoor = 0; icoor < M_dispFESpace->fieldDim(); icoor++ )
1452  {
1453  ID globalDofID (M_dispFESpace->dof().localToGlobalMap (eleID, iDof) + icoor * M_dispFESpace->dof().numTotalDof() );
1454  elVecDet[iloc + icoor * M_dispFESpace->fe().nbFEDof()] *= ( measure / patchArea[globalDofID] );
1455  }
1456 
1457  }
1458 }
1459 
1460 
1461 template <typename Mesh>
1462 void StructuralOperator<Mesh>::colorMesh ( vector_Type& meshColors )
1463 {
1464  UInt totalDof = this->M_dispFESpace->dof().numTotalDof();
1465 
1466  mapIterator_Type it;
1467 
1468  for ( it = (*M_mapMarkersVolumes).begin(); it != (*M_mapMarkersVolumes).end(); it++ )
1469  {
1470 
1471  //Given the marker pointed by the iterator, let's extract the material parameters
1472  UInt marker = it->first;
1473 
1474  for ( UInt j (0); j < it->second.size(); j++ )
1475  {
1476  this->M_dispFESpace->fe().updateFirstDerivQuadPt ( * (it->second[j]) );
1477 
1478  UInt eleID = this->M_dispFESpace->fe().currentLocalId();
1479 
1480  for ( UInt iNode = 0; iNode < ( UInt ) this->M_dispFESpace->fe().nbFEDof(); iNode++ )
1481  {
1482  UInt iloc = this->M_dispFESpace->fe().patternFirst ( iNode );
1483 
1484  //Extract the global ID of the x-component of the field
1485  UInt globalIDofDOF = this->M_dispFESpace->dof().localToGlobalMap ( eleID, iloc );
1486 
1487  if ( meshColors.blockMap().LID (static_cast<EpetraInt_Type>(globalIDofDOF)) != -1 ) // The Global ID is on the calling processors
1488  {
1489  Int LIDid = meshColors.blockMap().LID ( static_cast<EpetraInt_Type>(globalIDofDOF) );
1490  Int GIDid = meshColors.blockMap().GID ( LIDid );
1491  meshColors[ GIDid ] = marker;
1492 
1493  }
1494 
1495  }
1496  }
1497 
1498  }
1499 }
1500 
1501 template <typename Mesh>
1502 void StructuralOperator<Mesh>::computeCauchyStressTensor( const vectorPtr_Type disp,
1503  const QuadratureRule& evalQuad,
1504  vectorPtr_Type sigma_1,
1505  vectorPtr_Type sigma_2,
1506  vectorPtr_Type sigma_3)
1507 {
1508  /*
1509  The method uses the definition of the Cauchy stress tensor for the constitutive law.
1510  The tensor is computed using the material models classes where all the informations
1511  that are needed are stored (e.g. material parameters)
1512  */
1513 
1514  M_material->computeCauchyStressTensor ( disp, evalQuad, sigma_1, sigma_2, sigma_3 );
1515 }
1516 
1517 template <typename Mesh>
1518 void StructuralOperator<Mesh>::computePrincipalTensions( vectorPtr_Type sigma_1, vectorPtr_Type sigma_2,
1519  vectorPtr_Type sigma_3, vectorPtr_Type vectorEigenvalues)
1520 {
1521  /*
1522  In order to compute the nodal eigenvalues, for each DOF the cauchy stress tensor is extracted from the
1523  vectors of the columns. Then the nodal matrix is composed and the eigenvalues computed.
1524  The following method is a partial repetition of the code in AssemblyElementalStructure. Nevertheless it is
1525  consistent with the ETA approach to post-process structural dynamic simulations.
1526  */
1527 
1528  /*
1529  We loop over the local ID on the processors of the originVector
1530  The cut of the vector sigma_1 sigma_2 and sigma_3 should be done in the same way
1531  so for the for loop I consider only the sigma_1
1532  */
1533  for ( UInt iDOF = 0; iDOF < ( UInt ) M_dispFESpace->dof().numTotalDof(); ++iDOF )
1534  {
1535  if( sigma_1->blockMap().LID( static_cast<EpetraInt_Type>(iDOF) ) != -1 )
1536  {
1537  // Given the local ID we get the GID of the vector.
1538  Int GIDnode = sigma_1->blockMap().GID( iDOF );
1539 
1540  // LAPACK wrapper of Epetra
1541  Epetra_LAPACK lapack;
1542 
1543  //List of flags for Lapack Function
1544  //For documentation, have a look at http://www.netlib.org/lapack/double/dgeev.f
1545 
1546  char JOBVL = 'N';
1547  char JOBVR = 'N';
1548 
1549  //Size of the matrix
1550  Int Dim = nDimensions;
1551 
1552  //Arrays to store eigenvalues (their number = nDimensions)
1553  double WR[nDimensions];
1554  double WI[nDimensions];
1555 
1556  //Number of eigenvectors
1557  Int LDVR = nDimensions;
1558  Int LDVL = nDimensions;
1559 
1560  //Arrays to store eigenvectors
1561  Int length = nDimensions * 3;
1562 
1563  double VR[length];
1564  double VL[length];
1565 
1566  Int LWORK = 9;
1567  Int INFO = 0;
1568 
1569  double WORK[LWORK];
1570 
1571  double A[length];
1572 
1573  // Filling the matrix
1574  for (UInt j (0); j < nDimensions; j++)
1575  {
1576  Int LIDid = sigma_1->blockMap().LID (static_cast<EpetraInt_Type>(iDOF + j * M_dispFESpace->dof().numTotalDof() + M_offset));
1577  Int GIDid = sigma_1->blockMap().GID (LIDid);
1578 
1579  A[ nDimensions * j ] = (*sigma_1)( GIDid );
1580  A[ nDimensions * j + 1 ] = (*sigma_2)( GIDid );
1581  A[ nDimensions * j + 2 ] = (*sigma_3)( GIDid );
1582  }
1583 
1584  lapack.GEEV (JOBVL, JOBVR, Dim, A /*cauchy*/, Dim, &WR[0], &WI[0], VL, LDVL, VR, LDVR, WORK, LWORK, &INFO);
1585  ASSERT ( !INFO, "Calculation of the Eigenvalues failed!!!" );
1586 
1587  /*
1588  The Cauchy stress tensor is symmetric and positive definite therefore the
1589  eigenvalues have to be real and positive
1590  */
1591  Real sum(0);
1592  for( UInt k(0); k < nDimensions; k++ )
1593  sum += WI[ k ];
1594 
1595  ASSERT( sum < 1e-6, "The eigenvalues are not real!");
1596 
1597  std::vector<double> eigenvalues(nDimensions);
1598  for( UInt l(0); l < nDimensions; l++ )
1599  {
1600  eigenvalues[ l ] = WR[ l ];
1601  }
1602 
1603  std::sort( eigenvalues.begin(), eigenvalues.end() );
1604 
1605  // Putting the real eigenvalues in the right place
1606  for( UInt m(0); m < nDimensions; m++ )
1607  {
1608  Int LIDid = vectorEigenvalues->blockMap().LID (static_cast<EpetraInt_Type>(iDOF + m * M_dispFESpace->dof().numTotalDof() + M_offset));
1609  Int GIDid = vectorEigenvalues->blockMap().GID (LIDid);
1610 
1611  (*vectorEigenvalues)( GIDid ) = eigenvalues[ m ];
1612  }
1613  }
1614  }
1615 
1616 }
1617 
1618 template <typename Mesh>
1619 void
1620 StructuralOperator<Mesh>::evalResidual ( vector_Type& residual, const vector_Type& solution, Int iter)
1621 {
1622 
1623  //This method call the M_material computeStiffness
1624  computeMatrix (M_systemMatrix, solution, 1., iter);
1625 
1626 
1627  M_Displayer->leaderPrint (" S- Updating the boundary conditions ... \t");
1628  LifeChrono chrono;
1629 
1630  if ( !M_BCh->bcUpdateDone() )
1631  {
1632  M_BCh->bcUpdate ( *M_dispFESpace->mesh(), M_dispFESpace->feBd(), M_dispFESpace->dof() );
1633  }
1634 
1635  // ignoring non-local entries, Otherwise they are summed up lately
1636  if ( M_data->lawType() == "linear" )
1637  {
1638  chrono.start();
1639 
1640  matrix_Type matrixFull (*M_systemMatrix);
1641 
1642  if (iter == 0)
1643  {
1644  *M_rhs = *M_rhsNoBC;
1645 
1646  bcManageVector ( *M_rhs, *M_dispFESpace->mesh(), M_dispFESpace->dof(), *M_BCh, M_dispFESpace->feBd(), M_data->dataTime()->time(), 1.0 );
1647 
1648 
1649  //To export for check
1650  M_rhsCopy = M_rhs;
1651  // std::string nameFile="residualAfterBC";
1652  // M_rhs->spy(nameFile);
1653 
1654  }
1655 
1656  bcManageMatrix ( matrixFull, *M_dispFESpace->mesh(), M_dispFESpace->dof(), *M_BCh, M_dispFESpace->feBd(), 1.0 );
1657 
1658  residual = matrixFull * solution;
1659  residual -= *M_rhs;
1660  chrono.stop();
1661  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1662  }
1663  else //NH and Exp and SVK VK-Penalized
1664  {
1665  chrono.start();
1666  *M_rhs = *M_rhsNoBC;
1667  residual = *M_massMatrix * solution;
1668  residual += *M_material->stiffVector();
1669  vector_Type solRep (solution, Repeated);
1670  bcManageResidual ( residual, *M_rhs, solRep, *M_dispFESpace->mesh(), M_dispFESpace->dof(), *M_BCh, M_dispFESpace->feBd(), M_data->dataTime()->time(), 1.0 );
1671  residual -= *M_rhs;
1672  chrono.stop();
1673  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1674  }
1675 
1676  // Debug purpose. In production you should not export such vectors
1677  if ( iter == 0 )
1678  {
1679  *M_residualCopy = residual;
1680  M_rhsCopy = M_rhs;
1681  }
1682 }
1683 
1684 template <typename Mesh>
1685 void
1686 StructuralOperator<Mesh>::evalResidualDisplacement ( const vector_Type& solution )
1687 {
1688 
1689  M_Displayer->leaderPrint (" S- Computing the residual displacement for the structure..... \t");
1690  LifeChrono chrono;
1691  chrono.start();
1692 
1693  if ( M_data->lawType() == "linear" )
1694  {
1695  M_residual_d.reset (new vector_Type ( *M_systemMatrix * solution ) );
1696  *M_residual_d -= *M_rhsNoBC;
1697  }
1698  else //Cases: NH, Exp, VK-Penalized
1699  {
1700  M_residual_d.reset (new vector_Type ( *M_material->stiffVector() ) );
1701  *M_residual_d -= *M_rhsNoBC;
1702  }
1703  chrono.stop();
1704  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1705 }
1706 
1707 
1708 template <typename Mesh>
1709 void
1710 StructuralOperator<Mesh>::evalResidualDisplacementLin ( const vector_Type& solution )
1711 {
1712 
1713  M_Displayer->leaderPrint (" S- Computing the residual displacement for the structure..... \t");
1714  LifeChrono chrono;
1715  chrono.start();
1716 
1717  //This definition of residual_d is similar to the one of iterateLin in VenantKirchhoffSolver
1718  M_residual_d.reset (new vector_Type ( (*M_jacobian) *solution) );
1719 
1720  chrono.stop();
1721  M_Displayer->leaderPrintMax ("done in ", chrono.diff() );
1722 }
1723 
1724 
1725 template <typename Mesh>
1726 void
1727 StructuralOperator<Mesh>::initialize ( vectorPtr_Type disp )
1728 {
1729  *M_disp = *disp;
1730 }
1731 
1732 template <typename Mesh>
1733 void
1734 StructuralOperator<Mesh>::initialize ( const function& d0 )
1735 {
1736  M_dispFESpace->interpolate ( static_cast<typename FESpace<Mesh, MapEpetra>::function_Type> ( d0 ), *M_disp, 0.0);
1737 }
1738 
1739 template<typename Mesh>
1740 void
1741 StructuralOperator<Mesh>::reduceSolution ( Vector& displacement, Vector& velocity )
1742 {
1743  vector_Type disp (*M_disp, 0);
1744  //vector_Type vel(*M_vel , 0);
1745 
1746  if ( comunicator()->MyPID() == 0 )
1747  {
1748  for ( UInt iDof = 0; iDof < nDimensions * dim(); ++iDof )
1749  {
1750  disp[ iDof ] = displacement[ iDof + 1 ];
1751  }
1752  }
1753 }
1754 
1755 
1756 template <typename Mesh>
1757 void
1758 StructuralOperator<Mesh>::setDataFromGetPot ( const GetPot& dataFile )
1759 {
1760 
1761  M_Displayer->leaderPrint ( "Setting up Preconditioner... \n" );
1762  //Setting up the preconditioner
1763  const std::string preconditionerType = dataFile ( "solid/prec/prectype", "Ifpack" );
1764  const std::string xmlFileName = dataFile ( "solid/prec/xmlName", "xmlParameters.xml" );
1765  basePrecPtr_Type precPtr; //Abstract class for preconditioners
1766 
1767  if ( ! ( preconditionerType.compare ("Ifpack") ) ) //The preconditioner if Ifpack
1768  {
1769  precIfpack_Type* precRawPtr;
1770  precRawPtr = new precIfpack_Type;
1771  precRawPtr->setDataFromGetPot ( dataFile, "solid/prec" );
1772 
1773  //Initializing the preconditioner
1774  M_preconditioner.reset ( precRawPtr );
1775  }
1776  else
1777  {
1778  precML_Type* precRawPtr;
1779  precRawPtr = new precML_Type;
1780  precRawPtr->setDataFromGetPot ( dataFile, "solid/prec" );
1781 
1782  //Initializing the preconditioner
1783  M_preconditioner.reset ( precRawPtr );
1784  }
1785 
1786 
1787  M_Displayer->leaderPrint ( "Setting up LinearSolver... \n" );
1788 
1789  Teuchos::RCP< Teuchos::ParameterList > paramList = Teuchos::rcp ( new Teuchos::ParameterList );
1790  paramList = Teuchos::getParametersFromXmlFile ( xmlFileName );
1791 
1792 
1793  M_linearSolver->setParameters ( *paramList );
1794  M_linearSolver->setPreconditioner ( M_preconditioner );
1795  M_rescaleFactor = dataFile ( "solid/rescaleFactor", 0. );
1796 }
1797 
1798 
1799 //Method UpdateJacobian
1800 template <typename Mesh>
1801 void StructuralOperator<Mesh>::updateJacobian ( const vector_Type& sol, matrixPtr_Type& jacobian )
1802 {
1803  M_Displayer->leaderPrint (" S- Solid: Updating JACOBIAN... ");
1804 
1805  LifeChrono chrono;
1806  chrono.start();
1807 
1808  M_material->updateJacobianMatrix (sol, M_data, M_mapMarkersVolumes, M_mapMarkersIndexes, M_Displayer);
1809 
1810  jacobian.reset (new matrix_Type (*M_localMap) );
1811  *jacobian += * (M_material->jacobian() );
1812 
1813  //Spying the static part of the Jacobian to check if it is symmetric
1814  // M_material->jacobian()->spy("staticJacobianMatrix");
1815 
1816  // std::cout << "spyed" << std::endl;
1817  // int n;
1818  // std::cin >> n ;
1819 
1820  *jacobian += *M_massMatrix;
1821 
1822  jacobian->globalAssemble();
1823 
1824  chrono.stop();
1825  M_Displayer->leaderPrintMax (" ... done in ", chrono.diff() );
1826 
1827 }
1828 
1829 //Method UpdateJacobian
1830 template <typename Mesh>
1831 void StructuralOperator<Mesh>::updateJacobian ( const vector_Type& sol)
1832 {
1833  updateJacobian (sol, M_jacobian);
1834 }
1835 
1836 //solveJac( const Vector& res, Real& linear_rel_tol, Vector &step)
1837 template <typename Mesh>
1838 void StructuralOperator<Mesh>::
1839 solveJac ( vector_Type& step, const vector_Type& res, Real& linear_rel_tol)
1840 {
1841  updateJacobian ( *M_disp, M_jacobian );
1842  solveJacobian (step, res, linear_rel_tol, M_BCh);
1843 }
1844 
1845 
1846 //Method SolveJacobian
1847 template <typename Mesh>
1848 void StructuralOperator<Mesh>::
1849 solveJacobian (vector_Type& step,
1850  const vector_Type& res,
1851  Real& /*linear_rel_tol*/,
1852  bcHandler_Type& /* BCh*/)
1853 {
1854  LifeChrono chrono;
1855 
1856  //Creating pointers to vectors for linear solver
1857  vectorPtr_Type pointerToRes ( new vector_Type (res) );
1858  vectorPtr_Type pointerToStep ( new vector_Type (*M_localMap) );
1859 
1860  //Initializing the pointer
1861  *pointerToStep *= 0.0;
1862 
1863  matrixPtr_Type matrFull (new matrix_Type (*M_localMap) );
1864  *matrFull += *M_jacobian;
1865 
1866  M_Displayer->leaderPrint ("\tS'- Solving the linear system ... \n");
1867 
1868  M_Displayer->leaderPrint ("\tS'- Applying boundary conditions ... ");
1869 
1870 
1871  if ( !M_BCh->bcUpdateDone() )
1872  {
1873  M_BCh->bcUpdate ( *M_dispFESpace->mesh(), M_dispFESpace->feBd(), M_dispFESpace->dof() );
1874  }
1875  bcManageMatrix ( *matrFull, *M_dispFESpace->mesh(), M_dispFESpace->dof(), *M_BCh, M_dispFESpace->feBd(), 1.0 );
1876 
1877  M_Displayer->leaderPrintMax ( "done in ", chrono.diff() );
1878 
1879  M_Displayer->leaderPrint ("\tS'- Solving system ... \n");
1880  chrono.start();
1881 
1882  //Setting up the quantities
1883  M_linearSolver->setOperator ( matrFull );
1884  M_linearSolver->setRightHandSide ( pointerToRes );
1885 
1886  //Solving the system
1887  M_linearSolver->solve ( pointerToStep );
1888 
1889  step = *pointerToStep;
1890 
1891  chrono.stop();
1892 }
1893 
1894 template<typename Mesh>
1895 void StructuralOperator<Mesh>::apply ( const vector_Type& sol, vector_Type& res) const
1896 {
1897  M_material->apply (sol, res, M_mapMarkersVolumes, M_mapMarkersIndexes);
1898  res += (*M_massMatrix) * sol;
1899 }
1900 
1901 template<typename Mesh>
1902 void
1903 StructuralOperator<Mesh>::applyBoundaryConditions ( matrix_Type& matrix,
1904  vector_Type& rhs,
1905  bcHandler_Type& BCh,
1906  UInt offset)
1907 {
1908  // BC manage for the velocity
1909  if (offset)
1910  {
1911  BCh->setOffset (offset);
1912  }
1913  if ( !BCh->bcUpdateDone() )
1914  {
1915  BCh->bcUpdate ( *M_dispFESpace->mesh(), M_dispFESpace->feBd(), M_dispFESpace->dof() );
1916  }
1917 
1918  // vector_Type rhsFull(rhs, Repeated, Zero); // ignoring non-local entries, Otherwise they are summed up lately
1919  vector_Type rhsFull (rhs, Unique); // bcManages now manages the also repeated parts
1920 
1921  bcManage ( matrix, rhsFull, *M_dispFESpace->mesh(), M_dispFESpace->dof(), *BCh, M_dispFESpace->feBd(), 1., M_data->dataTime()->time() );
1922 
1923  // matrix should be GlobalAssembled by bcManage
1924 
1925  rhs = rhsFull;
1926 
1927 }
1928 
1929 
1930 
1931 }
1932 #endif
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
uint32_type ID
IDs.
Definition: LifeV.hpp:194
double Real
Generic real data.
Definition: LifeV.hpp:175
CurrentFE - A primordial class for the assembly of the local matrices/vectors retaining the values on...
Definition: CurrentFE.hpp:243
const UInt nDimensions(NDIM)
QuadratureRule - The basis class for storing and accessing quadrature rules.
DataElasticStructure - Data container for solid problems with elastic structure.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191