LifeV
OseenSolver.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 an Oseen equation solver class.
30 
31  @author Gilles Fourestey <gilles.fourestey@imag.fr>
32  Simone Deparis <simone.deparis@epfl.ch>
33  @contributor Zhen Wang <zhen.wang@emory.edu>
34 
35  @date 01-06-2007
36 
37  This file contains an Oseen equation solver class.
38  The resulting linear systems are solved by GMRES on the full
39  matrix ( u and p coupled ).
40 
41  */
42 
43 
44 #ifndef OSEENSOLVER_H
45 #define OSEENSOLVER_H 1
46 
47 #include <lifev/core/algorithm/SolverAztecOO.hpp>
48 #include <lifev/core/algorithm/Preconditioner.hpp>
49 #include <lifev/core/algorithm/PreconditionerIfpack.hpp>
50 #include <lifev/core/algorithm/PreconditionerAztecOO.hpp>
51 #include <lifev/core/array/MapEpetra.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/util/LifeChrono.hpp>
59 
60 #include <lifev/core/fem/Assembly.hpp>
61 #include <lifev/core/fem/BCManage.hpp>
62 #include <lifev/core/fem/AssemblyElemental.hpp>
63 #include <lifev/core/fem/SobolevNorms.hpp>
64 #include <lifev/core/fem/GeometricMap.hpp>
65 #include <lifev/core/fem/PostProcessingBoundary.hpp>
66 #include <lifev/core/fem/FESpace.hpp>
67 
68 #include <lifev/navier_stokes/solver/StabilizationIP.hpp>
69 #include <lifev/navier_stokes/solver/OseenData.hpp>
70 
71 #include <boost/shared_ptr.hpp>
72 
73 #include <list>
74 
75 namespace LifeV
76 {
77 //! @class Oseen
78 /*!
79  @brief This class contains an Oseen equation solver.
80 
81  @author Gilles Fourestey <gilles.fourestey@imag.fr>
82  Simone Deparis <simone.deparis@epfl.ch>
83  @contributor Zhen Wang <zhen.wang@emory.edu>
84 
85  */
86 
87 template< typename MeshType, typename SolverType = LifeV::SolverAztecOO >
88 class OseenSolver
89 {
90 
91 public:
92 
93  //! @name Public Types
94  //@{
95 
96  typedef MeshType mesh_Type;
97  typedef SolverType linearSolver_Type;
98  typedef std::shared_ptr<linearSolver_Type> linearSolverPtr_Type;
99  typedef OseenData data_Type;
100  typedef std::shared_ptr< data_Type > dataPtr_Type;
101 
102  typedef std::function < Real ( const Real& t, const Real& x, const Real& y,
103  const Real& z, const ID& i ) > function_Type;
104 
105  typedef std::function < Real ( const Real& t, const Real& x, const Real& y,
106  const Real& z, const ID& i ) > source_Type;
107 
108  typedef BCHandler bcHandler_Type;
109  typedef std::shared_ptr<bcHandler_Type> bcHandlerPtr_Type;
110 
111 #ifdef HAVE_NS_PREC
112  typedef MatrixEpetraStructured<Real> matrix_Type;
113 #else
114  typedef typename linearSolver_Type::matrix_type matrix_Type;
115 #endif
116  typedef std::shared_ptr<matrix_Type> matrixPtr_Type;
117  typedef typename linearSolver_Type::vector_type vector_Type;
118  typedef std::shared_ptr<vector_Type> vectorPtr_Type;
119 
120  typedef vector_Type solution_Type;
121  typedef std::shared_ptr<solution_Type> solutionPtr_Type;
122 
123  typedef typename linearSolver_Type::prec_raw_type preconditioner_Type;
124  typedef typename linearSolver_Type::prec_type preconditionerPtr_Type;
125 
126  //@}
127 
128  //! @name Constructors & Destructor
129  //@{
130 
131  //! Empty constructor
132  OseenSolver();
133 
134  //! Constructor
135  /*!
136  @param dataType OseenData class
137  @param velocityFESpace Velocity FE space
138  @param pressureFESpace Pressure FE space
139  @param communicator MPI communicator
140  @param lagrangeMultiplier Lagrange multiplier
141  */
142 
143  OseenSolver ( std::shared_ptr<data_Type> dataType,
144  FESpace<mesh_Type, MapEpetra>& velocityFESpace,
145  FESpace<mesh_Type, MapEpetra>& pressureFESpace,
146  std::shared_ptr<Epetra_Comm>& communicator,
147  const Int lagrangeMultiplier = 0 );
148 
149  //! Constructor
150  /*!
151  @param dataType OseenData class
152  @param velocityFESpace Velocity FE space
153  @param pressureFESpace Pressure FE space
154  @param communicator MPI communicator
155  @param monolithicMap MapEpetra class
156  @param offset
157  */
158  OseenSolver ( std::shared_ptr<data_Type> dataType,
159  FESpace<mesh_Type, MapEpetra>& velocityFESpace,
160  FESpace<mesh_Type, MapEpetra>& pressureFESpace,
161  std::shared_ptr<Epetra_Comm>& communicator,
162  const MapEpetra monolithicMap,
163  const UInt offset = 0 );
164 
165  //! Constructor
166  /*!
167  @param dataType OseenData class
168  @param velocityFESpace Velocity FE space
169  @param pressureFESpace Pressure FE space
170  @param lagrangeMultipliers (lagrange multipliers for the flux problem with rufaec flag)
171  @param communicator MPI communicator
172  */
173  OseenSolver ( std::shared_ptr<data_Type> dataType,
174  FESpace<mesh_Type, MapEpetra>& velocityFESpace,
175  FESpace<mesh_Type, MapEpetra>& pressureFESpace,
176  const std::vector<Int>& lagrangeMultipliers,
177  std::shared_ptr<Epetra_Comm>& communicator );
178 
179  //! virtual destructor
180  virtual ~OseenSolver();
181 
182  //@}
183 
184  //! @name Methods
185  //@{
186 
187  //! Set up data from GetPot
188  /*!
189  @param dataFile GetPot object
190  */
191  virtual void setUp ( const GetPot& dataFile );
192 
193  //! Initialize with velocityFunction and pressureFunction
194  /*!
195  @param velocityFunction
196  @param pressureFunction
197  */
198  void initialize ( const function_Type& velocityFunction, const function_Type& pressureFunction );
199 
200  //! Initialize with velocityInitialGuess and pressureInitialGuess
201  /*!
202  @param velocityInitialGuess
203  @param pressureInitialGuess
204  */
205  void initialize ( const vector_Type& velocityInitialGuess, const vector_Type& pressureInitialGuess );
206 
207  //! Initialize with velocityAndPressure
208  /*!
209  @param velocityAndPressure
210  */
211  void initialize ( const vector_Type& velocityAndPressure );
212 
213  //! Build linear system.
214  virtual void buildSystem();
215 
216  //! Update system
217  /*!
218  @param alpha
219  @param betaVector
220  @param sourceVector
221  */
222  virtual void updateSystem ( const Real alpha,
223  const vector_Type& betaVector,
224  const vector_Type& sourceVector );
225 
226  //! Update system
227  /*!
228  @param alpha
229  @param betaVector
230  @param sourceVector
231  @param matrix
232  @param un
233  */
234  virtual void updateSystem ( const Real alpha,
235  const vector_Type& betaVector,
236  const vector_Type& sourceVector,
237  matrixPtr_Type matrix,
238  const vector_Type& un );
239 
240  //! Update stabilization term
241  /*!
242  @param matrixFull
243  */
244  void updateStabilization ( matrix_Type& matrixFull );
245 
246  //! Update the right hand side
247  /*!
248  @param rightHandSide right hand side
249  */
250  virtual void updateRightHandSide ( const vector_Type& rightHandSide )
251  {
252  M_rightHandSideNoBC.reset (new vector_Type (rightHandSide) );
253  M_rightHandSideNoBC->globalAssemble();
254  }
255 
256  //! Update the source term
257  /*!
258  @param sourceTerm
259  */
260  void updateSourceTerm (const source_Type& source );
261 
262  //! Update convective term, boundary condition and solve the linearized ns system
263  /*!
264  @param bcHandler BC handler
265  */
266  virtual void iterate ( bcHandler_Type& bcHandler );
267 
268  //! Reduce the local solution in global vectors
269  /*!
270  @param velocity
271  @param pressure
272  */
273  void reduceSolution ( Vector& velocity, Vector& pressure );
274 
275  //! Reduce the residual
276  /*!
277  @param residual
278  */
279  void reduceResidual ( Vector& residual );
280 
281  //! Set a block preconditioner
282  /*!
283  @blockPrecconditioner Block preconditioner
284  */
285  void setBlockPreconditioner ( matrixPtr_Type blockPreconditioner );
286 
287  //! Update and return the coefficient matrix
288  /*!
289  @param matrixFull The coefficient matrix
290  */
291  void getFluidMatrix ( matrix_Type& matrixFull );
292 
293  //! Set up post processing
294  void setupPostProc( );
295 
296  //! Compute area on a boundary face with given flag
297  /*!
298  @param flag
299  @return area
300  */
301  Real area ( const markerID_Type& flag );
302 
303  //! Compute the outgoing normal of a boundary face with given flag
304  /*!
305  @param flag
306  @return boundary normal
307  */
308  Vector normal ( const markerID_Type& flag );
309 
310  //! Compute the geometric center of a boundary face with given flag
311  /*!
312  @param flag
313  @return geometric center
314  */
315  Vector geometricCenter ( const markerID_Type& flag );
316 
317  //! Compute flux on a boundary face with given flag and a given solution
318  /*!
319  @param flag
320  @param solution
321  @return flux
322  */
323  Real flux ( const markerID_Type& flag, const vector_Type& solution );
324 
325  //! Compute flux on a boundary face with given flag
326  /*!
327  @param flag
328  @return flux
329  */
330  Real flux ( const markerID_Type& flag );
331 
332  //! Compute the kinetic normal stress (i.e., the normal stress due to the kinetic energy) on a boundary face with a given flag and a given solution
333  /*!
334  * @see \cite BlancoMalossi2012 \cite Malossi-Thesis
335  *
336  * This method computes the following quantity:
337  *
338  * \f[
339  * \mathcal{K} = \frac{1}{2}\rho_\textrm{F}\frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}\left({\mathbf{u}}_\textrm{F} \mathbf{\cdot} {\mathbf{n}}_\textrm{F}\right)^2 \textrm{d} \Gamma
340  * \f]
341  *
342  * @param flag boundary flag
343  * @param solution problem solution
344  * @return kinetic normal stress
345  */
346  Real kineticNormalStress ( const markerID_Type& flag, const vector_Type& solution );
347 
348  //! Compute the kinetic normal stress (i.e., the normal stress due to the kinetic energy) on a boundary face with a given flag
349  /*!
350  * @see \cite BlancoMalossi2012 \cite Malossi-Thesis
351  *
352  * This method computes the following quantity:
353  *
354  * \f[
355  * \mathcal{K} = \frac{1}{2}\rho_\textrm{F}\frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}\left({\mathbf{u}}_\textrm{F} \mathbf{\cdot} {\mathbf{n}}_\textrm{F}\right)^2 \textrm{d} \Gamma
356  * \f]
357  *
358  * @param flag boundary flag
359  * @return kinetic normal stress
360  */
361  Real kineticNormalStress ( const markerID_Type& flag );
362 
363  //! Compute average pressure on a boundary face with given flag and a given solution
364  /*!
365  @param flag
366  @param solution
367  @return average pressure
368  */
369  Real pressure ( const markerID_Type& flag, const vector_Type& solution );
370 
371  //! Compute average pressure on a boundary face with given flag
372  /*!
373  @param flag
374  @return average pressure
375  */
376  Real pressure ( const markerID_Type& flag );
377 
378  //! Compute the mean normal stress on a boundary face with a given flag and a given solution
379  /*!
380  * @see \cite BlancoMalossi2012 \cite Malossi-Thesis
381  *
382  * The mean normal stress is defined as the average of the normal component of the traction vector.
383  *
384  * \f[
385  * \mathcal{S}^{3-D}_j = \frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}
386  * \left(\sigma_\textrm{F} \mathbf{\cdot} \mathbf{n}_\textrm{F}\right) \mathbf{\cdot} \mathbf{n}_\textrm{F} \: \textrm{d} \Gamma
387  * \f]
388  *
389  * @param flag Flag of the boundary face
390  * @param bcHandler BChandler containing the boundary conditions of the problem.
391  * @param solution Vector containing the solution of the problem
392  * (and also the Lagrange multipliers at the end).
393  * @return mean normal stress
394  */
395  Real meanNormalStress ( const markerID_Type& flag, bcHandler_Type& bcHandler, const vector_Type& solution );
396 
397  //! Compute the mean normal stress on a boundary face with a given flag
398  /*!
399  * @see \cite BlancoMalossi2012 \cite Malossi-Thesis
400  *
401  * The mean normal stress is defined as the average of the normal component of the traction vector.
402  *
403  * \f[
404  * \mathcal{S}^{3-D}_j = \frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}
405  * \left(\sigma_\textrm{F} \mathbf{\cdot} \mathbf{n}_\textrm{F}\right) \mathbf{\cdot} \mathbf{n}_\textrm{F} \: \textrm{d} \Gamma
406  * \f]
407  *
408  * TODO The current version returns the exact mean normal stress if a flow rate boundary condition is imposed on the chosen boundary face.
409  * On the contrary, if other boundary conditions are applied, the mean normal stress is approximated with the mean pressure, which is a
410  * reasonable approximation for several applications.
411  *
412  * @param flag Flag of the boundary face
413  * @param bcHandler BChandler containing the boundary conditions of the problem.
414  * @return mean normal stress
415  */
416  Real meanNormalStress ( const markerID_Type& flag, bcHandler_Type& bcHandler );
417 
418  //! Compute the mean total normal stress on a boundary face with a given flag and a given solution
419  /*!
420  * @see \cite BlancoMalossi2012 \cite Malossi-Thesis
421  *
422  * The mean total normal stress is defined as the average of the normal component of the traction vector minus the kinetic contribution.
423  *
424  * \f[
425  * \mathcal{T}^{3-D}_j = \frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}
426  * \left(\sigma_\textrm{F} \mathbf{\cdot} \mathbf{n}_\textrm{F}\right) \mathbf{\cdot} \mathbf{n}_\textrm{F} \: \textrm{d} \Gamma
427  * - \frac{1}{2}\rho_\textrm{F}\frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}\left(\mathbf{u}_\textrm{F} \mathbf{\cdot} \mathbf{n}_\textrm{F}\right)^2 \: \textrm{d} \Gamma
428  * \f]
429  *
430  * TODO The current version returns the exact mean normal stress if a flow rate boundary condition is imposed on the chosen boundary face.
431  * On the contrary, if other boundary conditions are applied, the mean normal stress is approximated with the mean pressure, which is a
432  * reasonable approximation for several applications.
433  *
434  * @param flag Flag of the boundary face
435  * @param bcHandler BChandler containing the boundary conditions of the problem.
436  * @param solution Vector containing the solution of the problem
437  * (and also the Lagrange multipliers at the end).
438  * @return mean total normal stress
439  */
440  Real meanTotalNormalStress ( const markerID_Type& flag, bcHandler_Type& bcHandler, const vector_Type& solution );
441 
442  //! Compute the mean total normal stress on a boundary face with a given flag
443  /*!
444  * @see \cite BlancoMalossi2012 \cite Malossi-Thesis
445  *
446  * The mean total normal stress is defined as the average of the normal component of the traction vector minus the kinetic contribution.
447  *
448  * \f[
449  * \mathcal{T}^{3-D}_j = \frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}
450  * \left(\sigma_\textrm{F} \mathbf{\cdot} \mathbf{n}_\textrm{F}\right) \mathbf{\cdot} \mathbf{n}_\textrm{F} \: \textrm{d} \Gamma
451  * - \frac{1}{2}\rho_\textrm{F}\frac{1}{\left|\Gamma^t_{\textrm{F},j}\right|}\displaystyle\int_{\Gamma^t_{\textrm{F},j}}\left(\mathbf{u}_\textrm{F} \mathbf{\cdot} \mathbf{n}_\textrm{F}\right)^2 \: \textrm{d} \Gamma
452  * \f]
453  *
454  * @param flag Flag of the boundary face
455  * @param bcHandler BChandler containing the boundary conditions of the problem.
456  * @return mean total normal stress
457  */
458  Real meanTotalNormalStress ( const markerID_Type& flag, bcHandler_Type& bcHandler );
459 
460  //! Get the Lagrange multiplier related to a flux imposed on a given part of the boundary
461  /*!
462  @param flag Flag of the boundary face associated with the flux
463  and the Lagrange multiplier we want.
464  @param bcHandler BChandler containing the boundary conditions of the problem.
465  @return Lagrange multiplier
466  */
467  Real lagrangeMultiplier ( const markerID_Type& flag, bcHandler_Type& bcHandler );
468 
469  //! Get the Lagrange multiplier related to a flux imposed on a given part of the boundary
470  /*!
471  @param flag Flag of the boundary face associated
472  with the flux and the Lagrange multiplier we want.
473  @param bcHandler BChandler containing the boundary conditions of the problem.
474  @param solution Vector containing the solution of the problem
475  (and also the Lagrange multipliers at the end).
476  @return Lagrange multiplier
477  */
478  Real lagrangeMultiplier ( const markerID_Type& flag,
479  bcHandler_Type& bcHandler,
480  const vector_Type& solution );
481 
482  //! Reset the preconditioner.
483  /*!
484  @param reset Reset preconditioner.
485  */
486  void resetPreconditioner ( bool reset = true )
487  {
488  if ( reset )
489  {
490  M_linearSolver->resetPreconditioner();
491  }
492  }
493 
494  //! Reset stabilization matrix at the same time as the preconditioner
495  void resetStabilization()
496  {
497  M_resetStabilization = true;
498  }
499 
500  //! Update
501  void updateUn()
502  {
503  *M_un = *M_solution;
504  }
505 
506  //! Update for the monolithic
507  void updateUn ( const vector_Type& solution )
508  {
509  *M_un = solution;
510  }
511 
512  //! Display general information about the content of the class
513  /*!
514  @param output specify the output format (std::cout by default)
515  */
516  void showMe ( std::ostream& output = std::cout ) const;
517 
518  //@}
519 
520  //! @name Set Methods
521  //@{
522 
523  //! Set
524  /*!
525  @param recomputeMatrix
526  */
527  void setRecomputeMatrix ( const bool& recomputeMatrix )
528  {
529  M_recomputeMatrix = recomputeMatrix;
530  }
531 
532  //! set the source term functor
533  /*!
534  @param source
535  */
536  void setSourceTerm ( source_Type source )
537  {
538  M_source = source;
539  }
540 
541  //! Set the tolerance and the maximum number of iterations of the linear solver
542  /*!
543  @param tolerance Tolerance
544  @param maxIteration maximum number of iterations
545  */
546  void setTolMaxIteration ( const Real& tolerance, const Int& maxIteration = -1 );
547 
548  //@}
549 
550  //! @name Get Methods
551  //@{
552 
553  //! Return the data container of the fluid
554  /*!
555  @return data container of the fluid
556  */
557  const dataPtr_Type& data() const
558  {
559  return M_oseenData;
560  }
561 
562  //! Return the density of the fluid
563  /*!
564  @return Density of the fluid
565  */
566  const Real& density() const
567  {
568  return M_oseenData->density();
569  }
570 
571  //! Return the viscosity of the fluid
572  /*!
573  @return Viscosity of the fluid
574  */
575  const Real& viscosity() const
576  {
577  return M_oseenData->viscosity();
578  }
579 
580  //! Return the local solution vector
581  /*!
582  @return vectorPtr_Type Solution vector
583  */
584  const vectorPtr_Type& solution() const
585  {
586  return M_solution;
587  }
588 
589  //! Return the local residual vector
590  /*!
591  @return Residual vector
592  */
593  const vector_Type& residual() const
594  {
595  return *M_residual;
596  }
597 
598  //! Return velocity FE space
599  /*!
600  @return velocity FE space
601  */
602  FESpace<mesh_Type, MapEpetra>& velocityFESpace()
603  {
604  return M_velocityFESpace;
605  }
606 
607  const FESpace<mesh_Type, MapEpetra>& velocityFESpace() const
608  {
609  return M_velocityFESpace;
610  }
611 
612  //! Return pressure FE space
613  /*!
614  @return pressure FE space
615  */
616  FESpace<mesh_Type, MapEpetra>& pressureFESpace()
617  {
618  return M_pressureFESpace;
619  }
620 
621  const FESpace<mesh_Type, MapEpetra>& pressureFESpace() const
622  {
623  return M_pressureFESpace;
624  }
625 
626  //! Get the source term
627  /*!
628  @return Source term
629  */
630  const source_Type& sourceTerm() const
631  {
632  return M_source;
633  }
634 
635  //! Returns the post processing structure
636  /*!
637  @return Post processing
638  */
639  PostProcessingBoundary<mesh_Type>& postProcessing()
640  {
641  return *M_postProcessing;
642  }
643 
644  const PostProcessingBoundary<mesh_Type>& postProcessing() const
645  {
646  return *M_postProcessing;
647  }
648 
649  //! Return MapEpetra.
650  /*!
651  @return MapEpetra
652  */
653  const MapEpetra& getMap() const
654  {
655  return M_localMap;
656  }
657 
658  //! Return Epetra communicator
659  /*!
660  @return Epetra communicator
661  */
662  const std::shared_ptr<Epetra_Comm>& comm() const
663  {
664  return M_Displayer.comm();
665  }
666 
667  //! Return displayer
668  /*!
669  @return
670  */
671  const Displayer& getDisplayer() const
672  {
673  return M_Displayer;
674  }
675 
676  //! Return
677  /*!
678  @return recomputeMatrix
679  */
680  const bool& recomputeMatrix() const
681  {
682  return M_recomputeMatrix;
683  }
684 
685  //! Return matrix without boundary conditions
686  /*!
687  @return Matrix without boundary conditions
688  */
689  matrix_Type& matrixNoBC()
690  {
691  return *M_matrixNoBC;
692  }
693 
694  const matrix_Type& matrixNoBC() const
695  {
696  return *M_matrixNoBC;
697  }
698 
699  //! Return mass matrix
700  /*!
701  @return Mass matrix
702  */
703  matrix_Type& matrixMass()
704  {
705  return *M_velocityMatrixMass;
706  }
707 
708  const matrix_Type& matrixMass() const
709  {
710  return *M_velocityMatrixMass;
711  }
712 
713  const matrixPtr_Type matrixMassPtr() const
714  {
715  return M_velocityMatrixMass;
716  }
717 
718  //@}
719 
720  //@{ unused methods
721 
722  //! Set up post processing structures
723  void postProcessingSetArea();
724 
725  //! Set up post processing
726  void postProcessingSetNormal();
727 
728  //! Set up post processing
729  void postProcessingSetPhi();
730 
731  //! Return a bool value if using diagonal block preconditioner
732  bool getIsDiagonalBlockPreconditioner()
733  {
734  return M_isDiagonalBlockPreconditioner;
735  }
736 
737  const bool& getIsDiagonalBlockPreconditioner() const
738  {
739  return M_isDiagonalBlockPreconditioner;
740  }
741 
742  //@}
743 
744  //! Return a shared pointer to the preconditioner (of type derived from EpetraPreconditioner)
745  preconditionerPtr_Type& preconditioner()
746  {
747  return M_linearSolver.preconditioner();
748  }
749 
750 protected:
751 
752  //! @name Constructor
753  //@{
754 
755  //! Empty copy constructor
756  OseenSolver ( const OseenSolver& oseen);
757 
758  //@}
759 
760  //! @name Private Methods
761  //@{
762 
763  //! Removes mean of component of vector x
764  /*!
765  @param x
766  @return
767  */
768  Real removeMean ( vector_Type& x );
769 
770  //! Apply boundary conditions.
771  /*!
772  @param matrix
773  @param rightHandSide
774  @param bcHandler
775  */
776  void applyBoundaryConditions ( matrix_Type& matrix,
777  vector_Type& rightHandSide,
778  bcHandler_Type& bcHandler );
779 
780  //! Echo message.
781  /*!
782  @param message
783  */
784  void echo ( std::string message );
785 
786  //! Return the dim of velocity FE space
787  const UInt& dimVelocity() const
788  {
789  return M_velocityFESpace.dim();
790  }
791 
792  //! Return the dim of pressure FE space
793  const UInt& dimPressure() const
794  {
795  return M_pressureFESpace.dim();
796  }
797 
798  //@}
799 
800  //private members
801 
802  //! data for Navier-Stokes solvers
803  dataPtr_Type M_oseenData;
804 
805  // FE spaces
806  FESpace<mesh_Type, MapEpetra>& M_velocityFESpace;
807  FESpace<mesh_Type, MapEpetra>& M_pressureFESpace;
808 
809  //! MPI communicator
810  Displayer M_Displayer;
811 
812  MapEpetra M_localMap;
813 
814  //! mass matrix
815  matrixPtr_Type M_velocityMatrixMass;
816 
817  //! mass matrix
818  matrixPtr_Type M_pressureMatrixMass;
819 
820  //! Stokes matrix: nu*stiff
821  matrixPtr_Type M_matrixStokes;
822 
823  //! matrix to be solved
824  // matrixPtr_Type M_matrixFull;
825 
826  //! matrix without boundary conditions
827  matrixPtr_Type M_matrixNoBC;
828 
829  //! stabilization matrix
830  matrixPtr_Type M_matrixStabilization;
831 
832  //! source term for Navier-Stokes equations
833  source_Type M_source;
834 
835  //! Right hand side for the velocity component
836  vectorPtr_Type M_rightHandSideNoBC;
837 
838  //! Global solution
839  vectorPtr_Type M_solution;
840 
841  //! residual
842  vectorPtr_Type M_residual;
843 
844  linearSolverPtr_Type M_linearSolver;
845 
846  bool M_steady;
847 
848  //! Postprocessing class
849  std::shared_ptr<PostProcessingBoundary<mesh_Type> > M_postProcessing;
850 
851  //! Stabilization
852  bool M_stabilization;
853  bool M_reuseStabilization;
854  bool M_resetStabilization;
855  Int M_iterReuseStabilization;
856 
857  details::StabilizationIP<mesh_Type, DOF> M_ipStabilization;
858  Real M_gammaBeta;
859  Real M_gammaDiv;
860  Real M_gammaPress;
861 
862  const function_Type* M_betaFunction;
863 
864  bool M_divBetaUv;
865 
866  bool M_stiffStrain;
867 
868  //
869  Real M_diagonalize;
870 
871  UInt M_count;
872 
873  bool M_recomputeMatrix;
874 
875  bool M_isDiagonalBlockPreconditioner;
876 
877  //! Elementary matrices and vectors
878  MatrixElemental M_elementMatrixStiff; // velocity Stokes
879  MatrixElemental M_elementMatrixMass; // velocity mass
880  MatrixElemental M_elementMatrixPreconditioner; // (p,q) bloc for preconditioners
881  MatrixElemental M_elementMatrixDivergence;
882  MatrixElemental M_elementMatrixGradient;
883  VectorElemental M_elementRightHandSide; // Elementary right hand side
884  matrixPtr_Type M_blockPreconditioner;
887  std::shared_ptr<vector_Type> M_un;
888 
889 }; // class OseenSolver
890 
891 
892 
893 // ===================================================
894 // Constructors & Destructor
895 // ===================================================
896 
897 template<typename MeshType, typename SolverType>
898 OseenSolver<MeshType, SolverType>::
899 OseenSolver ( std::shared_ptr<data_Type> dataType,
900  FESpace<mesh_Type, MapEpetra>& velocityFESpace,
901  FESpace<mesh_Type, MapEpetra>& pressureFESpace,
902  std::shared_ptr<Epetra_Comm>& communicator,
903  const Int lagrangeMultiplier ) :
904  M_oseenData ( dataType ),
905  M_velocityFESpace ( velocityFESpace ),
906  M_pressureFESpace ( pressureFESpace ),
907  M_Displayer ( communicator ),
908  M_localMap ( M_velocityFESpace.map() + M_pressureFESpace.map() + lagrangeMultiplier),
909  M_velocityMatrixMass ( ),
910  M_pressureMatrixMass ( ),
911  M_matrixStokes ( ),
912  M_matrixNoBC ( ),
913  M_matrixStabilization ( ),
914  M_rightHandSideNoBC ( ),
915  M_solution ( new vector_Type ( M_localMap ) ),
916  M_residual ( new vector_Type (M_localMap ) ),
917  M_linearSolver ( new linearSolver_Type (communicator) ),
918  M_steady ( ),
919  M_postProcessing ( new PostProcessingBoundary<mesh_Type> ( M_velocityFESpace.mesh(),
920  &M_velocityFESpace.feBd(),
921  &M_velocityFESpace.dof(),
922  &M_pressureFESpace.feBd(),
923  &M_pressureFESpace.dof(),
924  M_localMap ) ),
925  M_stabilization ( false ),
926  M_reuseStabilization ( false ),
927  M_resetStabilization ( false ),
928  M_iterReuseStabilization ( -1 ),
929  // M_ipStabilization ( M_velocityFESpace.mesh(),
930  // M_velocityFESpace.dof(),
931  // M_velocityFESpace.refFE(),
932  // M_velocityFESpace.feBd(),
933  // M_velocityFESpace.qr(),
934  // 0., 0., 0.,
935  // M_oseenData->viscosity() ),
936  M_betaFunction ( 0 ),
937  M_divBetaUv ( false ),
938  M_stiffStrain ( false ),
939  M_diagonalize ( false ),
940  M_count ( 0 ),
941  M_recomputeMatrix ( false ),
942  M_elementMatrixStiff ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim(), velocityFESpace.fieldDim() ),
943  M_elementMatrixMass ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim(), velocityFESpace.fieldDim() ),
944  M_elementMatrixPreconditioner ( M_pressureFESpace.fe().nbFEDof(), 1, 1 ),
945  M_elementMatrixDivergence ( M_pressureFESpace.fe().nbFEDof(), 1, 0,
946  M_velocityFESpace.fe().nbFEDof(), 0, velocityFESpace.fieldDim() ),
947  M_elementMatrixGradient ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim(), 0,
948  M_pressureFESpace.fe().nbFEDof(), 0, 1 ),
949  M_elementRightHandSide ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim() ),
950  M_blockPreconditioner ( ),
951  M_wLoc ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim() ),
952  M_uLoc ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim() ),
953  M_un ( new vector_Type (M_localMap) )
954 {
955  // if(M_stabilization = ( &M_velocityFESpace.refFE() == &M_pressureFESpace.refFE() ))
956  {
957  M_ipStabilization.setFeSpaceVelocity (M_velocityFESpace);
958  M_ipStabilization.setViscosity (M_oseenData->viscosity() );
959  }
960 }
961 
962 template<typename MeshType, typename SolverType>
963 OseenSolver<MeshType, SolverType>::
964 OseenSolver ( std::shared_ptr<data_Type> dataType,
965  FESpace<mesh_Type, MapEpetra>& velocityFESpace,
966  FESpace<mesh_Type, MapEpetra>& pressureFESpace,
967  std::shared_ptr<Epetra_Comm>& communicator,
968  MapEpetra monolithicMap,
969  UInt /*offset*/ ) :
970  M_oseenData ( dataType ),
971  M_velocityFESpace ( velocityFESpace ),
972  M_pressureFESpace ( pressureFESpace ),
973  M_Displayer ( communicator ),
974  M_localMap ( monolithicMap ),
975  M_velocityMatrixMass ( ),
976  M_matrixStokes ( ),
977  M_matrixNoBC ( ),
978  M_matrixStabilization ( ),
979  M_rightHandSideNoBC ( ),
980  M_solution ( ),
981  M_residual ( ),
982  M_linearSolver ( ),
983  M_postProcessing ( new PostProcessingBoundary<mesh_Type> (M_velocityFESpace.mesh(),
984  &M_velocityFESpace.feBd(),
985  &M_velocityFESpace.dof(),
986  &M_pressureFESpace.feBd(),
987  &M_pressureFESpace.dof(),
988  M_localMap ) ),
989  M_stabilization ( false ),
990  M_reuseStabilization ( false ),
991  M_resetStabilization ( false ),
992  M_iterReuseStabilization ( -1 ),
993  M_betaFunction ( 0 ),
994  M_divBetaUv ( false ),
995  M_stiffStrain ( false ),
996  M_diagonalize ( false ),
997  M_count ( 0 ),
998  M_recomputeMatrix ( false ),
999  M_elementMatrixStiff ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim(), M_velocityFESpace.fieldDim() ),
1000  M_elementMatrixMass ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim(), M_velocityFESpace.fieldDim() ),
1001  M_elementMatrixPreconditioner ( M_pressureFESpace.fe().nbFEDof(), 1, 1 ),
1002  M_elementMatrixDivergence ( M_pressureFESpace.fe().nbFEDof(), 1, 0,
1003  M_velocityFESpace.fe().nbFEDof(), 0, M_velocityFESpace.fieldDim() ),
1004  M_elementMatrixGradient ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim(), 0,
1005  M_pressureFESpace.fe().nbFEDof(), 0, 1 ),
1006  M_elementRightHandSide ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim() ),
1007  M_blockPreconditioner ( ),
1008  M_wLoc ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim() ),
1009  M_uLoc ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim() ),
1010  M_un ( /*new vector_Type(M_localMap)*/ )
1011 {
1012  // if(M_stabilization = ( &M_velocityFESpace.refFE() == &M_pressureFESpace.refFE() ))
1013  {
1014  M_ipStabilization.setFeSpaceVelocity (M_velocityFESpace);
1015  M_ipStabilization.setViscosity (M_oseenData->viscosity() );
1016  }
1017 }
1018 
1019 template<typename MeshType, typename SolverType>
1020 OseenSolver<MeshType, SolverType>::
1021 OseenSolver ( std::shared_ptr<data_Type> dataType,
1022  FESpace<mesh_Type, MapEpetra>& velocityFESpace,
1023  FESpace<mesh_Type, MapEpetra>& pressureFESpace,
1024  const std::vector<Int>& lagrangeMultipliers,
1025  std::shared_ptr<Epetra_Comm>& communicator ) :
1026  M_oseenData ( dataType ),
1027  M_velocityFESpace ( velocityFESpace ),
1028  M_pressureFESpace ( pressureFESpace ),
1029  M_Displayer ( communicator ),
1030  M_localMap ( M_velocityFESpace.map() + M_pressureFESpace.map() + lagrangeMultipliers ),
1031  M_velocityMatrixMass ( ),
1032  M_matrixStokes ( ),
1033  M_matrixNoBC ( ),
1034  M_matrixStabilization ( ),
1035  M_rightHandSideNoBC ( ),
1036  M_solution ( new vector_Type ( M_localMap ) ),
1037  M_residual ( ),
1038  M_linearSolver ( new linearSolver_Type (communicator) ),
1039  M_postProcessing ( new PostProcessingBoundary<mesh_Type> (M_velocityFESpace.mesh(),
1040  &M_velocityFESpace.feBd(),
1041  &M_velocityFESpace.dof(),
1042  &M_pressureFESpace.feBd(),
1043  &M_pressureFESpace.dof(),
1044  M_localMap ) ),
1045  M_stabilization ( false ),
1046  M_reuseStabilization ( false ),
1047  M_resetStabilization ( false ),
1048  M_iterReuseStabilization ( -1 ),
1049  M_betaFunction ( 0 ),
1050  M_divBetaUv ( false ),
1051  M_stiffStrain ( false ),
1052  M_diagonalize ( false ),
1053  M_count ( 0 ),
1054  M_recomputeMatrix ( false ),
1055  M_elementMatrixStiff ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim(), M_velocityFESpace.fieldDim() ),
1056  M_elementMatrixMass ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim(), M_velocityFESpace.fieldDim() ),
1057  M_elementMatrixPreconditioner ( M_pressureFESpace.fe().nbFEDof(), 1, 1 ),
1058  M_elementMatrixDivergence ( M_pressureFESpace.fe().nbFEDof(), 1, 0,
1059  M_velocityFESpace.fe().nbFEDof(), 0, M_velocityFESpace.fieldDim() ),
1060  M_elementMatrixGradient ( M_velocityFESpace.fe().nbFEDof(), M_velocityFESpace.fieldDim(), 0,
1061  M_pressureFESpace.fe().nbFEDof(), 0, 1 ),
1062  M_elementRightHandSide ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim() ),
1063  M_blockPreconditioner ( ),
1064  M_wLoc ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim() ),
1065  M_uLoc ( M_velocityFESpace.fe().nbFEDof(), velocityFESpace.fieldDim() ),
1066  M_un ( new vector_Type (M_localMap) )
1067 {
1068  // if(M_stabilization = ( &M_velocityFESpace.refFE() == &M_pressureFESpace.refFE() ))
1069  {
1070  M_ipStabilization.setFeSpaceVelocity (M_velocityFESpace);
1071  M_ipStabilization.setViscosity (M_oseenData->viscosity() );
1072  }
1073 }
1074 
1075 template<typename MeshType, typename SolverType>
1076 OseenSolver<MeshType, SolverType>::
1077 ~OseenSolver()
1078 {
1079 
1080 }
1081 
1082 
1083 // ===================================================
1084 // Methods
1085 // ===================================================
1086 
1087 template<typename MeshType, typename SolverType>
1088 void
1089 OseenSolver<MeshType, SolverType>::setUp ( const GetPot& dataFile )
1090 {
1091  if (M_linearSolver.get() )
1092  {
1093  M_linearSolver->setupPreconditioner ( dataFile, "fluid/prec" );
1094  M_linearSolver->setDataFromGetPot ( dataFile, "fluid/solver" );
1095  }
1096 
1097  M_stabilization = dataFile ( "fluid/ipstab/use", (&M_velocityFESpace.refFE() == &M_pressureFESpace.refFE() ) );
1098  M_steady = dataFile ( "fluid/miscellaneous/steady", 0 );
1099  if (M_stabilization)
1100  {
1101  M_gammaBeta = dataFile ( "fluid/ipstab/gammaBeta", 0. );
1102  M_gammaDiv = dataFile ( "fluid/ipstab/gammaDiv", 0. );
1103  M_gammaPress = dataFile ( "fluid/ipstab/gammaPress", 0. );
1104  M_reuseStabilization = dataFile ( "fluid/ipstab/reuse", false );
1105  if (M_linearSolver.get() )
1106  M_iterReuseStabilization = dataFile ( "fluid/ipstab/max_iter_reuse",
1107  static_cast<Int> ( M_linearSolver->maxNumIterations() * 8. / 10. ) );
1108  }
1109  // Energetic stabilization term
1110  M_divBetaUv = dataFile ( "fluid/space_discretization/div_beta_u_v", false);
1111  // Enable grad( u )^T in stress tensor
1112  M_stiffStrain = dataFile ( "fluid/space_discretization/stiff_strain", false);
1113  M_diagonalize = dataFile ( "fluid/space_discretization/diagonalize", 1. );
1114  M_isDiagonalBlockPreconditioner = dataFile ( "fluid/diagonalBlockPrec", false );
1115 
1116  // M_linearSolver.setAztecooPreconditioner( dataFile, "fluid/solver" );
1117 
1118  M_ipStabilization.setGammaBeta ( M_gammaBeta );
1119  M_ipStabilization.setGammaDiv ( M_gammaDiv );
1120  M_ipStabilization.setGammaPress ( M_gammaPress );
1121 }
1122 
1123 
1124 template<typename MeshType, typename SolverType>
1125 void
1126 OseenSolver<MeshType, SolverType>::
1127 initialize ( const function_Type& velocityFunction, const function_Type& pressureFunction )
1128 {
1129  vector_Type velocityInitialGuess ( M_velocityFESpace.map() );
1130  M_velocityFESpace.interpolate ( velocityFunction,
1131  velocityInitialGuess,
1132  M_oseenData->dataTime()->time() );
1133 
1134  vector_Type pressureInitialGuess ( M_pressureFESpace.map() );
1135  M_pressureFESpace.interpolate ( pressureFunction,
1136  pressureInitialGuess,
1137  M_oseenData->dataTime()->time() );
1138 
1139  initialize ( velocityInitialGuess, pressureInitialGuess );
1140 }
1141 
1142 
1143 template<typename MeshType, typename SolverType>
1144 void
1145 OseenSolver<MeshType, SolverType>::
1146 initialize ( const vector_Type& velocityInitialGuess, const vector_Type& pressureInitialGuess )
1147 {
1148 
1149  *M_solution = velocityInitialGuess;
1150  *M_un = velocityInitialGuess;
1151  M_solution->add ( pressureInitialGuess, M_velocityFESpace.fieldDim() * M_velocityFESpace.dof().numTotalDof() );
1152  M_un->add ( pressureInitialGuess, M_velocityFESpace.fieldDim() * M_velocityFESpace.dof().numTotalDof() );
1153 
1154 }
1155 
1156 template<typename MeshType, typename SolverType>
1157 void
1158 OseenSolver<MeshType, SolverType>::
1159 initialize ( const vector_Type& velocityAndPressure )
1160 {
1161 
1162  *M_un = velocityAndPressure;
1163  if ( M_solution.get() )
1164  {
1165  *M_solution = velocityAndPressure;
1166  }
1167 
1168 }
1169 
1170 template<typename MeshType, typename SolverType>
1171 void
1172 OseenSolver<MeshType, SolverType>::buildSystem()
1173 {
1174  M_velocityMatrixMass.reset ( new matrix_Type ( M_localMap ) );
1175  M_matrixStokes.reset ( new matrix_Type ( M_localMap ) );
1176 
1177  M_Displayer.leaderPrint ( " F- Computing constant matrices ... " );
1178 
1179  LifeChrono chrono;
1180 
1181  LifeChrono chronoDer;
1182  LifeChrono chronoStiff;
1183  LifeChrono chronoMass;
1184  LifeChrono chronoGrad;
1185 
1186  LifeChrono chronoStiffAssemble;
1187  LifeChrono chronoMassAssemble;
1188  LifeChrono chronoGradAssemble;
1189  LifeChrono chronoDivAssemble;
1190  LifeChrono chronoStab;
1191  LifeChrono chronoZero;
1192 
1193  // Number of velocity components
1194  UInt numVelocityComponent = M_velocityFESpace.fieldDim();
1195 
1196  // Elementary computation and matrix assembling
1197  // Loop on elements
1198 
1199  UInt velocityTotalDof = M_velocityFESpace.dof().numTotalDof();
1200  // UInt pressureTotalDof = M_pressureFESpace.dof().numTotalDof();
1201 
1202  if ( M_isDiagonalBlockPreconditioner == true )
1203  {
1204  M_blockPreconditioner.reset ( new matrix_Type ( M_localMap ) );
1205  }
1206  chrono.start();
1207 
1208  for ( UInt iElement = 0; iElement < M_velocityFESpace.mesh()->numElements(); iElement++ )
1209  {
1210  chronoDer.start();
1211  // just to provide the id number in the assem_mat_mixed
1212  M_pressureFESpace.fe().update ( M_velocityFESpace.mesh()->element ( iElement ) );
1213  // just to provide the id number in the assem_mat_mixed
1214  // M_pressureFESpace.fe().updateFirstDeriv( M_velocityFESpace.mesh()->element( iElement ) );
1215  M_velocityFESpace.fe().updateFirstDeriv ( M_velocityFESpace.mesh()->element ( iElement ) );
1216 
1217  chronoDer.stop();
1218 
1219  chronoZero.start();
1220  M_elementMatrixStiff.zero();
1221  M_elementMatrixMass.zero();
1222  M_elementMatrixPreconditioner.zero();
1223  M_elementMatrixDivergence.zero();
1224  M_elementMatrixGradient.zero();
1225  chronoZero.stop();
1226 
1227  // stiffness matrix
1228  chronoStiff.start();
1229  if ( M_stiffStrain )
1230  AssemblyElemental::stiff_strain ( 2.0 * M_oseenData->viscosity(),
1231  M_elementMatrixStiff,
1232  M_velocityFESpace.fe() );
1233  else
1234  AssemblyElemental::stiff ( M_oseenData->viscosity(),
1235  M_elementMatrixStiff,
1236  M_velocityFESpace.fe(), 0, 0, M_velocityFESpace.fieldDim() );
1237  //stiff_div( 0.5*M_velocityFESpace.fe().diameter(), M_elementMatrixStiff, M_velocityFESpace.fe() );
1238  chronoStiff.stop();
1239 
1240  // mass matrix
1241  if ( !M_steady )
1242  {
1243  chronoMass.start();
1244  AssemblyElemental::mass ( M_oseenData->density(),
1245  M_elementMatrixMass,
1246  M_velocityFESpace.fe(), 0, 0, M_velocityFESpace.fieldDim() );
1247  chronoMass.stop();
1248  }
1249 
1250  for ( UInt iComponent = 0; iComponent < numVelocityComponent; iComponent++ )
1251  {
1252  // stiffness matrix
1253  chronoStiffAssemble.start();
1254  if ( M_isDiagonalBlockPreconditioner == true )
1255  {
1256  assembleMatrix ( *M_blockPreconditioner,
1257  M_elementMatrixStiff,
1258  M_velocityFESpace.fe(),
1259  M_velocityFESpace.fe(),
1260  M_velocityFESpace.dof(),
1261  M_velocityFESpace.dof(),
1262  iComponent, iComponent,
1263  iComponent * velocityTotalDof, iComponent * velocityTotalDof);
1264  }
1265  else
1266  {
1267  if ( M_stiffStrain ) // sigma = 0.5 * mu (grad( u ) + grad ( u )^T)
1268  {
1269  for ( UInt jComp = 0; jComp < numVelocityComponent; jComp++ )
1270  {
1271  assembleMatrix ( *M_matrixStokes,
1272  M_elementMatrixStiff,
1273  M_velocityFESpace.fe(),
1274  M_velocityFESpace.fe(),
1275  M_velocityFESpace.dof(),
1276  M_velocityFESpace.dof(),
1277  iComponent, jComp,
1278  iComponent * velocityTotalDof, jComp * velocityTotalDof);
1279 
1280  }
1281  }
1282  else // sigma = mu grad( u )
1283  {
1284  assembleMatrix ( *M_matrixStokes,
1285  M_elementMatrixStiff,
1286  M_velocityFESpace.fe(),
1287  M_velocityFESpace.fe(),
1288  M_velocityFESpace.dof(),
1289  M_velocityFESpace.dof(),
1290  iComponent, iComponent,
1291  iComponent * velocityTotalDof, iComponent * velocityTotalDof);
1292  }
1293  }
1294  chronoStiffAssemble.stop();
1295 
1296  // mass matrix
1297  if ( !M_steady )
1298  {
1299  chronoMassAssemble.start();
1300  assembleMatrix ( *M_velocityMatrixMass,
1301  M_elementMatrixMass,
1302  M_velocityFESpace.fe(),
1303  M_velocityFESpace.fe(),
1304  M_velocityFESpace.dof(),
1305  M_velocityFESpace.dof(),
1306  iComponent, iComponent,
1307  iComponent * velocityTotalDof, iComponent * velocityTotalDof);
1308  chronoMassAssemble.stop();
1309  }
1310 
1311  // divergence
1312  chronoGrad.start();
1313  AssemblyElemental::grad ( iComponent, 1.0,
1314  M_elementMatrixGradient,
1315  M_velocityFESpace.fe(),
1316  M_pressureFESpace.fe(),
1317  iComponent, 0 );
1318  chronoGrad.stop();
1319 
1320  chronoGradAssemble.start();
1321  assembleMatrix ( *M_matrixStokes,
1322  M_elementMatrixGradient,
1323  M_velocityFESpace.fe(),
1324  M_pressureFESpace.fe(),
1325  M_velocityFESpace.dof(),
1326  M_pressureFESpace.dof(),
1327  iComponent, 0,
1328  iComponent * velocityTotalDof, numVelocityComponent * velocityTotalDof );
1329  chronoGradAssemble.stop();
1330 
1331  chronoDivAssemble.start();
1332  assembleTransposeMatrix ( *M_matrixStokes,
1333  -1.,
1334  M_elementMatrixGradient,
1335  M_pressureFESpace.fe(),
1336  M_velocityFESpace.fe(),
1337  M_pressureFESpace.dof(),
1338  M_velocityFESpace.dof(),
1339  0 , iComponent,
1340  numVelocityComponent * velocityTotalDof, iComponent * velocityTotalDof );
1341  chronoDivAssemble.stop();
1342  }
1343  }
1344 
1345  // for (UInt ii = M_velocityFESpace.fieldDim()*dimVelocity(); ii < M_velocityFESpace.fieldDim()*dimVelocity() + dimPressure(); ++ii)
1346  // M_matrixStokes->set_mat_inc( ii ,ii, 0. ); not scalable!!!
1347 
1348  if ( M_isDiagonalBlockPreconditioner == true )
1349  {
1350  M_blockPreconditioner->globalAssemble();
1351  *M_matrixStokes += *M_blockPreconditioner;
1352  }
1353  comm()->Barrier();
1354 
1355  chrono.stop();
1356  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1357 
1358  M_Displayer.leaderPrint ( " F- Finalizing the matrices ... " );
1359 
1360  chrono.start();
1361 
1362  M_matrixStokes->globalAssemble();
1363  M_velocityMatrixMass->globalAssemble();
1364 
1365  chrono.stop();
1366  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1367 
1368  if ( false )
1369  std::cout << " partial times: \n"
1370  << " Der " << chronoDer.diffCumul() << " s.\n"
1371  << " Zero " << chronoZero.diffCumul() << " s.\n"
1372  << " Stiff " << chronoStiff.diffCumul() << " s.\n"
1373  << " Stiff Assemble " << chronoStiffAssemble.diffCumul() << " s.\n"
1374  << " Mass " << chronoMass.diffCumul() << " s.\n"
1375  << " Mass Assemble " << chronoMassAssemble.diffCumul() << " s.\n"
1376  << " Grad " << chronoGrad.diffCumul() << " s.\n"
1377  << " Grad Assemble " << chronoGradAssemble.diffCumul() << " s.\n"
1378  << " Div Assemble " << chronoDivAssemble.diffCumul() << " s.\n"
1379  << std::endl;
1380 
1381 }
1382 
1383 template<typename MeshType, typename SolverType>
1384 void
1385 OseenSolver<MeshType, SolverType>::
1386 updateSystem ( const Real alpha,
1387  const vector_Type& betaVector,
1388  const vector_Type& sourceVector )
1389 {
1390  if ( M_matrixNoBC.get() )
1391  {
1392  M_matrixNoBC.reset ( new matrix_Type ( M_localMap, M_matrixNoBC->meanNumEntries() ) );
1393  }
1394  else
1395  {
1396  M_matrixNoBC.reset ( new matrix_Type ( M_localMap ) );
1397  }
1398 
1399  updateSystem ( alpha, betaVector, sourceVector, M_matrixNoBC, *M_un );
1400  if ( alpha != 0. )
1401  {
1402  M_matrixNoBC->globalAssemble();
1403  }
1404 
1405 }
1406 
1407 template<typename MeshType, typename SolverType>
1408 void
1409 OseenSolver<MeshType, SolverType>::
1410 updateSystem ( const Real alpha,
1411  const vector_Type& betaVector,
1412  const vector_Type& sourceVector,
1413  matrixPtr_Type matrixNoBC,
1414  const vector_Type& un )
1415 {
1416  LifeChrono chrono;
1417 
1418  // clearing pressure mass matrix in case we need it in removeMean;
1419  M_pressureMatrixMass.reset( );
1420 
1421 
1422  M_Displayer.leaderPrint ( " F- Updating mass term on right hand side... " );
1423 
1424  chrono.start();
1425 
1426  UInt velocityTotalDof = M_velocityFESpace.dof().numTotalDof();
1427  // UInt pressureTotalDof = M_pressureFESpace.dof().numTotalDof();
1428 
1429  // Right hand side for the velocity at time
1430 
1431  updateRightHandSide ( sourceVector );
1432 
1433  chrono.stop();
1434 
1435  M_Displayer.leaderPrintMax ( "done in ", chrono.diff() );
1436 
1437 
1438  // M_updated = false;
1439 
1440  if ( M_recomputeMatrix )
1441  {
1442  buildSystem();
1443  }
1444 
1445  M_Displayer.leaderPrint ( " F- Copying the matrices ... " );
1446 
1447  chrono.start();
1448 
1449  if ( M_isDiagonalBlockPreconditioner == true )
1450  {
1451  matrixPtr_Type tempMatrix ( M_blockPreconditioner );
1452  M_blockPreconditioner.reset ( new matrix_Type ( M_localMap,
1453  M_blockPreconditioner->meanNumEntries() ) );
1454  *M_blockPreconditioner += *tempMatrix;
1455  }
1456 
1457 
1458  chrono.stop();
1459  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1460 
1461 
1462  UInt numVelocityComponent = M_velocityFESpace.fieldDim();
1463 
1464  //! managing the convective term
1465 
1466  Real normInf;
1467  betaVector.normInf ( &normInf );
1468 
1469  if ( normInf != 0. )
1470  {
1471  M_Displayer.leaderPrint ( " F- Sharing convective term ... " );
1472  chrono.start();
1473 
1474  // vector with repeated nodes over the processors
1475 
1476  vector_Type betaVectorRepeated ( betaVector, Repeated );
1477  vector_Type unRepeated ( un, Repeated, Add );
1478 
1479  chrono.stop();
1480 
1481  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1482  M_Displayer.leaderPrint ( " F- Updating the convective terms ... " );
1483  chrono.start();
1484 
1485  for ( UInt iElement = 0; iElement < M_velocityFESpace.mesh()->numElements(); ++iElement )
1486  {
1487  // just to provide the id number in the assem_mat_mixed
1488  M_pressureFESpace.fe().updateFirstDeriv ( M_velocityFESpace.mesh()->element ( iElement ) );
1489  //as updateFirstDer
1490  M_velocityFESpace.fe().updateFirstDeriv ( M_velocityFESpace.mesh()->element ( iElement ) );
1491 
1492  M_elementMatrixStiff.zero();
1493 
1494  UInt elementID = M_velocityFESpace.fe().currentLocalId();
1495  // Non linear term, Semi-implicit approach
1496  // M_elementRightHandSide contains the velocity values in the nodes
1497  for ( UInt iNode = 0 ; iNode < M_velocityFESpace.fe().nbFEDof() ; iNode++ )
1498  {
1499  UInt iLocal = M_velocityFESpace.fe().patternFirst ( iNode );
1500  for ( UInt iComponent = 0; iComponent < numVelocityComponent; ++iComponent )
1501  {
1502  UInt iGlobal = M_velocityFESpace.dof().localToGlobalMap ( elementID, iLocal )
1503  + iComponent * dimVelocity();
1504  M_elementRightHandSide.vec() [ iLocal + iComponent * M_velocityFESpace.fe().nbFEDof() ]
1505  = betaVectorRepeated[iGlobal];
1506 
1507  M_uLoc.vec() [ iLocal + iComponent * M_velocityFESpace.fe().nbFEDof() ]
1508  = unRepeated (iGlobal);
1509  M_wLoc.vec() [ iLocal + iComponent * M_velocityFESpace.fe().nbFEDof() ]
1510  = unRepeated (iGlobal) - betaVectorRepeated (iGlobal);
1511  }
1512  }
1513 
1514  if (M_oseenData->conservativeFormulation() )
1515  {
1516  // ALE term: - rho div(w) u v
1517  AssemblyElemental::mass_divw ( - M_oseenData->density(),
1518  M_wLoc,
1519  M_elementMatrixStiff,
1520  M_velocityFESpace.fe(), 0, 0, numVelocityComponent );
1521  }
1522 
1523  // ALE stab implicit: 0.5 rho div u w v
1524  AssemblyElemental::mass_divw ( 0.5 * M_oseenData->density(),
1525  M_uLoc,
1526  M_elementMatrixStiff,
1527  M_velocityFESpace.fe(), 0, 0, numVelocityComponent );
1528 
1529  // Stabilising term: -rho div(u^n) u v
1530  if ( M_divBetaUv )
1531  AssemblyElemental::mass_divw ( -0.5 * M_oseenData->density(),
1532  M_uLoc,
1533  M_elementMatrixStiff,
1534  M_velocityFESpace.fe(), 0, 0, numVelocityComponent );
1535 
1536  // compute local convective terms
1537  AssemblyElemental::advection ( M_oseenData->density(),
1538  M_elementRightHandSide,
1539  M_elementMatrixStiff,
1540  M_velocityFESpace.fe(), 0, 0, numVelocityComponent );
1541 
1542  // loop on components
1543  for ( UInt iComponent = 0; iComponent < numVelocityComponent; ++iComponent )
1544  {
1545  // compute local convective term and assembling
1546  // grad( 0, M_elementRightHandSide, M_elementMatrixStiff, M_velocityFESpace.fe(),
1547  // M_velocityFESpace.fe(), iComponent, iComponent );
1548  // grad( 1, M_elementRightHandSide, M_elementMatrixStiff, M_velocityFESpace.fe(),
1549  // M_velocityFESpace.fe(), iComponent, iComponent );
1550  // grad( 2, M_elementRightHandSide, M_elementMatrixStiff, M_velocityFESpace.fe(),
1551  // M_velocityFESpace.fe(), iComponent, iComponent );
1552 
1553  assembleMatrix ( *matrixNoBC,
1554  M_elementMatrixStiff,
1555  M_velocityFESpace.fe(),
1556  M_velocityFESpace.fe(),
1557  M_velocityFESpace.dof(),
1558  M_velocityFESpace.dof(),
1559  iComponent, iComponent,
1560  iComponent * velocityTotalDof, iComponent * velocityTotalDof );
1561  }
1562  }
1563 
1564  chrono.stop();
1565  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1566 
1567  if ( M_stabilization &&
1568  ( M_resetStabilization || !M_reuseStabilization || ( M_matrixStabilization.get() == 0 ) ) )
1569  {
1570  M_Displayer.leaderPrint ( " F- Updating the stabilization terms ... " );
1571  chrono.start();
1572  M_matrixStabilization.reset ( new matrix_Type ( M_localMap ) );
1573  M_ipStabilization.apply ( *M_matrixStabilization, betaVectorRepeated, false );
1574  M_matrixStabilization->globalAssemble();
1575  M_resetStabilization = false;
1576  chrono.stop();
1577  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1578  }
1579 
1580  }
1581  else
1582  {
1583  if ( M_stabilization )
1584  {
1585  M_Displayer.leaderPrint ( " F- Updating the stabilization terms ... " );
1586  chrono.start();
1587 
1588  if ( M_resetStabilization || !M_reuseStabilization || ( M_matrixStabilization.get() == 0 ) )
1589  {
1590  M_matrixStabilization.reset ( new matrix_Type ( M_localMap ) );
1591  M_ipStabilization.apply ( *M_matrixStabilization, betaVector, false );
1592  M_matrixStabilization->globalAssemble();
1593  M_resetStabilization = false;
1594  chrono.stop();
1595  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1596  }
1597  else
1598  {
1599  M_Displayer.leaderPrint ( "reusing\n" );
1600  }
1601  }
1602  }
1603 
1604  if ( alpha != 0. )
1605  {
1606  *matrixNoBC += (*M_velocityMatrixMass) * alpha;
1607  if ( M_isDiagonalBlockPreconditioner == true )
1608  {
1609  matrixNoBC->globalAssemble();
1610  *M_blockPreconditioner += *matrixNoBC;
1611  matrix_Type tempMatrix ( *matrixNoBC );
1612  matrixNoBC.reset ( new matrix_Type ( M_localMap, tempMatrix.meanNumEntries() ) );
1613  *matrixNoBC += tempMatrix;
1614  M_blockPreconditioner->globalAssemble();
1615  }
1616  }
1617  *matrixNoBC += *M_matrixStokes;
1618 }
1619 
1620 
1621 template<typename MeshType, typename SolverType>
1622 void
1623 OseenSolver<MeshType, SolverType>::updateStabilization ( matrix_Type& matrixFull )
1624 {
1625 
1626  if ( M_stabilization )
1627  {
1628  matrixFull += *M_matrixStabilization;
1629  }
1630 
1631 }
1632 
1633 template <typename Mesh, typename SolverType>
1634 void OseenSolver<Mesh, SolverType>::updateSourceTerm ( source_Type const& source )
1635 {
1636  vector_Type rhs ( M_localMap );
1637 
1638  VectorElemental M_elvec (M_velocityFESpace->fe().nbFEDof(), nDimensions);
1639  UInt nc = nDimensions;
1640 
1641  // loop on volumes: assembling source term
1642  for ( UInt i = 1; i <= M_velocityFESpace->mesh()->numVolumes(); ++i )
1643  {
1644 
1645  M_velocityFESpace->fe().updateFirstDerivQuadPt ( M_velocityFESpace->mesh()->volumeList ( i ) );
1646 
1647  M_elvec.zero();
1648 
1649  for ( UInt ic = 0; ic < nc; ++ic )
1650  {
1651  compute_vec ( source, M_elvec, M_velocityFESpace->fe(), M_oseenData->dataTime()->time(), ic ); // compute local vector
1652  assembleVector ( *rhs, M_elvec, M_velocityFESpace->fe(), M_velocityFESpace->dof(), ic, ic * M_velocityFESpace->getDim() ); // assemble local vector into global one
1653  }
1654  }
1655  M_rightHandSideNoBC += rhs;
1656 }
1657 
1658 
1659 
1660 
1661 template<typename MeshType, typename SolverType>
1662 void
1663 OseenSolver<MeshType, SolverType>::iterate ( bcHandler_Type& bcHandler )
1664 {
1665 
1666  LifeChrono chrono;
1667 
1668  // matrix and vector assembling communication
1669  M_Displayer.leaderPrint ( " F- Updating the boundary conditions ... " );
1670 
1671  chrono.start();
1672 
1673  M_matrixNoBC->globalAssemble();
1674 
1675  matrixPtr_Type matrixFull ( new matrix_Type ( M_localMap, M_matrixNoBC->meanNumEntries() ) );
1676 
1677  updateStabilization ( *matrixFull );
1678  getFluidMatrix ( *matrixFull );
1679 
1680  vector_Type rightHandSideFull ( *M_rightHandSideNoBC );
1681 
1682  // matrixFull.reset( new matrix_Type( *M_matrixNoBC ) );
1683  // M_rightHandSideFull = M_rightHandSideNoBC;
1684 
1685  chrono.stop();
1686 
1687  M_Displayer.leaderPrintMax ( "done in ", chrono.diff() );
1688 
1689  // boundary conditions update
1690  M_Displayer.leaderPrint (" F- Applying boundary conditions ... ");
1691 
1692  chrono.start();
1693  applyBoundaryConditions ( *matrixFull, rightHandSideFull, bcHandler );
1694 
1695  matrixFull->globalAssemble();
1696  chrono.stop();
1697 
1698  M_Displayer.leaderPrintMax ( "done in " , chrono.diff() );
1699 
1700  // solving the system
1701  M_linearSolver->setMatrix ( *matrixFull );
1702 
1703  std::shared_ptr<MatrixEpetra<Real> > staticCast = std::static_pointer_cast<MatrixEpetra<Real> > (matrixFull);
1704 
1705  Int numIter = M_linearSolver->solveSystem ( rightHandSideFull, *M_solution, staticCast );
1706 
1707  // if the preconditioner has been rese the stab terms are to be updated
1708  if ( numIter < 0 || numIter > M_iterReuseStabilization )
1709  {
1710  resetStabilization();
1711  }
1712 
1713  *M_residual = *M_rightHandSideNoBC;
1714  *M_residual -= (*M_matrixNoBC) * (*M_solution);
1715 
1716  //M_residual.spy("residual");
1717 } // iterate()
1718 
1719 
1720 template<typename MeshType, typename SolverType>
1721 void
1722 OseenSolver<MeshType, SolverType>::reduceSolution ( Vector& velocityVector, Vector& pressureVector )
1723 {
1724  vector_Type solution ( *M_solution, 0 );
1725 
1726  if ( false /*S_verbose*/ )
1727  {
1728  for ( UInt iDof = 0; iDof < M_velocityFESpace.fieldDim() * dimVelocity(); ++iDof )
1729  {
1730  velocityVector[ iDof ] = solution[ iDof ];
1731  }
1732 
1733  for ( UInt iDof = 0; iDof < dimPressure(); ++iDof )
1734  {
1735  pressureVector[ iDof ] = solution[ iDof + M_velocityFESpace.fieldDim() * dimVelocity() ];
1736  }
1737  }
1738 
1739 }
1740 
1741 template<typename MeshType, typename SolverType>
1742 void
1743 OseenSolver<MeshType, SolverType>::reduceResidual ( Vector& residualVector )
1744 {
1745  vector_Type residual ( *M_residual, 0 );
1746 
1747  if ( false /*S_verbose*/ )
1748  {
1749  for ( UInt iDof = 0; iDof < M_velocityFESpace.fieldDim() * dimVelocity(); ++iDof )
1750  {
1751  residualVector[ iDof ] = residual[ iDof ];
1752  }
1753 
1754  }
1755 }
1756 
1757 template<typename MeshType, typename SolverType>
1758 void
1759 OseenSolver<MeshType, SolverType>::setBlockPreconditioner ( matrixPtr_Type blockPreconditioner )
1760 {
1761  // blockPreconditioner.reset(new matrix_Type(M_monolithicMap, M_solid->getMatrixPtr()->getMeanNumEntries()));
1762  *blockPreconditioner += *M_blockPreconditioner;
1763 }
1764 
1765 template<typename MeshType, typename SolverType>
1766 void
1767 OseenSolver<MeshType, SolverType>::getFluidMatrix ( matrix_Type& matrixFull )
1768 {
1769  M_matrixNoBC->globalAssemble();
1770  matrixFull += *M_matrixNoBC;
1771 }
1772 
1773 template<typename MeshType, typename SolverType>
1774 void
1775 OseenSolver<MeshType, SolverType>::postProcessingSetArea()
1776 {
1777  M_postProcessing->set_area();
1778 }
1779 
1780 template<typename MeshType, typename SolverType>
1781 void
1782 OseenSolver<MeshType, SolverType>::postProcessingSetNormal()
1783 {
1784  M_postProcessing->set_normal();
1785 }
1786 
1787 template<typename MeshType, typename SolverType>
1788 void
1789 OseenSolver<MeshType, SolverType>::postProcessingSetPhi()
1790 {
1791  M_postProcessing->set_phi();
1792 }
1793 
1794 template<typename MeshType, typename SolverType>
1795 Real
1796 OseenSolver<MeshType, SolverType>::flux ( const markerID_Type& flag )
1797 {
1798  return flux ( flag, *M_solution );
1799 }
1800 
1801 template<typename MeshType, typename SolverType>
1802 Real
1803 OseenSolver<MeshType, SolverType>::flux ( const markerID_Type& flag,
1804  const vector_Type& solution )
1805 {
1806  vector_Type velocityAndPressure ( solution, Repeated, Add );
1807  vector_Type velocity ( this->M_velocityFESpace.map(), Repeated );
1808  velocity.subset ( velocityAndPressure );
1809 
1810  return M_postProcessing->flux ( velocity, flag );
1811 }
1812 
1813 template<typename MeshType, typename SolverType>
1814 Real
1815 OseenSolver<MeshType, SolverType>::kineticNormalStress ( const markerID_Type& flag )
1816 {
1817  return kineticNormalStress ( flag, *M_solution );
1818 }
1819 
1820 template<typename MeshType, typename SolverType>
1821 Real
1822 OseenSolver<MeshType, SolverType>::kineticNormalStress ( const markerID_Type& flag,
1823  const vector_Type& solution )
1824 {
1825  vector_Type velocityAndPressure ( solution, Repeated, Add );
1826  vector_Type velocity ( this->M_velocityFESpace.map(), Repeated );
1827  velocity.subset ( velocityAndPressure );
1828 
1829  return M_postProcessing->kineticNormalStress ( velocity, M_oseenData->density(), flag );
1830 }
1831 
1832 template<typename MeshType, typename SolverType>
1833 Real
1834 OseenSolver<MeshType, SolverType>::area ( const markerID_Type& flag )
1835 {
1836  return M_postProcessing->measure ( flag );
1837 }
1838 
1839 template<typename MeshType, typename SolverType>
1840 Vector
1841 OseenSolver<MeshType, SolverType>::normal ( const markerID_Type& flag )
1842 {
1843  return M_postProcessing->normal ( flag );
1844 }
1845 
1846 template<typename MeshType, typename SolverType>
1847 Vector
1848 OseenSolver<MeshType, SolverType>::geometricCenter ( const markerID_Type& flag )
1849 {
1850  return M_postProcessing->geometricCenter ( flag );
1851 }
1852 
1853 template<typename MeshType, typename SolverType>
1854 Real
1855 OseenSolver<MeshType, SolverType>::pressure ( const markerID_Type& flag )
1856 {
1857  return pressure ( flag, *M_solution );
1858 }
1859 
1860 template<typename MeshType, typename SolverType>
1861 Real
1862 OseenSolver<MeshType, SolverType>::pressure (const markerID_Type& flag,
1863  const vector_Type& solution)
1864 {
1865  vector_Type velocityAndPressure ( solution, Repeated, Add );
1866  vector_Type pressure ( this->M_pressureFESpace.map(), Repeated );
1867  pressure.subset ( velocityAndPressure,
1868  this->M_velocityFESpace.dim() *this->M_velocityFESpace.fieldDim() );
1869 
1870  // third argument is 1, to use the pressure finite element space (see PostProcessingBoundary docs)
1871  return M_postProcessing->average ( pressure, flag, 1 ) [0];
1872 }
1873 
1874 template<typename MeshType, typename SolverType>
1875 Real
1876 OseenSolver<MeshType, SolverType>::meanNormalStress ( const markerID_Type& flag, bcHandler_Type& bcHandler )
1877 {
1878  return meanNormalStress ( flag, bcHandler, *M_solution );
1879 }
1880 
1881 template<typename MeshType, typename SolverType>
1882 Real
1883 OseenSolver<MeshType, SolverType>::meanNormalStress (const markerID_Type& flag, bcHandler_Type& bcHandler, const vector_Type& solution )
1884 {
1885  if ( bcHandler.findBCWithFlag ( flag ).type() == Flux )
1886  {
1887  return -lagrangeMultiplier ( flag, bcHandler, solution );
1888  }
1889  else
1890  {
1891 #ifdef HAVE_LIFEV_DEBUG
1892  M_Displayer.leaderPrint ( " !!! WARNING - OseenSolver::meanNormalStress( flag, bcHandler, solution) is returning an approximation \n" );
1893 #endif
1894  return -pressure ( flag, solution ); // TODO: This is an approximation of the mean normal stress as the pressure.
1895  // A proper method should be coded in the PostprocessingBoundary class
1896  // to compute the exact mean normal stress.
1897  }
1898 }
1899 
1900 template<typename MeshType, typename SolverType>
1901 Real
1902 OseenSolver<MeshType, SolverType>::meanTotalNormalStress ( const markerID_Type& flag, bcHandler_Type& bcHandler )
1903 {
1904  return meanTotalNormalStress ( flag, bcHandler, *M_solution );
1905 }
1906 
1907 template<typename MeshType, typename SolverType>
1908 Real
1909 OseenSolver<MeshType, SolverType>::meanTotalNormalStress (const markerID_Type& flag, bcHandler_Type& bcHandler, const vector_Type& solution )
1910 {
1911  return meanNormalStress ( flag, bcHandler, solution ) - kineticNormalStress ( flag, solution );
1912 }
1913 
1914 template<typename MeshType, typename SolverType>
1915 Real
1916 OseenSolver<MeshType, SolverType>::lagrangeMultiplier ( const markerID_Type& flag, bcHandler_Type& bcHandler )
1917 {
1918  return lagrangeMultiplier ( flag, bcHandler, *M_solution );
1919 }
1920 
1921 template<typename MeshType, typename SolverType>
1922 Real
1923 OseenSolver<MeshType, SolverType>::lagrangeMultiplier ( const markerID_Type& flag,
1924  bcHandler_Type& bcHandler,
1925  const vector_Type& solution )
1926 {
1927  // Create a list of Flux bcName_Type ??
1928  std::vector< bcName_Type > fluxBCVector = bcHandler.findAllBCWithType ( Flux );
1929  bcName_Type fluxbcName_Type = bcHandler.findBCWithFlag ( flag ).name();
1930 
1931  // Create a Repeated vector for looking to the lambda
1932  vector_Type velocityPressureLambda ( solution, Repeated, Add );
1933 
1934  // Find the index associated to the correct Lagrange multiplier
1935  for ( UInt lmIndex = 0; lmIndex < static_cast <UInt> ( fluxBCVector.size() ); ++lmIndex )
1936  if ( fluxbcName_Type.compare ( fluxBCVector[ lmIndex ] ) == 0 )
1937  return velocityPressureLambda[M_velocityFESpace.fieldDim() * M_velocityFESpace.dof().numTotalDof()
1938  + M_pressureFESpace.dof().numTotalDof() + lmIndex];
1939 
1940  // If lmIndex has not been found a warning message is printed
1941  M_Displayer.leaderPrint ( "!!! Warning - Lagrange multiplier for Flux BC not found!\n" );
1942  return 0;
1943 }
1944 
1945 template<typename MeshType, typename SolverType>
1946 Real
1947 OseenSolver<MeshType, SolverType>::removeMean ( vector_Type& x )
1948 {
1949 
1950  LifeChrono chrono;
1951  chrono.start();
1952 
1953  const UInt numVelocityComponent ( M_velocityFESpace.fieldDim() );
1954  const UInt velocityTotalDof ( M_velocityFESpace.dof().numTotalDof() );
1955 
1956 
1957  if ( M_pressureMatrixMass.get() == 0 )
1958  {
1959  M_pressureMatrixMass.reset ( new matrix_Type ( M_localMap ) );
1960  }
1961 
1962  for ( UInt iElement = 0; iElement < M_velocityFESpace.mesh()->numElements(); iElement++ )
1963  {
1964  chrono.start();
1965  // just to provide the id number in the assem_mat_mixed
1966  M_pressureFESpace.fe().update ( M_pressureFESpace.mesh()->element ( iElement ) );
1967 
1968  M_elementMatrixPreconditioner.zero();
1969  // mass
1970  chrono.start();
1971  AssemblyElemental::mass ( 1, M_elementMatrixPreconditioner, M_pressureFESpace.fe(), 0, 0, M_velocityFESpace.fieldDim() );
1972  chrono.stop();
1973 
1974  chrono.start();
1975  assembleMatrix ( *M_pressureMatrixMass,
1976  M_elementMatrixPreconditioner,
1977  M_pressureFESpace.fe(),
1978  M_pressureFESpace.fe(),
1979  M_pressureFESpace.dof(),
1980  M_pressureFESpace.dof(),
1981  numVelocityComponent,
1982  numVelocityComponent,
1983  numVelocityComponent * velocityTotalDof,
1984  numVelocityComponent * velocityTotalDof );
1985  chrono.stop();
1986  }
1987 
1988  M_pressureMatrixMass->globalAssemble();
1989 
1990  vector_Type ones ( *M_solution );
1991  ones = 1.0;
1992 
1993  Real mean;
1994  mean = ones * ( M_pressureMatrixMass * x );
1995  x += ( -mean );
1996 
1997  ASSERT ( std::fabs ( ones * ( M_pressureMatrixMass * x ) ) < 1e-9 , "after removeMean the mean pressure should be zero!");
1998 
1999  return mean;
2000 
2001 } // removeMean()
2002 
2003 template<typename MeshType, typename SolverType>
2004 void
2005 OseenSolver<MeshType, SolverType>::applyBoundaryConditions ( matrix_Type& matrix,
2006  vector_Type& rightHandSide,
2007  bcHandler_Type& bcHandler )
2008 {
2009  // M_rightHandSideFull = M_rightHandSideNoBC;
2010 
2011  // BC manage for the velocity
2012  if ( !bcHandler.bcUpdateDone() || M_recomputeMatrix )
2013  {
2014  bcHandler.bcUpdate ( *M_velocityFESpace.mesh(),
2015  M_velocityFESpace.feBd(),
2016  M_velocityFESpace.dof() );
2017  }
2018 
2019  // ignoring non-local entries, Otherwise they are summed up lately
2020  //vector_Type rightHandSideFull( rightHandSide, Repeated, Zero );
2021  // ignoring non-local entries, Otherwise they are summed up lately
2022  vector_Type rightHandSideFull ( rightHandSide, Unique );
2023 
2024  bcManage ( matrix, rightHandSideFull,
2025  *M_velocityFESpace.mesh(),
2026  M_velocityFESpace.dof(),
2027  bcHandler,
2028  M_velocityFESpace.feBd(),
2029  1.,
2030  M_oseenData->dataTime()->time() );
2031 
2032  rightHandSide = rightHandSideFull;
2033 
2034  if ( bcHandler.hasOnlyEssential() && M_diagonalize )
2035  {
2036  matrix.diagonalize ( M_velocityFESpace.fieldDim() *dimVelocity(),
2037  M_diagonalize,
2038  rightHandSide,
2039  0. );
2040  }
2041 
2042 } // applyBoundaryCondition
2043 
2044 // ===================================================
2045 // Set Methods
2046 // ===================================================
2047 
2048 
2049 template<typename MeshType, typename SolverType>
2050 void
2051 OseenSolver<MeshType, SolverType>::setupPostProc( )
2052 {
2053  M_postProcessing.reset ( new PostProcessingBoundary<mesh_Type> ( M_velocityFESpace.mesh(),
2054  &M_velocityFESpace.feBd(),
2055  &M_velocityFESpace.dof(),
2056  &M_pressureFESpace.feBd(),
2057  &M_pressureFESpace.dof(),
2058  M_localMap ) );
2059 }
2060 
2061 template<typename MeshType, typename SolverType>
2062 void
2063 OseenSolver<MeshType, SolverType>::setTolMaxIteration ( const Real& tolerance, const Int& maxIteration )
2064 {
2065  M_linearSolver->setTolerance ( tolerance );
2066  M_linearSolver->setMaxNumIterations ( maxIteration );
2067 }
2068 
2069 
2070 } // namespace LifeV
2071 
2072 #endif // OSEENSOLVER_H
BCBase & findBCWithFlag(const bcFlag_Type &aFlag)
Extract a BC in the list according to its flag.
Definition: BCHandler.cpp:304
double operator()(const char *VarName, const double &Default) const
Definition: GetPot.hpp:2033
bcType_Type type() const
Returns the boundary condition type.
Definition: BCBase.cpp:717
void start()
Start the timer.
Definition: LifeChrono.hpp:93
SolverAztecOO - Class to wrap linear solver.
BCHandler - class for handling boundary conditions.
Definition: BCHandler.hpp:100
const commPtr_Type & comm() const
Get the communicator.
Definition: Displayer.hpp:167
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
ID markerID_Type
markerID_Type is the type used to store the geometric entity marker IDs
Definition: Marker.hpp:81
void updateInverseJacobian(const UInt &iQuadPt)
bool hasOnlyEssential() const
Determine whether all the stored boundary conditions have EssentialXXX type.
Definition: BCHandler.cpp:394
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
Real diff()
Compute the difference in time between start and stop.
Definition: LifeChrono.hpp:111
std::string bcName_Type
Definition: BCBase.hpp:116
double Real
Generic real data.
Definition: LifeV.hpp:175
int operator()(const char *VarName, int Default) const
Definition: GetPot.hpp:2021
const UInt nDimensions(NDIM)
void stop()
Stop the timer.
Definition: LifeChrono.hpp:100
bool bcUpdateDone() const
Determine whether bcUpdate has been done before.
Definition: BCHandler.hpp:502
bool operator()(const char *VarName, bool Default) const
Definition: GetPot.hpp:2008
Displayer - This class is used to display messages in parallel simulations.
Definition: Displayer.hpp:62
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191