LifeV
FSIMonolithicGI.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 #include <lifev/core/LifeV.hpp>
29 
30 #include <lifev/fsi/solver/FSIMonolithicGI.hpp>
31 #include <lifev/fsi/solver/MonolithicBlockComposedDN.hpp>
32 #include <lifev/fsi/solver/MonolithicBlockComposedDND.hpp>
33 #include <lifev/fsi/solver/MonolithicBlockMatrixRN.hpp>
34 
35 namespace LifeV
36 {
37 
38 // ===================================================
39 // Constructors and Descructor
40 // ===================================================
41 FSIMonolithicGI::FSIMonolithicGI() :
42  super_Type (),
43  M_mapWithoutMesh (),
44  M_uk (),
45  M_interface (0),
46  M_meshBlock (),
47  M_shapeDerivativesBlock (),
48  M_solidDerBlock ()
49 {
50 }
51 
52 // ===================================================
53 // Public Methods
54 // ===================================================
55 void FSIMonolithicGI::setup ( const GetPot& dataFile )
56 {
57  super_Type::setup ( dataFile );
58 }
59 
60 void FSIMonolithicGI::setupFluidSolid ( UInt const fluxes )
61 {
62  super_Type::setupFluidSolid ( fluxes );
63  UInt offset = M_monolithicMap->map ( Unique )->NumGlobalElements();
64  M_mapWithoutMesh.reset ( new MapEpetra ( *M_monolithicMap ) );
65 
66  *M_monolithicMap += M_mmFESpace->map();
67 
68  M_interface = M_monolithicMatrix->interface();
69 
70  M_beta.reset ( new vector_Type (M_uFESpace->map() ) );
71  M_rhs.reset (new vector_Type (*M_monolithicMap) );
72  M_rhsFull.reset (new vector_Type (*M_monolithicMap) );
73  if (M_data->dataFluid()->useShapeDerivatives() )
74  {
75  M_shapeDerivativesBlock.reset (new matrix_Type (*M_monolithicMap) );
76  }
77  M_uk.reset (new vector_Type (*M_monolithicMap) );
78 
79  M_meshMotion.reset (new meshMotion_Type (*M_mmFESpace,
80  M_epetraComm,
81  *M_monolithicMap,
82  offset) );
83 
84  M_fluid.reset (new fluid_Type (M_data->dataFluid(),
85  *M_uFESpace,
86  *M_pFESpace,
87  *M_mmFESpace,
88  M_epetraComm,
89  *M_monolithicMap,
90  fluxes) );
91  M_solid.reset (new solid_Type() );
92 
93  M_solid->setup (M_data->dataSolid(),
94  M_dFESpace,
95  M_dETFESpace,
96  M_epetraComm,
97  M_dFESpace->mapPtr(),
98  UInt (0)
99  );
100 }
101 
102 void
103 FSIMonolithicGI::buildSystem()
104 {
105  super_Type::buildSystem();
106  M_meshMotion->computeMatrix();
107 }
108 
109 void
110 FSIMonolithicGI::evalResidual ( vector_Type& res,
111  const vector_Type& disp,
112  const UInt iter )
113 {
114  // disp here is the current solution guess (u,p,ds,df)
115 
116  res = 0.;//this is important. Don't remove it!
117 
118  M_uk.reset (new vector_Type ( disp ) );
119 
120  UInt offset ( M_solidAndFluidDim + nDimensions * M_interface );
121 
122  vectorPtr_Type meshDisp ( new vector_Type (M_mmFESpace->map() ) );
123 
124  meshDisp->subset (disp, offset); //if the conv. term is to be condidered implicitly
125 
126  vectorPtr_Type mmRep ( new vector_Type (*meshDisp, Repeated ) );
127 
128  moveMesh ( *mmRep );
129 
130  //here should use extrapolationFirstDerivative instead of velocity
131  if (iter == 0)
132  {
133  M_ALETimeAdvance->updateRHSFirstDerivative (M_data->dataFluid()->dataTime()->timeStep() );
134  }
135  vector_Type meshVelocityRepeated ( this->M_ALETimeAdvance->firstDerivative ( *meshDisp ), Repeated );
136  vector_Type interpolatedMeshVelocity (this->M_uFESpace->map() );
137 
138  interpolateVelocity ( meshVelocityRepeated, interpolatedMeshVelocity );
139  vectorPtr_Type fluid ( new vector_Type ( M_uFESpace->map() ) );
140  M_beta->subset ( disp, 0 );
141 
142  *M_beta -= interpolatedMeshVelocity; // convective term, u^(n+1) - w^(n+1)
143 
144  assembleSolidBlock ( iter, disp );
145  assembleFluidBlock ( iter, disp );
146  assembleMeshBlock ( iter );
147 
148  *M_rhsFull = *M_rhs;
149 
150  M_monolithicMatrix->setRobin ( M_robinCoupling, M_rhsFull );
151  M_precPtr->setRobin (M_robinCoupling, M_rhsFull);
152 
153  if (!M_monolithicMatrix->set() )
154  {
155  M_BChs.push_back (M_BCh_d);
156  M_BChs.push_back (M_BCh_u);
157 
158  M_FESpaces.push_back (M_dFESpace);
159  M_FESpaces.push_back (M_uFESpace);
160 
161  M_BChs.push_back (M_BCh_mesh);
162  M_FESpaces.push_back (M_mmFESpace);
163 
164  M_monolithicMatrix->push_back_matrix (M_solidBlockPrec, false);
165  M_monolithicMatrix->push_back_matrix (M_fluidBlock, true);
166  M_monolithicMatrix->push_back_matrix (M_meshBlock, false);
167  M_monolithicMatrix->setConditions (M_BChs);
168  M_monolithicMatrix->setSpaces (M_FESpaces);
169  M_monolithicMatrix->setOffsets (3, M_offset, 0, M_solidAndFluidDim + nDimensions * M_interface);
170  M_monolithicMatrix->coupler (M_monolithicMap, M_dofStructureToFluid->localDofMap(), M_numerationInterface, M_data->dataFluid()->dataTime()->timeStep(), M_solidTimeAdvance->coefficientFirstDerivative ( 0 ), M_solid->rescaleFactor() );
171  M_monolithicMatrix->coupler ( M_monolithicMap, M_dofStructureToFluid->localDofMap(), M_numerationInterface, M_data->dataFluid()->dataTime()->timeStep(), M_solidTimeAdvance->coefficientFirstDerivative ( 0 ), M_solid->rescaleFactor(), 2);
172  }
173  else
174  {
175  M_monolithicMatrix->replace_matrix (M_solidBlockPrec, 0);
176  M_monolithicMatrix->replace_matrix (M_fluidBlock, 1);
177  M_monolithicMatrix->replace_matrix (M_meshBlock, 2);
178  }
179 
180  M_monolithicMatrix->blockAssembling();
181  super_Type::checkIfChangedFluxBC ( M_monolithicMatrix );
182 
183  // formulation matrix * vector (i.e. linear elastic )
184  // todo: pass to boolean for nonlinear structures
185  if ( ! (M_data->dataSolid()->lawType().compare ("linear") ) )
186  {
187  applyBoundaryConditions();
188  }
189 
190  M_monolithicMatrix->GlobalAssemble();
191 
192  super_Type::evalResidual ( disp, M_rhsFull, res, false );
193 
194  //case for nonlinear laws which are formulated in the residual form
195  if ( ! ( M_data->dataSolid()->lawType().compare ( "nonlinear" ) ) )
196  {
197  res += *M_meshBlock * disp;
198 
199  if ( !M_BCh_u->bcUpdateDone() )
200  {
201  M_BCh_u->bcUpdate ( *M_uFESpace->mesh(), M_uFESpace->feBd(), M_uFESpace->dof() );
202  }
203  M_BCh_d->setOffset ( M_offset );
204  if ( !M_BCh_d->bcUpdateDone() )
205  {
206  M_BCh_d->bcUpdate ( *M_dFESpace->mesh(), M_dFESpace->feBd(), M_dFESpace->dof() );
207  }
208  M_BCh_mesh->setOffset ( M_solidAndFluidDim + nDimensions * M_interface );
209  if ( !M_BCh_mesh->bcUpdateDone() )
210  {
211  M_BCh_mesh->bcUpdate ( *M_mmFESpace->mesh(), M_mmFESpace->feBd(), M_mmFESpace->dof() );
212  }
213 
214  M_monolithicMatrix->applyBoundaryConditions ( dataFluid()->dataTime()->time() /*, M_rhsFull*/);
215  M_monolithicMatrix->GlobalAssemble();
216 
217  bcManageResidual ( res, *M_rhsFull, disp, *M_uFESpace->mesh(), M_uFESpace->dof(), *M_BCh_u,
218  M_uFESpace->feBd(), M_data->dataFluid()->dataTime()->time(), 1. );
219 
220  // below sol is repeated by BCManageResidual
221  bcManageResidual ( res, *M_rhsFull, disp, *M_dFESpace->mesh(), M_dFESpace->dof(), *M_BCh_d,
222  M_dFESpace->feBd(), M_data->dataSolid()->dataTime()->time(), 1. );
223  bcManageResidual ( res, *M_rhsFull, disp, *M_mmFESpace->mesh(), M_mmFESpace->dof(), *M_BCh_mesh,
224  M_mmFESpace->feBd(), M_data->dataFluid()->dataTime()->time(), 1. );
225  res -= *M_rhsFull;
226  }
227 }
228 
229 void FSIMonolithicGI::applyBoundaryConditions()
230 {
231  if ( !M_BCh_u->bcUpdateDone() )
232  M_BCh_u->bcUpdate ( *M_uFESpace->mesh(),
233  M_uFESpace->feBd(),
234  M_uFESpace->dof() );
235  M_BCh_d->setOffset ( M_offset );
236  if ( !M_BCh_d->bcUpdateDone() )
237  M_BCh_d->bcUpdate ( *M_dFESpace->mesh(),
238  M_dFESpace->feBd(),
239  M_dFESpace->dof() );
240  M_BCh_mesh->setOffset ( M_solidAndFluidDim + nDimensions * M_interface );
241  if ( !M_BCh_mesh->bcUpdateDone() )
242  M_BCh_mesh->bcUpdate ( *M_mmFESpace->mesh(),
243  M_mmFESpace->feBd(),
244  M_mmFESpace->dof() );
245 
246  M_monolithicMatrix->applyBoundaryConditions (dataFluid()->dataTime()->time(), M_rhsFull);
247 }
248 
249 void FSIMonolithicGI::setALEVectorInStencil ( const vectorPtr_Type& fluidDisp,
250  const UInt iter,
251  const bool lastVector)
252 {
253 
254  //The fluid timeAdvance has size = orderBDF because it is seen as an equation frist order in time.
255  //We need to add the solidVector to the fluidVector in the fluid TimeAdvance because we have the
256  //extrapolation on it.
257  if ( ( iter < M_fluidTimeAdvance->size() - 1 ) && !lastVector )
258  {
259  vectorPtr_Type harmonicSolutionRestartTime (new vector_Type ( *M_monolithicMap, Unique, Zero ) );
260 
261  *harmonicSolutionRestartTime *= 0.0;
262 
263  UInt givenOffset ( M_solidAndFluidDim + nDimensions * M_interface );
264  harmonicSolutionRestartTime->subset (*fluidDisp, fluidDisp->map(), (UInt) 0, givenOffset );
265 
266  //We sum the vector in the first element of fluidtimeAdvance
267  * ( M_fluidTimeAdvance->stencil() [ iter + 1 ] ) += *harmonicSolutionRestartTime;
268  }
269 
270  if ( !lastVector )
271  {
272  //The shared_pointer for the vectors has to be trasformed into a pointer to VectorEpetra
273  //That is the type of pointers that are used in TimeAdvance
274  vector_Type* normalPointerToALEVector ( new vector_Type (*fluidDisp) );
275  (M_ALETimeAdvance->stencil() ).push_back ( normalPointerToALEVector );
276  }
277  else
278  {
279  vectorPtr_Type harmonicSolutionRestartTime (new vector_Type ( *M_monolithicMap, Unique, Zero ) );
280 
281  *harmonicSolutionRestartTime *= 0.0;
282 
283  UInt givenOffset ( M_solidAndFluidDim + nDimensions * M_interface );
284  harmonicSolutionRestartTime->subset (*fluidDisp, fluidDisp->map(), (UInt) 0, givenOffset );
285 
286  //We sum the vector in the first element of fluidtimeAdvance
287  * ( M_fluidTimeAdvance->stencil() [ 0 ] ) += *harmonicSolutionRestartTime;
288  }
289 
290 }
291 
292 
293 
294 //============ Protected Methods ===================
295 
296 void FSIMonolithicGI::setupBlockPrec()
297 {
298 
299  //The following part accounts for a possibly nonlinear structure model, should not be run when linear
300  //elasticity is used
301 
302  // case of exponential and neohookean model
303  // todo: pass to boolean variable for Nonlinear models ( i.e. for vector formulation )
304  // if ( M_data->dataSolid()->getUseExactJacobian() && ( M_data->dataSolid()->solidType().compare( "exponential" )
305  // && M_data->dataSolid()->solidType().compare( "neoHookean" ) ) )
306  // {
307  // M_solid->material()->updateJacobianMatrix ( *M_uk * M_solid->rescaleFactor(),
308  // dataSolid(),
309  // M_solid->mapMarkersVolumes(),
310  // M_solid->mapMarkersIndexes(),
311  // M_solid->displayerPtr() ); // computing the derivatives if nonlinear (comment this for inexact Newton);
312  // M_solidBlockPrec.reset ( new matrix_Type ( *M_monolithicMap,
313  // 1 ) );
314  // *M_solidBlockPrec += *M_solid->massMatrix();
315  // *M_solidBlockPrec += *M_solid->material()->jacobian();
316  // M_solidBlockPrec->globalAssemble();
317  // *M_solidBlockPrec *= M_solid->rescaleFactor();
318 
319  // M_monolithicMatrix->replace_matrix ( M_solidBlockPrec, 0 );
320  // }
321 
322  M_monolithicMatrix->blockAssembling();
323 
324  if ( M_data->dataFluid()->useShapeDerivatives() )
325  {
326  *M_shapeDerivativesBlock *= 0.;
327  M_shapeDerivativesBlock->openCrsMatrix();
328  shapeDerivatives ( M_shapeDerivativesBlock );
329  M_shapeDerivativesBlock->globalAssemble();
330  M_monolithicMatrix->addToGlobalMatrix ( M_shapeDerivativesBlock );
331  }
332 
333  if ( M_data->dataFluid()->useShapeDerivatives() || M_data->dataSolid()->getUseExactJacobian() )
334  {
335  if ( !M_BCh_u->bcUpdateDone() )
336  M_BCh_u->bcUpdate ( *M_uFESpace->mesh(),
337  M_uFESpace->feBd(),
338  M_uFESpace->dof() );
339  M_BCh_d->setOffset ( M_offset );
340  if ( !M_BCh_d->bcUpdateDone() )
341  M_BCh_d->bcUpdate ( *M_dFESpace->mesh(),
342  M_dFESpace->feBd(),
343  M_dFESpace->dof() );
344  M_BCh_mesh->setOffset ( M_solidAndFluidDim + nDimensions * M_interface );
345  if ( !M_BCh_mesh->bcUpdateDone() )
346  M_BCh_mesh->bcUpdate ( *M_mmFESpace->mesh(),
347  M_mmFESpace->feBd(),
348  M_mmFESpace->dof() );
349 
350  M_monolithicMatrix->applyBoundaryConditions ( dataFluid()->dataTime()->time() );
351  M_monolithicMatrix->GlobalAssemble();
352  }
353 
354  super_Type::setupBlockPrec();
355 
356  if ( M_precPtr->blockVector().size() < 3 )
357  {
358  M_precPtr->push_back_matrix ( M_meshBlock,
359  false );
360  M_precPtr->setConditions ( M_BChs );
361  M_precPtr->setSpaces ( M_FESpaces );
362  M_precPtr->setOffsets ( 3, M_offset, 0, M_solidAndFluidDim + nDimensions * M_interface );
363  M_precPtr->coupler ( M_monolithicMap, M_dofStructureToFluid->localDofMap(), M_numerationInterface, M_data->dataFluid()->dataTime()->timeStep() , M_solidTimeAdvance->coefficientFirstDerivative ( 0 ), M_solid->rescaleFactor(), 2);
364 
365  if (M_data->dataFluid()->useShapeDerivatives() )
366  {
367  std::shared_ptr<MatrixEpetra<Real> > staticCast = std::static_pointer_cast<MatrixEpetra<Real> > (M_shapeDerivativesBlock);
368  M_precPtr->push_back_coupling ( staticCast );
369  }
370  }
371  else
372  {
373  //M_precPtr->replace_matrix( M_solidBlockPrec, 0 );
374  //M_precPtr->replace_matrix( M_fluidBlock, 1 );
375  M_precPtr->replace_matrix ( M_meshBlock, 2 );
376 
377  if ( M_data->dataFluid()->useShapeDerivatives() )
378  {
379  M_precPtr->replace_coupling ( M_shapeDerivativesBlock, 2 );
380  }
381  }
382 }
383 
384 void FSIMonolithicGI::shapeDerivatives ( FSIOperator::fluid_Type::matrixPtr_Type sdMatrix )
385 {
386  Real alpha = M_fluidTimeAdvance->coefficientFirstDerivative ( 0 ) / M_data->dataFluid()->dataTime()->timeStep();
387  vectorPtr_Type rhsNew (new vector_Type (*M_monolithicMap) );
388  vector_Type un (M_uFESpace->map() );
389  vector_Type uk (M_uFESpace->map() + M_pFESpace->map() );
390 
391  vectorPtr_Type meshVelRep ( new vector_Type ( M_mmFESpace->map(), Repeated ) );
392 
393  *meshVelRep = M_ALETimeAdvance->firstDerivative();
394 
395  //When this class is used, the convective term is used implictly
396  un.subset ( *M_uk, 0 );
397 
398  uk.subset ( *M_uk, 0 );
399  vector_Type veloFluidMesh ( M_uFESpace->map(), Repeated );
400  this->transferMeshMotionOnFluid ( *meshVelRep, veloFluidMesh );
401 
402  //The last two flags are consistent with the currect interface.
403  //When this class is used, they should not be changed.
404  M_fluid->updateShapeDerivatives ( *sdMatrix, alpha,
405  un,
406  uk,
407  veloFluidMesh, //(xk-xn)/dt (FI), or (xn-xn-1)/dt (CE)//Repeated
408  M_solidAndFluidDim + M_interface * nDimensions,
409  *M_mmFESpace,
410  true /*This flag tells the method to consider the velocity of the domain implicitly*/,
411  true /*This flag tells the method to consider the convective term implicitly */ );
412 }
413 
414 void FSIMonolithicGI::assembleMeshBlock ( UInt /*iter*/ )
415 {
416 
417  M_meshBlock.reset ( new matrix_Type ( *M_monolithicMap ) );
418  M_meshMotion->addSystemMatrixTo ( M_meshBlock );
419  M_meshBlock->globalAssemble();
420  UInt offset ( M_solidAndFluidDim + nDimensions * M_interface );
421  std::map< ID, ID >::const_iterator ITrow;
422  std::map< ID, ID > locdofmap ( M_dofStructureToFluid->localDofMap() );
423 
424  /******************alternative way************************/
425  // BCFunctionBase bcf(fZero);
426  // fluidBchandlerPtr_Type BCh(new fluidBchandler_Type() );
427  // BCh->addBC("Interface", 1, Essential, Full,
428  // bcf, 3);
429 
430  // BCh->setOffset(M_solidAndFluidDim + nDimensions*M_interface);
431 
432  // if ( !BCh->bcUpdateDone() )
433  // BCh->bcUpdate( *M_mmFESpace->mesh(), M_mmFESpace->feBd(), M_mmFESpace->dof() );
434 
435  // bcManage( *M_meshBlock, *M_rhsFull, *M_mmFESpace->mesh(), M_mmFESpace->dof(), *BCh, M_mmFESpace->feBd(), 1., dataFluid()->dataTime()->time());
436  /********************************************************/
437 
438  matrixPtr_Type diagFilter (new matrix_Type (*M_monolithicMap) );
439  diagFilter->insertZeroDiagonal ();
440  for ( ID dim = 0; dim < nDimensions; ++dim )
441  {
442  for ( ITrow = locdofmap.begin(); ITrow != locdofmap.end(); ++ITrow )
443  {
444  int i = ITrow->first;
445  int iRow = i + offset + dim * M_mmFESpace->dof().numTotalDof();
446  if ( M_meshBlock->mapPtr()->map (Unique)->MyGID (iRow) )
447  {
448  M_meshBlock->diagonalize ( iRow, 1. );
449  }
450  else
451  {
452  double myValues[1];
453  myValues[0] = -1;
454  int myIndices[1];
455  myIndices[0] = iRow;
456  diagFilter->matrixPtr()->SumIntoGlobalValues ( iRow, 1, myValues, myIndices );
457  }
458  }
459  }
460 
461  diagFilter->globalAssemble();
462  // Processor informations
463  Int numLocalEntries = diagFilter->matrixPtr()->RowMap().NumMyElements();
464  Int* globalEntries = diagFilter->matrixPtr()->RowMap().MyGlobalElements();
465  UInt globalRowIndex (0);
466 
467  // Source informations handlers
468  double* diagValue;
469  Int* indices;
470  Int srcRow (0);
471  Int controlValue (0); // This value should be one since it is a diagonal matrix
472 
473  for (Int i (0); i < numLocalEntries; ++i)
474  {
475  // Collecting the data from the source
476  globalRowIndex = globalEntries[i];
477 
478  // Get the data of the row
479  srcRow = diagFilter->matrixPtr()->LRID (static_cast<EpetraInt_Type> (globalRowIndex) );
480  diagFilter->matrixPtr()->ExtractMyRowView (srcRow, controlValue, diagValue, indices);
481 
482  ASSERT ( controlValue == 1, "Error: The matrix should be diagonal.");
483  if (diagValue[0] < 0.0)
484  {
485  M_meshBlock->diagonalize ( globalRowIndex, 1. );
486  }
487  }
488 }
489 
490 // ===================================================
491 // Products registration
492 // ===================================================
493 bool FSIMonolithicGI::S_register = BlockPrecFactory::instance().registerProduct ( "AdditiveSchwarzGI",
494  &MonolithicBlockMatrix::createAdditiveSchwarz )
495  && BlockPrecFactory::instance().registerProduct ( "ComposedDNGI",
496  &MonolithicBlockComposedDN::createComposedDNGI )
497  && MonolithicBlockMatrix::Factory_Type::instance().registerProduct ( "AdditiveSchwarzGI",
498  &MonolithicBlockMatrix::createAdditiveSchwarz )
499  && MonolithicBlockMatrix::Factory_Type::instance().registerProduct ( "AdditiveSchwarzRNGI",
500  &MonolithicBlockMatrixRN::createAdditiveSchwarzRN )
501  && FSIOperator::FSIFactory_Type::instance().registerProduct ( "monolithicGI",
502  &FSIMonolithicGI::instantiate )
503  && BlockPrecFactory::instance().registerProduct ( "ComposedDNDGI",
504  &MonolithicBlockComposedDND::createComposedDNDGI )
505  && BlockPrecFactory::instance().registerProduct ( "ComposedDND2GI",
506  &MonolithicBlockComposedDND::createComposedDND2GI )
507  && BlockPrecFactory::instance().registerProduct ( "ComposedDN2GI",
508  &MonolithicBlockComposedDN::createComposedDN2GI );
509 
510 }
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90