LifeV
OneDFSIFunctionSolverDefined.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 some functions for the boundary conditions of 1D models.
30  *
31  * @version 1.0
32  * @date 01-08-2006
33  * @author Lucia Mirabella <lucia.mirabella@gmail.com>
34  *
35  * @version 2.0
36  * @date 20-04-2010
37  * @author Cristiano Malossi <cristiano.malossi@epfl.ch>
38  *
39  * @contributors Ricardo Ruiz-Baier <ricardo.ruiz@epfl.ch>
40  * @maintainer Cristiano Malossi <cristiano.malossi@epfl.ch>
41  */
42 
43 #include <lifev/one_d_fsi/function/OneDFSIFunctionSolverDefined.hpp>
44 
45 namespace LifeV
46 {
47 
48 // ===================================================
49 // Constructors & Destructor
50 // ===================================================
51 OneDFSIFunctionSolverDefined::OneDFSIFunctionSolverDefined ( const bcSide_Type& bcSide, const bcType_Type& bcType ) :
52  M_fluxPtr (),
53  M_sourcePtr (),
54  M_solutionPtr (),
55  M_bcNode (),
56  M_bcSide ( bcSide ),
57  M_bcType ( bcType )
58 {
59 }
60 
62  M_fluxPtr ( bcFunctionDefault.M_fluxPtr ), // Ptr copy
63  M_sourcePtr ( bcFunctionDefault.M_sourcePtr ), // Ptr copy
64  M_solutionPtr ( bcFunctionDefault.M_solutionPtr ), // Ptr copy
65  M_bcNode ( bcFunctionDefault.M_bcNode ),
66  M_bcType ( bcFunctionDefault.M_bcType )
67 {}
68 
69 // ===================================================
70 // Methods
71 // ===================================================
72 Real
73 OneDFSIFunctionSolverDefined::operator() ( const Real& /*time*/, const Real& /*timeStep*/ )
74 {
75 #ifdef HAVE_LIFEV_DEBUG
76  assert ( false );
77 #endif
78  return 0.;
79 }
80 
81 // ===================================================
82 // Set Methods
83 // ===================================================
84 void
86 {
87  M_fluxPtr = fluxPtr;
88  M_sourcePtr = sourcePtr;
89 
90  this->setupNode();
91 }
92 
93 // ===================================================
94 // Protected Methods
95 // ===================================================
96 void
98 {
99  ( M_bcSide == OneDFSI::left ) ? M_bcNode = 0 : M_bcNode = M_fluxPtr->physics()->data()->numberOfNodes() - 1;
100 }
101 
102 
103 
104 // ===================================================
105 // Constructors & Destructor
106 // ===================================================
107 OneDFSIFunctionSolverDefinedRiemann::OneDFSIFunctionSolverDefinedRiemann ( const bcSide_Type& bcSide, const bcType_Type& bcType ) :
108  super ( bcSide, bcType ),
109  M_bcU (),
110  M_bcW ()
111 {}
112 
114  super ( bcFunctionRiemann ),
115  M_bcU ( bcFunctionRiemann.M_bcU ),
116  M_bcW ( bcFunctionRiemann.M_bcW )
117 {}
118 
119 // ===================================================
120 // Methods
121 // ===================================================
122 Real
123 OneDFSIFunctionSolverDefinedRiemann::operator() ( const Real& /*time*/, const Real& /*timeStep*/ )
124 {
126 
127  return ( ( M_bcType == OneDFSI::W1 ) ? M_bcW[0] : M_bcW[1] );
128 }
129 
130 // ===================================================
131 // Protected Methods
132 // ===================================================
133 void
135 {
136  M_bcU[0] = (* (*M_solutionPtr) ["A"]) (M_bcNode);
137  M_bcU[1] = (* (*M_solutionPtr) ["Q"]) (M_bcNode);
138  M_bcW[0] = (* (*M_solutionPtr) ["W1"]) (M_bcNode);
139  M_bcW[1] = (* (*M_solutionPtr) ["W2"]) (M_bcNode);
140 }
141 
142 
143 
144 // ===================================================
145 // Constructors & Destructor
146 // ===================================================
147 OneDFSIFunctionSolverDefinedCompatibility::OneDFSIFunctionSolverDefinedCompatibility ( const bcSide_Type& bcSide, const bcType_Type& bcType ) :
148  super ( bcSide, bcType ),
149  M_bcElement (),
150  M_bcInternalNode (),
151  M_eigenvalues (),
157 {
158 }
159 
161  super ( bcFunctionCompatibility ),
162  M_bcElement ( bcFunctionCompatibility.M_bcElement ),
163  M_bcInternalNode ( bcFunctionCompatibility.M_bcInternalNode ),
164  M_eigenvalues ( bcFunctionCompatibility.M_eigenvalues ),
165  M_deltaEigenvalues ( bcFunctionCompatibility.M_deltaEigenvalues ),
166  M_leftEigenvector1 ( bcFunctionCompatibility.M_leftEigenvector1 ),
167  M_leftEigenvector2 ( bcFunctionCompatibility.M_leftEigenvector2 ),
168  M_deltaLeftEigenvector1 ( bcFunctionCompatibility.M_deltaLeftEigenvector1 ),
169  M_deltaLeftEigenvector2 ( bcFunctionCompatibility.M_deltaLeftEigenvector2 )
170 {
171 }
172 
173 // ===================================================
174 // Protected Methods
175 // ===================================================
176 void
178 {
180 
181  mesh_Type::edge_Type boundaryEdge;
182  switch ( M_bcSide )
183  {
184  case OneDFSI::left:
185  M_bcElement = 0;
187  break;
188 
189  case OneDFSI::right:
190  M_bcElement = M_bcNode - 1;
192  break;
193 
194  default:
195  std::cout << "Warning: bcSide \"" << M_bcSide << "\" not available!" << std::endl;
196  break;
197  }
198 }
199 
200 Real
202 {
205 
206  switch ( M_bcType )
207  {
208  case OneDFSI::W1:
209  return evaluateRHS ( M_eigenvalues[0], M_leftEigenvector1, M_deltaLeftEigenvector1, timeStep );
210  break;
211 
212  case OneDFSI::W2:
213  return evaluateRHS ( M_eigenvalues[1], M_leftEigenvector2, M_deltaLeftEigenvector2, timeStep );
214  break;
215 
216  default:
217  std::cout << "Warning: bcType \"" << M_bcType << "\"not available!" << std::endl;
218  return 0.;
219  }
220 }
221 
222 void
224 {
225  M_fluxPtr->eigenValuesEigenVectors ( M_bcU[0], M_bcU[1],
226  M_eigenvalues, M_leftEigenvector1, M_leftEigenvector2,
227  M_bcNode );
228 
229  M_fluxPtr->deltaEigenValuesEigenVectors ( M_bcU[0], M_bcU[1],
230  M_deltaEigenvalues, M_deltaLeftEigenvector1, M_deltaLeftEigenvector2,
231  M_bcNode );
232 }
233 
234 Real
235 OneDFSIFunctionSolverDefinedCompatibility::evaluateRHS ( const Real& eigenvalue, const container2D_Type& eigenvector,
236  const container2D_Type& deltaEigenvector, const Real& timeStep )
237 {
238  Real cfl = computeCFL ( eigenvalue, timeStep );
239 
240  container2D_Type U_interpolated;
241  Real Qvisco_interpolated;
242  U_interpolated[0] = ( 1 - cfl ) * M_bcU[0] + cfl * (* (*M_solutionPtr) ["A"]) ( M_bcInternalNode );
243  U_interpolated[1] = ( 1 - cfl ) * M_bcU[1] + cfl * (* (*M_solutionPtr) ["Q"]) ( M_bcInternalNode );
244 
245  // The second condition detects if there is a viscoelastic flow on the bondary.
246  if ( M_fluxPtr->physics()->data()->viscoelasticWall() && (* (*M_solutionPtr) ["Q_visc"]) (M_bcNode) > 1e-10 )
247  {
248  Qvisco_interpolated = ( 1 - cfl ) * (* (*M_solutionPtr) ["Q_visc"]) (M_bcNode) + cfl * (* (*M_solutionPtr) ["Q_visc"]) ( M_bcInternalNode );
249  }
250  else
251  {
252  Qvisco_interpolated = 0;
253  }
254 
255  container2D_Type U;
256 
257  container2D_Type bcNodes;
258  bcNodes[0] = M_bcNode;
259  bcNodes[1] = M_bcInternalNode;
260 
261 #ifdef OLD_COMPATIBILITY
262  U[0] = U_interpolated[0] - timeStep * M_sourcePtr->interpolatedNonConservativeSource ( U_interpolated[0], U_interpolated[1], 0, bcNodes, cfl );
263  U[1] = U_interpolated[1] - timeStep * M_sourcePtr->interpolatedNonConservativeSource ( U_interpolated[0], U_interpolated[1], 1, bcNodes, cfl );
264 #else
265  container2D_Type U0_interpolated;
266  U0_interpolated[0] = ( 1 - cfl ) * M_fluxPtr->physics()->data()->area0 (bcNodes[0]) + cfl * M_fluxPtr->physics()->data()->area0 (bcNodes[1]);
267  U0_interpolated[1] = 0;
268 
269  U[0] = U_interpolated[0]
270  - U0_interpolated[0] - timeStep * ( M_sourcePtr->interpolatedNonConservativeSource ( U_interpolated[0], U_interpolated[1], 0, bcNodes, cfl ) -
271  M_sourcePtr->interpolatedNonConservativeSource ( U0_interpolated[0], U0_interpolated[1], 0, bcNodes, cfl ) );
272  U[1] = (U_interpolated[1] - Qvisco_interpolated) // We consider just the elastic component
273  - U0_interpolated[1] - timeStep * ( M_sourcePtr->interpolatedNonConservativeSource ( U_interpolated[0], U_interpolated[1], 1, bcNodes, cfl ) -
274  M_sourcePtr->interpolatedNonConservativeSource ( U0_interpolated[0], U0_interpolated[1], 1, bcNodes, cfl ) );
275 
276  U_interpolated[0] -= U0_interpolated[0];
277  U_interpolated[1] -= U0_interpolated[1];
278 
279  // Adding Z_0
280  U[0] += M_fluxPtr->physics()->data()->area0 (bcNodes[0]);
281  U[1] += 0;
282 #endif
283  return scalarProduct ( eigenvector, U ) + timeStep * eigenvalue * scalarProduct ( deltaEigenvector, U_interpolated );
284 }
285 
286 Real
287 OneDFSIFunctionSolverDefinedCompatibility::computeCFL ( const Real& eigenvalue, const Real& timeStep ) const
288 {
289  Real cfl = eigenvalue * timeStep / edgeLength (M_fluxPtr->physics()->data()->mesh()->edge ( M_bcElement ) );
290 
291 #ifdef HAVE_LIFEV_DEBUG
292  if ( M_bcInternalNode == 1 ) // the edge is on the left of the domain
293  {
294  ASSERT ( -1. < cfl && cfl < 0. , "This characteristics is wrong!\nEither it is not outcoming (eigenvalue>0 at the left of the domain),\n or CFL is too high.");
295 
296  }
297  else // the edge is on the right of the domain
298  {
299  ASSERT ( 0. < cfl && cfl < 1. , "This characteristics is wrong!\nEither it is not outcoming (eigenvalue<0 at the right of the domain),\n or CFL is too high.");
300  }
301 #endif
302 
303  return std::abs (cfl);
304 }
305 
306 
307 
308 // ===================================================
309 // Methods
310 // ===================================================
311 Real
312 OneDFSIFunctionSolverDefinedAbsorbing::operator() ( const Real& /*time*/, const Real& timeStep )
313 {
316 
317  Real W_out (0.), W_out_old (0.);
318  switch ( M_bcType )
319  {
320  case OneDFSI::W1:
321  W_out = M_bcW[1] + evaluateRHS ( M_eigenvalues[1], M_leftEigenvector2, M_deltaLeftEigenvector2, timeStep ) - scalarProduct ( M_leftEigenvector2, M_bcU );
322  W_out_old = -M_bcW[0] + scalarProduct ( M_leftEigenvector1, M_bcU );
323  break;
324 
325  case OneDFSI::W2:
326  W_out = M_bcW[0] + evaluateRHS ( M_eigenvalues[0], M_leftEigenvector1, M_deltaLeftEigenvector1, timeStep ) - scalarProduct ( M_leftEigenvector1, M_bcU );
327  W_out_old = -M_bcW[1] + scalarProduct ( M_leftEigenvector2, M_bcU );
328  break;
329  default:
330  std::cout << "Warning: bcType \"" << M_bcType << "\"not available!" << std::endl;
331  break;
332  }
333 
334  Real a1, a2, a11, a22, b1, b2, c1, c2;
335  a1 = M_fluxPtr->physics()->pressure ( M_bcU[0], timeStep, M_bcNode ) - this->venousPressure(); // pressure at previous time step
336  a2 = M_bcU[1]; // flux at previous time step
337 
338  b1 = M_fluxPtr->physics()->dPdW ( M_bcW[0], M_bcW[1], 0, M_bcNode ); // dP / dW1
339  b2 = M_bcU[0] / 2; // dQ / dW1
340 
341  c1 = M_fluxPtr->physics()->dPdW ( M_bcW[0], M_bcW[1], 1, M_bcNode ); // dP / dW2
342  c2 = b2; // dQ / dW2
343 
344  a11 = a1 - b1 * M_bcW[0] - c1 * M_bcW[1];
345  a22 = a2 - b2 * M_bcW[0] - c2 * M_bcW[1];
346 
347  Real resistance (b1 / b2);
348  this->resistance ( resistance );
349 
350  return W_out_old + W_out * (b2 * resistance - b1) / (c1 - c2 * resistance) + (a22 * resistance - a11) / (c1 - c2 * resistance);
351 }
352 
353 
354 
355 // ===================================================
356 // Constructors & Destructor
357 // ===================================================
358 OneDFSIFunctionSolverDefinedResistance::OneDFSIFunctionSolverDefinedResistance ( const bcSide_Type& bcSide, const bcType_Type& bcType, const Real& resistance ) :
359  super ( bcSide, bcType ),
360  M_resistance ( resistance )
361 {}
362 
364  super ( bcFunctionResistance ),
365  M_resistance ( bcFunctionResistance.M_resistance )
366 {}
367 // ===================================================
368 // Constructors & Destructor
369 // ===================================================
371  const bcType_Type& bcType,
372  const Real& resistance1,
373  const Real& resistance2,
374  const Real& compliance,
375  const bool& absorbing,
376  const Real& venousPressure ) :
377  super ( bcSide, bcType ),
378  M_resistance1 ( resistance1 ),
379  M_resistance2 ( resistance2 ),
380  M_compliance ( compliance ),
381  M_absorbing ( absorbing ),
382  M_venousPressure ( venousPressure ),
383  M_P0 ( 0. ),
384  M_Q_tn ( 0. ),
385  M_dQdt_tn ( 0. ),
386  M_integral_tn ( 0. )
387 {}
388 
390  super ( bcFunctionWindkessel3 ),
391  M_resistance1 ( bcFunctionWindkessel3.M_resistance1 ),
392  M_resistance2 ( bcFunctionWindkessel3.M_resistance2 ),
393  M_compliance ( bcFunctionWindkessel3.M_compliance ),
394  M_absorbing ( bcFunctionWindkessel3.M_absorbing ),
395  M_venousPressure ( bcFunctionWindkessel3.M_venousPressure ),
396  M_P0 ( bcFunctionWindkessel3.M_P0 ),
397  M_Q_tn ( bcFunctionWindkessel3.M_Q_tn ),
398  M_dQdt_tn ( bcFunctionWindkessel3.M_dQdt_tn ),
399  M_integral_tn ( bcFunctionWindkessel3.M_integral_tn )
400 {}
401 
402 // ===================================================
403 // Methods
404 // ===================================================
405 Real
406 OneDFSIFunctionSolverDefinedWindkessel3::operator() ( const Real& time, const Real& timeStep )
407 {
408  UInt W_outID;
409  Real W_out;
410 
411  switch ( M_bcType )
412  {
413  case OneDFSI::W1:
414  W_outID = 1;
415  W_out = computeRHS ( timeStep );
416  break;
417  case OneDFSI::W2:
418  W_outID = 0;
419  W_out = computeRHS ( timeStep );
420  break;
421  default:
422  std::cout << "Warning: bcType \"" << M_bcType << "\"not available!" << std::endl;
423  break;
424  }
425 
426  Real A ( M_bcU[0] );
427  Real Q ( M_bcU[1] );
428 
429  if ( M_absorbing )
430  {
431  Real b1 ( M_fluxPtr->physics()->dPdW ( A, Q, 0, M_bcNode ) ); // dP / dW1 - Missing W_outID ???
432  Real b2 ( A / 2 ); // dQ / dW1
433  M_resistance1 = b1 / b2;
434  }
435 
436  // Trapezoidal rule for given integral
437  //
438  // \int_0^t ( pv/(R2*C) + (R1+R2)/(R2*C) Q(s) + R1 dQ(s)/ds ) exp( s / (R2*C) ) ds
439  //
440  // this gives: \int_0^t(n+1) = \int_0^t(n) + \int_t(n)^t(n+1)
441  //
442  // \int_0^t(n) is stored from previous time step
443  // \int_t(n)^t(n+1) f(s) exp( a * s ) ds =
444  // = dt/2 * ( f(t(n+1)) exp( a * t(n+1) ) + f(t(n)) exp( a * t(n) ) ) + O( dt^2 )
445  // = dt/2 * [ exp(a*t(n)) * ( f(t(n+1))*exp(a*dt) + f(t(n)) ) ] + O( dt^2 )
446  Real a ( 1 / ( M_compliance * M_resistance2 ) );
447  Real dQdt ( ( Q - M_Q_tn ) / timeStep );
448  Real F ( a * M_venousPressure + a * (M_resistance1 + M_resistance2) * Q + M_resistance1 * dQdt );
450  Real EXP ( std::exp ( a * time ) );
451  Real EXPdt ( std::exp ( a * timeStep ) );
452  Real integral ( M_integral_tn + ( timeStep / 2 ) * ( EXP * ( F * EXPdt + Fn ) ) );
453 
454  // Compute the solution of circuital ODE
455  // P(t) = P(0) + [ \int_0^t ( pv/(R2*C) + (R1+R2)/(R2*C) Q(s)
456  // + R1 dQ(s)/ds ) exp( s / (R2*C) ) ds ] * exp( - t / (R2*C) )
457  Real P ( M_P0 + integral / EXP );
458 
459  // Update variable for the next time step
460  M_integral_tn = integral;
461  M_dQdt_tn = dQdt;
462  M_Q_tn = Q;
463 
464  // Remove this call to fromPToW it is not compatible with viscoelasticity!
465  return M_fluxPtr->physics()->fromPToW ( P, W_out, W_outID, M_bcNode ); // W_in
466 }
467 
468 }
void setFluxSource(const fluxPtr_Type &fluxPtr, const sourcePtr_Type &sourcePtr)
Set the flux and the source classes for the problem.
Real computeCFL(const Real &eigenvalue, const Real &timeStep) const
Compute the current CFL.
OneDFSIFunctionSolverDefinedCompatibility(const bcSide_Type &bcSide, const bcType_Type &bcType)
Constructor.
OneDFSIFunctionSolverDefinedAbsorbing - Class which implements absorbing boundary conditions for the ...
OneDFSIFunctionSolverDefinedWindkessel3(const bcSide_Type &bcSide, const bcType_Type &bcType, const Real &resistance1, const Real &resistance2, const Real &compliance, const bool &absorbing=false, const Real &venousPressure=6666.)
Constructor.
Real operator()(const Real &time, const Real &timeStep)
Operator()
container2D_Type M_bcW
Value of W at the boundary.
virtual Real operator()(const Real &time, const Real &timeStep)
Operator()
UInt M_bcInternalNode
Dof of the internal node adjacent to the boundary.
virtual void resistance(Real &)
Set the value of the resistance.
container2D_Type M_leftEigenvector1
Left eigen vectors for the two eigen values.
void updateInverseJacobian(const UInt &iQuadPt)
OneDFSIFunctionSolverDefinedWindkessel3 - Class which implements windkessel RCR boundary conditions f...
virtual Real operator()(const Real &time, const Real &timeStep)
Operator()
Real computeRHS(const Real &timeStep)
Compute the rhs.
Real operator()(const Real &time, const Real &timeStep)
Operator()
OneDFSIFunctionSolverDefined(const OneDFSIFunctionSolverDefined &bcFunctionDefault)
Copy constructor.
OneDFSIFunctionSolverDefinedResistance - Class which implements resistance boundary conditions for th...
Real evaluateRHS(const Real &eigenvalue, const container2D_Type &eigenvector, const container2D_Type &deltaEigenvector, const Real &timeStep)
Compute the rhs.
OneDFSIFunctionSolverDefinedRiemann(const OneDFSIFunctionSolverDefinedRiemann &bcFunctionRiemann)
Copy constructor.
OneDFSIFunctionSolverDefinedResistance(const OneDFSIFunctionSolverDefinedResistance &bcFunctionResistance)
Copy constructor.
OneDFSIFunctionSolverDefinedCompatibility - Class which implements Compatibility boundary conditions ...
OneDFSIFunctionSolverDefinedAbsorbing(const OneDFSIFunctionSolverDefinedAbsorbing &bcFunctionAbsorbing)
Copy constructor.
void setupNode()
Automatically identify the boundary node.
OneDFSIFunctionSolverDefined(const bcSide_Type &bcSide, const bcType_Type &bcType)
Constructor.
container2D_Type M_eigenvalues
Eigen values of the jacobian diffFlux (= dF/dU = H)
OneDFSIFunctionSolverDefinedCompatibility(const OneDFSIFunctionSolverDefinedCompatibility &bcFunctionCompatibility)
Copy constructor.
double Real
Generic real data.
Definition: LifeV.hpp:175
OneDFSIModelBCFunctionDefault - Base class for deriving specific 1D boundary functions.
void updateBCVariables()
Update the boundary condition variables.
virtual void setupNode()
Automatically identify the boundary node.
OneDFSIFunctionSolverDefinedResistance(const bcSide_Type &bcSide, const bcType_Type &bcType, const Real &resistance)
Constructor.
OneDFSIFunctionSolverDefinedAbsorbing(const bcSide_Type &bcSide, const bcType_Type &bcType)
Constructor.
OneDFSIFunctionSolverDefinedWindkessel3(const OneDFSIFunctionSolverDefinedWindkessel3 &bcFunctionWindkessel3)
Copy constructor.
OneDFSIFunctionSolverDefinedRiemann(const bcSide_Type &bcSide, const bcType_Type &bcType)
Constructor.
void computeEigenValuesVectors()
Compute the current eigenvalues and eigenvectors.
Real scalarProduct(const container2D_Type &vector1, const container2D_Type &vector2)
Scalar product between 2 2D vectors.
container2D_Type M_bcU
Value of U at the boundary.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
OneDFSIFunctionSolverDefinedRiemann - Class which implements Riemann boundary conditions for the 1D s...