LifeV
FSISolver.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 solver for the instances of the FSI class.
30  \author Christophe Prud'homme <christophe.prudhomme@epfl.ch>
31  \date 2004-11-18
32  */
33 
34 #ifndef TWODIM
35 
36 #include <lifev/core/LifeV.hpp>
37 #include <lifev/fsi/solver/FSISolver.hpp>
38 //!\todo remove this header
39 #include <lifev/core/algorithm/NonLinearRichardson.hpp>
40 
41 namespace LifeV
42 {
43 
44 // ===================================================
45 // Constructors
46 // ===================================================
47 FSISolver::FSISolver() :
48  M_oper ( ),
49  M_data ( ),
50  M_fluidInterfaceMap ( ),
51  M_solidInterfaceMap ( ),
52  M_epetraComm ( ),
53  M_epetraWorldComm ( ),
54  M_localComm ( new MPI_Comm ),
55  M_interComm ( new MPI_Comm )
56 {
57 #ifdef DEBUG
58  debugStream ( 6220 ) << "FSISolver::FSISolver constructor starts\n";
59 #endif
60 }
61 
62 
63 
64 // ===================================================
65 // Methods
66 // ===================================================
67 void
68 FSISolver::setData ( const dataPtr_Type& data )
69 {
70  M_data = data;
71 
72  int rank, numtasks;
73  MPI_Comm_rank (MPI_COMM_WORLD, &rank);
74  MPI_Comm_size (MPI_COMM_WORLD, &numtasks);
75 
76  bool fluid = false;
77  bool solid = false;
78 
79  int fluidLeader (0);
80  int solidLeader (0);
81 
82  if ( ( data->method().compare ("monolithicGE") && data->method().compare ("monolithicGI") ) )
83  {
84  MPI_Group originGroup, newGroup;
85  MPI_Comm_group (MPI_COMM_WORLD, &originGroup);
86 
87  if ( numtasks == 1 )
88  {
89  std::cout << "Serial Fluid/Structure computation" << std::endl;
90  fluid = true;
91  solid = true;
92  solidLeader = 0;
93  fluidLeader = solidLeader;
94 
95  M_epetraWorldComm.reset ( new Epetra_MpiComm (MPI_COMM_WORLD) );
96  M_epetraComm = M_epetraWorldComm;
97  }
98  else
99  {
100  std::vector<int> members (numtasks);
101 
102  solidLeader = 0;
103  fluidLeader = 1 - solidLeader;
104 
105  if (rank == solidLeader)
106  {
107  members[0] = solidLeader;
108  /* int ierr = */
109  MPI_Group_incl (originGroup, 1, &members[0], &newGroup);
110  solid = true;
111  }
112  else
113  {
114  for (Int ii = 0; ii <= numtasks; ++ii)
115  {
116  if ( ii < solidLeader)
117  {
118  members[ii] = ii;
119  }
120  else if ( ii > solidLeader)
121  {
122  members[ii - 1] = ii;
123  }
124  }
125 
126  /* int ierr = */ MPI_Group_incl (originGroup, numtasks - 1, &members[0], &newGroup);
127  fluid = true;
128  }
129 
130  MPI_Comm* localComm = new MPI_Comm;
131  MPI_Comm_create (MPI_COMM_WORLD, newGroup, localComm);
132  M_localComm.reset (localComm);
133 
134  M_epetraComm.reset (new Epetra_MpiComm (*M_localComm.get() ) );
135  M_epetraWorldComm.reset (new Epetra_MpiComm (MPI_COMM_WORLD) );
136  }
137  }
138  else // Monolithic or FullMonolithic
139  {
140  fluid = true;
141  solid = true;
142  solidLeader = 0;
143  fluidLeader = solidLeader;
144 
145  M_epetraWorldComm.reset ( new Epetra_MpiComm (MPI_COMM_WORLD) );
146  M_epetraComm = M_epetraWorldComm;
147  }
148 
149 #ifdef DEBUG
150  if ( fluid )
151  {
152  debugStream (6220) << M_epetraComm->MyPID()
153  << " ( " << rank << " ) "
154  << " out of " << M_epetraComm->NumProc()
155  << " ( " << numtasks << " ) "
156  << " is fluid." << std::endl;
157  }
158  if ( solid )
159  {
160  debugStream (6220) << M_epetraComm->MyPID()
161  << " ( " << rank << " ) "
162  << " out of " << M_epetraComm->NumProc()
163  << " ( " << numtasks << " ) "
164  << " is solid." << std::endl;
165  }
166 #endif
167 
168  M_epetraWorldComm->Barrier();
169 
170  /*
171  if (solid)
172  {
173  std::cout << "fluid: Building the intercommunicators ... " << std::flush;
174  MPI_Comm* interComm = new MPI_Comm;
175  Int ierr = MPI_Intercomm_create(*M_localComm, 0, MPI_COMM_WORLD, 1, 1, interComm);
176  std::cout << ierr << std::endl;
177  M_interComm.reset(interComm);
178  }
179 
180 
181  if (fluid)
182  {
183  std::cout << "solid: Building the intercommunicators ... " << std::flush;
184  MPI_Comm* interComm = new MPI_Comm;
185  Int ierr = MPI_Intercomm_create(*M_localComm, 0, MPI_COMM_WORLD, 0, 1, interComm);
186  std::cout << ierr << std::endl;
187  M_interComm.reset(interComm);
188  }
189 
190  std::cout << M_interComm.get() << std::endl;
191 
192  //M_oper->setInterComm(M_interComm.get());
193 
194  std::cout << "done." << std::endl;
195 
196  MPI_Barrier(MPI_COMM_WORLD);
197  */
198 
199  this->setFSI( );
200 
201  M_oper->setFluid ( fluid );
202  M_oper->setSolid ( solid );
203 
204  M_oper->setFluidLeader ( fluidLeader );
205  M_oper->setSolidLeader ( solidLeader );
206 
207  M_oper->setComm ( M_epetraComm, M_epetraWorldComm );
208 
209  // opening files for output on the leader only
210  if (M_epetraWorldComm->MyPID() == 0)
211  {
212  M_out_iter.open ("iter");
213  M_out_res .open ("res");
214  }
215 
216  M_epetraWorldComm->Barrier();
217 
218 #ifdef DEBUG
219  debugStream ( 6220 ) << "FSISolver constructor ends\n";
220 #endif
221 
222  //@ M_lambda.resize(M_oper->displacement().size());
223  //@ M_lambdaDot.resize(M_oper->velocity().size());
224 
225  // M_lambda = ZeroVector( M_lambda.size() );
226  // M_lambdaDot = ZeroVector( M_lambdaDot.size() );
227 
228  // debugStream( 6220 ) << "FSISolver::M_lambda: " << M_lambda.size() << "\n";
229  // debugStream( 6220 ) << "FSISolver::M_lambdaDot: " << M_lambdaDot.size() << "\n";
230 
231  M_oper->setData ( data );
232 }
233 
234 void
235 FSISolver::setup ( void )
236 {
237  M_oper->setupFluidSolid();
238 
239  M_oper->setupSystem();
240 
241  M_oper->buildSystem();
242 }
243 
244 void
245 FSISolver::initialize (std::vector< vectorPtr_Type> u0, std::vector< vectorPtr_Type> ds0, std::vector< vectorPtr_Type> df0)
246 {
247  UInt i;
248  if (!u0.size() || !ds0.size() || !df0.size() )
249  {
250  if ( this->isFluid() )
251  {
252  for (i = 0; i < M_oper->fluidTimeAdvance()->size(); ++i)
253  {
254  vectorPtr_Type vec (new vector_Type (M_oper->fluid().getMap() ) );
255  u0.push_back (vec); // couplingVariableMap()
256  }
257  for (i = 0; i < M_oper->ALETimeAdvance()->size(); ++i)
258  {
259  vectorPtr_Type vec (new vector_Type (M_oper->meshMotion().getMap() ) );
260  df0.push_back (vec); // couplingVariableMap()
261  }
262  }
263  if ( this->isSolid() )
264  {
265  for (i = 0; i < M_oper->solidTimeAdvance()->size(); ++i)
266  {
267  vectorPtr_Type vec (new vector_Type (M_oper->solid().map() ) );
268  ds0.push_back (vec); // couplingVariableMap()
269  }
270  }
271  M_oper->initializeTimeAdvance (u0, ds0, df0);
272  // M_oper->initializeBDF(*u0);
273  }
274  else
275  {
276  M_oper->initializeTimeAdvance (u0, ds0, df0); // couplingVariableMap()//copy
277  }
278 }
279 
280 
281 void
282 FSISolver::initializeMonolithicOperator (std::vector< vectorPtr_Type> u0, std::vector< vectorPtr_Type> ds0, std::vector< vectorPtr_Type> df0)
283 {
284  M_oper->initializeMonolithicOperator ( u0, ds0, df0);
285 }
286 
287 
288 void
289 FSISolver::iterate()
290 {
291  debugStream ( 6220 ) << "============================================================\n";
292  debugStream ( 6220 ) << "Solving FSI at time " << M_data->dataFluid()->dataTime()->time() << " with FSI: " << M_data->method() << "\n";
293  debugStream ( 6220 ) << "============================================================\n";
294 
295  if (M_epetraWorldComm->MyPID() == 0)
296  {
297  std::cerr << std::endl << "Warning: FSISolver::iterate() is deprecated!" << std::endl
298  << " You should use FSISolver::iterate( solution ) instead!" << std::endl;
299  }
300 
301  // Update the system
302  M_oper->updateSystem( );
303 
304  // We extract a copy of the solution (\todo{uselessly})
305  vector_Type lambda = M_oper->solution();
306 
307  // The Newton solver
308  UInt maxiter = M_data->maxSubIterationNumber();
309  UInt status = NonLinearRichardson ( lambda,
310  *M_oper,
311  M_data->absoluteTolerance(),
312  M_data->relativeTolerance(),
313  maxiter,
314  M_data->errorTolerance(),
315  M_data->NonLinearLineSearch(),
316  0,/*first newton iter*/
317  2,/*verbosity level*/
318  M_out_res,
319  M_data->dataFluid()->dataTime()->time()
320  );
321 
322  // We update the solution
323  M_oper->updateSolution ( lambda );
324 
325  // Update the system
326  M_oper->updateSystem( );
327 
328  if (status == EXIT_FAILURE)
329  {
330  std::ostringstream __ex;
331  __ex << "FSISolver::iterate ( " << M_data->dataFluid()->dataTime()->time() << " ) Inners iterations failed to converge\n";
332  throw std::logic_error ( __ex.str() );
333  }
334  else
335  {
336  //M_oper->displayer().leaderPrint("FSI- Number of inner iterations: ", maxiter, "\n" );
337  if (M_epetraWorldComm->MyPID() == 0)
338  {
339  M_out_iter << M_data->dataFluid()->dataTime()->time() << " " << maxiter;
340  }
341  }
342 
343  debugStream ( 6220 ) << "FSISolver iteration at time " << M_data->dataFluid()->dataTime()->time() << " done\n";
344  debugStream ( 6220 ) << "============================================================\n";
345  std::cout << std::flush;
346 }
347 
348 
349 void
350 FSISolver::iterate ( vectorPtr_Type& solution )
351 {
352  debugStream ( 6220 ) << "============================================================\n";
353  debugStream ( 6220 ) << "Solving FSI at time " << M_data->dataFluid()->dataTime()->time() << " with FSI: " << M_data->method() << "\n";
354  debugStream ( 6220 ) << "============================================================\n";
355 
356  // Update the system
357  M_oper->updateSystem( );
358 
359  // The initial guess for the Newton method is received from outside.
360  // For instance, it can be the solution at the previous time or an extrapolation
361  vector_Type lambda ( *solution );
362 
363 
364  // the newton solver
365  UInt maxiter = M_data->maxSubIterationNumber();
366  UInt status = NonLinearRichardson ( lambda,
367  *M_oper,
368  M_data->absoluteTolerance(),
369  M_data->relativeTolerance(),
370  maxiter,
371  M_data->errorTolerance(),
372  M_data->NonLinearLineSearch(),
373  0,/*first newton iter*/
374  2,/*verbosity level*/
375  M_out_res,
376  M_data->dataFluid()->dataTime()->time()
377  );
378 
379  // After the Newton method, the solution that was received is modified with the current solution
380  // It is passed outside where it is used as the user wants.
381  *solution = lambda;
382 
383  if (status == EXIT_FAILURE)
384  {
385  std::ostringstream __ex;
386  __ex << "FSISolver::iterate ( " << M_data->dataFluid()->dataTime()->time() << " ) Inners iterations failed to converge\n";
387  throw std::logic_error ( __ex.str() );
388  }
389  else
390  {
391  //M_oper->displayer().leaderPrint("FSI- Number of inner iterations: ", maxiter, "\n" );
392  if (M_epetraWorldComm->MyPID() == 0)
393  {
394  M_out_iter << M_data->dataFluid()->dataTime()->time() << " " << maxiter;
395  }
396  }
397 
398  debugStream ( 6220 ) << "FSISolver iteration at time " << M_data->dataFluid()->dataTime()->time() << " done\n";
399  debugStream ( 6220 ) << "============================================================\n";
400  std::cout << std::flush;
401 }
402 
403 // ===================================================
404 // Set Functions
405 // ===================================================
406 void
407 FSISolver::setSourceTerms ( const fluidSource_Type& fluidSource,
408  const solidSource_Type& solidSource )
409 {
410  M_oper->fluid().setSourceTerm ( fluidSource );
411  M_oper->solid().setSourceTerm ( solidSource );
412 }
413 
414 void
415 FSISolver::setFSI( )
416 {
417  debugStream ( 6220 ) << "FSISolver::setFSI with operator " << M_data->method() << "\n";
418  M_oper = FSIOperPtr_Type ( FSIOperator::FSIFactory_Type::instance().createObject ( M_data->method() ) );
419 }
420 
421 void
422 FSISolver::setFluidBC ( const fluidBchandlerPtr_Type& bc_fluid )
423 {
424  if ( this->isFluid() )
425  {
426  M_oper->setFluidBC ( bc_fluid );
427  }
428 }
429 
430 void
431 FSISolver::setLinFluidBC ( const fluidBchandlerPtr_Type& bc_dfluid )
432 {
433  if ( this->isFluid() )
434  {
435  M_oper->setLinFluidBC ( bc_dfluid );
436  }
437 }
438 
439 void
440 FSISolver::setInvLinFluidBC ( const fluidBchandlerPtr_Type& bc_dfluid_inv )
441 {
442  if ( this->isFluid() )
443  {
444  M_oper->setInvLinFluidBC ( bc_dfluid_inv );
445  }
446 }
447 
448 void
449 FSISolver::setHarmonicExtensionBC ( const fluidBchandlerPtr_Type& bc_he )
450 {
451  if ( this->isFluid() )
452  {
453  M_oper->setHarmonicExtensionBC ( bc_he );
454  }
455 }
456 
457 void
458 FSISolver::setSolidBC ( const solidBchandlerPtr_Type& bc_solid )
459 {
460  if ( this->isSolid() )
461  {
462  M_oper->setSolidBC ( bc_solid );
463  }
464 }
465 
466 void
467 FSISolver::setLinSolidBC ( const solidBchandlerPtr_Type& bc_dsolid )
468 {
469  if ( this->isSolid() )
470  {
471  M_oper->setLinSolidBC ( bc_dsolid );
472  }
473 }
474 
475 void
476 FSISolver::setInvLinSolidBC ( const solidBchandlerPtr_Type& bc_dsolid_inv )
477 {
478  if ( this->isSolid() )
479  {
480  M_oper->setInvLinSolidBC ( bc_dsolid_inv );
481  }
482 }
483 
484 // void
485 // FSISolver::setReducedLinFluidBC( const fluidBchandlerPtr_Type& bc_dredfluid )
486 // {
487 // M_oper->setReducedLinFluidBC( bc_dredfluid );
488 // }
489 
490 // void
491 // FSISolver::setInvReducedLinFluidBC( const fluidBchandlerPtr_Type& bc_dredfluid_inv )
492 // {
493 // M_oper->setInvReducedLinFluidBC( bc_dredfluid_inv );
494 // }
495 
496 } // Namespace LifeV
497 #endif /* TWODIM */
#define debugStream
Definition: LifeDebug.hpp:182