LifeV
MonolithicBlockMatrix.hpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*- */
2 //@HEADER
3 /*
4 *******************************************************************************
5 
6  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
7  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
8 
9  This file is part of LifeV.
10 
11  LifeV is free software; you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  LifeV is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
23 
24 *******************************************************************************
25 */
26 //@HEADER
27 
28 /*!
29  @file
30  @brief This file contains a class which handles matrices with a block structure.
31 
32  @author Paolo Crosetto <crosetto@iacspc70.epfl.ch>
33  @date 08 Jun 2010
34  */
35 
36 #ifndef BLOCKMATRIX_H
37 #define BLOCKMATRIX_H 1
38 
39 #include <boost/scoped_ptr.hpp>
40 #include <lifev/fsi/solver/MonolithicBlock.hpp>
41 
42 namespace LifeV
43 {
44 
45 //! MonolithicBlockMatrix - class which handles matrices with a block structure.
46 /*!
47  @author Paolo Crosetto
48 
49  This class handles a matrix with block structure. In particular a vector of shared_ptr
50  points to the different blocks, while one matrix contains the coupling part. all the blocks and the coupling
51  are summed into the matrix M_globalMatrix for the solution of the linear system. If a MonolithicBlockMatrix is used as
52  a preconditioner by default an algebraic additive Schwarz preconditioner is built on the matrix M_globalMatrix.
53  */
54 
55 class MonolithicBlockMatrix : public MonolithicBlock
56 {
57 public:
58 
59  //! @name Public Types
60  //@{
61  typedef MonolithicBlock super_Type;
62  typedef super_Type::fespacePtr_Type fespacePtr_Type;
63  typedef super_Type::vector_Type vector_Type;
64  typedef super_Type::vectorPtr_Type vectorPtr_Type;
65  typedef super_Type::solverPtr_Type solverPtr_Type;
66  typedef super_Type::matrix_Type matrix_Type;
67  typedef super_Type::matrixPtr_Type matrixPtr_Type;
68  typedef super_Type::epetraOperatorPtr_Type epetraOperatorPtr_Type;
69  typedef super_Type::mapPtr_Type mapPtr_Type;
70  typedef FactorySingleton<Factory<MonolithicBlockMatrix, std::string> > Factory_Type;
71  //@}
72 
73 
74  //! @name Constructor & Destructor
75  //@{
76 
77  MonolithicBlockMatrix (const std::vector<Int>& flags/*UInt coupling*/) :
78  super_Type(),
79  M_globalMatrix(),
80  M_coupling(),
81  M_interfaceMap(),
82  M_interface (0),
83  M_couplingFlags (new std::vector<Int> (flags) ),
84  M_numerationInterface()
85  {}
86 
87  ~MonolithicBlockMatrix() {}
88  //@}
89 
90  //! @name Virtual methods
91  //@{
92  //! Sets the parameters needed by the class from data file
93  /*!
94  @param data GetPot object reading the text data file
95  @param section string specifying the path in the data file where to find the options for the operator
96  */
97  virtual void setDataFromGetPot ( const GetPot& data, const std::string& section);
98 
99  virtual void setupSolver (solver_Type& solver, const GetPot& data);
100 
101  //! runs GlobalAssemble on the blocks
102  /*!
103  closes and distributes all the blocks, sums all the blocks together into
104  M_globalMatrix.
105  */
106  virtual void GlobalAssemble();
107 
108  //! Computes the coupling matrix
109  /*!
110  computes the coupling matrix for the system (or for the preconditioner). The coupling is handled
111  through an augmented formulation, introducing new variables (multipliers). Needs as input: the global map of the problem,
112  the two FESpaces of the subproblems to be coupled with their offsets, a std::map holding the two numerations of the
113  interface between the two subproblems (the numeration can be different but the nodes must be matching in each
114  subdomain), an EpetraVector defined on the multipliers map containing the corresponding dof at the interface (NB: the multipliers map should be constructed from the second numeration in the std::map)
115  @param map the map of the global problem
116  @param FESpace1 FESpace of the first problem
117  @param offset1 offset for the first block in the global matrix
118  @param FESpace2 FESpace of the second problem
119  @param offset2 offset for the second block in the global matrix
120  @param locDofMap std::map with the correspondence between the interface dofs for the two different maps in
121  the subproblems
122  @param numerationInterface vector containing the correspondence of the Lagrange multipliers with the interface dofs
123  */
124  virtual void coupler (mapPtr_Type& map,
125  const std::map<ID, ID>& locDofMap,
126  const vectorPtr_Type& numerationInterface,
127  const Real& timeStep,
128  const Real& coefficient,
129  const Real& rescaleFactor);
130 
131 
132  //! Adds a coupling part to the already existing coupling matrix
133  /*!
134  The coupling is handled
135  through an augmented formulation, introducing new variables (multipliers). Needs as input: the global map of the problem,
136  the two FESpaces of the subproblems to be coupled with their offsets, a std::map holding the two numerations of the
137  interface between the two subproblems (the numeration can be different but the nodes must be matching in each
138  subdomain), an EpetraVector defined on the multipliers map containing the corresponding dof at the interface (NB: the multipliers map should be constructed from the second numeration in the std::map)
139  @param map the map of the global problem
140  @param locDofMap std::map with the correspondence between the interface dofs for the two different maps in
141  the subproblems
142  @param numerationInterface vector containing the correspondence of the Lagrange multipliers with the interface dofs
143  @param unused flag kept for compliance with the base class
144  @param couplingFlag flag specifying which block must be coupled whith which block.
145  */
146  void coupler (mapPtr_Type& /*map*/,
147  const std::map<ID, ID>& locDofMap,
148  const vectorPtr_Type& numerationInterface,
149  const Real& timeStep,
150  const Real& coefficient,
151  const Real& rescaleFactor,
152  UInt couplingBlock
153  );
154 
155  //! returns true if the operator has at least one block
156  /*!
157  */
158  virtual bool set()
159  {
160  return (bool) super_Type::M_blocks.size();
161  }
162 
163  //@}
164  //! @name Public methods
165  //@{
166 
167  //! Solves the preconditioned linear system (used only when blockMatrix is used as a preconditioner)
168  /*!
169  Provided the linear solver and the right hand side this method computes the solution and returns it into
170  the result vector.
171  @param rhs right hand side of the linear system
172  @param result output result
173  @param linearSolver the linear system
174  */
175  int solveSystem ( const vector_Type& rhs, vector_Type& step, solverPtr_Type& linearSolver);
176 
177 
178  //! pushes a block at the end of the vector
179  /*!
180  adds a new block
181  @param Mat block matrix to push
182  @param recompute flag stating wether the preconditioner for this block have to be recomputed at every time step.
183  In this case it is not used since it is equal to the boolean specifying wether the whole preconditioner must be
184  recomputed or not.
185  */
186  void push_back_matrix ( const matrixPtr_Type& Mat, bool /*recompute*/);
187 
188  //! replaces a block
189  /*!
190  replaces a block on a specified position in the vector
191  @param Mat block matrix to push
192  @param index position in the vector
193  */
194  void replace_matrix ( const matrixPtr_Type& Mat, UInt index);
195 
196 
197  //! replaces the coupling matrix without copies
198  /*!
199  this method is deprecated, it is implemented for compatibility with the base class
200  \param Mat replacing matrix
201  */
202  void replace_coupling ( const matrixPtr_Type& /*Mat*/, UInt /*index*/)
203  {
204  // not used for matrices (only for preconditioners)
205  /*M_coupling = Mat;*/
206  }
207 
208  //! never used within this class
209  /*!
210  runs assert(false) when called. This method is used only when the preconditioner is a composed operator
211  */
212  void replace_precs ( const epetraOperatorPtr_Type& Mat, UInt index);
213 
214  //!sums the coupling matrix in the specified position with the global matrix
215  /*!
216  Everything (but the boundary conditions) must have been set before calling this
217  */
218  void blockAssembling( );
219 
220  //! returns the global matrix, with all the blocks and the coupling parts
221  /*!
222  */
223  matrixPtr_Type& matrix( )
224  {
225  return M_globalMatrix;
226  }
227 
228  //! multiplies the whole system times a matrix
229  /*!
230  applies a matrix robinCoupling to the system matrix M_globalMatrix, to the rpeconditioner prec passed as input,
231  to the rhs passed as input. This is useful e.g. when we want to substitute the Dirichlet-Neumann coupling with a
232  Robin-Robin one.
233  \param robinCoupling matrix that multiplies the system
234  \param prec preconditioner matrix
235  \param rhs right hand side of the system
236  */
237  void applyPreconditioner ( matrixPtr_Type robinCoupling, matrixPtr_Type prec, vectorPtr_Type& rhs);
238 
239  //! multiplies two matrices
240  /*!
241  multiplies on the left the matrix prec times the matrix robinCoupling
242  \param robinCoupling the matrix that multiplies
243  \param prec the matrix multiplied (modified)
244  */
245  void applyPreconditioner ( const matrixPtr_Type robinCoupling, matrixPtr_Type& prec );
246 
247 
248  //! applies a matrix to the system
249  /*!
250  multiplies on the left the system matrix M_globalMatrix and the rhs times the matrix matrix.
251  \param matrix the preconditioning matrix
252  \param rhsFull the right hand side of the system
253  */
254  void applyPreconditioner ( const matrixPtr_Type matrix, vectorPtr_Type& rhsFull);
255 
256  //!creates the map for the coupling
257  /*!
258  This method create the coupling map needed for two blocks. The coupling is handled adding a number of Lagrange
259  multipliers equal to the interface degrees of freedom. This method generates the map for the vector of the Lagrange
260  multipliers.
261  \param interfaceMap: the map of the interface (not contiguous, the numeration of this map has "holes")
262  \param locDofMap: the map between the two (e. g. in FSI the fluid (first) and the solid (second)) numerations of
263  the interface
264  \param subdomainMaxId: The maximum ID of the sub-map built from interfaceMap (is the number of dof in the subdomain
265  used to buid the interfaceMap divided by the number of dimensions). The interface map used to build the
266  vector M_numerationInterface contains once every node, not every interface degree of freedom (that is nDimensions *
267  interfaceNodes)
268  \param epetraWorldComm: The communicator
269  */
270  void createInterfaceMap ( const MapEpetra& interfaceMap,
271  const std::map<ID, ID>& locDofMap,
272  const UInt subdomainMaxId,
273  const std::shared_ptr<Epetra_Comm> epetraWorldComm );
274 
275 
276  //! applies the b.c. to every block
277  void applyBoundaryConditions (const Real& time);
278 
279  //! applies the b.c. to a specific block
280  void applyBoundaryConditions (const Real& time, const UInt block );
281 
282  //! applies all the b.c.s to the global matrix, updates the rhs
283  void applyBoundaryConditions (const Real& time, vectorPtr_Type& rhs);
284 
285  //! applies the b.c. to the a specific block, updates the rhs
286  void applyBoundaryConditions (const Real& time, vectorPtr_Type& rhs, const UInt block);
287 
288  //! adds a block to the coupling matrix
289  /*!
290  @param Mat: block added
291  @param position of the block, unused here because there is only one coupling matrix
292  */
293  void addToCoupling ( const matrixPtr_Type& Mat, UInt /*position*/);
294 
295 
296  //!
297  /*!
298  adds an entry to the coupling matrix
299  @param entry entry
300  @param row row for the insertion
301  @param col colon for the insertion
302  */
303  void addToCoupling ( const Real& entry , UInt row, UInt col, UInt position );
304 
305  //! adds a block to the coupling matrix
306  /*!
307  This method is specific for the MonolithicBlockMatrix class, it is used e.g. to add the shape derivatives block in FSI
308  to the global matrix
309  @param Mat: block matrix to be added.
310  */
311  void addToGlobalMatrix ( const matrixPtr_Type& Mat)
312  {
313  if (M_globalMatrix->matrixPtr()->Filled() )
314  {
315  matrixPtr_Type tmp (new matrix_Type (M_globalMatrix->map() ) );
316  *tmp += *M_globalMatrix;
317  *tmp += *Mat;
318  tmp->globalAssemble();
319  M_globalMatrix = tmp;
320  }
321  else
322  {
323  *M_globalMatrix += *Mat;
324  }
325  }
326 
327  //! adds a coupling block to the coupling matrix
328  /*!
329  This method is kept for compatibility with the base class. It calls the method addToCoupling.
330  */
331  void push_back_coupling ( matrixPtr_Type& coupling)
332  {
333  addToCoupling (coupling, 0);
334  }
335  //@}
336 
337  //!@name Get Methods
338  //@{
339  //! returns the dimension of the interface
340  /*!
341  NOTE: it has to be multiplied times nDimensions to get the number of interface dofs
342  */
343  UInt interface()
344  {
345  return M_interface;
346  }
347 
348  //! returns the map built for theLagrange multipliers
349  mapPtr_Type interfaceMap() const
350  {
351  return M_interfaceMap;
352  }
353 
354  matrixPtr_Type coupling() const
355  {
356  return M_coupling;
357  }
358 
359  //! returns the numeration of the interface
360  /*!
361  \param numeration: output vector
362  */
363  void numerationInterface ( vectorPtr_Type& numeration )
364  {
365  numeration = M_numerationInterface;
366  }
367 
368  const UInt whereIsBlock ( UInt /*position*/ ) const
369  {
370  return 0;
371  }
372 
373  //@}
374 
375  //!@name Factory Method
376  //@{
377  static MonolithicBlockMatrix* createAdditiveSchwarz()
378  {
379  const Int couplings[] = { 15, 0, 16 };//to modify (15 to 7, for DN, or 14, for DN2) to neglect the coupling (and solve Navier--Stokes)
380  const std::vector<Int> couplingVector (couplings, couplings + 3);
381  return new MonolithicBlockMatrix (couplingVector);
382  }
383 
384  //@}
385 
386 
387 protected:
388 
389  //! @name Protected Members
390  //@{
391  matrixPtr_Type M_globalMatrix;
392  matrixPtr_Type M_coupling;
393  mapPtr_Type M_interfaceMap;
394  UInt M_interface;
395  //@}
396 
397 private:
398 
399  //! @name Private Members
400  //@{
401  std::unique_ptr<std::vector<Int> > M_couplingFlags;
402  vectorPtr_Type M_numerationInterface;
403  //@}
404 };
405 
406 
407 } // Namespace LifeV
408 
409 #endif /* BLOCKMATRIX_H */
void assignFunction(bcBase_Type &base)
Assign the function to the base of the BCHandler.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
double Real
Generic real data.
Definition: LifeV.hpp:175
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191