LifeV
lifev/fsi/examples/example_SmoothAneurysm/main.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 File containing the Monolithic Test
30  *
31  * @date 2009-04-09
32  * @author Paolo Crosetto <crosetto@iacspc70.epfl.ch>
33  *
34  * @contributor Cristiano Malossi <cristiano.malossi@epfl.ch>
35  * @maintainer Paolo Crosetto <crosetto@iacspc70.epfl.ch>
36  *
37  * Monolithic problem. Features:
38  * - fullMonolithic (CE):
39  * -# solution with exact Newton (semiImplicit = false, useShapeDerivatives = true, domainVelImplicit = false, convectiveTermDer = false)
40  * -# solution with quasi Newton (semiImplicit = false, useShapeDerivatives = false, domainVelImplicit = false, convectiveTermDer = false)
41  * -# preconditioner choice: see the classes Monolithic and fullMonolithic
42  * - Monolithic (GCE):
43  * -# solution extrapolating the fluid domain (semiImplicit = true, useShapeDerivatives = false, domainVelImplicit = false, convectiveTermDer = false)
44  * -# preconditioner choice: see the classes Monolithic and fullMonolithic
45  * - boundary conditions:
46  * -# Neumann
47  * -# Dirichlet
48  * -# Robin
49  * -# Fluxes (defective)
50  * -# absorbing \cite BadiaNobileVergara2008 :
51  * through the class flowConditions.
52  * - optional: computation of wall shear stress (not properly tested in parallel)
53  * - optional: computation of the largest singular values of the preconditioned matrix
54  *
55  * \b Features:
56  * This test by default solves the FSI probem discretized in time using the GCE or CE methods, implemented respectively
57  * in the files monolithicGE.hpp and monolithicGI.hpp . The geometry is that of a tube (benchmark test introduced in \cite Gerbeau2003).
58  * In this test the boundary conditions assigned are of type:
59  * - flux (defective b.c.) at the inlet
60  * - absorbing (see \cite BadiaNobileVergara2008) at the outlet
61  * - Robin b.c. on the solid external wall
62  * - Dirichlet homogeneous at the solid rings on the inlet-outlet (clamped tube).
63  *
64  * The output is written at every timestep, in HDF5 (if available) or ensight format.
65  * This test implements an inlet flux bundary condition for the first three time steps, then at the fourth time step
66  * the inlet boundary condition is replaced by a Neumann one (this mechanism is useful to implement rudimental valves).
67  * The outflow boundary condition is of absorbing type. At the outer wall for the structure a Robin condition is imposed.
68  */
69 
70 #undef HAVE_HDF5
71 
72 #include <cassert>
73 #include <cstdlib>
74 
75 #include <boost/timer.hpp>
76 
77 #include <Epetra_ConfigDefs.h>
78 #ifdef EPETRA_MPI
79 #include <mpi.h>
80 #include <Epetra_MpiComm.h>
81 #else
82 #include <Epetra_SerialComm.h>
83 #endif
84 
85 
86 // LifeV includes
87 //#include <lifev/core/fem/BCHandler.hpp>
88 #include <lifev/core/LifeV.hpp>
89 
90 #include <lifev/core/algorithm/PreconditionerIfpack.hpp>
91 #include <lifev/core/algorithm/PreconditionerML.hpp>
92 
93 // The registration of the material laws is done inside the
94 // FSIOperator class
95 #include <lifev/fsi/solver/FSISolver.hpp>
96 
97 #include <lifev/structure/solver/StructuralOperator.hpp>
98 #include <lifev/fsi/solver/FSIMonolithicGI.hpp>
99 
100 #include <lifev/core/filter/ExporterEnsight.hpp>
101 #include <lifev/core/filter/ExporterEmpty.hpp>
102 #ifdef HAVE_HDF5
103 #include <lifev/core/filter/ExporterHDF5.hpp>
104 #endif
105 
106 #include <lifev/fsi/examples/example_SmoothAneurysm/flowConditions.hpp>
107 #include <lifev/fsi/examples/example_SmoothAneurysm/ud_functions.hpp>
108 #include <lifev/fsi/examples/example_SmoothAneurysm/resistance.hpp>
109 #include <lifev/fsi/examples/example_SmoothAneurysm/boundaryConditions.hpp>
110 
111 #define OUTLET 3
112 
113 class Problem
114 {
115 public:
116 
118 
119  typedef LifeV::FSIOperator::data_Type data_Type;
120  typedef LifeV::FSIOperator::dataPtr_Type dataPtr_Type;
121 
122  typedef LifeV::FSIOperator::vector_Type vector_Type;
123  typedef LifeV::FSIOperator::vectorPtr_Type vectorPtr_Type;
124 
126 
127  typedef LifeV::ExporterEnsight<LifeV::FSIOperator::mesh_Type> ensightFilter_Type;
129 #ifdef HAVE_HDF5
132 #endif
134 
137 
138 #ifdef ENABLE_ANISOTROPIC_LAW
139  // typedefs for fibers
140  // Boost function for fiber direction
141  typedef boost::function<LifeV::Real ( LifeV::Real const&, LifeV::Real const&, LifeV::Real const&, LifeV::Real const&, LifeV::ID const& ) > fiberFunction_Type;
143 
146 
148 #endif
149 
150  /*!
151  This routine sets up the problem:
152 
153  -# create the standard boundary conditions for the fluid and
154  structure problems.
155 
156  -# initialize and setup the FSIsolver
157  */
158 
159  Problem ( GetPot const& data_file, std::shared_ptr<Epetra_Comm> comm) :
160  M_Tstart (0.),
161  M_tolSave (1),
162  M_saveEvery (1),
163  IR1( ),
164  M_comm( comm )
165  {
166  using namespace LifeV;
167 
168  // Building the communicator for output purposes
169  //M_comm.reset( new Epetra_Comm( MPI_COMM_WORLD ) );
170 
171  M_data = dataPtr_Type ( new data_Type() );
172  M_data->setup ( data_file );
173 
174  M_data->showMe();
175 
176 #ifdef DEBUG
177  debugStream ( 10000 ) << "creating FSISolver with operator : " << method << "\n";
178 #endif
179  M_fsi = fsi_solver_ptr ( new FSISolver( ) );
180  MPI_Barrier ( MPI_COMM_WORLD );
181 
182 #ifdef DEBUG
183  debugStream ( 10000 ) << "Setting up data from GetPot \n";
184 #endif
185  M_fsi->setData ( M_data );
186  M_fsi->FSIOper()->setDataFile ( data_file ); //TO BE REMOVED!
187  MPI_Barrier ( MPI_COMM_WORLD );
188 
189  // Setting FESpace and DOF
190 
191  std::string fluidMeshPartitioned = data_file ( "problem/fluidMeshPartitioned", "none" );
192  std::string solidMeshPartitioned = data_file ( "problem/solidMeshPartitioned", "none" );
193 #ifdef HAVE_HDF5
194  if ( fluidMeshPartitioned.compare ( "none" ) )
195  {
196  FSIOperator::meshFilter_Type fluidMeshFilter ( data_file, fluidMeshPartitioned );
197  fluidMeshFilter.setComm ( M_fsi->FSIOper()->worldComm() );
198  FSIOperator::meshFilter_Type solidMeshFilter ( data_file, solidMeshPartitioned );
199  solidMeshFilter.setComm ( M_fsi->FSIOper( )->worldComm( ) );
200  M_fsi->FSIOper( )->partitionMeshes ( fluidMeshFilter, solidMeshFilter );
201  M_fsi->FSIOper( )->setupFEspace( );
202  M_fsi->FSIOper( )->setupDOF ( fluidMeshFilter );
203  fluidMeshFilter.closeFile( );
204  solidMeshFilter.closeFile( );
205  }
206  else
207 #endif
208  {
209  M_fsi->FSIOper( )->partitionMeshes( );
210  M_fsi->FSIOper( )->setupFEspace( );
211  M_fsi->FSIOper( )->setupDOF( );
212  }
213 
214  std::cout << "register MonolithicGI : " << FSIMonolithicGI::S_register << std::endl;
215 
216  debugStream ( 10000 ) << "Setting up the FESpace and DOF \n";
217 
218  MPI_Barrier ( MPI_COMM_WORLD );
219 
220  Real resistance = data_file ("fluid/physics/resistance", 0.0);
221  IR1.setQuantities( *(M_fsi->FSIOper()), resistance );
222 
223 #ifdef DEBUG
224  debugStream ( 10000 ) << "Setting up the BC \n";
225 #endif
226  M_fsi->setFluidBC ( BCh_monolithicFlux ( true ) );
227  M_fsi->setSolidBC ( BCh_monolithicSolid ( *M_fsi->FSIOper( ) ) );
228 
229  M_fsi->setup (/*data_file*/);
230 
231 
232  FSIOperator::fluidBchandlerPtr_Type BCh_fluidM ( new FSIOperator::fluidBchandler_Type );
233 
234  BCFunctionBase bcf (fZero);
235  BCFunctionBase pressureEpsilon (epsilon);
236 
237  BCFunctionBase InletVect (aneurismFluxInVectorial);
238 
239  //Inlets
240  BCh_fluidM->addBC ("InFlow" , INLET, EssentialVertices, Full, InletVect, 3);
241  BCh_fluidM->addBC ("InFlow" , 20, EssentialVertices, Full, bcf, 3);
242 
243  // resistanceBC.vector() gives back the vector we are considering.
244  BCh_fluidM->addBC ("out3", OUTLET, Resistance, Full, IR1.vector() , 3);
245 
246  M_fsi->setFluidBC ( BCh_fluidM );
247  M_fsi->setHarmonicExtensionBC ( BCh_harmonicExtension ( *M_fsi->FSIOper( ) ) );
248 
249  dynamic_cast<LifeV::FSIMonolithic*> (M_fsi->FSIOper().get() )->mergeBCHandlers();
250 
251 #ifdef DEBUG
252  debugStream ( 10000 ) << "BC set\n";
253 #endif
254 
255  std::string const exporterType = data_file ( "exporter/type", "ensight" );
256  std::string const fluidName = data_file ( "exporter/fluid/filename", "fluid" );
257  std::string const solidName = data_file ( "exporter/solid/filename", "solid" );
258 
259 #ifdef HAVE_HDF5
260  if (exporterType.compare ("hdf5") == 0)
261  {
262  M_exporterFluid.reset ( new hdf5Filter_Type ( data_file, fluidName) );
263  M_exporterSolid.reset ( new hdf5Filter_Type ( data_file, solidName) );
264  }
265  else
266 #endif
267  {
268  if (exporterType.compare ("none") == 0)
269  {
270  M_exporterFluid.reset ( new ExporterEmpty<RegionMesh<LinearTetra> > ( data_file, M_fsi->FSIOper()->uFESpace().mesh(), fluidName, M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ) );
271  M_exporterSolid.reset ( new ExporterEmpty<RegionMesh<LinearTetra> > ( data_file, M_fsi->FSIOper()->dFESpace().mesh(), solidName, M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ) );
272  }
273  else
274  {
275  M_exporterFluid.reset ( new ensightFilter_Type ( data_file, fluidName) );
276  M_exporterSolid.reset ( new ensightFilter_Type ( data_file, solidName) );
277  }
278  }
279 
280 #ifdef ENABLE_ANISOTROPIC_LAW
281  vectorFiberFunctionPtr_Type pointerToVectorOfFamilies;
282  listOfFiberDirections_Type fiberDirections;
283  fibersDirectionList setOfFiberFunctions;
284 
285  if( !M_fsi->FSIOper()->dataSolid()->constitutiveLaw().compare("anisotropic") )
286  {
287  // Setting the fibers
288  pointerToVectorOfFamilies.reset( new vectorFiberFunction_Type( ) );
289  (*pointerToVectorOfFamilies).resize( M_fsi->FSIOper()->dataSolid()->numberFibersFamilies( ) );
290 
291  fiberDirections.resize( M_fsi->FSIOper()->dataSolid()->numberFibersFamilies( ) );
292 
293  setOfFiberFunctions.setupFiberDefinitions( M_fsi->FSIOper()->dataSolid()->numberFibersFamilies( ) );
294  }
295 #endif
296 
297 
298  //reading the saveEvery
299  M_saveEvery = data_file ("exporter/saveEvery", 1);
300  M_tolSave = data_file ("exporter/tolSave", 1);
301 
302  // load using ensight/hdf5
303  std::string restartType (data_file ("importer/restartFSI", "false") );
304 
305  if (!restartType.compare ("true") )
306  {
307  restartFSI (data_file);
308  }
309  else if ( !restartType.compare ("vectors") )
310  {
312 
313  M_velAndPressure.reset ( new vector_Type ( M_fsi->FSIOper()->fluid().getMap(), LifeV::Unique ) );
314  M_fluidDisp.reset ( new vector_Type ( M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique ) );
315  M_solidDisp.reset ( new vector_Type ( M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique ) );
316  // M_solidVel.reset ( new vector_Type( M_fsi->FSIOper()->dFESpace().map(), M_exporterSolid->mapType() ));
317  M_WS.reset ( new vector_Type ( M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique ) );
318 
319  }
320  else
321  {
322  M_fsi->initializeMonolithicOperator();
323 
324  M_velAndPressure.reset ( new vector_Type ( M_fsi->FSIOper()->fluid().getMap(), LifeV::Unique ) );
325  M_fluidDisp.reset ( new vector_Type ( M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique ) );
326  M_solidDisp.reset ( new vector_Type ( M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique ) );
327  // M_solidVel.reset ( new vector_Type( M_fsi->FSIOper()->dFESpace().map(), M_exporterSolid->mapType() ));
328  M_WS.reset ( new vector_Type ( M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique ) );
329  }
330 
331 
332  M_exporterFluid->setMeshProcId (M_fsi->FSIOper()->uFESpace().mesh(), M_fsi->FSIOper()->uFESpace().map().comm().MyPID() );
333  M_exporterSolid->setMeshProcId (M_fsi->FSIOper()->dFESpace().mesh(), M_fsi->FSIOper()->dFESpace().map().comm().MyPID() );
334  M_exporterFluid->addVariable ( ExporterData<FSIOperator::mesh_Type>::VectorField, "f-velocity",
335  M_fsi->FSIOper()->uFESpacePtr(), M_velAndPressure, UInt (0) );
336  M_exporterFluid->addVariable ( ExporterData<FSIOperator::mesh_Type>::ScalarField, "f-pressure",
337  M_fsi->FSIOper()->pFESpacePtr(), M_velAndPressure,
338  UInt (3 * M_fsi->FSIOper()->uFESpace().dof().numTotalDof() ) );
339 
340  M_exporterFluid->addVariable ( ExporterData<FSIOperator::mesh_Type>::VectorField, "f-displacement",
341  M_fsi->FSIOper()->mmFESpacePtr(), M_fluidDisp, UInt (0) );
342 
343 
344  M_exporterSolid->addVariable ( ExporterData<FSIOperator::mesh_Type>::VectorField, "s-displacement",
345  M_fsi->FSIOper()->dFESpacePtr(), M_solidDisp, UInt (0) );
346 
347 #ifdef ENABLE_ANISOTROPIC_LAW
348  if( !M_fsi->FSIOper()->dataSolid()->constitutiveLaw().compare("anisotropic") )
349  {
350 
351  // Initializing fibers
352  // Setting the vector of fibers functions
353  for( UInt k(1); k <= pointerToVectorOfFamilies->size( ); k++ )
354  {
355  // Setting up the name of the function to define the family
356  std::string family="Family";
357  // adding the number of the family
358  std::string familyNumber;
359  std::ostringstream number;
360  number << ( k );
361  familyNumber = number.str();
362 
363  // Name of the function to create
364  std::string creationString = family + familyNumber;
365  (*pointerToVectorOfFamilies)[ k-1 ].reset( new fiberFunction_Type() );
366  (*pointerToVectorOfFamilies)[ k-1 ] = setOfFiberFunctions.fiberDefinition( creationString );
367 
368  fiberDirections[ k-1 ].reset( new vector_Type( M_fsi->FSIOper()->dFESpacePtr()->map() , Unique) );
369  }
370 
371  //! 3.b Setting the fibers in the abstract class of Anisotropic materials
372  M_fsi->FSIOper()->solid().material()->anisotropicLaw()->setupFiberDirections( pointerToVectorOfFamilies );
373 
374  // Adding the fibers vectors
375  // Setting the vector of fibers functions
376  for( UInt k(1); k <= pointerToVectorOfFamilies->size( ); k++ )
377  {
378  // Setting up the name of the function to define the family
379  std::string family="Family-";
380  // adding the number of the family
381  std::string familyNumber;
382  std::ostringstream number;
383  number << ( k );
384  familyNumber = number.str();
385 
386  // Name of the function to create
387  std::string creationString = family + familyNumber;
388  M_exporterSolid->addVariable ( ExporterData<RegionMesh<LinearTetra> >::VectorField, creationString, M_fsi->FSIOper()->dFESpacePtr(), fiberDirections[ k-1 ], UInt (0) );
389 
390  // Extracting the fibers vectors
391  *(fiberDirections[ k-1 ]) = M_fsi->FSIOper()->solid().material()->anisotropicLaw()->ithFiberVector( k );
392  }
393  }
394 #endif
395  // M_exporterSolid->addVariable( ExporterData<FSIOperator::mesh_Type>::VectorField, "s-velocity",
396  // M_fsi->FSIOper()->dFESpacePtr(), M_solidVel, UInt(0) );
397  // M_exporterSolid->addVariable( ExporterData<FSIOperator::mesh_Type>::VectorField, "s-ws",
398  // M_fsi->FSIOper()->dFESpacePtr(), M_WS, UInt(0) );
399 
400  M_fsi->FSIOper()->fluid().setupPostProc(); //this has to be called if we want to initialize the postProcess
401 
402  // Initializing either resistance of absorbing BCs
403  // At the moment, the resistance BCs are applied explicitly in order to limit the ill-conditioning
404  // of the linear system
405  Real hydrostatic = data_file ("fluid/physics/hydrostatic", 0.0);
406 
407 
408  //R1.initParameters( OUTLET, resistance, hydrostatic, "outlet-3" );
409  //FC2.initParameters ( *M_fsi->FSIOper(), OUTLET);
410 
411  M_data->dataFluid()->dataTime()->setInitialTime ( M_data->dataFluid()->dataTime()->initialTime() );
412  M_data->dataFluid()->dataTime()->setTime ( M_data->dataFluid()->dataTime()->initialTime() );
413  M_data->dataSolid()->dataTime()->setInitialTime ( M_data->dataFluid()->dataTime()->initialTime() );
414  M_data->dataSolid()->dataTime()->setTime ( M_data->dataFluid()->dataTime()->initialTime() );
415  M_data->timeDataALE()->setInitialTime ( M_data->dataFluid()->dataTime()->initialTime() );
416  M_data->timeDataALE()->setTime ( M_data->dataFluid()->dataTime()->initialTime() );
417 
418 
419  }
420 
422  {
423  return M_fsi;
424  }
425 
426  dataPtr_Type fsiData()
427  {
428  return M_data;
429  }
430 
431  /*!
432  This routine runs the temporal loop
433  */
434  void
435  run()
436  {
437  boost::timer _overall_timer;
438 
439  LifeV::UInt iter = 0;
440  //LifeV::UInt offset=dynamic_cast<LifeV::FSIMonolithic*>(M_fsi->FSIOper().get())->offset();
441 
442  dynamic_cast<LifeV::FSIMonolithic*> (M_fsi->FSIOper().get() )->enableStressComputation (1);
443 
444  // Exporting the initial time
445  *M_fluidDisp = M_fsi->FSIOper()->meshDisp();
446  M_fsi->FSIOper()->exportSolidDisplacement (*M_solidDisp);
447  //M_fsi->FSIOper()->exportSolidVelocity(*M_solidVel);// displacement(), M_offset);
448  M_fsi->FSIOper()->exportFluidVelocityAndPressure (*M_velAndPressure);
449  M_exporterSolid->postProcess ( M_data->dataFluid()->dataTime()->time() );
450  M_exporterFluid->postProcess ( M_data->dataFluid()->dataTime()->time() );
451 
452  //Quantities related to the save
453  LifeV::UInt r (0);
454  LifeV::UInt d (0);
455  //This is the size of the TimeAdvaces classes. It uses the size of the solid.
456  //It could be changed and it's better to set it up as the highest size of TA
457  LifeV::UInt tol ( M_fsi->FSIOper()->solidTimeAdvance()->size() );
458 
459  vectorPtr_Type solution ( new vector_Type ( (*M_fsi->FSIOper()->couplingVariableMap() ) ) );
460  vector_Type fluidSolution ( M_fsi->FSIOper()->fluid().getMap(), LifeV::Unique );
461  fluidSolution *= 0.0;
462 
463  M_fsi->FSIOper()->extrapolation ( *solution );
464 
465  for ( ; M_data->dataFluid()->dataTime()->canAdvance();)
466  {
467  M_data->dataFluid()->dataTime()->updateTime();
468  M_data->dataSolid()->dataTime()->updateTime();
469  M_data->timeDataALE()->updateTime();
470 
471  fluidSolution = *M_velAndPressure;
472 
473 
474  //R1.renewParameters( M_fsi->FSIOper()->fluid(), fluidSolution, M_data->dataFluid()->dataTime()->time() );
475  //FC2.renewParameters ( *M_fsi, OUTLET, fluidSolution );
476 
477  boost::timer _timer;
478 
479  // This is just the previous solution. Should use the extrapolation from time advance
480  M_fsi->FSIOper()->extrapolation ( *solution );
481 
482  M_fsi->iterate ( solution );
483 
484  // shift_right of the solution of all the time advance classes in the FSIOperator
485  M_fsi->FSIOper()->updateSolution ( *solution );
486 
487  iter = iter + 1;
488 
489  r = iter % M_saveEvery;
490  d = iter - r;
491 
492  if ( (iter - d) <= tol || ( (std::floor (d / M_saveEvery) + 1) *M_saveEvery - iter ) <= tol )
493  {
494  *M_fluidDisp = M_fsi->FSIOper()->meshDisp();
495  M_fsi->FSIOper()->exportSolidDisplacement (*M_solidDisp); // displacement(), M_offset);
496  //M_fsi->FSIOper()->exportSolidVelocity(*M_solidVel);// displacement(), M_offset);
497  M_fsi->FSIOper()->exportFluidVelocityAndPressure (*M_velAndPressure);
498 
499  M_exporterSolid->postProcess ( M_data->dataFluid()->dataTime()->time() );
500  M_exporterFluid->postProcess ( M_data->dataFluid()->dataTime()->time() );
501  }
502  }
503 
504  }
505 
506 private:
507 
508  void restartFSI ( GetPot const& data_file );
509  void initializeWithVectors ( void );
510  //Methods to conclude the reading for restart
511  void readLastVectorSolidTimeAdvance ( vectorPtr_Type fluidDisp, const LifeV::UInt iterInit, std::string iterationString);
512  void readLastVectorALETimeAdvance ( vectorPtr_Type fluidDisp, const std::string loadInitSol);
513 
515  dataPtr_Type M_data;
516 
519  filterPtr_Type M_importerSolid;
520  filterPtr_Type M_importerFluid;
521  vectorPtr_Type M_velAndPressure;
522  vectorPtr_Type M_fluidDisp;
523  vectorPtr_Type M_solidDisp;
524  vectorPtr_Type M_solidVel;
525 
526  std::vector<vectorPtr_Type> M_solidStencil;
527  std::vector<vectorPtr_Type> M_fluidStencil;
528  std::vector<vectorPtr_Type> M_ALEStencil;
529 
530  // LifeV::FlowConditions FC2;
533 
535 
537  LifeV::UInt M_saveEvery;
538 
539  vectorPtr_Type M_WS;
540 
542 };
543 
544 struct FSIChecker
545 {
546  FSIChecker ( GetPot const& _data_file,
547  std::shared_ptr<Epetra_Comm> comm ) :
548  data_file ( _data_file ),
549  communicator ( comm )
550  {}
551 
552  void operator() ()
553  {
554  std::shared_ptr<Problem> fsip;
555 
556  try
557  {
558  fsip = std::shared_ptr<Problem> ( new Problem ( data_file, communicator ) );
559 
560  fsip->run();
561  }
562  catch ( std::exception const& _ex )
563  {
564  std::cout << "caught exception : " << _ex.what() << "\n";
565  }
566 
567  //@disp = fsip->fsiSolver()->FSIOper()->displacementOnInterface();
568  }
569 
570  GetPot data_file;
572  LifeV::Vector disp;
573 };
574 
575 
576 namespace LifeV
577 {
578 
579 namespace
580 {
581 static bool regIF = (PRECFactory::instance().registerProduct ( "Ifpack", &createIfpack ) );
582 static bool regML = (PRECFactory::instance().registerProduct ( "ML", &createML ) );
583 }
584 }
585 
586 
587 int main (int argc, char** argv)
588 {
589 
590 #ifdef HAVE_MPI
591  MPI_Init (&argc, &argv);
592  std::shared_ptr<Epetra_MpiComm> Comm (new Epetra_MpiComm ( MPI_COMM_WORLD ) );
593  if ( Comm->MyPID() == 0 )
594  {
595  std::cout << "% using MPI" << std::endl;
596  }
597 #else
598  std::shared_ptr<Epetra_SerialComm> Comm ( new Epetra_SerialComm() );
599  std::cout << "% using serial Version" << std::endl;
600 #endif
601 
602  GetPot command_line (argc, argv);
603  const bool check = command_line.search (2, "-c", "--check");
604 
605  if (check)
606  {
607  GetPot data_fileGCE ("dataGCE");
608  FSIChecker _GCE_check ( data_fileGCE, Comm );
609  _GCE_check();
610 
611  GetPot data_fileCE ("dataCE");
612  FSIChecker _CE_check (data_fileCE, Comm);
613  _CE_check();
614 
615 #ifdef HAVE_MPI
616  MPI_Finalize();
617 #endif
618  return 0;
619  }
620  else
621  {
622  const std::string data_file_name = command_line.follow ("data", 2, "-f", "--file");
623  GetPot data_file (data_file_name);
624  FSIChecker _sp_check ( data_file, Comm );
625  _sp_check();
626  }
627 #ifdef HAVE_MPI
628  MPI_Finalize();
629 #endif
630 
631 
632  return 0;
633 
634 }
635 
636 void Problem::restartFSI ( GetPot const& data_file )
637 {
638  using namespace LifeV;
639 
640  typedef FSIOperator::mesh_Type mesh_Type;
641 
642  //Creating the pointer to the filter
643  std::string const importerType = data_file ( "importer/type", "ensight");
644  std::string const fluidName = data_file ( "importer/fluid/filename", "fluid");
645  std::string const solidName = data_file ( "importer/solid/filename", "solid");
646 
647  std::string const loadInitSol = data_file ( "importer/initSol", "00000");
648  std::string const loadInitSolFD = data_file ("importer/initSolFD", "-1");
649  std::string iterationString;
650 
651  M_Tstart = data_file ( "fluid/time_discretization/initialtime", 0.);
652 
653  // std::cout << "The file for fluid is : " << fluidName << std::endl;
654  // std::cout << "The file for solid is : " << solidName << std::endl;
655  // std::cout << "The importerType is : " << importerType << std::endl;
656  // std::cout << "The iteration is : " << loadInitSol << std::endl;
657  // std::cout << "For the fluid disp is : " << loadInitSolFD << std::endl;
658  // std::cout << "Starting time : " << M_Tstart << std::endl;
659 
660  //At the moment the restart works only if BDF methods are used in time.
661  // For Newmark method a almost new implementation is needed
662 
663  std::string methodFluid = data_file ( "fluid/time_discretization/method", "Newmark");
664  std::string methodSolid = data_file ( "solid/time_discretization/method", "Newmark");
665  std::string methodALE = data_file ( "mesh_motion/time_discretization/method", "Newmark");
666 
667 #ifdef HAVE_HDF5
668  if (importerType.compare ("hdf5") == 0)
669  {
670  M_importerFluid.reset ( new hdf5Filter_Type ( data_file, fluidName) );
671  M_importerSolid.reset ( new hdf5Filter_Type ( data_file, solidName) );
672  }
673  else
674 #endif
675  {
676  if (importerType.compare ("none") == 0)
677  {
678  M_importerFluid.reset ( new ExporterEmpty<mesh_Type > ( data_file, M_fsi->FSIOper()->uFESpace().mesh(), "fluid", M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ) );
679  M_importerSolid.reset ( new ExporterEmpty<mesh_Type > ( data_file, M_fsi->FSIOper()->dFESpace().mesh(), "solid", M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ) );
680  }
681  else
682  {
683  M_importerFluid.reset ( new ensightFilter_Type ( data_file, fluidName) );
684  M_importerSolid.reset ( new ensightFilter_Type ( data_file, solidName) );
685  }
686  }
687 
688  M_importerFluid->setMeshProcId (M_fsi->FSIOper()->uFESpace().mesh(), M_fsi->FSIOper()->uFESpace().map().comm().MyPID() );
689  M_importerSolid->setMeshProcId (M_fsi->FSIOper()->dFESpace().mesh(), M_fsi->FSIOper()->dFESpace().map().comm().MyPID() );
690 
691  //Each of the vectors of the stencils has the dimension of the big vector
692  //Performing a cycle of the size of the timeAdvance classes for each problem
693  //The size of TimeAdvanceClass depends on the order of the BDF (data file)
694 
695  //The hypothesis used for this method is that the three TimeAdvance classes have the same size
696  iterationString = loadInitSol;
697 
698  UInt iterInit;
699 
700  vectorPtr_Type vel;
701  vectorPtr_Type pressure;
702  vectorPtr_Type solidDisp;
703  vectorPtr_Type fluidDisp;
704 
705  for (iterInit = 0; iterInit < M_fsi->FSIOper()->fluidTimeAdvance()->size(); iterInit++ )
706  {
707 
708  //It should work just initializing the timeAdvance classes
709  //Three stencils are needed (Fluid-Structure-Geometric)
710  vel.reset (new vector_Type (M_fsi->FSIOper()->uFESpace().map(), LifeV::Unique) );
711  pressure.reset (new vector_Type (M_fsi->FSIOper()->pFESpace().map(), LifeV::Unique) );
712  solidDisp.reset (new vector_Type (M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique) );
713 
714  //First the three fields are read at the same time
715  //Creating the exporter data for the fields
716  //Fluid
717  LifeV::ExporterData<mesh_Type> initSolFluidVel (LifeV::ExporterData<mesh_Type>::VectorField, std::string ("f-velocity." + iterationString), M_fsi->FSIOper()->uFESpacePtr(), vel, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime );
718  LifeV::ExporterData<mesh_Type> initSolFluidPress (LifeV::ExporterData<mesh_Type>::ScalarField, std::string ("f-pressure." + iterationString), M_fsi->FSIOper()->pFESpacePtr(), pressure, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime );
719 
720  //Structure
721  LifeV::ExporterData<mesh_Type> initSolSolidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "s-displacement." + iterationString, M_fsi->FSIOper()->dFESpacePtr(), solidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime );
722 
723  //Initialization of the vectors used to read
724  *vel *= 0.0;
725  *pressure *= 0.0;
726  *solidDisp *= 0.0;
727 
728  //load of the solutions
729  M_importerFluid->readVariable (initSolFluidVel); //Fluid u
730  M_importerFluid->readVariable (initSolFluidPress); //Fluid p
731  M_importerSolid->readVariable (initSolSolidDisp); //Solid d
732 
733  // std::cout << "Norm of the vel " << vel->norm2() << std::endl;
734  // std::cout << "Norm of the pressure " << pressure->norm2() << std::endl;
735  // std::cout << "Norm of the solid " << solidDisp->norm2() << std::endl;
736 
737  //We send the vectors to the FSIMonolithic class using the interface of FSIOper
738  M_fsi->FSIOper()->setVectorInStencils (vel, pressure, solidDisp, iterInit );
739 
740  //Updating string name
741  int iterations = std::atoi (iterationString.c_str() );
742  iterations--;
743 
744  std::ostringstream iter;
745  iter.fill ( '0' );
746  iter << std::setw (5) << ( iterations );
747  iterationString = iter.str();
748  }
749 
750  readLastVectorSolidTimeAdvance ( solidDisp, iterInit, iterationString );
751 
752  //For the ALE timeAdvance, one should be careful on the vectors that are used
753  //to compute the RHSFirstDerivative. That is why we first load the stencil using previous
754  //vectors and then we read the last one
755  iterationString = loadInitSol;
756  int iterationStartALE = std::atoi (iterationString.c_str() );
757  iterationStartALE--;
758 
759  std::ostringstream iter;
760  iter.fill ( '0' );
761  iter << std::setw (5) << ( iterationStartALE );
762  iterationString = iter.str();
763 
764  // std::cout << "The load init sol is: " << loadInitSol << std::endl;
765  // std::cout << "The first read sol is: " << iterationString << std::endl;
766 
767  for (iterInit = 0; iterInit < M_fsi->FSIOper()->ALETimeAdvance()->size(); iterInit++ )
768  {
769  //Reset the pointer
770  fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) );
771 
772  //Setting the exporterData to read: ALE problem
773  LifeV::ExporterData<mesh_Type> initSolFluidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "f-displacement." + iterationString, M_fsi->FSIOper()->mmFESpacePtr(), fluidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime );
774 
775  //Initializing
776  *fluidDisp *= 0.0;
777 
778  //Reading
779  M_importerFluid->readVariable (initSolFluidDisp); //Fluid df
780 
781  //Output
782  // std::cout << "Norm of the df " << fluidDisp->norm2() << std::endl;
783 
784  //Setting the vector in the stencil
785  M_fsi->FSIOper()->setALEVectorInStencil ( fluidDisp, iterInit, false );
786 
787  //Updating string name
788  int iterations = std::atoi (iterationString.c_str() );
789  iterations--;
790 
791  std::ostringstream iter;
792  iter.fill ( '0' );
793  iter << std::setw (5) << ( iterations );
794  iterationString = iter.str();
795  }
796 
797  //Initializing the vector for the RHS terms of the formulas
798  M_fsi->FSIOper()->finalizeRestart();
799 
800  //Need to read still one vector and shiftright it.
801  readLastVectorALETimeAdvance ( fluidDisp, loadInitSol);
802 
803  //This are used to export the loaded solution to check it is correct.
804  vel.reset (new vector_Type (M_fsi->FSIOper()->uFESpace().map(), LifeV::Unique) );
805  pressure.reset (new vector_Type (M_fsi->FSIOper()->pFESpace().map(), LifeV::Unique) );
806  fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) );
807  M_velAndPressure.reset ( new vector_Type ( M_fsi->FSIOper()->fluid().getMap(), M_importerFluid->mapType() ) );
808  M_velAndPressure->subset (*pressure, pressure->map(), UInt (0), (UInt) 3 * M_fsi->FSIOper()->uFESpace().dof().numTotalDof() );
809  *M_velAndPressure += *vel;
810 
811  M_fluidDisp.reset ( new vector_Type ( *fluidDisp, M_importerFluid->mapType() ) );
812 
813  M_solidDisp.reset ( new vector_Type ( *solidDisp, M_importerSolid->mapType() ) );
814 
815 }
816 
817 void Problem::readLastVectorSolidTimeAdvance ( vectorPtr_Type solidDisp,
818  LifeV::UInt iterInit,
819  std::string iterationString)
820 {
821  using namespace LifeV;
822 
823  typedef FSIOperator::mesh_Type mesh_Type;
824 
825  //Reading another vector for the solidTimeAdvance since its BDF has the same order
826  //as the other ones but since the orderDerivative = 2, the size of the stencil is
827  //orderBDF + 1
828 
829  solidDisp.reset (new vector_Type (M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique) );
830  *solidDisp *= 0.0;
831  LifeV::ExporterData<mesh_Type> initSolSolidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "s-displacement." + iterationString, M_fsi->FSIOper()->dFESpacePtr(), solidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime );
832 
833  M_importerSolid->readVariable (initSolSolidDisp); //Solid d
834 
835  M_fsi->FSIOper()->setSolidVectorInStencil ( solidDisp, iterInit );
836 }
837 
838 
839 void Problem::readLastVectorALETimeAdvance ( vectorPtr_Type fluidDisp,
840  const std::string loadInitSol)
841 {
842  using namespace LifeV;
843  typedef FSIOperator::mesh_Type mesh_Type;
844 
845  //We still need to load the last vector for ALE
846  std::string iterationString = loadInitSol;
847  fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) );
848 
849  //Setting the exporterData to read: ALE problem
850  LifeV::ExporterData<mesh_Type> initSolFluidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "f-displacement." + iterationString, M_fsi->FSIOper()->mmFESpacePtr(), fluidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime );
851 
852  //Initializing
853  *fluidDisp *= 0.0;
854 
855  //Reading
856  M_importerFluid->readVariable (initSolFluidDisp); //Fluid df
857 
858  //Output
859  // std::cout << "Norm of the df " << fluidDisp->norm2() << std::endl;
860 
861  //This is ugly but it's the only way I have figured out at the moment
862  if ( M_data->method().compare ("monolithicGI") == 0 )
863  {
864  //Don't be scared by the ten. The goal of 10 is just to make the first if fail
865  M_fsi->FSIOper()->setALEVectorInStencil ( fluidDisp, 10, true );
866  }
867 
868  //Setting the vector in the stencil
869  M_fsi->FSIOper()->ALETimeAdvance()->shiftRight ( *fluidDisp );
870 }
871 
873 {
874 
875  using namespace LifeV;
876  // vectors to store the solutions we want.
877  vectorPtr_Type vel;
878  vectorPtr_Type pressure;
879  vectorPtr_Type solidDisp;
880  vectorPtr_Type fluidDisp;
881 
882  vel.reset (new vector_Type (M_fsi->FSIOper()->uFESpace().map(), LifeV::Unique) );
883  pressure.reset (new vector_Type (M_fsi->FSIOper()->pFESpace().map(), LifeV::Unique) );
884  solidDisp.reset (new vector_Type (M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique) );
885  fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) );
886 
887  // In this case we want to initialize only the pressure
888  M_fsi->FSIOper()->pFESpacePtr()->interpolate ( static_cast<FESpace<RegionMesh<LinearTetra>, MapEpetra> ::function_Type> ( pressureInitial ), *pressure, 0.0 );
889 
890  *vel *= 0.0;
891  *solidDisp *= 0.0;
892  *fluidDisp *= 0.0;
893 
894  UInt iterInit;
895 
896  // Filling the stencils
897  for (iterInit = 0; iterInit < M_fsi->FSIOper()->fluidTimeAdvance()->size(); iterInit++ )
898  {
899  //We send the vectors to the FSIMonolithic class using the interface of FSIOper
900  M_fsi->FSIOper()->setVectorInStencils (vel, pressure, solidDisp, iterInit );
901  }
902 
903  // This was in readLastVectorSolidStencil
904  M_fsi->FSIOper()->setSolidVectorInStencil ( solidDisp, iterInit );
905 
906  // Ale part
907  for (iterInit = 0; iterInit < M_fsi->FSIOper()->ALETimeAdvance()->size(); iterInit++ )
908  {
909  //Setting the vector in the stencil
910  M_fsi->FSIOper()->setALEVectorInStencil ( fluidDisp, iterInit, false );
911  }
912 
913  //Initializing the vector for the RHS terms of the formulas
914  M_fsi->FSIOper()->finalizeRestart();
915 
916  // This was read the last vector from ALE
917  //This is ugly but it's the only way I have figured out at the moment
918  if ( M_data->method().compare ("monolithicGI") == 0 )
919  {
920  //Don't be scared by the ten. The goal of 10 is just to make the first if fail
921  M_fsi->FSIOper()->setALEVectorInStencil ( fluidDisp, 10, true );
922  }
923 
924  //Setting the vector in the stencil
925  M_fsi->FSIOper()->ALETimeAdvance()->shiftRight ( *fluidDisp );
926 
927 }
std::shared_ptr< Epetra_Comm > M_comm
void assignFunction(bcBase_Type &base)
Assign the function to the base of the BCHandler.
Problem(GetPot const &data_file, std::shared_ptr< Epetra_Comm > comm)
double operator()(const char *VarName, const double &Default) const
Definition: GetPot.hpp:2033
LifeV::FactorySingleton< LifeV::Factory< LifeV::FSIOperator, std::string > > FSIFactory_Type
int main(int argc, char **argv)
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
#define debugStream
Definition: LifeDebug.hpp:182
LifeV::ImplicitResistance implicitResistance_Type
std::shared_ptr< FSISolver > fsi_solver_ptr
FSIChecker(GetPot const &_data_file, std::shared_ptr< Epetra_Comm > comm)
void readLastVectorALETimeAdvance(vectorPtr_Type fluidDisp, const std::string loadInitSol)
void readLastVectorSolidTimeAdvance(vectorPtr_Type fluidDisp, const LifeV::UInt iterInit, std::string iterationString)
double Real
Generic real data.
Definition: LifeV.hpp:175
GetPot(const char *FileName, const char *CommentStart=0x0, const char *CommentEnd=0x0, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:541
void restartFSI(GetPot const &data_file)
NdebugStream noDebugStream(int=0, NdebugStream::stprintf=&printf)
Definition: LifeDebug.hpp:183
bool search(unsigned No, const char *P,...)
Definition: GetPot.hpp:1217
std::shared_ptr< Epetra_Comm > communicator
std::shared_ptr< ensightFilter_Type > ensightFilterPtr_Type
LifeV::ExporterEnsight< LifeV::FSIOperator::mesh_Type > ensightFilter_Type
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191