LifeV
PreconditionerSIMPLE.cpp
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 PreconditionerSIMPLE
30 
31  @author Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
32  @maintainer Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
33 
34  @date 24-01-2011
35  */
36 
37 #include <vector>
39 #include <lifev/core/algorithm/PreconditionerIfpack.hpp>
40 #include <lifev/core/algorithm/PreconditionerML.hpp>
41 // #include <lifev/core/algorithm/PreconditionerML2.hpp>
42 #include <lifev/core/util/LifeChrono.hpp>
43 #include <lifev/core/array/MatrixEpetraStructured.hpp>
44 #include <lifev/core/array/MatrixEpetraStructuredView.hpp>
45 #include <lifev/core/array/MatrixEpetraStructuredUtility.hpp>
46 
47 namespace LifeV
48 {
49 
50 PreconditionerSIMPLE::PreconditionerSIMPLE ( std::shared_ptr<Epetra_Comm> comm ) :
51  PreconditionerComposition ( comm ),
52  M_velocityBlockSize ( -1 ),
53  M_pressureBlockSize ( -1 ),
54  M_dampingFactor ( 0.5 ),
55  M_SIMPLEType ( "SIMPLE" )
56 {
57 
58 }
59 
61 {
62 
63 }
64 
65 void
67  const GetPot& dataFile,
68  const std::string& section,
69  const std::string& subsection )
70 {
71  const bool verbose ( M_comm->MyPID() == 0 );
72 
73  bool displayList = dataFile ( ( section + "/displayList" ).data(), false);
74 
75  std::string precType = dataFile ( ( section + "/prectype" ).data(), "SIMPLE" );
76  list.set ( "prectype", precType );
77  std::string SIMPLEType = dataFile ( ( section + "/" + subsection + "/SIMPLE_type" ).data(), "SIMPLE" );
78 
79  std::string fluidPrec = dataFile ( ( section + "/" + subsection + "/subprecs/fluid_prec" ).data(), "ML" );
80  list.set ( "subprecs: fluid prec", fluidPrec );
81  std::string fluidPrecDataSection = dataFile ( ( section + "/" + subsection + "/subprecs/fluid_prec_data_section" ).data(), "" );
82  list.set ( "subprecs: fluid prec data section", ( fluidPrecDataSection ).data() );
83 
84  std::string schurPrec = dataFile ( ( section + "/" + subsection + "/subprecs/schur_prec" ).data(), "ML" );
85  list.set ( "subprecs: Schur prec", schurPrec );
86  std::string schurPrecDataSection = dataFile ( ( section + "/" + subsection + "/subprecs/schur_prec_data_section" ).data(), "" );
87  list.set ( "subprecs: Schur prec data section", ( schurPrecDataSection ).data() );
88 
89  list.set ( "SIMPLE Type", SIMPLEType );
90 
91  if ( displayList && verbose )
92  {
93  std::cout << "SIMPLE parameters list:" << std::endl;
94  std::cout << "-----------------------------" << std::endl;
95  list.print ( std::cout );
96  std::cout << "-----------------------------" << std::endl;
97  }
98 }
99 
100 Real
102 {
103  return 0.0;
104 }
105 
106 int
108 {
109  if ( M_velocityBlockSize < 0 || M_pressureBlockSize < 0 )
110  {
111  std::cout << "You must specified manually the pointers to the FESpaces" << std::endl;
112  exit ( 0 );
113  }
114 
115  // Make sure that the preconditioner is reset
116  this->resetPreconditioner();
117 
118  const bool verbose ( M_comm->MyPID() == 0 );
119 
120  std::vector<UInt> blockNumRows ( 2, 0 );
121  blockNumRows[0] = M_velocityBlockSize;
122  blockNumRows[1] = M_pressureBlockSize;
123  std::vector<UInt> blockNumColumns ( blockNumRows );
124 
125  const bool inversed ( true );
126  const bool notInversed ( false );
127  const bool notTransposed ( false );
128 
129  map_Type map ( oper->map() );
130  //oper->spy( "A" );
131 
132  LifeChrono timer;
133 
134  /*
135  * Getting the block structure of A
136  * / F Bt \
137  * \ B C /
138  */
139  if ( verbose )
140  {
141  std::cout << " >Getting the structure of A... ";
142  }
143  timer.start();
144  matrixBlockView_Type F, Bt, B, C;
145  //oper.blockView( 0, 0, F );
146  F.setup ( 0, 0, blockNumRows[0], blockNumColumns[0], oper.get() );
147 
148  //oper.blockView( 0, 1, Bt );
149  Bt.setup ( 0, blockNumColumns[0], blockNumRows[0], blockNumColumns[1], oper.get() );
150 
151  //oper.blockView( 1, 0, B );
152  B.setup ( blockNumRows[0], 0, blockNumRows[1], blockNumColumns[0], oper.get() );
153 
154  //oper.blockView( 1, 1, C );
155  C.setup ( blockNumRows[0], blockNumColumns[0], blockNumRows[1], blockNumColumns[1], oper.get() );
156 
157  if ( verbose )
158  {
159  std::cout << " done in " << timer.diff() << " s." << std::endl;
160  }
161 
162  /*
163  * SIMPLE:
164  * P = / F 0 \ / I D^-1Bt \
165  * \ B -S / \ 0 alphaI /
166  */
167 
168  // Getting the block structure of B
169  matrixBlockView_Type B11, B12, B21, B22, B22base;
170 
171  /*
172  * Building the First block
173  * / F 0 \ = / F 0 \/ I 0 \/ I 0 \
174  * \ B -S / \ 0 I /\ B I /\ 0 -S /
175  *
176  * / F 0 \
177  * \ 0 I /
178  */
179  if ( verbose )
180  {
181  std::cout << " Block 1 (F)" << std::endl;
182  }
183  timer.start();
184  std::shared_ptr<matrixBlock_Type> P1a ( new matrixBlock_Type ( map ) );
185  P1a->setBlockStructure ( blockNumRows, blockNumColumns );
186  P1a->blockView ( 0, 0, B11 );
187  P1a->blockView ( 1, 1, B22 );
188  MatrixEpetraStructuredUtility::copyBlock ( F, B11 );
189  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
190  P1a->globalAssemble();
191  std::shared_ptr<matrix_Type> p1a = P1a;
192  superPtr_Type precForBlock1 ( PRECFactory::instance().createObject ( M_fluidPrec ) );
193  precForBlock1->setDataFromGetPot ( M_dataFile, M_fluidDataSection );
194  // if ( M_fluidPrec == "ML2" )
195  // {
196  // PreconditionerML2* tmpPrecPtr = dynamic_cast<PreconditionerML2*> ( precForBlock1.get() );
197  // tmpPrecPtr->setFESpace ( M_uFESpace, M_pFESpace );
198  // }
199  this->pushBack ( p1a, precForBlock1, notInversed, notTransposed );
200  if ( verbose )
201  {
202  std::cout << " done in " << timer.diff() << " s." << std::endl;
203  }
204 
205  /*
206  * / I 0 \
207  * \ B I /
208  */
209  if ( verbose )
210  {
211  std::cout << " Block 1 (B)" << std::endl;
212  }
213  timer.start();
214  std::shared_ptr<matrixBlock_Type> P1b ( new matrixBlock_Type ( map ) );
215  P1b->setBlockStructure ( blockNumRows, blockNumColumns );
216  P1b->blockView ( 0, 0, B11 );
217  P1b->blockView ( 1, 0, B21 );
218  P1b->blockView ( 1, 1, B22 );
219  MatrixEpetraStructuredUtility::copyBlock ( B, B21 );
220  ( *P1b ) *= -1;
221  MatrixEpetraStructuredUtility::createIdentityBlock ( B11 );
222  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
223  P1b->globalAssemble();
224  std::shared_ptr<matrix_Type> p1b = P1b;
225  this->pushBack ( p1b, inversed, notTransposed );
226  if ( verbose )
227  {
228  std::cout << " done in " << timer.diff() << " s." << std::endl;
229  }
230 
231  /*
232  * / I 0 \
233  * \ 0 -S /
234  */
235  if ( verbose )
236  {
237  std::cout << " Block 1 (Schur)" << std::endl;
238  }
239  timer.start();
240  std::shared_ptr<matrixBlock_Type> P1c ( new matrixBlock_Type ( map ) );
241 
242  std::shared_ptr<matrixBlock_Type> BBlockMat ( new matrixBlock_Type ( map ) );
243  BBlockMat->setBlockStructure ( blockNumRows, blockNumColumns );
244  BBlockMat->blockView ( 1, 0, B21 );
245  MatrixEpetraStructuredUtility::copyBlock ( B, B21 );
246  BBlockMat->globalAssemble();
247  std::shared_ptr<matrixBlock_Type> invDBlockMat ( new matrixBlock_Type ( map ) );
248  invDBlockMat->setBlockStructure ( blockNumRows, blockNumColumns );
249  invDBlockMat->blockView ( 0, 0, B11 );
250  if ( M_SIMPLEType == "SIMPLE" )
251  {
252  MatrixEpetraStructuredUtility::createInvDiagBlock ( F, B11 );
253  }
254  else if ( M_SIMPLEType == "SIMPLEC" )
255  {
256  MatrixEpetraStructuredUtility::createInvLumpedBlock ( F, B11 );
257  }
258  *invDBlockMat *= -1.0;
259  invDBlockMat->globalAssemble();
260  std::shared_ptr<matrixBlock_Type> tmpResultMat ( new matrixBlock_Type ( map ) );
261  BBlockMat->multiply ( false,
262  *invDBlockMat, false,
263  *tmpResultMat, true );
264  BBlockMat.reset();
265  invDBlockMat.reset();
266  std::shared_ptr<matrixBlock_Type> BtBlockMat ( new matrixBlock_Type ( map ) );
267  BtBlockMat->setBlockStructure ( blockNumRows, blockNumColumns );
268  BtBlockMat->blockView ( 0, 1, B12 );
269  MatrixEpetraStructuredUtility::copyBlock ( Bt, B12 );
270  BtBlockMat->globalAssemble();
271  tmpResultMat->multiply ( false,
272  *BtBlockMat, false,
273  *P1c, false );
274  BtBlockMat.reset();
275  tmpResultMat.reset();
276 
277  P1c->setBlockStructure ( blockNumRows, blockNumColumns );
278  P1c->blockView ( 0, 0, B11 );
279  MatrixEpetraStructuredUtility::createIdentityBlock ( B11 );
280  P1c->globalAssemble();
281  std::shared_ptr<matrix_Type> p1c = P1c;
282  superPtr_Type precForBlock2 ( PRECFactory::instance().createObject ( M_schurPrec ) );
283  precForBlock2->setDataFromGetPot ( M_dataFile, M_schurDataSection );
284  this->pushBack ( p1c, precForBlock2, notInversed, notTransposed );
285  if ( verbose )
286  {
287  std::cout << " done in " << timer.diff() << " s." << std::endl;
288  }
289 
290  /*
291  * Building the Second block
292  * / I D^-1Bt \ = / D^-1 0 \/ I Bt \/ D 0 \
293  * \ 0 alphaI / \ 0 alphaI /\ 0 I /\ 0 I /
294  */
295  if ( verbose )
296  {
297  std::cout << " Block 2 (D^-1,alpha I)" << std::endl;
298  }
299  timer.start();
300  std::shared_ptr<matrixBlock_Type> P2a ( new matrixBlock_Type ( map ) );
301  *P2a *= 0.0;
302  P2a->setBlockStructure ( blockNumRows, blockNumColumns );
303  P2a->blockView ( 0, 0, B11 );
304  P2a->blockView ( 1, 1, B22 );
305  if ( M_SIMPLEType == "SIMPLE" )
306  {
307  MatrixEpetraStructuredUtility::createDiagBlock ( F, B11 );
308  }
309  else if ( M_SIMPLEType == "SIMPLEC" )
310  {
311  MatrixEpetraStructuredUtility::createLumpedBlock ( F, B11 );
312  }
313  MatrixEpetraStructuredUtility::createScalarBlock ( B22, 1 / M_dampingFactor );
314  P2a->globalAssemble();
315  std::shared_ptr<matrix_Type> p2a = P2a;
316  this->pushBack ( p2a, inversed, notTransposed );
317  if ( verbose )
318  {
319  std::cout << " done in " << timer.diff() << " s." << std::endl;
320  }
321 
322  /*
323  * / I -Bt \
324  * \ 0 I /
325  */
326  if ( verbose )
327  {
328  std::cout << " Block 2 (Bt)" << std::endl;
329  }
330  timer.start();
331  std::shared_ptr<matrixBlock_Type> P2b ( new matrixBlock_Type ( map ) );
332  P2b->setBlockStructure ( blockNumRows, blockNumColumns );
333  P2b->blockView ( 0, 0, B11 );
334  P2b->blockView ( 0, 1, B12 );
335  P2b->blockView ( 1, 1, B22 );
336  MatrixEpetraStructuredUtility::copyBlock ( Bt, B12 );
337  //( *P2b ) *= -1; // We inverse already the block
338  MatrixEpetraStructuredUtility::createIdentityBlock ( B11 );
339  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
340  P2b->globalAssemble();
341  std::shared_ptr<matrix_Type> p2b = P2b;
342  this->pushBack ( p2b, inversed, notTransposed );
343  if ( verbose )
344  {
345  std::cout << " done in " << timer.diff() << " s." << std::endl;
346  }
347 
348  /*
349  * / D 0 \
350  * \ 0 I /
351  */
352  if ( verbose )
353  {
354  std::cout << " Block2 (D)" << std::endl;
355  }
356  timer.start();
357  std::shared_ptr<matrixBlock_Type> P2c ( new matrixBlock_Type ( map ) );
358  *P2c *= 0.0;
359  P2c->setBlockStructure ( blockNumRows, blockNumColumns );
360  P2c->blockView ( 0, 0, B11 );
361  P2c->blockView ( 1, 1, B22 );
362  if ( M_SIMPLEType == "SIMPLE" )
363  {
364  MatrixEpetraStructuredUtility::createInvDiagBlock ( F, B11 );
365  }
366  else if ( M_SIMPLEType == "SIMPLEC" )
367  {
368  MatrixEpetraStructuredUtility::createInvLumpedBlock ( F, B11 );
369  }
370  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
371  P2c->globalAssemble();
372  std::shared_ptr<matrix_Type> p2c = P2c;
373  this->pushBack ( p2c, inversed, notTransposed );
374  if ( verbose )
375  {
376  std::cout << " done in " << timer.diff() << " s." << std::endl;
377  }
378 
379  this->M_preconditionerCreated = true;
380 
381  if ( verbose ) std::cout << " >All the blocks are built" << std::endl
382  << " >";
383  return ( EXIT_SUCCESS );
384 }
385 
386 int
388 {
389  return 2;
390 }
391 
392 int
394 {
395  return 2;
396 }
397 
398 void
400  const std::string& section )
401 {
402  M_dataFile = dataFile;
403  this->createParametersList ( M_list, dataFile, section, "SIMPLE" );
404  this->setParameters ( M_list );
405 }
406 
407 void
408 PreconditionerSIMPLE::setParameters ( Teuchos::ParameterList& list )
409 {
410  M_precType = list.get ( "prectype", "SIMPLE" );
411  M_SIMPLEType = list.get ( "SIMPLE Type", "SIMPLE" );
412 
413  M_fluidPrec = list.get ( "subprecs: fluid prec", "ML" );
414  M_fluidDataSection = list.get ( "subprecs: fluid prec data section", "" );
415 
416  M_schurPrec = list.get ( "subprecs: Schur prec", "ML" );
417  M_schurDataSection = list.get ( "subprecs: Schur prec data section", "" );
418 }
419 
420 void
422 {
423  // We setup the size of the blocks
424  M_uFESpace = uFESpace;
425  M_pFESpace = pFESpace;
426  M_velocityBlockSize = uFESpace->fieldDim() * uFESpace->dof().numTotalDof();
427  M_pressureBlockSize = pFESpace->dof().numTotalDof();
428 }
429 
430 void
431 PreconditionerSIMPLE::setDampingFactor ( const Real& dampingFactor )
432 {
433  M_dampingFactor = dampingFactor;
434 }
435 
436 } // namespace LifeV
std::shared_ptr< FESpace< mesh_Type, map_Type > > FESpacePtr_Type
std::shared_ptr< super_Type > superPtr_Type
void start()
Start the timer.
Definition: LifeChrono.hpp:93
PreconditionerSIMPLE(std::shared_ptr< Epetra_Comm > comm=std::shared_ptr< Epetra_Comm >(new Epetra_MpiComm(MPI_COMM_WORLD)))
default constructor
void setDataFromGetPot(const GetPot &dataFile, const std::string &section)
Setter using GetPot.
Teuchos::ParameterList list_Type
void updateInverseJacobian(const UInt &iQuadPt)
MatrixEpetraStructuredView< Real > matrixBlockView_Type
double condest()
Return an estimation of the conditionement number of the preconditioner.
int buildPreconditioner(matrixPtr_Type &A)
Build the preconditioner.
double Real
Generic real data.
Definition: LifeV.hpp:175
void createParametersList(list_Type &list, const GetPot &dataFile, const std::string &section, const std::string &subsection="SIMPLE")
Create the list of parameters of the preconditioner.
void setFESpace(FESpacePtr_Type uFESpace, FESpacePtr_Type pFESpace)
Setter for the FESpace.
virtual void setParameters(Teuchos::ParameterList &list)
Method to setup the solver using Teuchos::ParameterList.
void setDampingFactor(const Real &dampingFactor)
Setter for the damping factor.
std::shared_ptr< matrix_Type > matrixPtr_Type
virtual ~PreconditionerSIMPLE()
constructor from matrix A.