LifeV
MultiscaleModelWindkessel0D.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 Multiscale Windkessel 0D
30  *
31  * @date 08-02-2011
32  * @author Cristiano Malossi <cristiano.malossi@epfl.ch>
33  * @author Mahmoud Jafargholi <mahmoud.jafargholi@epfl.ch>
34  *
35  * @mantainer Cristiano Malossi <cristiano.malossi@epfl.ch>
36  */
37 
38 #include <lifev/multiscale/models/MultiscaleModelWindkessel0D.hpp>
39 
40 namespace LifeV
41 {
42 namespace Multiscale
43 {
44 
45 // ===================================================
46 // Constructors & Destructor
47 // ===================================================
51  M_outputFile (),
52  M_bc ( new bcInterface_Type() ),
53  M_data ( new data_Type() ),
56  M_pressureLeft (),
57  M_flowRateLeft (),
58  M_pressureRight (),
61  M_resistance1 (),
62  M_resistance2 (),
63  M_capacitance ()
64 {
65 
66 #ifdef HAVE_LIFEV_DEBUG
67  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::MultiscaleModelWindkessel0D() \n";
68 #endif
69 
71 }
72 
73 // ===================================================
74 // MultiscaleModel Methods
75 // ===================================================
76 void
77 MultiscaleModelWindkessel0D::setupData ( const std::string& fileName )
78 {
79 
80 #ifdef HAVE_LIFEV_DEBUG
81  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::setupData( fileName ) \n";
82 #endif
83 
84  multiscaleModel_Type::setupData ( fileName );
85 
86  GetPot dataFile ( fileName );
87 
88  // R1, R2, and C can have global scaling factors applied to them, these are overridden by local scaling factors
89  Real resistanceScalingFactor = dataFile ( "ScalingFactors/Resistance", M_globalData->scalingFactorResistance() );
90  Real complianceScalingFactor = dataFile ( "ScalingFactors/Compliance", M_globalData->scalingFactorCompliance() );
91 
92  M_resistance1 = dataFile ( "Coefficients/Resistance1" , 1.0 ) * resistanceScalingFactor;
93  M_resistance2 = dataFile ( "Coefficients/Resistance2" , 1.0 ) * resistanceScalingFactor;
94  M_capacitance = dataFile ( "Coefficients/Capacitance" , 1.0 ) * complianceScalingFactor;
95 
96  if ( M_globalData.get() )
97  {
98  setupGlobalData ( fileName );
99  }
100 
101  // We need to create the BCHandler before using it
102  M_bc->createHandler();
103 
104  // Exporter/Importer
106 }
107 
108 void
110 {
111 
112 #ifdef HAVE_LIFEV_DEBUG
113  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::setupModel() \n";
114 #endif
115 
117 
118  M_bc->setPhysicalSolver ( M_data );
119 
120  // Safety check
121  if ( M_bc->handler()->bc ( 1 ).bcType() != Voltage )
122  {
123  std::cout << "!!! Error: the Windkessel model support only stress boundary conditions on the right at the present time !!!" << std::endl;
124  }
125 }
126 
127 void
129 {
130 
131 #ifdef HAVE_LIFEV_DEBUG
132  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::buildModel() \n";
133 #endif
134 
136 }
137 
138 void
140 {
141 
142 #ifdef HAVE_LIFEV_DEBUG
143  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::updateModel() \n";
144 #endif
145 
148 
149  // Update BCInterface solver variables
150  M_bc->updatePhysicalSolverVariables();
151 
152  M_pressureRight = -M_bc->handler()->bc ( 1 ).evaluate ( M_globalData->dataTime()->time() );
153 }
154 
155 void
157 {
158 
159 #ifdef HAVE_LIFEV_DEBUG
160  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::solveModel() \n";
161 #endif
162 
163  displayModelStatus ( "Solve" );
164 
165  switch ( M_bc->handler()->bc ( 0 ).bcType() )
166  {
167  case Current:
168 
169  M_flowRateLeft = M_bc->handler()->bc ( 0 ).evaluate ( M_globalData->dataTime()->time() );
170  M_pressureLeft = solveForPressure();
171 
172  break;
173 
174  case Voltage:
175 
176  M_pressureLeft = -M_bc->handler()->bc ( 0 ).evaluate ( M_globalData->dataTime()->time() );
177  M_flowRateLeft = solveForFlowRate();
178 
179  break;
180 
181  default:
182 
183  std::cout << "Warning: bcType \"" << M_bc->handler()->bc ( 0 ).bcType() << "\"not available!" << std::endl;
184 
185  break;
186  }
187 }
188 
189 void
191 {
192 
193 #ifdef HAVE_LIFEV_DEBUG
194  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::updateSolution() \n";
195 #endif
196 
197 }
198 
199 void
201 {
202 
203 #ifdef HAVE_LIFEV_DEBUG
204  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::saveSolution() \n";
205 #endif
206 
207  M_outputFile << " " << M_globalData->dataTime()->time()
208  << " " << M_flowRateLeft
209  << " " << M_pressureLeft << std::endl;
210 
211  if ( M_globalData->dataTime()->isLastTimeStep() )
212  {
213  M_outputFile.close();
214  }
215 }
216 
217 void
219 {
220  if ( M_comm->MyPID() == 0 )
221  {
222  multiscaleModel_Type::showMe();
223 
224  std::cout << "Resistance1 = " << M_resistance1 << std::endl
225  << "Resistance2 = " << M_resistance2 << std::endl
226  << "Capacitance = " << M_capacitance << std::endl << std::endl;
227  }
228 }
229 
230 Real
232 {
234 }
235 
236 // ===================================================
237 // MultiscaleInterface Methods
238 // ===================================================
239 void
241 {
243  base.setFunction ( std::bind ( function, std::placeholders::_1, std::placeholders::_1, std::placeholders::_1, std::placeholders::_1, std::placeholders::_1 ) );
244 
245  M_bc->handler()->setBC ( boundaryFlag ( boundaryID ), Current, base );
246 }
247 
248 void
250 {
252  base.setFunction ( std::bind ( function, std::placeholders::_1, std::placeholders::_1, std::placeholders::_1, std::placeholders::_1, std::placeholders::_1 ) );
253 
254  M_bc->handler()->setBC ( boundaryFlag ( boundaryID ), Voltage, base );
255 }
256 
257 Real
258 MultiscaleModelWindkessel0D::boundaryDeltaFlowRate ( const multiscaleID_Type& boundaryID, bool& solveLinearSystem )
259 {
260  if ( boundaryFlag ( boundaryID ) == 1 )
261  {
262  return 0;
263  }
264 
265  solveLinearModel ( solveLinearSystem );
266 
267  return M_tangentFlowRateLeft;
268 }
269 
270 Real
271 MultiscaleModelWindkessel0D::boundaryDeltaMeanNormalStress ( const multiscaleID_Type& boundaryID, bool& solveLinearSystem )
272 {
273  if ( boundaryFlag ( boundaryID ) == 1 )
274  {
275  return 0;
276  }
277 
278  solveLinearModel ( solveLinearSystem );
279 
280  return -M_tangentPressureLeft;
281 }
282 
283 // ===================================================
284 // Private Methods
285 // ===================================================
286 void
287 MultiscaleModelWindkessel0D::setupGlobalData ( const std::string& fileName )
288 {
289  GetPot dataFile ( fileName );
290 
291  //Global data time
292  M_data->setTimeData ( M_globalData->dataTime() );
293 
294  if ( !dataFile.checkVariable ( "Coefficients/VenousPressure" ) )
295  {
296  M_pressureRight = M_globalData->fluidVenousPressure();
297  }
298  M_data->setVenousPressure ( M_pressureRight );
299 }
300 
301 void
303 {
304 
305 #ifdef HAVE_LIFEV_DEBUG
306  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::initializeSolution() \n";
307 #endif
308 
309  if ( multiscaleProblemStep > 0 )
310  {
311  std::string fileName = multiscaleProblemFolder + multiscaleProblemPrefix + "_Model_" + number2string ( M_ID ) + "_" + number2string ( multiscaleProblemStep - 1 ) + ".mfile";
312 
313  std::ifstream inputFile;
314  inputFile.open ( fileName.c_str(), std::ios::in );
315 
316  if ( inputFile.is_open() )
317  {
318  // Define some variables
319  std::string line;
320  std::vector<std::string> stringsVector;
321  Real deltaT (1e15);
322 
323  // Read the first line with comments
324  std::getline ( inputFile, line, '\n' );
325 
326  // Read one-by-one all the others lines of the fileName
327  while ( std::getline ( inputFile, line, '\n' ) )
328  {
329  // Split the three entries
330  boost::split ( stringsVector, line, boost::is_any_of ( " " ), boost::token_compress_on );
331 
332  // Import values
333  if ( std::abs ( string2number ( stringsVector[1] ) - M_globalData->dataTime()->initialTime() ) <= deltaT )
334  {
335  deltaT = std::abs ( string2number ( stringsVector[1] ) - M_globalData->dataTime()->initialTime() );
336 
337  M_flowRateLeft = string2number ( stringsVector[2] );
338  M_pressureLeft = string2number ( stringsVector[3] );
339  }
340  }
341 
342  // Close file
343  inputFile.close();
344  }
345  else
346  {
347  std::cerr << " !!! Error: cannot open fileName: " << fileName.c_str() << " !!!" << std::endl;
348  }
349  }
350  else
351  {
352  M_flowRateLeft = 0;
353  M_pressureLeft = M_globalData->solidExternalPressure();
354 
355  switch ( M_bc->handler()->bc ( 0 ).bcType() )
356  {
357  case Current:
358 
359  M_flowRateLeft = M_bc->handler()->bc ( 0 ).evaluate ( M_globalData->dataTime()->time() );
360 
361  break;
362 
363  case Voltage:
364 
365  // if ( std::abs( M_globalData->solidExternalPressure() + M_bc->handler()->bc( 0 ).evaluate( M_globalData->dataTime()->time() ) ) > 1e-14 )
366  // std::cout << "!!! Warning: external pressure should be equal to the initial pressure !!! " << std::endl;
367 
368  break;
369 
370  default:
371 
372  std::cout << "Warning: bcType \"" << M_bc->handler()->bc ( 0 ).bcType() << "\"not available!" << std::endl;
373 
374  break;
375  }
376  }
377 }
378 
379 void
381 {
382 
383 #ifdef HAVE_LIFEV_DEBUG
384  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::setupExporterImporter() \n";
385 #endif
386 
387  std::string file = multiscaleProblemFolder + multiscaleProblemPrefix + "_Model_" + number2string ( M_ID ) + "_" + number2string ( multiscaleProblemStep ) + ".mfile";
388  M_outputFile.open ( file.c_str(), std::ios::trunc );
389  M_outputFile << std::scientific << std::setprecision ( 15 )
390  << "% MODEL: " << M_modelName << std::endl
391  << "% TIME FLOW RATE PRESSURE" << std::endl;
392 }
393 
394 Real
396 {
397 #ifdef HAVE_LIFEV_DEBUG
398  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::solveForFlowRate() \n";
399 #endif
400 
401  if ( std::abs ( M_capacitance ) < 1e-14 )
402  {
404  }
405  else
406  {
407  Real dt = M_globalData->dataTime()->timeStep();
408  Real dP = - ( M_pressureLeft - M_pressureLeft_tn ) / dt;
410  Real K2 = 1.0 / ( M_resistance1 * M_resistance2 * M_capacitance );
411  Real K3 = 1.0 / M_resistance1;
412 
413  return - 1.0 / ( K1 * K1 )
414  * ( K2 * dP - std::exp ( -K1 * dt ) * ( K2 * dP + (K1 * K1) * M_flowRateLeft_tn - K1 * K2 * M_pressureRight + K1 * K2 * M_pressureLeft_tn - K1 * K3 * dP ) )
415  + ( K3 * dP - K2 * M_pressureLeft_tn + K2 * M_pressureRight + K2 * dP * dt ) / K1;
416  }
417 }
418 
419 Real
421 {
422 #ifdef HAVE_LIFEV_DEBUG
423  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::solveForPressure() \n";
424 #endif
425 
426  if ( std::abs ( M_capacitance ) < 1e-14 )
427  {
429  }
430  else
431  {
432  Real dt = M_globalData->dataTime()->timeStep();
433  Real dQ = - ( M_flowRateLeft - M_flowRateLeft_tn ) / dt;
434  Real K1 = 1.0 / ( M_resistance2 * M_capacitance );
436  Real K3 = M_resistance1;
437 
438  return - 1.0 / ( K1 * K1 )
439  * ( K2 * dQ - std::exp ( -K1 * dt ) * ( K2 * dQ + ( K1 * K1 ) * M_pressureLeft_tn - K1 * K1 * M_pressureRight + K1 * K2 * M_flowRateLeft_tn - K1 * K3 * dQ) )
440  + ( K3 * dQ - K2 * M_flowRateLeft_tn + K1 * M_pressureRight + K2 * dQ * dt ) / K1;
441  }
442 }
443 
444 void
445 MultiscaleModelWindkessel0D::solveLinearModel ( bool& solveLinearSystem )
446 {
447 
448 #ifdef HAVE_LIFEV_DEBUG
449  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::solveLinearModel() \n";
450 #endif
451 
452  if ( !solveLinearSystem )
453  {
454  return;
455  }
456 
457  //Solve the linear problem
458  displayModelStatus ( "Solve linear" );
459  switch ( M_bc->handler()->bc ( 0 ).bcType() )
460  {
461  case Current: // dP/dQ
462 
463  M_tangentFlowRateLeft = 1.;
464  M_tangentPressureLeft = tangentSolveForPressure();
465 
466  break;
467 
468  case Voltage: // dQ/dS
469 
470  M_tangentPressureLeft = 1.;
471  M_tangentFlowRateLeft = -tangentSolveForFlowRate();
472 
473  break;
474 
475  default:
476 
477  std::cout << "Warning: bcType \"" << M_bc->handler()->bc ( 0 ).bcType() << "\"not available!" << std::endl;
478 
479  break;
480  }
481 
482  // This flag avoid recomputation of the same system
483  solveLinearSystem = false;
484 }
485 
486 Real
488 {
489 #ifdef HAVE_LIFEV_DEBUG
490  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::tangentSolveForFlowRate() \n";
491 #endif
492 
493  if ( std::abs ( M_capacitance ) < 1e-14 )
494  {
495  return -1.0 / ( M_resistance1 + M_resistance2 );
496  }
497  else
498  {
499  Real dt = M_globalData->dataTime()->timeStep();
501  Real K2 = 1.0 / ( M_resistance1 * M_resistance2 * M_capacitance);
502  Real K3 = 1.0 / M_resistance1;
503 
504  return - ( K2 + K3 / dt ) / K1
505  - 1.0 / ( K1 * K1 ) * ( std::exp ( -K1 * dt ) * ( K2 / dt - ( K1 * K3 ) / dt ) - K2 / dt );
506  }
507 }
508 
509 Real
511 {
512 #ifdef HAVE_LIFEV_DEBUG
513  debugStream ( 8150 ) << "MultiscaleModelWindkessel0D::tangentSolveForPressure() \n";
514 #endif
515 
516  if ( std::abs ( M_capacitance ) < 1e-14 )
517  {
518  return - ( M_resistance1 + M_resistance2 );
519  }
520  else
521  {
522  Real dt = M_globalData->dataTime()->timeStep();
523  Real K1 = 1.0 / ( M_resistance2 * M_capacitance );
525  Real K3 = M_resistance1;
526 
527  return - ( K2 + K3 / dt ) / K1
528  - 1.0 / ( K1 * K1 ) * ( std::exp ( -K1 * dt ) * ( K2 / dt - ( K1 * K3 ) / dt ) - K2 / dt );
529  }
530 }
531 
532 } // Namespace multiscale
533 } // Namespace LifeV
std::function< Real(const Real &, const Real &, const Real &, const Real &, const ID &) > function_Type
Real boundaryDeltaMeanNormalStress(const multiscaleID_Type &boundaryID, bool &solveLinearSystem)
Get the variation of the integral of the mean normal stress (on a specific boundary interface) using ...
MultiscaleModel()
The main constructor.
Real tangentSolveForPressure()
Solve the tangent problem for the flow rate.
void imposeBoundaryMeanNormalStress(const multiscaleID_Type &boundaryID, const function_Type &function)
Impose the integral of the mean normal stress on a specific boundary interface of the model...
void imposeBoundaryFlowRate(const multiscaleID_Type &boundaryID, const function_Type &function)
Impose the flow rate on a specific interface of the model.
void updateInverseJacobian(const UInt &iQuadPt)
MultiscaleModel multiscaleModel_Type
Real checkSolution() const
Return a specific scalar quantity to be used for a comparison with a reference value.
Real boundaryDeltaFlowRate(const multiscaleID_Type &boundaryID, bool &solveLinearSystem)
Get the variation of the flow rate (on a specific boundary interface) using the linear model...
void showMe()
Display some information about the model.
MultiscaleModelWindkessel0D - Multiscale model for Windkessel 0D terminals.
double Real
Generic real data.
Definition: LifeV.hpp:175
void setupGlobalData(const std::string &fileName)
Setup the global data of the model.
void setupData(const std::string &fileName)
Setup the data of the model.
void solveLinearModel(bool &solveLinearSystem)
Solve the tangent problem.
Real tangentSolveForFlowRate()
Solve the tangent problem for the flow rate.
MultiscaleInterface - The multiscale interface for fluid problems.
ZeroDimensionalFunction - A boundary conditions function for zero-dimensional models.