LifeV
PreconditionerPCD.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 PreconditionerPCD
30 
31  @author Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
32  @maintainer Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
33 
34  @date 29-11-2010
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/fem/BCManage.hpp>
44 #include <lifev/core/fem/BCBase.hpp>
45 #include <lifev/core/fem/BCIdentifier.hpp>
46 #include <lifev/core/array/MatrixEpetraStructured.hpp>
47 #include <lifev/core/array/MatrixEpetraStructuredView.hpp>
48 #include <lifev/core/array/MatrixEpetraStructuredUtility.hpp>
49 #include <lifev/core/array/VectorBlockStructure.hpp>
50 
51 
52 #include <EpetraExt_MatrixMatrix.h>
53 
54 namespace LifeV
55 {
56 
57 PreconditionerPCD::PreconditionerPCD ( std::shared_ptr<Epetra_Comm> comm ) :
58  PreconditionerComposition ( comm ),
59  M_velocityBlockSize ( -1 ),
60  M_pressureBlockSize ( -1 ),
61  M_timestep ( 1.0 ),
62  M_viscosity ( 1.0 ),
63  M_density ( 1.0 ),
64  M_pressureLaplacianOperator ( "standard" ),
65  M_pressureMassOperator ( "lumped" ),
66  M_setApBoundaryConditions ( false ),
67  M_setFpBoundaryConditions ( false ),
68  M_setMpBoundaryConditions ( false ),
69  M_fullFactorization ( false ),
71  M_useStiffStrain ( false ),
72  M_enableTransient ( true ),
73  M_divergenceCoeff ( 1.0 ),
74  M_recomputeNormalVectors ( true ),
75  M_inflowBoundaryType ( "Robin" ),
76  M_outflowBoundaryType ( "Neumann" ),
77  M_characteristicBoundaryType ( "Neumann" )
78 {
79  M_uFESpace.reset();
80  M_pFESpace.reset();
81  M_beta.reset();
82 }
83 
85 {
86 
87 }
88 
89 void
91  const GetPot& dataFile,
92  const std::string& section,
93  const std::string& subsection )
94 {
95  const bool verbose ( M_comm->MyPID() == 0 );
96 
97  bool displayList = dataFile ( ( section + "/displayList" ).data(), false );
98 
99  std::string precType = dataFile ( ( section + "/prectype" ).data(), "PCD" );
100  list.set ( "prectype", precType );
101 
102  std::string fluidPrec = dataFile ( ( section + "/" + subsection + "/subprecs/fluid_prec" ).data(), "ML" );
103  list.set ( "subprecs: fluid prec", fluidPrec );
104  std::string fluidPrecDataSection = dataFile ( ( section + "/" + subsection + "/subprecs/fluid_prec_data_section" ).data(), "" );
105  list.set ( "subprecs: fluid prec data section", ( fluidPrecDataSection ).data() );
106 
107  std::string pressureLaplacianPrec = dataFile ( ( section + "/" + subsection + "/subprecs/pressure_laplacian_prec" ).data(), "ML" );
108  list.set ( "subprecs: pressure laplacian prec", pressureLaplacianPrec );
109  std::string pressureLaplacianPrecDataSection = dataFile ( ( section + "/" + subsection + "/subprecs/pressure_laplacian_prec_data_section" ).data(), "" );
110  list.set ( "subprecs: pressure laplacian prec data section", ( pressureLaplacianPrecDataSection ).data() );
111 
112  std::string pressureMassPrec = dataFile ( ( section + "/" + subsection + "/subprecs/pressure_mass_prec" ).data(), "ML" );
113  list.set ( "subprecs: pressure mass prec", pressureMassPrec );
114  std::string pressureMassPrecDataSection = dataFile ( ( section + "/" + subsection + "/subprecs/pressure_mass_prec_data_section" ).data(), "" );
115  list.set ( "subprecs: pressure mass prec data section", ( pressureMassPrecDataSection ).data() );
116 
117  std::string pressureBoundaryConditions = dataFile ( ( section + "/" + subsection + "/pressure_boundary_conditions").data(), "none" );
118  list.set ( "pressure boundary conditions", pressureBoundaryConditions );
119 
120  std::string pressureLaplacianOperator = dataFile ( ( section + "/" + subsection + "/pressure_laplacian_operator").data(), "standard" );
121  list.set ( "pressure laplacian operator", pressureLaplacianOperator );
122 
123  std::string pressureMassOperator = dataFile ( ( section + "/" + subsection + "/pressure_mass_operator").data(), "lumped" );
124  list.set ( "pressure mass operator", pressureMassOperator );
125 
126  bool setApBoundaryConditions = dataFile ( ( section + "/" + subsection + "/set_Ap_boundary_conditions" ).data(), false );
127  list.set ( "set Ap boundary conditions", setApBoundaryConditions );
128 
129  bool setFpBoundaryConditions = dataFile ( ( section + "/" + subsection + "/set_Fp_boundary_conditions" ).data(), false );
130  list.set ( "set Fp boundary conditions", setFpBoundaryConditions );
131 
132  bool setMpBoundaryConditions = dataFile ( ( section + "/" + subsection + "/set_Mp_boundary_conditions" ).data(), false );
133  list.set ( "set Mp boundary conditions", setMpBoundaryConditions );
134 
135  bool fullFactorization = dataFile ( ( section + "/" + subsection + "/full_factorization" ).data(), false );
136  list.set ( "full factorization", fullFactorization );
137 
138  bool useStiffStrain = dataFile ( ( section + "/" + subsection + "/use_StiffStrain" ).data(), false );
139  list.set ( "use stiff strain", useStiffStrain );
140 
141  bool enableTransient = dataFile ( ( section + "/" + subsection + "/enable_transient" ).data(), true );
142  list.set ( "enable transient", enableTransient );
143 
144  bool useMinusDivergence = dataFile ( ( section + "/" + subsection + "/use_minus_divergence" ).data(), false );
145  list.set ( "use minus divergence", useMinusDivergence );
146 
147  bool recomputeNormalVectors = dataFile ( ( section + "/" + subsection + "/recompute_normal_vectors" ).data(), true );
148  list.set ( "recompute normal vectors", recomputeNormalVectors );
149 
150  bool schurOperatorReverseOrder = dataFile ( ( section + "/" + subsection + "/Schur_operator_reverse_order" ).data(), false );
151  list.set ( "Schur operator reverse order", schurOperatorReverseOrder );
152 
153  std::string inflowBoundaryType = dataFile ( ( section + "/" + subsection + "/inflow_boundary_type" ).data(), "Robin" );
154  list.set ( "inflow boundary type", inflowBoundaryType );
155 
156  std::string outflowBoundaryType = dataFile ( ( section + "/" + subsection + "/outflow_boundary_type" ).data(), "Neumann" );
157  list.set ( "outflow boundary type", outflowBoundaryType );
158 
159  std::string characteristicBoundaryType = dataFile ( ( section + "/" + subsection + "/characteristic_boundary_type" ).data(), "Neumann" );
160  list.set ( "characteristic boundary type", characteristicBoundaryType );
161 
162  if ( displayList && verbose )
163  {
164  std::cout << "PCD parameters list:" << std::endl;
165  std::cout << "-----------------------------" << std::endl;
166  list.print ( std::cout );
167  std::cout << "-----------------------------" << std::endl;
168  }
169 }
170 
171 Real
173 {
174  return 0.0;
175 }
176 
177 void
179 {
180  *M_beta = beta;
181 }
182 
183 int
185 {
186  if ( ( M_uFESpace.get() == NULL ) || ( M_pFESpace.get() == NULL ) )
187  {
188  std::cout << "You must specified manually the pointers to the FESpaces" << std::endl;
189  exit ( -1 );
190  }
191 
192  const bool verbose ( M_comm->MyPID() == 0 );
193 
194  // Make sure that the preconditioner is reset
195  this->resetPreconditioner();
196 
197  std::vector<UInt> blockNumRows ( 2, 0 );
198  blockNumRows[0] = M_velocityBlockSize;
199  blockNumRows[1] = M_pressureBlockSize;
200  std::vector<UInt> blockNumColumns ( blockNumRows );
201  VectorBlockStructure vectorStructure;
202  vectorStructure.setBlockStructure ( blockNumColumns );
203 
204  const bool inversed ( true );
205  const bool notInversed ( false );
206  const bool notTransposed ( false );
207 
208  map_Type map ( oper->map() );
209  map_Type velocityMap ( M_uFESpace->map() );
210  map_Type pressureMap ( M_pFESpace->map() );
211 
212  LifeChrono timer;
213 
214  /*
215  * Getting the block structure of A
216  * / F Bt \
217  * \ B C /
218  */
219  if ( verbose )
220  {
221  std::cout << " >Getting the structure of A... ";
222  }
223  timer.start();
224  matrixBlockView_Type F, Bt, B, C;
225  //oper.blockView( 0, 0, F );
226  F.setup ( 0 , 0, blockNumRows[0], blockNumColumns[0], oper.get() );
227 
228  //oper.blockView( 0, 1, Bt );
229  Bt.setup ( 0, blockNumColumns[0], blockNumRows[0], blockNumColumns[1], oper.get() );
230 
231  //oper.blockView( 1, 0, B );
232  B.setup ( blockNumRows[0], 0, blockNumRows[1], blockNumColumns[0], oper.get() );
233 
234  //oper.blockView( 1, 1, C );
235  C.setup ( blockNumRows[0], blockNumColumns[0], blockNumRows[1], blockNumColumns[1], oper.get() );
236  if ( verbose )
237  {
238  std::cout << "done in " << timer.diff() << " s." << std::endl;
239  }
240 
241  // Getting the block structure of B
242  matrixBlockView_Type B11, B12, B21, B22, B22base;
243 
244  /*
245  * PCD:
246  * / F Bt \ / I 0 \ / I Bt \ / F 0 \
247  * \ 0 -S / = \ 0 -S / \ 0 I / \ 0 I /
248  *
249  * PCD^-1:
250  * / F Bt \^-1 / F^-1 0 \ / I -Bt \ / I 0 \
251  * \ 0 -S / = \ 0 I / \ 0 I / \ 0 -S^-1 /
252  */
253 
254  std::shared_ptr<matrix_Type> p3;
255  superPtr_Type precForBlock3;
256  std::shared_ptr<matrixBlock_Type> P3;
257  if ( M_fluidPrec == "LinearSolver" )
258  {
259  MatrixEpetraStructuredUtility::createMatrixFromBlock ( F, P3, velocityMap, true );
260  }
261  else
262  {
263  P3.reset ( new matrixBlock_Type ( map ) );
264  P3->setBlockStructure ( blockNumRows, blockNumColumns );
265  P3->blockView ( 0, 0, B11 );
266  P3->blockView ( 1, 1, B22 );
267  MatrixEpetraStructuredUtility::copyBlock ( F, B11 );
268  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
269  P3->globalAssemble();
270  }
271  p3 = P3;
272 
273  if ( M_fullFactorization == true )
274  {
275  /*
276  * Building the block
277  * / I 0 \ / F 0 \ / I 0 \ / F^-1 0 \
278  * \ BF^-1 I / = \ 0 I / \ B I / \ 0 I /
279  */
280 
281  /*
282  * Building the block
283  * / F 0 \
284  * \ 0 I /
285  */
286  if ( verbose )
287  {
288  std::cout << " >Fluid block... ";
289  }
290  timer.start();
291  precForBlock3.reset ( PRECFactory::instance().createObject ( M_fluidPrec ) );
292  precForBlock3->setDataFromGetPot ( M_dataFile, M_fluidPrecDataSection );
293  // if ( M_fluidPrec == "ML2" )
294  // {
295  // PreconditionerML2* tmpPrecPtr = dynamic_cast<PreconditionerML2*> ( precForBlock3.get() );
296  // tmpPrecPtr->setFESpace ( M_uFESpace, M_pFESpace );
297  // }
298  if ( M_fluidPrec == "LinearSolver" )
299  {
300  this->pushBack ( p3, precForBlock3, vectorStructure, 0, oper->map(), notInversed, notTransposed );
301  }
302  else
303  {
304  this->pushBack ( p3, precForBlock3, notInversed, notTransposed );
305  }
306  if ( verbose )
307  {
308  std::cout << " done in " << timer.diff() << " s." << std::endl;
309  }
310 
311  /*
312  * Building the block (the block is inversed)
313  * / I 0 \
314  * \ -B I /
315  */
316  if ( verbose )
317  {
318  std::cout << " >Divergence block... ";
319  }
320  timer.start();
321  std::shared_ptr<matrixBlock_Type> P2e ( new matrixBlock_Type ( map ) );
322  P2e->setBlockStructure ( blockNumRows, blockNumColumns );
323  P2e->blockView ( 0, 0, B11 );
324  P2e->blockView ( 1, 0, B21 );
325  P2e->blockView ( 1, 1, B22 );
326  MatrixEpetraStructuredUtility::copyBlock ( B, B21 );
327  ( *P2e ) *= -1;
328  MatrixEpetraStructuredUtility::createIdentityBlock ( B11 );
329  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
330  P2e->globalAssemble();
331  std::shared_ptr<matrix_Type> p2e = P2e;
332  this->pushBack ( p2e, inversed, notTransposed );
333  if ( verbose )
334  {
335  std::cout << " done in " << timer.diff() << " s." << std::endl;
336  }
337 
338  /*
339  * Building the block
340  * / F^-1 0 \
341  * \ 0 I /
342  */
343  if ( verbose )
344  {
345  std::cout << " >Fluid block... ";
346  }
347  this->pushBack ( p3, inversed, notTransposed );
348  if ( verbose )
349  {
350  std::cout << " done in " << timer.diff() << " s." << std::endl;
351  }
352  }
353 
354  /*
355  * Building the block
356  * / I 0 \ / I 0 \ / I 0 \ / I 0 \ / I 0 \
357  * \ 0 -S / = \ 0 -ApFp^-1Mp / = \ 0 Ap / \ 0 Fp^-1 / \ 0 -Mp /
358  */
359  UInt ApOffset ( 0 );
360  UInt FpOffset ( 0 );
361  UInt MpOffset ( 0 );
362 
363  if ( verbose )
364  {
365  std::cout << " >Building Fp... ";
366  }
367  timer.start();
368  std::shared_ptr<matrixBlock_Type> PFp;
369  PFp.reset ( new matrixBlock_Type ( map ) );
370  PFp->setBlockStructure ( blockNumRows, blockNumColumns );
371  *PFp *= 0.0;
372  PFp->blockView ( 0, 0, B11 );
373  PFp->blockView ( 1, 1, B22 );
374  MatrixEpetraStructuredUtility::createScalarBlock ( B11, 1.0 );
375  if ( M_useStiffStrain )
376  {
377  M_adrPressureAssembler.addStiffStrain ( PFp, M_viscosity / M_density, B22.firstRowIndex(), B22.firstColumnIndex() );
378  }
379  else
380  {
381  M_adrPressureAssembler.addDiffusion ( PFp, M_viscosity / M_density, B22.firstRowIndex(), B22.firstColumnIndex() );
382  }
383  M_adrPressureAssembler.addAdvection ( PFp, *M_beta, B22.firstRowIndex(), B22.firstColumnIndex() );
384  if ( M_enableTransient )
385  {
386  M_adrPressureAssembler.addMass ( PFp, 1.0 / M_timestep, B22.firstRowIndex(), B22.firstColumnIndex() );
387  }
388  std::shared_ptr<matrix_Type> pFp = PFp;
389  FpOffset = B22.firstRowIndex();
390  if ( verbose )
391  {
392  std::cout << "done in " << timer.diff() << " s." << std::endl;
393  }
394 
395  if ( verbose )
396  {
397  std::cout << " >Building Ap";
398  }
399  timer.start();
400  std::shared_ptr<matrixBlock_Type> PAp;
401  if ( M_pressureLaplacianPrec == "LinearSolver" )
402  {
403  PAp.reset ( new matrixBlock_Type ( pressureMap ) );
404  *PAp *= 0.0;
405  PAp->blockView ( 0, 0, B22 );
406  ApOffset = B22.firstRowIndex();
407  }
408  else
409  {
410  PAp.reset ( new matrixBlock_Type ( map ) );
411  PAp->setBlockStructure ( blockNumRows, blockNumColumns );
412  *PAp *= 0.0;
413  PAp->blockView ( 0, 0, B11 );
414  PAp->blockView ( 1, 1, B22 );
415  MatrixEpetraStructuredUtility::createScalarBlock ( B11, 1.0 );
416  ApOffset = B22.firstRowIndex();
417  }
418 
419  if ( M_pressureLaplacianOperator == "symmetric" )
420  {
421  if ( verbose )
422  {
423  std::cout << " (Symm(Fp) version)... ";
424  }
425  Epetra_CrsMatrix* tmpCrsMatrix ( NULL );
426  tmpCrsMatrix = PAp->matrixPtr().get();
427  EpetraExt::MatrixMatrix::Add ( * ( pFp->matrixPtr() ), false, 0.5 * M_density / M_viscosity,
428  * ( pFp->matrixPtr() ), true, 0.5 * M_density / M_viscosity,
429  tmpCrsMatrix );
430  *PAp *= M_divergenceCoeff;
431  }
432  else if ( M_pressureLaplacianOperator == "BBt" )
433  {
434  if ( verbose )
435  {
436  std::cout << " (BBt version)... ";
437  }
438  std::shared_ptr<matrixBlock_Type> BMat ( new matrixBlock_Type ( map ) );
439  BMat->setBlockStructure ( blockNumRows, blockNumColumns );
440  MatrixEpetraStructuredUtility::copyBlock ( B, * ( BMat->block ( 1, 0 ) ) );
441  BMat->globalAssemble();
442  std::shared_ptr<matrixBlock_Type> BtMat ( new matrixBlock_Type ( map ) );
443  BtMat->setBlockStructure ( blockNumRows, blockNumColumns );
444  MatrixEpetraStructuredUtility::copyBlock ( Bt, * ( BtMat->block ( 0, 1 ) ) );
445  BtMat->globalAssemble();
446  std::shared_ptr<matrixBlock_Type> BBtMat ( new matrixBlock_Type ( map ) );
447  BBtMat->setBlockStructure ( blockNumRows, blockNumColumns );
448  BMat->multiply ( false,
449  *BtMat , false,
450  *BBtMat, true );
451  MatrixEpetraStructuredUtility::copyBlock ( * ( BBtMat->block ( 1, 1 ) ), B22 );
452  }
453  else if ( M_pressureLaplacianOperator == "BinvDBt" )
454  {
455  if ( verbose )
456  {
457  std::cout << " (BinvDBt version)... ";
458  }
459  // Create B
460  std::shared_ptr<matrixBlock_Type> BMat ( new matrixBlock_Type ( map ) );
461  BMat->setBlockStructure ( blockNumRows, blockNumColumns );
462  MatrixEpetraStructuredUtility::copyBlock ( B, * ( BMat->block ( 1, 0 ) ) );
463  BMat->globalAssemble();
464 
465  // Create the inverse of the diagonal mass matrix D
466  std::shared_ptr<matrixBlock_Type> tmpVelocityMass ( new matrixBlock_Type ( map ) );
467  tmpVelocityMass->setBlockStructure ( blockNumRows, blockNumColumns );
468  M_adrVelocityAssembler.addMass ( tmpVelocityMass, 1.0 );
469  tmpVelocityMass->globalAssemble();
470  std::shared_ptr<matrixBlock_Type> invDMat ( new matrixBlock_Type ( map ) );
471  invDMat->setBlockStructure ( blockNumRows, blockNumColumns );
472  MatrixEpetraStructuredUtility::createInvDiagBlock ( * ( tmpVelocityMass->block ( 0, 0 ) ), * ( invDMat->block ( 0, 0 ) ) );
473  invDMat->globalAssemble();
474  tmpVelocityMass.reset(); // Free the memory
475 
476  // Compute BD^-1
477  std::shared_ptr<matrixBlock_Type> BinvDMat ( new matrixBlock_Type ( map ) );
478  BinvDMat->setBlockStructure ( blockNumRows, blockNumColumns );
479  BMat->multiply ( false,
480  *invDMat , false,
481  *BinvDMat, true );
482  invDMat.reset(); // Free the memory
483  BMat.reset();
484 
485  // Compute BD^-1Bt
486  std::shared_ptr<matrixBlock_Type> BtMat ( new matrixBlock_Type ( map ) );
487  BtMat->setBlockStructure ( blockNumRows, blockNumColumns );
488  MatrixEpetraStructuredUtility::copyBlock ( Bt, * ( BtMat->block ( 0, 1 ) ) );
489  BtMat->globalAssemble();
490  std::shared_ptr<matrixBlock_Type> BBtMat ( new matrixBlock_Type ( map ) );
491  BBtMat->setBlockStructure ( blockNumRows, blockNumColumns );
492  BinvDMat->multiply ( false,
493  *BtMat , false,
494  *BBtMat, true );
495  BinvDMat.reset(); // Free the memory
496  BtMat.reset();
497 
498  // Export the matrix
499  MatrixEpetraStructuredUtility::copyBlock ( * ( BBtMat->block ( 1, 1 ) ), B22 );
500  }
501  else
502  {
503  if ( verbose )
504  {
505  std::cout << "... ";
506  }
507  M_adrPressureAssembler.addDiffusion ( PAp, M_divergenceCoeff, B22.firstRowIndex(), B22.firstColumnIndex() );
508  }
509  std::shared_ptr<matrix_Type> pAp = PAp;
510  if ( verbose )
511  {
512  std::cout << "done in " << timer.diff() << " s." << std::endl;
513  }
514 
515 
516  if ( verbose )
517  {
518  std::cout << " >Building Mp";
519  }
520  timer.start();
521  std::shared_ptr<matrixBlock_Type> PMp;
522  if ( M_pressureMassPrec == "LinearSolver" && M_pressureMassOperator == "standard" )
523  {
524  PMp.reset ( new matrixBlock_Type ( pressureMap ) );
525  *PMp *= 0.0;
526  PMp->blockView ( 0, 0, B22 );
527  MpOffset = 0;
528  }
529  else
530  {
531  PMp.reset ( new matrixBlock_Type ( map ) );
532  PMp->setBlockStructure ( blockNumRows, blockNumColumns );
533  *PMp *= 0.0;
534  PMp->blockView ( 0, 0, B11 );
535  PMp->blockView ( 1, 1, B22 );
536  MatrixEpetraStructuredUtility::createScalarBlock ( B11, 1.0 );
537  MpOffset = B22.firstRowIndex();
538  }
539  if ( M_pressureMassOperator == "lumped" )
540  {
541  if ( verbose )
542  {
543  std::cout << " (Lumped version)... ";
544  }
545  std::shared_ptr<matrixBlock_Type> tmpMass ( new matrixBlock_Type ( map ) );
546  M_adrPressureAssembler.addMass ( tmpMass, -1.0, B22.firstRowIndex(), B22.firstColumnIndex() );
547  tmpMass->globalAssemble();
548  tmpMass->setBlockStructure ( blockNumRows, blockNumColumns );
549  tmpMass->blockView ( 1, 1, B11 );
550  MatrixEpetraStructuredUtility::createInvLumpedBlock ( B11, B22 );
551  tmpMass.reset();
552  }
553  if ( M_pressureMassOperator == "diagonal" )
554  {
555  if ( verbose )
556  {
557  std::cout << " (diagonal version)... ";
558  }
559  std::shared_ptr<matrixBlock_Type> tmpMass ( new matrixBlock_Type ( map ) );
560  M_adrPressureAssembler.addMass ( tmpMass, -1.0, B22.firstRowIndex(), B22.firstColumnIndex() );
561  tmpMass->globalAssemble();
562  tmpMass->setBlockStructure ( blockNumRows, blockNumColumns );
563  tmpMass->blockView ( 1, 1, B11 );
564  MatrixEpetraStructuredUtility::createInvDiagBlock ( B11, B22 );
565  tmpMass.reset();
566  }
567  else
568  {
569  if ( verbose )
570  {
571  std::cout << "... ";
572  }
573  M_adrPressureAssembler.addMass ( PMp, -1.0, B22.firstRowIndex(), B22.firstColumnIndex() );
574  }
575  std::shared_ptr<matrix_Type> pMp = PMp;
576  if ( verbose )
577  {
578  std::cout << "done in " << timer.diff() << " s." << std::endl;
579  }
580 
581  // This option is the one used by Elman & al. in the original PCD:
582  // * Dirichlet boundary conditions at inflows
583  // * Neumann boundary conditions at outflows
584  // * Neumann boundary conditions on characteristic boundaries
585 
586  // This option is the one used by Elman & al. in the New PCD:
587  // * Robin boundary conditions at inflows
588  // * Neumann boundary conditions at outflows
589  // * Neumann boundary conditions on characteristic boundaries
590  this->setBCByBoundaryType ( pAp, ApOffset,
591  pFp, FpOffset,
592  pMp, MpOffset );
593 
594  // For enclosed flow where only characteristics BC are imposed,
595  // the choice is correct by default, i.e. Neumann BC.
596  if ( ( verbose ) && ( M_setApBoundaryConditions ) )
597  {
598  std::cout << " >BC imposed on Ap" << std::endl;
599  }
600  if ( ( verbose ) && ( M_setFpBoundaryConditions ) )
601  {
602  std::cout << " >BC imposed on Fp" << std::endl;
603  }
604  if ( ( verbose ) && ( M_setMpBoundaryConditions ) )
605  {
606  std::cout << " >BC imposed on Mp" << std::endl;
607  }
608 
610  {
611  if ( verbose )
612  {
613  std::cout << " >Use reverse order for the Schur approximation" << std::endl;
614  }
615 
616  if ( verbose )
617  {
618  std::cout << " >Schur block (a)... ";
619  }
620  timer.start();
621  if ( M_pressureMassOperator != "standard" )
622  {
623  this->pushBack ( pMp, inversed, notTransposed );
624  }
625  else
626  {
627  superPtr_Type precForBlock2 ( PRECFactory::instance().createObject ( M_pressureMassPrec ) );
628  precForBlock2->setDataFromGetPot ( M_dataFile, M_pressureMassPrecDataSection );
629  if ( M_pressureMassPrec == "LinearSolver" )
630  {
631  this->pushBack ( pMp, precForBlock2, vectorStructure, 1, oper->map(), notInversed, notTransposed );
632  }
633  else
634  {
635  this->pushBack ( pMp, precForBlock2, notInversed, notTransposed );
636  }
637  }
638  if ( verbose )
639  {
640  std::cout << " done in " << timer.diff() << " s." << std::endl;
641  }
642 
643  if ( verbose )
644  {
645  std::cout << " >Schur block (b)... ";
646  }
647  timer.start();
648  std::shared_ptr<matrix_Type> p1b = PFp;
649  this->pushBack ( p1b, inversed, notTransposed );
650  if ( verbose )
651  {
652  std::cout << " done in " << timer.diff() << " s." << std::endl;
653  }
654 
655  if ( verbose )
656  {
657  std::cout << " >Schur block (c)... ";
658  }
659  timer.start();
660  superPtr_Type precForBlock1 ( PRECFactory::instance().createObject ( M_pressureLaplacianPrec ) );
661  precForBlock1->setDataFromGetPot ( M_dataFile, M_pressureLaplacianPrecDataSection );
662  if ( M_pressureLaplacianPrec == "LinearSolver" )
663  {
664  this->pushBack ( pAp, precForBlock1, vectorStructure, 1, oper->map(), notInversed, notTransposed );
665  }
666  else
667  {
668  this->pushBack ( pAp, precForBlock1, notInversed, notTransposed );
669  }
670  if ( verbose )
671  {
672  std::cout << " done in " << timer.diff() << " s." << std::endl;
673  }
674  }
675  else
676  {
677  if ( verbose )
678  {
679  std::cout << " >Schur block (a)... ";
680  }
681  timer.start();
682  superPtr_Type precForBlock1 ( PRECFactory::instance().createObject ( M_pressureLaplacianPrec ) );
683  precForBlock1->setDataFromGetPot ( M_dataFile, M_pressureLaplacianPrecDataSection );
684  if ( M_pressureLaplacianPrec == "LinearSolver" )
685  {
686  this->pushBack ( pAp, precForBlock1, vectorStructure, 1, oper->map(), notInversed, notTransposed );
687  }
688  else
689  {
690  this->pushBack ( pAp, precForBlock1, notInversed, notTransposed );
691  }
692  if ( verbose )
693  {
694  std::cout << " done in " << timer.diff() << " s." << std::endl;
695  }
696 
697  if ( verbose )
698  {
699  std::cout << " >Schur block (b)... ";
700  }
701  timer.start();
702  std::shared_ptr<matrix_Type> p1b = PFp;
703  this->pushBack ( p1b, inversed, notTransposed );
704  if ( verbose )
705  {
706  std::cout << " done in " << timer.diff() << " s." << std::endl;
707  }
708 
709  if ( verbose )
710  {
711  std::cout << " >Schur block (c)... ";
712  }
713  timer.start();
714  if ( M_pressureMassOperator != "standard" )
715  {
716  this->pushBack ( pMp, inversed, notTransposed );
717  }
718  else
719  {
720  superPtr_Type precForBlock2 ( PRECFactory::instance().createObject ( M_pressureMassPrec ) );
721  precForBlock2->setDataFromGetPot ( M_dataFile, M_pressureMassPrecDataSection );
722  if ( M_pressureMassPrec == "LinearSolver" )
723  {
724  this->pushBack ( pMp, precForBlock2, vectorStructure, 1, oper->map(), notInversed, notTransposed );
725  }
726  else
727  {
728  this->pushBack ( pMp, precForBlock2, notInversed, notTransposed );
729  }
730  }
731  if ( verbose )
732  {
733  std::cout << " done in " << timer.diff() << " s." << std::endl;
734  }
735  }
736 
737  /*
738  * Building the block (the block is inversed)
739  * / I -Bt \
740  * \ 0 I /
741  */
742  if ( verbose )
743  {
744  std::cout << " >Gradient block... ";
745  }
746  timer.start();
747  std::shared_ptr<matrixBlock_Type> P2 ( new matrixBlock_Type ( map ) );
748  P2->setBlockStructure ( blockNumRows, blockNumColumns );
749  P2->blockView ( 0, 0, B11 );
750  P2->blockView ( 0, 1, B12 );
751  P2->blockView ( 1, 1, B22 );
752  MatrixEpetraStructuredUtility::copyBlock ( Bt, B12 );
753  ( *P2 ) *= -1;
754  MatrixEpetraStructuredUtility::createIdentityBlock ( B11 );
755  MatrixEpetraStructuredUtility::createIdentityBlock ( B22 );
756  P2->globalAssemble();
757  std::shared_ptr<matrix_Type> p2 = P2;
758  this->pushBack ( p2, inversed, notTransposed );
759  if ( verbose )
760  {
761  std::cout << " done in " << timer.diff() << " s." << std::endl;
762  }
763 
764  /*
765  * Building the block
766  * / F 0 \
767  * \ 0 I /
768  */
769  if ( M_fullFactorization == true )
770  {
771  if ( M_fluidPrec == "LinearSolver" )
772  {
773  this->pushBack ( p3, precForBlock3, vectorStructure, 0, oper->map(), notInversed, notTransposed );
774  }
775  else
776  {
777  this->pushBack ( p3, precForBlock3, notInversed, notTransposed );
778  }
779  if ( verbose )
780  {
781  std::cout << " done in " << timer.diff() << " s." << std::endl;
782  }
783  }
784  else
785  {
786  if ( verbose )
787  {
788  std::cout << " >Fluid block... ";
789  }
790  timer.start();
791  precForBlock3.reset ( PRECFactory::instance().createObject ( M_fluidPrec ) );
792  precForBlock3->setDataFromGetPot ( M_dataFile, M_fluidPrecDataSection );
793  // if ( M_fluidPrec == "ML2" )
794  // {
795  // PreconditionerML2* tmpPrecPtr = dynamic_cast<PreconditionerML2*> ( precForBlock3.get() );
796  // tmpPrecPtr->setFESpace ( M_uFESpace, M_pFESpace );
797  // }
798  if ( M_fluidPrec == "LinearSolver" )
799  {
800  this->pushBack ( p3, precForBlock3, vectorStructure, 0, oper->map(), notInversed, notTransposed );
801  }
802  else
803  {
804  this->pushBack ( p3, precForBlock3, notInversed, notTransposed );
805  }
806  if ( verbose )
807  {
808  std::cout << " done in " << timer.diff() << " s." << std::endl;
809  }
810  }
811 
812  this->M_preconditionerCreated = true;
813 
814  if ( verbose ) std::cout << " >All the blocks are built" << std::endl
815  << " >";
816  return ( EXIT_SUCCESS );
817 }
818 
819 int
821 {
822  return 2;
823 }
824 
825 int
827 {
828  return 2;
829 }
830 
831 void
833  const std::string& section )
834 {
835  M_dataFile = dataFile;
836  this->createParametersList ( M_list, dataFile, section, "PCD" );
837  this->setParameters ( M_list );
838 }
839 
840 void
841 PreconditionerPCD::setParameters ( Teuchos::ParameterList& list )
842 {
843  M_precType = list.get ( "prectype", "PCD" );
844 
845  M_fluidPrec = list.get ( "subprecs: fluid prec", "ML" );
846  M_fluidPrecDataSection = list.get ( "subprecs: fluid prec data section", "" );
847 
848  M_pressureLaplacianPrec = list.get ( "subprecs: pressure laplacian prec", "ML");
849  M_pressureLaplacianPrecDataSection = list.get ( "subprecs: pressure laplacian prec data section", "" );
850 
851  M_pressureMassPrec = list.get ( "subprecs: pressure mass prec", "ML" );
852  M_pressureMassPrecDataSection = list.get ( "subprecs: pressure mass prec data section", "" );
853 
854  M_pressureLaplacianOperator = list.get ( "pressure laplacian operator", "standard" );
855 
856  M_pressureMassOperator = list.get ( "pressure mass operator", "lumped" );
857  M_setApBoundaryConditions = list.get ( "set Ap boundary conditions", false );
858  M_setFpBoundaryConditions = list.get ( "set Fp boundary conditions", false );
859  M_setMpBoundaryConditions = list.get ( "set Mp boundary conditions", false );
860  M_fullFactorization = list.get ( "full factorization", false );
861  M_useStiffStrain = list.get ( "use stiff strain", false );
862  M_enableTransient = list.get ( "enable transient", true );
863  bool useMinusDivergence = list.get ( "use minus divergence", false );
864  this->setUseMinusDivergence ( useMinusDivergence );
865  M_recomputeNormalVectors = list.get ( "recompute normal vectors", true );
866  M_schurOperatorReverseOrder = list.get ( "Schur operator reverse order", false );
867  M_inflowBoundaryType = list.get ( "inflow boundary type", "Robin" );
868  M_outflowBoundaryType = list.get ( "outflow boundary type", "Neumann" );
869  M_characteristicBoundaryType = list.get ( "characteristic boundary type", "Neumann" );
870 }
871 
872 void
874 {
875  M_uFESpace = uFESpace;
876  M_pFESpace = pFESpace;
877  M_adrPressureAssembler.setup ( pFESpace, uFESpace ); // p,beta=u
878  M_adrVelocityAssembler.setup ( uFESpace, uFESpace ); // u,beta=u
879  M_beta.reset ( new vector_Type ( M_uFESpace->map() + M_pFESpace->map() ) );
880  *M_beta *= 0;
881 
882  // We setup the size of the blocks
883  M_velocityBlockSize = M_uFESpace->fieldDim() * M_uFESpace->dof().numTotalDof();
884  M_pressureBlockSize = M_pFESpace->dof().numTotalDof();
885 }
886 
887 void
889 {
890  M_bcHandlerPtr = bchPtr;
891 }
892 
893 void
894 PreconditionerPCD::setTimestep ( const Real& timestep )
895 {
896  M_timestep = timestep;
897 }
898 
899 void
900 PreconditionerPCD::setViscosity ( const Real& viscosity )
901 {
902  M_viscosity = viscosity;
903 }
904 
905 void
906 PreconditionerPCD::setDensity ( const Real& density )
907 {
908  M_density = density;
909 }
910 
911 void
912 PreconditionerPCD::setUseMinusDivergence ( const bool& useMinusDivergence )
913 {
914  if ( useMinusDivergence )
915  {
916  M_divergenceCoeff = -1.0;
917  }
918  else
919  {
920  M_divergenceCoeff = 1.0;
921  }
922 }
923 
924 void
926 {
927  bool verbose ( false );
928  if ( M_comm->MyPID() == 0 )
929  {
930  verbose = true;
931  }
932 
933  LifeChrono timer;
934 
935  if ( verbose )
936  {
937  std::cout << " >Computing the normal vectors on the boundary... ";
938  }
939  timer.start();
940 
941  //-----------------------------------------------------
942  // STEP 1: Calculating the normals
943  //-----------------------------------------------------
944 
945  vector_Type repNormals ( M_pFESpace->map() + M_pFESpace->map() + M_pFESpace->map(), Repeated );
946  UInt numTotalDofs ( M_pFESpace->dof().numTotalDof() );
947 
948  //Loop on the Faces
949  UInt numBoundaryFacets ( M_pFESpace->mesh()->numBoundaryFacets() );
950  for ( UInt iFace = 0; iFace < numBoundaryFacets; ++iFace )
951  {
952  //Update the currentBdFE with the face data
953  M_pFESpace->feBd().update ( M_pFESpace->mesh()->boundaryFacet ( iFace ), UPDATE_NORMALS | UPDATE_W_ROOT_DET_METRIC );
954  UInt nDofF = M_pFESpace->feBd().nbFEDof();
955 
956  //For each node on the face
957  for ( UInt icheck = 0; icheck < nDofF; ++icheck )
958  {
959  ID idf = M_pFESpace->dof().localToGlobalMapByBdFacet ( iFace, icheck );
960 
961  //If the point is on this processor
962  if ( repNormals.isGlobalIDPresent ( idf ) )
963  {
964  // ID flag = M_flags[idf];
965 
966  //if the normal is not already calculated
967  //and the marker correspond to the flag of the point
968  // if ((flag == M_uFESpace->mesh().boundaryFacet( iFace ).markerID())||(flag == 0))
969  // {
970  //Warning: the normal is taken in the first Gauss point
971  //since the normal is the same over the triangle
972  //(not true in the case of quadratic and bilinear maps)
973  Real nx ( M_pFESpace->feBd().normal ( 0, 0 ) );
974  Real ny ( M_pFESpace->feBd().normal ( 1, 0 ) );
975  Real nz ( M_pFESpace->feBd().normal ( 2, 0 ) );
976 
977  //We get the area
978  Real area ( M_pFESpace->feBd().measure() );
979 
980  //We update the normal component of the boundary point
981  ( repNormals ) [idf] += nx * area;
982  ( repNormals ) [idf + numTotalDofs] += ny * area;
983  ( repNormals ) [idf + 2 * numTotalDofs] += nz * area;
984  // }
985  }
986  }
987  }
988 
989  //-----------------------------------------------------
990  // STEP 2: Gathering the data from others processors
991  //-----------------------------------------------------
992 
993  M_normalVectors.reset ( new vector_Type ( repNormals, Unique ) );
994 
995  //-----------------------------------------------------
996  // STEP 3: Normalizing the vectors
997  //-----------------------------------------------------
998 
999  //We obtain the ID of the element
1000  Int NumMyElements = M_normalVectors->map().map ( Unique )->NumMyElements();
1001  std::vector<Int> MyGlobalElements ( NumMyElements );
1002  M_normalVectors->map().map ( Unique )->MyGlobalElements ( & ( MyGlobalElements[0] ) );
1003 
1004  //We normalize the normal
1005  Real norm;
1006  UInt id;
1007 
1008  //Need to run only over the first third of MyGlobalElements
1009  //(the larger values are the y and z components)
1010  for ( Int i ( 0 ); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
1011  {
1012  id = MyGlobalElements[i];
1013  Real nx ( ( *M_normalVectors ) [id] );
1014  Real ny ( ( *M_normalVectors ) [id + numTotalDofs] );
1015  Real nz ( ( *M_normalVectors ) [id + 2 * numTotalDofs] );
1016  norm = sqrt ( nx * nx + ny * ny + nz * nz );
1017 
1018  // If the norm is exactly 0 it means that the point is an interior point
1019  if ( norm != 0.0 )
1020  {
1021  ( *M_normalVectors ) [id] /= norm;
1022  ( *M_normalVectors ) [id + numTotalDofs] /= norm;
1023  ( *M_normalVectors ) [id + 2 * numTotalDofs] /= norm;
1024  }
1025  }
1026 
1027  if ( verbose )
1028  {
1029  std::cout << " done in " << timer.diff() << " s." << std::endl;
1030  }
1031 }
1032 
1035 {
1036  if ( M_normalVectors.get() == 0 || M_recomputeNormalVectors )
1037  {
1039  }
1040 
1041  vectorPtr_Type robinCoeffVector ( new vector_Type ( M_pFESpace->map(), Unique ) );
1042 
1043  //We obtain the ID of the element
1044  Int numVelocityTotalDofs ( M_uFESpace->dof().numTotalDof() );
1045  Int numPressureTotalDofs ( M_pFESpace->dof().numTotalDof() );
1046  Int NumMyElements = robinCoeffVector->map().map ( Unique )->NumMyElements();
1047  std::vector<Int> MyGlobalElements ( NumMyElements );
1048  robinCoeffVector->map().map ( Unique )->MyGlobalElements ( & ( MyGlobalElements[0] ) );
1049 
1050  //We compute (beta*n)/nu
1051  UInt id;
1052  Real invNu = -M_density / M_viscosity;
1053 
1054  //Need to run only over the first third of MyGlobalElements
1055  //(the larger values are the y and z components)
1056  for ( Int i ( 0 ); i < NumMyElements; ++i )
1057  {
1058  id = MyGlobalElements[i];
1059  Real x ( ( *M_normalVectors ) [id] * ( *M_beta ) [id] );
1060  Real y ( ( *M_normalVectors ) [id + numPressureTotalDofs] * ( *M_beta ) [id + numVelocityTotalDofs] );
1061  Real z ( ( *M_normalVectors ) [id + 2 * numPressureTotalDofs] * ( *M_beta ) [id + 2 * numVelocityTotalDofs] );
1062  ( *robinCoeffVector ) [id] = ( x + y + z ) * invNu;
1063  }
1064 
1065  return robinCoeffVector;
1066 }
1067 
1068 void
1070  matrixPtr_type Fp, UInt FpOffset,
1071  matrixPtr_type Mp, UInt MpOffset )
1072 {
1073  std::string boundaryType ( "none" );
1074  Real indicator ( 0.0 );
1075 
1076  vector_Type robinCoeffVector ( *computeRobinCoefficient(), Repeated );
1077  vector_Type robinRHS ( M_pFESpace->map(), Repeated );
1078  BCVector uRobin ( robinRHS, M_pFESpace->dof().numTotalDof(), 0 );
1079  uRobin.setRobinCoeffVector ( robinCoeffVector );
1080  uRobin.setBetaCoeff ( 0 );
1081  BCFunctionBase uZero ( fZero );
1082 
1083  // <-- DEBUG
1084  /*{
1085  Int NumMyElements = M_pFESpace->map().map( Unique )->NumMyElements();
1086  std::vector<Int> MyGlobalElements( NumMyElements );
1087  M_pFESpace->map().map( Unique )->MyGlobalElements(&MyGlobalElements[0]);
1088  ID idof(0);
1089 
1090  UInt numPressureDofs = M_pFESpace->dof().numTotalDof();
1091 
1092  VTKWriter writer;
1093  writer.setLabel( "Debug normal and boundary classification" );
1094  writer.addScalarField( "BCType" );
1095  writer.addVectorField( "Normal_vectors" );
1096 
1097  Real x, y, z;
1098  UInt boundaryTypeId;
1099  for ( Int i(0); i<NumMyElements; ++i )
1100  {
1101  idof = MyGlobalElements[i];
1102 
1103  if( robinCoeffVector[idof] > 0.0 )
1104  {
1105  // Inflow
1106  boundaryTypeId = 1;
1107  }
1108  else if( robinCoeffVector[idof] < 0.0 )
1109  {
1110  // Outflow
1111  boundaryTypeId = 2;
1112  }
1113  else if( robinCoeffVector[idof] == 0.0 )
1114  {
1115  // Characteristic
1116  boundaryTypeId = 3;
1117  }
1118  writer.addToScalarField( "BCType", boundaryTypeId );
1119  writer.addToScalarField( "Robin_coeff", robinCoeffVector[idof] );
1120  writer.addToVectorField( "Normal_vectors",
1121  (*M_normalVectors)[idof],
1122  (*M_normalVectors)[idof + numPressureDofs],
1123  (*M_normalVectors)[idof + 2*numPressureDofs] );
1124 
1125  for ( UInt j( 0 ); j < M_pFESpace->mesh()->pointList.size(); ++j )
1126  {
1127  if ( idof == M_pFESpace->mesh()->pointList[j].id() )
1128  {
1129  x = M_pFESpace->mesh()->pointList[j].x();
1130  y = M_pFESpace->mesh()->pointList[j].y();
1131  z = M_pFESpace->mesh()->pointList[j].z();
1132  j = M_pFESpace->mesh()->pointList.size();
1133  }
1134  }
1135  writer.addPoint( x, y, z );
1136  }
1137  std::string fileName( "debugInfos_" );
1138  std::ostringstream ossMyPid;
1139  ossMyPid << M_pFESpace->map().comm().MyPID();
1140  fileName.append( ossMyPid.str() );
1141  writer.write( fileName );
1142  }*/
1143  // --> DEBUG END
1144 
1145  BCHandler bcHandler;
1146 
1147  // BC for the inflow, outflow, and characteristic boundaries
1148  BCBase* currentBoundary;
1149  BCBase* inflowBoundary, *outflowBoundary, *characteristicBoundary;
1150 
1151  // inflow
1152  if ( M_inflowBoundaryType == "Dirichlet" )
1153  {
1154  bcHandler.addBC ( BCBase ( "inflow",
1155  1,
1156  Essential,
1157  Full,
1158  uZero,
1159  1 ) );
1160 
1161  }
1162  else if ( M_inflowBoundaryType == "Neumann" )
1163  {
1164  bcHandler.addBC ( BCBase ( "inflow",
1165  1,
1166  Natural,
1167  Full,
1168  uZero,
1169  1 ) );
1170  }
1171  else if ( M_inflowBoundaryType == "Robin" )
1172  {
1173  bcHandler.addBC ( BCBase ( "inflow",
1174  1,
1175  Robin,
1176  Full,
1177  uRobin,
1178  1 ) );
1179  }
1180 
1181  // outflow
1182  if ( M_outflowBoundaryType == "Dirichlet" )
1183  {
1184  bcHandler.addBC ( BCBase ( "outflow",
1185  2,
1186  Essential,
1187  Full,
1188  uZero,
1189  1 ) );
1190  }
1191  else if ( M_outflowBoundaryType == "Neumann" )
1192  {
1193  bcHandler.addBC ( BCBase ( "outflow",
1194  2,
1195  Natural,
1196  Full,
1197  uZero,
1198  1 ) );
1199  }
1200  else if ( M_outflowBoundaryType == "Robin" )
1201  {
1202  bcHandler.addBC ( BCBase ( "outflow",
1203  2,
1204  Robin,
1205  Full,
1206  uRobin,
1207  1 ) );
1208  }
1209 
1210  // characteristic
1211  if ( M_characteristicBoundaryType == "Dirichlet" )
1212  {
1213  bcHandler.addBC ( BCBase ( "characteristic",
1214  3,
1215  Essential,
1216  Full,
1217  uZero,
1218  1 ) );
1219  }
1220  else if ( M_characteristicBoundaryType == "Neumann" )
1221  {
1222  bcHandler.addBC ( BCBase ( "characteristic",
1223  3,
1224  Natural,
1225  Full,
1226  uZero,
1227  1 ) );
1228  }
1229  else if ( M_characteristicBoundaryType == "Robin" )
1230  {
1231  bcHandler.addBC ( BCBase ( "characteristic",
1232  3,
1233  Robin,
1234  Full,
1235  uRobin,
1236  1 ) );
1237  }
1238 
1239  inflowBoundary = & ( bcHandler.findBCWithFlag ( 1 ) );
1240  outflowBoundary = & ( bcHandler.findBCWithFlag ( 2 ) );
1241  characteristicBoundary = & ( bcHandler.findBCWithFlag ( 3 ) );
1242 
1243 // bcFlag_Type elementMarker; //will store the marker of the element
1244 
1245  // Loop on boundary faces
1246  for ( ID iBoundaryElement = 0 ; iBoundaryElement < M_pFESpace->mesh()->numBoundaryFacets(); ++iBoundaryElement )
1247  {
1248  // construction of localToGlobalMapOnBElem (this part should be moved in DOF.hpp)
1249  M_pFESpace->feBd().update ( M_pFESpace->mesh()->boundaryFacet ( iBoundaryElement ), UPDATE_W_ROOT_DET_METRIC ); // updating finite element information
1250 // elementMarker = M_pFESpace->mesh()->boundaryFacet ( iBoundaryElement ).markerID(); // We keep the element marker
1251 
1252 
1253  //vector containing the local to global map on each element
1254  std::vector<ID> localToGlobalMapOnBElem = M_pFESpace->dof().localToGlobalMapOnBdFacet ( iBoundaryElement );
1255 
1256  // We classify and build bc objects:
1257  // a) inflow where -(w*n)/nu > 0
1258  // b) outflow where -(w*n)/nu < 0
1259  // c) characteristic where -(w*n)/nu = 0
1260  indicator = 0.0;
1261  for (ID lDof = 0; lDof < localToGlobalMapOnBElem.size(); lDof++)
1262  {
1263  ID gDof = localToGlobalMapOnBElem[lDof];
1264  indicator += robinCoeffVector[gDof];
1265  }
1266  if ( indicator > 0.0 ) // inflow
1267  {
1268  boundaryType = M_inflowBoundaryType;
1269  currentBoundary = inflowBoundary;
1270  }
1271  else if ( indicator < 0.0 ) // outflow
1272  {
1273  boundaryType = M_outflowBoundaryType;
1274  currentBoundary = outflowBoundary;
1275  }
1276  else if ( indicator == 0.0 ) // characteristic
1277  {
1278  boundaryType = M_characteristicBoundaryType;
1279  currentBoundary = characteristicBoundary;
1280  }
1281 
1282  // Setup the boundary conditions
1283  if ( boundaryType == "Dirichlet" )
1284  {
1285  for (ID lDof = 0; lDof < localToGlobalMapOnBElem.size(); lDof++)
1286  {
1287  ID gDof = localToGlobalMapOnBElem[lDof]; // global DOF
1288 
1289  //providing Essential boundary conditions with user defined functions
1290  currentBoundary->addBCIdentifier ( new BCIdentifierEssential ( gDof, 0.0, 0.0, 0.0 ) );
1291  }
1292  }
1293  else if ( boundaryType == "Robin" )
1294  {
1295  //providing Robin boundary conditions with global DOFs on element
1296  currentBoundary->addBCIdentifier ( new BCIdentifierNatural ( iBoundaryElement, localToGlobalMapOnBElem ) );
1297  }
1298  else if ( boundaryType == "Neumann" )
1299  {
1300  // For Neumann BC we do not need to do anything
1301  }
1302  }
1303 
1304  // Copying the IDs
1305  inflowBoundary->copyIdSetIntoIdVector();
1306  outflowBoundary->copyIdSetIntoIdVector();
1307  characteristicBoundary->copyIdSetIntoIdVector();
1308 
1309  // We do not update the BCHandler!
1310 
1312  {
1313  bcHandler.setOffset ( ApOffset );
1314  bcManageMatrix ( *Ap, *M_pFESpace->mesh(), M_pFESpace->dof(), bcHandler, M_pFESpace->feBd(), 1.0, 0.0 );
1315  }
1317  {
1318  bcHandler.setOffset ( FpOffset );
1319  bcManageMatrix ( *Fp, *M_pFESpace->mesh(), M_pFESpace->dof(), bcHandler, M_pFESpace->feBd(), 1.0, 0.0 );
1320  }
1322  {
1323  bcHandler.setOffset ( MpOffset );
1324  bcManageMatrix ( *Mp, *M_pFESpace->mesh(), M_pFESpace->dof(), bcHandler, M_pFESpace->feBd(), 1.0, 0.0 );
1325  }
1326  Ap->globalAssemble();
1327  Fp->globalAssemble();
1328  Mp->globalAssemble();
1329 }
1330 
1331 } // namespace LifeV
bool isGlobalIDPresent(const UInt row) const
Access operators.
BCBase & findBCWithFlag(const bcFlag_Type &aFlag)
Extract a BC in the list according to its flag.
Definition: BCHandler.cpp:304
PreconditionerPCD(std::shared_ptr< Epetra_Comm > comm=std::shared_ptr< Epetra_Comm >(new Epetra_MpiComm(MPI_COMM_WORLD)))
default constructor
void start()
Start the timer.
Definition: LifeChrono.hpp:93
std::shared_ptr< vector_Type > vectorPtr_Type
virtual void setParameters(Teuchos::ParameterList &list)
Method to setup the solver using Teuchos::ParameterList.
std::shared_ptr< BCHandler > BCHandlerPtr_Type
double condest()
Return an estimation of the conditionement number of the preconditioner.
BCHandler - class for handling boundary conditions.
Definition: BCHandler.hpp:100
VectorBlockStructure - class representing the structure of a vector.
void setFESpace(FESpacePtr_Type uFESpace, FESpacePtr_Type pFESpace)
Setter for the FESpace.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void updateInverseJacobian(const UInt &iQuadPt)
void setDataFromGetPot(const GetPot &dataFile, const std::string &section)
Setter using GetPot.
BCHandlerPtr_Type M_bcHandlerPtr
int buildPreconditioner(matrixPtr_type &A)
Build the preconditioner.
void setBetaCoeff(const Real &betaCoeff)
set the Beta coefficient FE vector
Definition: BCVector.hpp:275
BCFunctionBase - class that holds the function used for prescribing boundary conditions.
Definition: BCFunction.hpp:77
void setUseMinusDivergence(const bool &useMinusDivergence)
Setter to know if we used B or -B in the discretization of the Navier-Stokes equations.
void setOffset(const UInt &offset)
Set offset in all boundary conditions.
Definition: BCHandler.cpp:282
std::shared_ptr< matrix_Type > matrixPtr_type
uint32_type ID
IDs.
Definition: LifeV.hpp:194
void setTimestep(const Real &timestep)
Setter for the timestep.
virtual ~PreconditionerPCD()
constructor from matrix A.
void setBCByBoundaryType(matrixPtr_type Ap, UInt ApOffset, matrixPtr_type Fp, UInt FpOffset, matrixPtr_type Mp, UInt MpOffset)
void setBCHandler(BCHandlerPtr_Type bchPtr)
Setter for the BCHandler.
std::shared_ptr< FESpace< mesh_Type, map_Type > > FESpacePtr_Type
vectorPtr_Type computeRobinCoefficient()
void setRobinCoeffVector(const vector_Type &robinBoundaryMassCoeffVector)
set the boundary mass coefficient FE vector for Robin boundary conditions
Definition: BCVector.cpp:167
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="PCD")
Create the list of parameters of the preconditioner.
void setViscosity(const Real &viscosity)
Setter for the viscosity.
const UInt nDimensions(NDIM)
void setDensity(const Real &density)
Setter for the density.
BCVector - class that holds the FE vectors used for prescribing boundary conditions.
Definition: BCVector.hpp:381
Teuchos::ParameterList list_Type
void copyIdSetIntoIdVector()
Definition: BCBase.cpp:795
std::vector< std::shared_ptr< BCIdentifierBase > > M_idVector
container for id&#39;s when the list is finalized
Definition: BCBase.hpp:647
std::shared_ptr< super_Type > superPtr_Type
void updateBeta(const vector_Type &beta)
Update the vector beta of the convective term in Fp.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
data_type & operator[](const UInt row)
Access operators.
MatrixEpetraStructuredView< Real > matrixBlockView_Type