LifeV
OneDFSISolver.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 a solver class for the 1D model.
30  *
31  * @version 1.0
32  * @date 01-10-2006
33  * @author Vincent Martin
34  * @author Tiziano Passerini
35  * @author Lucia Mirabella
36  *
37  * @version 2.0
38  * @author Gilles Fourestey <gilles.fourestey@epfl.ch>
39  * @date 01-08-2009
40  *
41  * @version 2.1
42  * @date 21-04-2010
43  * @author Cristiano Malossi <cristiano.malossi@epfl.ch>
44  *
45  * @contributors Simone Rossi <simone.rossi@epfl.ch>, Ricardo Ruiz-Baier <ricardo.ruiz@epfl.ch>
46  * @maintainer Cristiano Malossi <cristiano.malossi@epfl.ch>
47  */
48 
49 #include <lifev/one_d_fsi/solver/OneDFSISolver.hpp>
50 
51 namespace LifeV
52 {
53 
57 
58 // ===================================================
59 // Constructors & Destructor
60 // ===================================================
62  M_physicsPtr (),
63  M_fluxPtr (),
64  M_sourcePtr (),
65  M_feSpacePtr (),
66  M_commPtr (),
72  M_rhs (),
73  M_residual (),
74  M_fluxVector (),
75  M_sourceVector (),
76  M_dFdUVector (),
77  M_dSdUVector (),
86 {
87 }
88 
89 // ===================================================
90 // Methods
91 // ===================================================
92 void
94 {
95  std::fill ( M_dFdUVector.begin(), M_dFdUVector.end(), ublas::zero_vector<Real> ( M_physicsPtr->data()->numberOfNodes() ) );
96  std::fill ( M_dSdUVector.begin(), M_dSdUVector.end(), ublas::zero_vector<Real> ( M_physicsPtr->data()->numberOfNodes() ) );
97 
98  for ( UInt i (0); i < 4; ++i )
99  {
100  M_dSdUMassMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
101  M_dFdUStiffnessMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
102  M_dFdUGradientMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
103  M_dSdUDivergenceMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
104  }
105 
106  // Elementary computation and matrix assembling
107  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements(); ++iElement )
108  {
109  // set the elementary matrices to 0.
110  M_elementalMassMatrixPtr->zero();
111  M_elementalGradientMatrixPtr->zero();
112 
113  // update the current element
114  M_feSpacePtr->fe().update ( M_feSpacePtr->mesh()->edgeList ( iElement ), UPDATE_DPHI | UPDATE_WDET );
115 
116  // update the mass and grad matrices
117  AssemblyElemental::mass ( 1, *M_elementalMassMatrixPtr, M_feSpacePtr->fe(), 0, 0 );
118  AssemblyElemental::grad ( 0 , -1, *M_elementalGradientMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->fe(), 0, 0 );
119 
120  // assemble the mass and grad matrices
121  assembleMatrix ( *M_homogeneousMassMatrixPtr, *M_elementalMassMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof() , 0, 0, 0, 0 );
122  assembleMatrix ( *M_homogeneousGradientMatrixPtr, *M_elementalGradientMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof() , 0, 0, 0, 0 );
123  }
124 
125  // Dirichlet boundary conditions set in the mass matrix
126  M_homogeneousMassMatrixPtr->globalAssemble();
127  M_homogeneousGradientMatrixPtr->globalAssemble();
128 
129  // In the classical case the linear system use a mass matrix (with Dirichlet BC)
130  //matrixPtr_Type systemMatrix( new matrix_Type( M_feSpacePtr->map() ) );
131  //systemMatrix->insertValueDiagonal( M_physicsPtr->data()->mesh()->meanH() );
132  matrix_Type systemMatrix ( *M_homogeneousMassMatrixPtr );
133  applyDirichletBCToMatrix ( systemMatrix );
134  M_linearSolverPtr->setMatrix ( systemMatrix );
135 }
136 
137 void
138 OneDFSISolver::setupSolution ( solution_Type& solution, const MapEpetra& map, const bool& onlyMainQuantities )
139 {
140  solution["Q"].reset ( new vector_Type ( map ) );
141  solution["P"].reset ( new vector_Type ( map ) );
142  solution["AoverA0minus1"].reset ( new vector_Type ( map ) );
143 
144  if ( onlyMainQuantities )
145  {
146  return;
147  }
148 
149  solution["A"].reset ( new vector_Type ( map ) );
150  solution["W1"].reset ( new vector_Type ( map ) );
151  solution["W2"].reset ( new vector_Type ( map ) );
152 
153  // Flux correction with viscoelastic term
154  if ( M_physicsPtr->data()->viscoelasticWall() )
155  {
156  solution["Q_visc"].reset ( new vector_Type ( map ) ); // viscoelastic contribution to the flux
157  solution["P_visc"].reset ( new vector_Type ( map ) ); // viscoelastic contribution to the pressure
158  }
159 
160  // correction flux with inertial term
161  if ( M_physicsPtr->data()->inertialWall() )
162  {
163  solution["Q_inert"].reset ( new vector_Type ( map ) );
164  }
165 
166  // correction flux with longitudinal term
167  if ( M_physicsPtr->data()->longitudinalWall() )
168  {
169  solution["Q_long"].reset ( new vector_Type ( map ) );
170  }
171 
172  // Initialize solution to zero
173  for ( solutionConstIterator_Type i = solution.begin(); i != solution.end(); ++i )
174  {
175  *i->second = 0.;
176  }
177 }
178 
179 void
181 {
182  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
183  {
184  (*solution["A"]) [iNode] = M_physicsPtr->data()->area0 ( iNode );
185  (*solution["Q"]) [iNode] = 0;
186  }
187 
188  // Compute W1 and W2 from A and Q
189  computeW1W2 ( solution );
190 
191  // Compute A/A0 from A
192  computeAreaRatio ( solution );
193 
194  // Compute initial pressure (taking into account the viscoelastic wall)
195  M_physicsPtr->setArea_tn ( *solution["A"] );
196  computePressure ( solution, M_physicsPtr->data()->dataTime()->timeStep() );
197 }
198 
199 void
201 {
202  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
203  {
204  M_physicsPtr->fromUToW ( ( *solution["W1"]) [iNode], (*solution["W2"]) [iNode],
205  ( *solution["A"] ) [iNode], (*solution["Q"] ) [iNode], iNode );
206  }
207 }
208 
209 void
210 OneDFSISolver::computePressure ( solution_Type& solution, const Real& timeStep )
211 {
212  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
213  {
214  ( *solution["P"] ) [iNode] = M_physicsPtr->elasticPressure ( ( *solution["A"] ) [iNode], iNode )
215  + M_physicsPtr->externalPressure();
216 
217  if ( M_physicsPtr->data()->viscoelasticWall() )
218  {
219  ( *solution["P_visc"] ) [iNode] = M_physicsPtr->viscoelasticPressure ( ( *solution["A"]) [iNode], timeStep, iNode );
220  ( *solution["P"] ) [iNode] += ( *solution["P_visc"] ) [iNode];
221  }
222  }
223 }
224 
225 void
227 {
228  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
229  {
230  ( *solution["AoverA0minus1"] ) [iNode] = ( *solution["A"] ) [iNode] / M_physicsPtr->data()->area0 ( iNode ) - 1;
231  }
232 }
233 
234 void
236 {
237  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
238  {
239  ( *solution["A"] ) [iNode] = ( (*solution["AoverA0minus1"] ) [iNode] + 1 ) * M_physicsPtr->data()->area0 ( iNode );
240  }
241 }
242 
243 void
244 OneDFSISolver::updateRHS ( const solution_Type& solution, const Real& timeStep )
245 {
246  updatedFdU ( solution ); // Update the vector containing the values of the flux at the nodes and its jacobian
247  updatedSdU ( solution ); // Update the vector containing the values of the source term at the nodes and its jacobian
248  updateMatrices(); // Update the matrices for the non-linear terms
249 
250  // Taylor-Galerkin scheme: (explicit, U = [U1,U2]^T, with U1=A, U2=Q )
251  // (Un+1, phi) = ( Un, phi )-> massFactor^{-1} * Un+1 = mass * U
252  // + dt * ( Fh(Un), dphi/dz )-> grad * F(U)
253  // - dt^2/2 * (diffFh(Un) Sh(Un), dphi/dz )-> gradDiffFlux(U) * S(U)
254  // + dt^2/2 * (diffSh(Un) dFh/dz(Un), phi )-> divDiffSrc(U) * F(U)
255  // - dt^2/2 * (diffFh(Un) dFh/dz(Un), dphi/dz )->stiffDiffFlux(U) * F(U)
256  // - dt * ( Sh(Un), phi )-> mass * S(U)
257  // + dt^2/2 * (diffSh(Un) Sh(Un), phi )-> massDiffSrc(U) * S(U)
258 
259  Real dt2over2 = timeStep * timeStep * 0.5;
260 
261  // Initialize residual to 0
262  *M_residual[0] *= 0;
263  *M_residual[1] *= 0;
264 
265  for ( UInt i (0); i < 2; ++i )
266  {
267  // rhs = rhs + dt * grad * F(Un)
268  *M_residual[i] += ( *M_homogeneousGradientMatrixPtr ) * ( timeStep * *M_fluxVector[i] );
269 
270  // rhs = rhs - dt * mass * S(Un)
271  *M_residual[i] += ( *M_homogeneousMassMatrixPtr ) * ( - timeStep * *M_sourceVector[i] );
272 
273  for ( UInt j (0); j < 2; ++j )
274  {
275  // rhs = rhs - dt^2/2 * gradDiffFlux * S(Un)
276  M_dFdUGradientMatrixPtr[2 * i + j]->globalAssemble();
277  *M_residual[i] += *M_dFdUGradientMatrixPtr[2 * i + j] * ( -dt2over2 * *M_sourceVector[j] );
278 
279  // rhs = rhs + dt^2/2 * divDiffSrc * F(Un)
280  M_dSdUDivergenceMatrixPtr[2 * i + j]->globalAssemble();
281  *M_residual[i] += *M_dSdUDivergenceMatrixPtr[2 * i + j] * ( dt2over2 * *M_fluxVector[j] );
282 
283  // rhs = rhs - dt^2/2 * stiffDiffFlux * F(Un)
284  M_dFdUStiffnessMatrixPtr[2 * i + j]->globalAssemble();
285  *M_residual[i] += *M_dFdUStiffnessMatrixPtr[2 * i + j] * ( -dt2over2 * *M_fluxVector[j] );
286 
287  // rhs = rhs + dt^2/2 * massDiffSrc * S(Un)
288  M_dSdUMassMatrixPtr[2 * i + j]->globalAssemble();
289  *M_residual[i] += *M_dSdUMassMatrixPtr[2 * i + j] * ( dt2over2 * *M_sourceVector[j] );
290  }
291  }
292 
293  // rhs = mass * Un + residual
294  *M_rhs[0] = *M_residual[0] + ( *M_homogeneousMassMatrixPtr ) * *solution.find ("A")->second;
295  *M_rhs[1] = *M_residual[1] + ( *M_homogeneousMassMatrixPtr ) * *solution.find ("Q")->second;
296 
297  if ( M_physicsPtr->data()->viscoelasticWall() )
298  {
299  *M_rhs[1] -= ( *M_homogeneousMassMatrixPtr ) * *solution.find ("Q_visc")->second;
300  }
301 }
302 
303 void
304 OneDFSISolver::iterate ( OneDFSIBCHandler& bcHandler, solution_Type& solution, const Real& time, const Real& timeStep )
305 {
306  // Apply BC to RHS
307  bcHandler.applyBC ( time, timeStep, solution, M_fluxPtr, M_rhs );
308 
309  // Compute A^n+1
310  vector_Type area ( *M_rhs[0] );
311  M_linearSolverPtr->solveSystem ( *M_rhs[0], area, M_homogeneousMassMatrixPtr );
312 
313  // Compute Q^n+1
314  vector_Type flowRate ( *M_rhs[1] );
315  M_linearSolverPtr->solveSystem ( *M_rhs[1], flowRate, M_homogeneousMassMatrixPtr );
316 
317  // Correct flux with inertial, viscoelastic and longitudinal terms
318  if ( M_physicsPtr->data()->inertialWall() )
319  {
320  *solution["Q_inert"] = inertialFlowRateCorrection ( flowRate );
321  flowRate += *solution["Q_inert"];
322  }
323 
324  if ( M_physicsPtr->data()->viscoelasticWall() )
325  {
326  *solution["Q_visc"] = viscoelasticFlowRateCorrection ( area, flowRate, *solution.find ("Q_visc")->second, timeStep, bcHandler );
327  flowRate += *solution["Q_visc"];
328  }
329 
330  if ( M_physicsPtr->data()->longitudinalWall() )
331  {
332  *solution["Q_long"] = longitudinalFlowRateCorrection();
333  flowRate += *solution["Q_long"];
334  }
335 
336  // Update the solution container
337  *solution["A"] = area;
338  *solution["Q"] = flowRate;
339 
340  // Compute W1 and W2 from A and Q
341  computeW1W2 ( solution );
342 
343  // Compute A/A0 from A
344  computeAreaRatio ( solution );
345 
346  // Update the pressure (taking into account the viscoelastic wall)
347  computePressure ( solution, timeStep );
348 }
349 
351 OneDFSISolver::viscoelasticFlowRateCorrection ( const vector_Type& newArea, const vector_Type& newElasticFlowRate,
352  const vector_Type& oldViscoelasticFlowRate,
353  const Real& timeStep, OneDFSIBCHandler& bcHandler,
354  const bool& updateSystemMatrix )
355 {
356  // Matrix
357  matrix_Type massMatrix ( M_feSpacePtr->map() );
358  matrix_Type stiffnessMatrix ( M_feSpacePtr->map() );
359 
360  Real massCoefficient;
361  Real stiffnessCoefficient;
362 
363  // RHS
364  vector_Type rhs ( M_feSpacePtr->map() );
365  rhs = 0;
366 
367  // Elementary computation and matrix assembling
368  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements() ; ++iElement )
369  {
370  // Update the current element
371  M_feSpacePtr->fe().update ( M_feSpacePtr->mesh()->edgeList (iElement), UPDATE_DPHI | UPDATE_WDET );
372 
373  // Compute mass coefficient
374  massCoefficient = 1 / ( 0.5 * ( newArea[ iElement ] + newArea[ iElement + 1 ] ) );
375  // massCoefficient = 1 / ( 0.5 * ( M_physicsPtr->data()->area0( iElement ) + M_physicsPtr->data()->area0( iElement + 1 ) ) ); // For debug purposes
376 
377  // Compute stiffness coefficient
378  stiffnessCoefficient = timeStep * 0.5 * ( M_physicsPtr->data()->viscoelasticCoefficient ( iElement ) + M_physicsPtr->data()->viscoelasticCoefficient ( iElement + 1 ) )
379  / M_physicsPtr->data()->densityRho() * massCoefficient * std::sqrt ( massCoefficient );
380 
381  // Set the elementary matrices to 0.
382  M_elementalMassMatrixPtr->zero();
383  M_elementalStiffnessMatrixPtr->zero();
384 
385  // Assemble the elemental matrix
386  AssemblyElemental::mass ( massCoefficient, *M_elementalMassMatrixPtr, M_feSpacePtr->fe(), 0, 0 );
387  AssemblyElemental::stiff ( stiffnessCoefficient, *M_elementalStiffnessMatrixPtr, M_feSpacePtr->fe(), 0, 0 );
388 
389  // Assemble the stiffness matrix
390  assembleMatrix ( massMatrix, *M_elementalMassMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
391  assembleMatrix ( stiffnessMatrix, *M_elementalStiffnessMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
392 
393  // Natural BC
394  if ( iElement == 0 )
395  {
396  rhs ( 0 ) -= stiffnessCoefficient * M_fluxPtr->physics()->data()->computeSpatialDerivativeAtNode ( newElasticFlowRate, 0, 1 );
397  }
398  if ( iElement == M_physicsPtr->data()->numberOfElements() - 1 )
399  {
400  rhs ( iElement + 1 ) += stiffnessCoefficient * M_fluxPtr->physics()->data()->computeSpatialDerivativeAtNode ( newElasticFlowRate, iElement + 1, 1 );
401  }
402  }
403 
404  // Matrices global assemble
405  massMatrix.globalAssemble();
406  stiffnessMatrix.globalAssemble();
407 
408  // RHS
409  rhs += massMatrix * (oldViscoelasticFlowRate) + stiffnessMatrix * (-newElasticFlowRate);
410 
411  // System matrix
412  massMatrix += stiffnessMatrix;
413 
414  // Apply BC to Matrix and RHS
415  bcHandler.applyViscoelasticBC ( M_fluxPtr, massMatrix, rhs );
416 
417  // Compute flow rate correction at t^n+1
418  vector_Type newViscoelasticFlowRate ( rhs );
419 
420  if ( updateSystemMatrix )
421  {
422  M_linearViscoelasticSolverPtr->setMatrix ( massMatrix );
423  }
424  M_linearViscoelasticSolverPtr->solveSystem ( rhs, newViscoelasticFlowRate, M_homogeneousMassMatrixPtr );
425 
426  return newViscoelasticFlowRate;
427 }
428 
429 Real
430 OneDFSISolver::computeCFL ( const solution_Type& solution, const Real& timeStep ) const
431 {
432  Real lambdaMax ( 0. );
433 
434  container2D_Type eigenvalues;
435  container2D_Type leftEigenvector1;
436  container2D_Type leftEigenvector2;
437 
438  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
439  {
440  // compute the eigenvalues at node
441  M_fluxPtr->eigenValuesEigenVectors ( ( *solution.find ("A")->second ) ( iNode ),
442  ( *solution.find ("Q")->second ) ( iNode ),
443  eigenvalues, leftEigenvector1, leftEigenvector2, iNode );
444 
445  lambdaMax = std::max<Real> ( std::max<Real> ( std::fabs (eigenvalues[0]), std::fabs (eigenvalues[1]) ), lambdaMax );
446  }
447 
448  Real minH = MeshUtility::MeshStatistics::computeSize (*M_feSpacePtr->mesh() ).minH;
449  return lambdaMax * timeStep / minH;
450 }
451 
452 void
454 {
455  std::ofstream outfile;
456  for ( solutionConstIterator_Type i = solution.begin(); i != solution.end(); ++i )
457  {
458  std::string file = M_physicsPtr->data()->postprocessingDirectory() + "/" + M_physicsPtr->data()->postprocessingFile() + "_" + i->first + ".mfile";
459  outfile.open ( file.c_str(), std::ios::trunc );
460  outfile.close();
461  }
462 }
463 
464 void
465 OneDFSISolver::postProcess ( const solution_Type& solution, const Real& time )
466 {
467  std::ofstream outfile;
468  for ( solutionConstIterator_Type i = solution.begin(); i != solution.end(); ++i )
469  {
470  std::string file = M_physicsPtr->data()->postprocessingDirectory() + "/" + M_physicsPtr->data()->postprocessingFile() + "_" + i->first + ".mfile";
471  outfile.open ( file.c_str(), std::ios::app );
472  outfile.setf ( std::ios::scientific, std::ios::floatfield );
473 
474  outfile << time << " ";
475  for ( UInt iNode (0); iNode < static_cast< UInt > ( (*i->second).size() ); ++iNode )
476  {
477  outfile << (*i->second) (iNode) << " ";
478  }
479 
480  outfile << std::endl;
481  outfile.close();
482  }
483 }
484 
485 // ===================================================
486 // Set Methods
487 // ===================================================
488 void
490  const fluxPtr_Type& fluxPtr,
491  const sourcePtr_Type& sourcePtr )
492 {
493  M_physicsPtr = physicsPtr;
494  M_fluxPtr = fluxPtr;
495  M_sourcePtr = sourcePtr;
496 }
497 
498 void
500 {
501  M_commPtr = commPtr;
503 }
504 
505 void
507 {
508  M_feSpacePtr = feSpacePtr;
509 
510  //Elementary Matrices
511  M_elementalMassMatrixPtr.reset ( new MatrixElemental ( M_feSpacePtr->fe().nbFEDof(), 1, 1 ) );
512  M_elementalStiffnessMatrixPtr.reset ( new MatrixElemental ( M_feSpacePtr->fe().nbFEDof(), 1, 1 ) );
513  M_elementalGradientMatrixPtr.reset ( new MatrixElemental ( M_feSpacePtr->fe().nbFEDof(), 1, 1 ) );
514  M_elementalDivergenceMatrixPtr.reset ( new MatrixElemental ( M_feSpacePtr->fe().nbFEDof(), 1, 1 ) );
515 
516  //Vectors
517  for ( UInt i (0) ; i < 2 ; ++i )
518  {
519  M_rhs[i].reset ( new vector_Type ( M_feSpacePtr->map() ) );
520  M_residual[i].reset ( new vector_Type ( M_feSpacePtr->map() ) );
521  M_fluxVector[i].reset ( new vector_Type ( M_feSpacePtr->map() ) );
522  M_sourceVector[i].reset ( new vector_Type ( M_feSpacePtr->map() ) );
523  }
524 
525  //Matrix
526  M_homogeneousMassMatrixPtr.reset ( new matrix_Type ( M_feSpacePtr->map() ) );
527  M_homogeneousGradientMatrixPtr.reset ( new matrix_Type ( M_feSpacePtr->map() ) );
528 }
529 
530 void
532 {
533  M_linearSolverPtr = linearSolverPtr;
534 }
535 
536 void
537 OneDFSISolver::setLinearViscoelasticSolver ( const linearSolverPtr_Type& linearViscoelasticSolverPtr )
538 {
539  M_linearViscoelasticSolverPtr = linearViscoelasticSolverPtr;
540 }
541 
542 // ===================================================
543 // Get Methods
544 // ===================================================
545 UInt
546 OneDFSISolver::boundaryDOF ( const bcSide_Type& bcSide ) const
547 {
548  switch ( bcSide )
549  {
550  case OneDFSI::left:
551 
552  return 0;
553 
554  break;
555 
556  case OneDFSI::right:
557 
558  return M_physicsPtr->data()->numberOfNodes() - 1;
559 
560  break;
561 
562  default:
563 
564  std::cout << "Warning: bcSide \"" << bcSide << "\" not available!" << std::endl;
565 
566  return 0;
567  }
568 }
569 
570 Real
571 OneDFSISolver::boundaryValue ( const solution_Type& solution, const bcType_Type& bcType, const bcSide_Type& bcSide ) const
572 {
573  UInt boundaryDof ( boundaryDOF ( bcSide ) );
574 
575  switch ( bcType )
576  {
577  case OneDFSI::A:
578 
579  return (*solution.find ("A")->second) ( boundaryDof );
580 
581  case OneDFSI::Q:
582 
583  // Flow rate is positive with respect to the outgoing normal
584  return (*solution.find ("Q")->second) ( boundaryDof ) * ( ( bcSide == OneDFSI::left ) ? -1. : 1. );
585 
586  case OneDFSI::W1:
587 
588  return (*solution.find ("W1")->second) ( boundaryDof );
589 
590  case OneDFSI::W2:
591 
592  return (*solution.find ("W2")->second) ( boundaryDof );
593 
594  case OneDFSI::P:
595 
596  return (*solution.find ("P")->second) ( boundaryDof );
597 
598  case OneDFSI::S:
599 
600  return - (*solution.find ("P")->second) ( boundaryDof );
601 
602  case OneDFSI::T:
603  {
604  Real P = ( *solution.find ("P")->second ) ( boundaryDof );
605  Real rho = M_physicsPtr->data()->densityRho();
606  Real alpha = M_physicsPtr->data()->alpha ( boundaryDof );
607  Real Q = ( *solution.find ("Q")->second ) ( boundaryDof );
608  Real A = ( *solution.find ("A")->second ) ( boundaryDof );
609 
610  // Note that the kinetic contribution should account for the real velocity profile
611  // through the alpha coefficient (i.e., the Coriolis coefficient)
612  return -P - 0.5 * rho * alpha * Q * Q / ( A * A );
613  }
614  default:
615 
616  std::cout << "Warning: bcType \"" << bcType << "\"not available!" << std::endl;
617  return 0.;
618 
619  }
620 }
621 
622 void
623 OneDFSISolver::boundaryEigenValuesEigenVectors ( const bcSide_Type& bcSide,
624  const solution_Type& solution,
625  container2D_Type& eigenvalues,
626  container2D_Type& leftEigenvector1,
627  container2D_Type& leftEigenvector2 )
628 {
629  UInt boundaryDof ( boundaryDOF ( bcSide ) );
630 
631  M_fluxPtr->eigenValuesEigenVectors ( (*solution.find ("A")->second) ( boundaryDof ),
632  (*solution.find ("Q")->second) ( boundaryDof ),
633  eigenvalues, leftEigenvector1, leftEigenvector2,
634  boundaryDof );
635 }
636 
637 // ===================================================
638 // Private Methods
639 // ===================================================
640 void
642 {
643  Real Ai, Qi;
644 
645  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
646  {
647  Ai = (*solution.find ("A")->second) ( iNode );
648  Qi = (*solution.find ("Q")->second) ( iNode );
649 
650  (*M_fluxVector[0]) ( iNode ) = M_fluxPtr->flux ( Ai, Qi, 0, iNode );
651  (*M_fluxVector[1]) ( iNode ) = M_fluxPtr->flux ( Ai, Qi, 1, iNode );
652  }
653 }
654 
655 void
657 {
658  // first update the Flux vector
659  updateFlux ( solution );
660 
661  // then update the derivative of the Flux vector
662  Real tmp;
663  Real Aii, Qii;
664  Real Aiip1, Qiip1;
665 
666  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements(); ++iElement )
667  {
668  // for P1Seg and appropriate mesh only!
669  Aii = (*solution.find ("A")->second) ( iElement );
670  Qii = (*solution.find ("Q")->second) ( iElement );
671 
672  Aiip1 = (*solution.find ("A")->second) ( iElement + 1 );
673  Qiip1 = (*solution.find ("Q")->second) ( iElement + 1 );
674 
675  for ( UInt ii = 0; ii < 2; ++ii )
676  {
677  for ( UInt jj = 0; jj < 2; ++jj )
678  {
679  tmp = M_fluxPtr->dFdU ( Aii, Qii, ii, jj, iElement ); // left node of current element
680  tmp += M_fluxPtr->dFdU ( Aiip1, Qiip1, ii, jj, iElement + 1 ); // right node of current element
681 
682  M_dFdUVector[ 2 * ii + jj ] ( iElement ) = 0.5 * tmp;
683  }
684  }
685  }
686 }
687 
688 void
690 {
691  Real Ai, Qi;
692 
693  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes() ; ++iNode )
694  {
695  Ai = (*solution.find ("A")->second) ( iNode );
696  Qi = (*solution.find ("Q")->second) ( iNode );
697 
698  (*M_sourceVector[0]) ( iNode ) = M_sourcePtr->source ( Ai, Qi, 0, iNode );
699  (*M_sourceVector[1]) ( iNode ) = M_sourcePtr->source ( Ai, Qi, 1, iNode );
700  }
701 }
702 
703 void
705 {
706  // first update the Source vector
707  updateSource ( solution );
708 
709  // then update the derivative of the Source vector
710  Real tmp;
711  Real Aii, Qii;
712  Real Aiip1, Qiip1;
713 
714  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements(); ++iElement )
715  {
716  // for P1Seg and appropriate mesh only!
717  Aii = (*solution.find ("A")->second) ( iElement);
718  Qii = (*solution.find ("Q")->second) ( iElement);
719  Aiip1 = (*solution.find ("A")->second) ( iElement + 1 );
720  Qiip1 = (*solution.find ("Q")->second) ( iElement + 1 );
721 
722  for ( UInt ii = 0; ii < 2; ++ii )
723  {
724  for ( UInt jj = 0; jj < 2; ++jj )
725  {
726  tmp = M_sourcePtr->dSdU ( Aii, Qii, ii, jj, iElement ); // left node of current element
727  tmp += M_sourcePtr->dSdU ( Aiip1, Qiip1, ii, jj, iElement + 1 ); // right node of current element
728 
729  M_dSdUVector[ 2 * ii + jj ] ( iElement ) = 0.5 * tmp;
730  }
731  }
732  }
733 }
734 
735 void
737 {
738  // Matrices initialization
739  for ( UInt i (0); i < 4; ++i )
740  {
741  M_dSdUMassMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
742  M_dFdUStiffnessMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
743  M_dFdUGradientMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
744  M_dSdUDivergenceMatrixPtr[i].reset ( new matrix_Type ( M_feSpacePtr->map() ) );
745  }
746 
747  // Elementary computation and matrix assembling
748  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements(); ++iElement )
749  {
750  // Update the current element
751  M_feSpacePtr->fe().update ( M_feSpacePtr->mesh()->edgeList ( iElement), UPDATE_DPHI | UPDATE_WDET );
752 
753  for ( UInt ii (0); ii < 2; ++ii )
754  {
755  for ( UInt jj (0); jj < 2; ++jj )
756  {
757  // Update the elemental matrices
758  updateElementalMatrices ( M_dFdUVector[ 2 * ii + jj ] ( iElement ), M_dSdUVector[ 2 * ii + jj ] ( iElement ) );
759 
760  // Assemble the global matrices
761  matrixAssemble ( ii, jj );
762  }
763  }
764  }
765 }
766 
767 void
768 OneDFSISolver::updateElementalMatrices ( const Real& dFdU, const Real& dSdU )
769 {
770  // Set the elementary matrices to 0.
771  M_elementalMassMatrixPtr->zero();
772  M_elementalStiffnessMatrixPtr->zero();
773  M_elementalGradientMatrixPtr->zero();
774  M_elementalDivergenceMatrixPtr->zero();
775 
776  // Update the mass matrix
777  AssemblyElemental::mass ( dSdU, *M_elementalMassMatrixPtr, M_feSpacePtr->fe(), 0, 0 );
778  // std::cout << "Elem Stiff matrix :" << std::endl;
779  // M_elementalMassMatrixPtr->showMe( std::cout );
780 
781  // Update the stiffness matrix
782  AssemblyElemental::stiff ( dFdU, *M_elementalStiffnessMatrixPtr, M_feSpacePtr->fe(), 0 , 0 );
783  //AssemblyElemental::stiffness( *M_elementalStiffnessMatrixPtr, M_feSpacePtr->fe(), M_coeffStiff, 0 );
784  // std::cout << "Elem Stiff matrix :" << std::endl;
785  // M_elementalStiffnessMatrixPtr->showMe( std::cout );
786 
787  /*! Update the gradient matrix
788  gradient operator:
789  grad_{ij} = \int_{fe} coeff \phi_j \frac{d \phi_i}{d x}
790 
791  BEWARE :
792  \param 0: the first argument "0" corresponds to the first
793  and only coordinate (1D!), and HERE it starts from 0... (Damm'!)
794 
795  \param - M_coeffGrad: the sign "-" in the second argument
796  is added to correspond to the described operator.
797  (There is a minus in the elemOper implementation).
798  */
799  AssemblyElemental::grad ( 0, -dFdU, *M_elementalGradientMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->fe(), 0, 0 );
800  // std::cout << "Elem Grad matrix :" << std::endl;
801  // M_elementalGradientMatrixPtr->showMe( std::cout );
802 
803  /*! update the divergence matrix
804  divergence operator: (transpose of the gradient)
805  div_{ij} = \int_{fe} coeff \frac{d \phi_j}{d x} \phi_i
806 
807  \note formally this M_elementalDivergenceMatrixPtr is not necessary
808  as it is the transpose of the M_elementalGradientMatrixPtr.
809  But for the sake of clarity, I prefer to keep it. (low cost!)
810 
811  BEWARE : same remarks as grad (see above).
812  */
813  AssemblyElemental::div ( 0, -dSdU, *M_elementalDivergenceMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->fe(), 0, 0 );
814  // std::cout << "Elem Div matrix :" << std::endl;
815  // M_elementalDivergenceMatrixPtr->showMe( std::cout );
816 }
817 
818 void
819 OneDFSISolver::matrixAssemble ( const UInt& ii, const UInt& jj )
820 {
821  // Assemble the mass matrix
822  assembleMatrix ( *M_dSdUMassMatrixPtr[ 2 * ii + jj ], *M_elementalMassMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
823 
824  // Assemble the stiffness matrix
825  assembleMatrix ( *M_dFdUStiffnessMatrixPtr[ 2 * ii + jj ], *M_elementalStiffnessMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
826 
827  // Assemble the gradient matrix
828  assembleMatrix ( *M_dFdUGradientMatrixPtr[ 2 * ii + jj ], *M_elementalGradientMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
829 
830  // Assemble the divergence matrix
831  assembleMatrix ( *M_dSdUDivergenceMatrixPtr[ 2 * ii + jj ], *M_elementalDivergenceMatrixPtr, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
832 }
833 
834 void
836 {
837  // Dirichlet BC
838  matrix.globalAssemble();
839  matrix.diagonalize ( 0, 1, 0 );
840  matrix.diagonalize ( M_physicsPtr->data()->numberOfNodes() - 1, 1, 0 );
841 
842  //matrix.spy("SystemMatrix");
843 }
844 
847 {
848  matrix_Type matrixLHS (M_feSpacePtr->map() );
849  matrix_Type stiffRHS (M_feSpacePtr->map() );
850 
851  MatrixElemental elmatMassLHS (M_feSpacePtr->fe().nbFEDof(), 1, 1);
852  MatrixElemental elmatStiffLHS (M_feSpacePtr->fe().nbFEDof(), 1, 1);
853  MatrixElemental elmatStiffRHS (M_feSpacePtr->fe().nbFEDof(), 1, 1);
854 
855  vector_Type rhs (M_feSpacePtr->map() );
856 
857  Real coeffMass;
858  Real coeffStiff;
859 
860  Real m, meanA0;
861 
862  matrixLHS *= 0.;
863  stiffRHS *= 0.;
864 
865  // Elementary computation and matrix assembling
866  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements(); ++iElement )
867  {
868  // set the elementary matrices to 0.
869  elmatMassLHS. zero();
870  elmatStiffLHS.zero();
871  elmatStiffRHS.zero();
872 
873  coeffMass = (*M_rhs[0]) ( iElement ) + (*M_rhs[0]) ( iElement + 1 );
874  coeffMass /= 2;
875  coeffMass = 1. / coeffMass;
876 
877  meanA0 = M_physicsPtr->data()->area0 (iElement) + M_physicsPtr->data()->area0 (iElement + 1);
878  meanA0 /= 2;
879 
880  m = M_physicsPtr->data()->densityWall() * M_physicsPtr->data()->thickness (iElement + 1) /
881  ( 2 * std::sqrt (4 * std::atan (1.) ) * std::sqrt (meanA0) );
882 
883  coeffStiff = m / M_physicsPtr->data()->densityRho();
884 
885  // Update the current element
886  M_feSpacePtr->fe().update ( M_feSpacePtr->mesh()->edgeList (iElement), UPDATE_DPHI | UPDATE_WDET );
887 
888  AssemblyElemental::mass ( coeffMass, elmatMassLHS, M_feSpacePtr->fe(), 0, 0 );
889  AssemblyElemental::stiff ( coeffStiff, elmatStiffLHS, M_feSpacePtr->fe(), 0, 0 );
890  AssemblyElemental::stiff ( - coeffStiff, elmatStiffRHS, M_feSpacePtr->fe(), 0, 0 );
891 
892  // assemble the mass and grad matrices
893  assembleMatrix ( matrixLHS, elmatMassLHS, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
894  assembleMatrix ( matrixLHS, elmatStiffLHS, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
895  assembleMatrix ( stiffRHS, elmatStiffRHS, M_feSpacePtr->fe(), M_feSpacePtr->dof(), 0, 0, 0, 0 );
896 
897 #ifdef HAVE_LIFEV_DEBUG
898  debugStream ( 6310 ) << "\n\tm = " << m << "\n\t_coeffMass = " << coeffMass << "\n\t_coeffStiff = " << coeffStiff << "\n";
899 #endif
900  } // end loop on elements
901 
902  // update rhs
903  //_stiffRHS.Axpy( 1., flux , 0., _rhs );
904 
905  rhs = stiffRHS * flux;
906 
907  UInt firstDof = 0;
908  UInt lastDof = rhs.size() - 1;
909 
910  // symmetric treatment (cholesky can be used)
911  // first row modified (Dirichlet)
912  rhs ( firstDof ) = 0.;
913  // second row modified (for symmetry)
914  // _rhs( firstDof + 1 ) += - _matrix.LowDiag()( firstDof ) * M_bcDirLeft.second;
915 
916  // last row modified (Dirichlet)
917  rhs ( lastDof ) = 0.;
918  // penultimate row modified (for symmetry)
919  // _rhs( lastDof - 1 ) += - _matrix.UpDiag()( lastDof - 1 ) * M_bcDirRight.second;
920 
921  applyDirichletBCToMatrix ( matrixLHS );
922 
923  //_tridiagsolver.Factor( _matrixLHS );
924 
925  // cholesky or lapack lu solve
926  // solve the system: rhs1 = massFactor^{-1} * rhs1
927  //_tridiagsolver.Solve( _matrixLHS, _rhs );
928 
929  vector_Type sol ( rhs);
930 
931  M_linearSolverPtr->setMatrix ( matrixLHS );
932  //@int numIter = M_linearSolverPtr->solveSystem( _rhs, _sol, _matrixLHS, true);
933 
934  //std::cout <<" iterations number : " << numIter << std::endl;
935 
936  return sol;
937 }
938 
941 {
942  matrix_Type massLHS (M_feSpacePtr->map() );
943  matrix_Type massRHS (M_feSpacePtr->map() );
944 
945  //TriDiagCholesky< Real, matrix_Type, Vector > _tridiagsolver(M_physicsPtr->data()->numberOfNodes());
946 
947  MatrixElemental elmatMassLHS (M_feSpacePtr->fe().nbFEDof(), 1, 1);
948  MatrixElemental elmatMassRHS (M_feSpacePtr->fe().nbFEDof(), 1, 1);
949 
950  vector_Type rhs (M_feSpacePtr->map() );
951  // let g = sqrt(A) - sqrt(A0)
952  // now f = _d3g_dz3
953  vector_Type g (M_feSpacePtr->map() );
954  vector_Type f (M_feSpacePtr->map() );
955 
956  // _g = *M_rhs[0];
957  for ( UInt iNode (0); iNode < M_physicsPtr->data()->numberOfNodes(); ++iNode )
958  {
959  g (iNode) = std::sqrt ( (*M_rhs[0]) (iNode) ) - std::sqrt (M_physicsPtr->data()->area0 (iNode) );
960  }
961 
962  UInt iNode;
963 
964  Real coeffMassLHS;
965  Real coeffMassRHS;
966 
967  Real a;
968  // std::ostringstream output;
969  massLHS *= 0.;
970  massRHS *= 0.;
971 
972  Real h ( M_physicsPtr->data()->length() / static_cast<Real> (M_physicsPtr->data()->numberOfElements() - 1) );
973 
974  // Elementary computation and matrix assembling
975  // Loop on elements
976  for ( UInt iElement (0); iElement < M_physicsPtr->data()->numberOfElements() ; ++iElement )
977  {
978  iNode = iElement;
979 
980  // set the elementary matrices to 0.
981  elmatMassLHS.zero();
982  elmatMassRHS.zero();
983 
984  // coeff (1/A) (average values over the element)
985  coeffMassLHS = (*M_rhs[0]) ( iNode ) + (*M_rhs[0]) ( iNode + 1 );
986  coeffMassLHS /= 2;
987  coeffMassLHS = 1. / coeffMassLHS;
988 
989  a = M_physicsPtr->data()->inertialModulus() / std::sqrt (4 * std::atan (1.) );
990  coeffMassRHS = M_physicsPtr->data()->dataTime()->timeStep() * a / M_physicsPtr->data()->densityRho();
991 
992  // backward differentiation when near to the left boundary
993  // d3 A (xi)/ dz3 = (1/h^3) * ( -A(xi) + A(xi+3) - 3A(xi+2) + 3A(xi+1) )
994 
995  // forward differentiation when near to the right boundary
996  // d3 A (xi)/ dz3 = (1/h^3) * ( A(xi) - A(xi-3) + 3A(xi-2) - 3A(xi-1) )
997 
998  // central differentiation otherwise
999  // d3 A (xi)/ dz3 = (1/h^3) * ( -A(xi-2) + 2A(xi-1) - 2A(xi+1) + A(xi+2) )
1000 
1001 #ifdef HAVE_LIFEV_DEBUG
1002  debugStream ( 6310 ) << "\ninode = " << iNode << "\n";
1003 #endif
1004  if (iNode < 2)
1005  {
1006  // backward differentiation
1007  f ( iNode ) = - g ( iNode ) + g ( iNode + 3 ) - 3 * g ( iNode + 2 ) + 3 * g ( iNode + 1 );
1008 #ifdef HAVE_LIFEV_DEBUG
1009  debugStream ( 6310 ) << "\n\tbackward differentiation = " << coeffMassLHS << "\n";
1010 #endif
1011  }
1012  else if (iNode > M_feSpacePtr->mesh()->numEdges() - 2)
1013  {
1014  // forward differentiation
1015  f ( iNode ) = g ( iNode ) - g ( iNode - 3 ) + 3 * g ( iNode - 2 ) - 3 * g ( iNode - 1 );
1016 #ifdef HAVE_LIFEV_DEBUG
1017  debugStream ( 6310 ) << "\n\forward differentiation = " << coeffMassLHS << "\n";
1018 #endif
1019  }
1020  else
1021  {
1022  // central differentiation
1023  f ( iNode ) = - g ( iNode - 2 ) + 2 * g ( iNode - 1 ) - 2 * g ( iNode + 1 ) + g ( iNode + 2 );
1024 #ifdef HAVE_LIFEV_DEBUG
1025  debugStream ( 6310 ) << "\n\tcentral differentiation = " << coeffMassLHS << "\n";
1026 #endif
1027  }
1028 
1029  f (iNode) *= 1 / ( 2 * OneDFSI::pow30 (h, 3) );
1030 
1031  // Update the current element
1032  M_feSpacePtr->fe().update ( M_feSpacePtr->mesh()->edgeList (iElement), UPDATE_DPHI | UPDATE_WDET );
1033 
1034  AssemblyElemental::mass ( coeffMassLHS, elmatMassLHS, M_feSpacePtr->fe(), 0, 0 );
1035  AssemblyElemental::mass ( coeffMassRHS, elmatMassRHS, M_feSpacePtr->fe(), 0, 0 );
1036 
1037  // assemble the mass and grad matrices
1038  //assemb_mat( massLHS, elmatMassLHS, M_feSpacePtr->fe(), M_feSpacePtr->dof() , 0, 0 );
1039  assembleMatrix ( massLHS, elmatMassLHS, M_feSpacePtr->fe(), M_feSpacePtr->dof() , 0, 0, 0, 0 );
1040  //assemb_mat( massRHS, elmatMassRHS, M_feSpacePtr->fe(), M_feSpacePtr->dof() , 0, 0 );
1041  assembleMatrix ( massRHS, elmatMassRHS, M_feSpacePtr->fe(), M_feSpacePtr->dof() , 0, 0, 0, 0 );
1042 
1043 #ifdef HAVE_LIFEV_DEBUG
1044  debugStream ( 6310 ) << "\n\t_coeffMassLHS = " << coeffMassLHS << "\n";
1045  debugStream ( 6310 ) << "\n\t_coeffMassRHS = " << coeffMassRHS << "\n";
1046 #endif
1047  } // end loop on elements
1048 
1049  // update rhs
1050  // _massLHS.Axpy( 1., (*solution["P"]) , 0., _rhs );
1051  rhs = massRHS * f;
1052 
1053  UInt firstDof = 0;
1054  UInt lastDof = rhs.size() - 1;
1055 
1056  // symmetric treatment (cholesky can be used)
1057  // first row modified (Dirichlet)
1058  rhs ( firstDof ) = 0.;
1059  // second row modified (for symmetry)
1060  // _rhs( firstDof + 1 ) += - _matrix.LowDiag()( firstDof ) * M_bcDirLeft.second;
1061 
1062  // last row modified (Dirichlet)
1063  rhs ( lastDof ) = 0.;
1064  // penultimate row modified (for symmetry)
1065  // _rhs( lastDof - 1 ) += - _matrix.UpDiag()( lastDof - 1 ) * M_bcDirRight.second;
1066 
1067  applyDirichletBCToMatrix ( massLHS);
1068 
1069  //@_tridiagsolver.Factor( _massLHS );
1070 
1071  // cholesky or lapack lu solve
1072  // solve the system: rhs1 = massFactor^{-1} * rhs1
1073  //@_tridiagsolver.Solve( _massLHS, _rhs );
1074 
1075  return rhs;
1076 }
1077 
1078 }
sourcePtr_Type M_sourcePtr
void initialize(solution_Type &solution)
Initialize all the variables of the solution to a reference condition with , , and ...
void setLinearSolver(const linearSolverPtr_Type &linearSolverPtr)
Set the linear solver.
void updatedSdU(const solution_Type &solution)
Call _updateSource and update the P0 derivative of source vector from U:
scalarVectorContainer_Type M_dFdUVector
diffFlux = dF(U)/dU (in P0)
matrixPtrContainer_Type M_dSdUMassMatrixPtr
tridiagonal mass matrices multiplied by diffSrcij
linearSolverPtr_Type M_linearViscoelasticSolverPtr
void updateRHS(const solution_Type &solution, const Real &timeStep)
Compute the right hand side.
linearSolver_Type::matrix_type matrix_Type
std::shared_ptr< comm_Type > commPtr_Type
data_type & operator()(const UInt row)
Access operators.
vector_Type viscoelasticFlowRateCorrection(const vector_Type &newArea, const vector_Type &newElasticFlowRate, const vector_Type &oldViscoelasticFlowRate, const Real &timeStep, OneDFSIBCHandler &bcHandler, const bool &updateSystemMatrix=true)
Apply the viscoelastic flow rate correction.
Real computeCFL(const solution_Type &solution, const Real &timeStep) const
CFL computation (correct for constant mesh)
std::map< std::string, fluxTerm_Type > fluxMap
std::shared_ptr< physics_Type > physicsPtr_Type
scalarVectorContainer_Type M_dSdUVector
diffSrc = dSource(U)/dU (in P0)
void buildConstantMatrices()
Build constant matrices (mass and grad)
linearSolverPtr_Type M_linearSolverPtr
The linear solver.
std::map< std::string, physicsType_Type > physicsMap
void setCommunicator(const commPtr_Type &comm)
Set the communicator.
Definition: Displayer.cpp:86
void setCommunicator(const commPtr_Type &commPtr)
Set the communicator.
OneDFSISolver()
Empty Constructor.
void updateInverseJacobian(const UInt &iQuadPt)
void setProblem(const physicsPtr_Type &physicsPtr, const fluxPtr_Type &fluxPtr, const sourcePtr_Type &sourcePtr)
Set problem classes.
void updateMatrices()
Update the matrices.
void computeAreaRatio(solution_Type &solution)
Update the ratio between and .
void computePressure(solution_Type &solution, const Real &timeStep)
Update the pressure.
void applyBC(const Real &time, const Real &timeStep, const solution_Type &solution, const fluxPtr_Type &fluxPtr, vectorPtrContainer_Type &rhs)
Apply boundary conditions to the rhs of the Taylor-Galerkin problem.
matrixPtrContainer_Type M_dSdUDivergenceMatrixPtr
tridiagonal divergence matrices multiplied by diffSrcij
UInt boundaryDOF(const bcSide_Type &bcSide) const
Return the ID of the boundary node given a side.
linearSolver_Type::vector_type vector_Type
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
void boundaryEigenValuesEigenVectors(const bcSide_Type &bcSide, const solution_Type &solution, container2D_Type &eigenvalues, container2D_Type &leftEigenvector1, container2D_Type &leftEigenvector2)
Return the value of the eigenvalues and eigenvectors on a specified boundary.
matrixPtrContainer_Type M_dFdUGradientMatrixPtr
tridiagonal gradient matrices multiplied by diffFluxij
void matrixAssemble(const UInt &ii, const UInt &jj)
Assemble the matrices.
vectorPtrContainer_Type M_residual
Residual of the linear system.
Displayer()
Constructor.
Definition: Displayer.cpp:46
void setLinearViscoelasticSolver(const linearSolverPtr_Type &linearViscoelasticSolverPtr)
Set the viscoelastic linear solver.
void iterate(OneDFSIBCHandler &bcH, solution_Type &solution, const Real &time, const Real &timeStep)
Update convective term and BC. Then solve the linearized system.
Real boundaryValue(const solution_Type &solution, const bcType_Type &bcType, const bcSide_Type &bcSide) const
Return the value of a quantity ( , , , , ) on a specified boundary.
OneDFSIBCHandler - Class featuring methods to handle boundary conditions.
matrixPtr_Type M_homogeneousMassMatrixPtr
tridiagonal mass matrix
void updateSource(const solution_Type &solution)
Update the P1 source vector from U: M_sourcei = S_h(Un) i=1,2 (works only for P1Seg elements) ...
VectorEpetra & operator=(data_type scalar)
Affectation operator.
std::shared_ptr< flux_Type > fluxPtr_Type
vector_Type longitudinalFlowRateCorrection()
Apply the longitudinal Flux correction:
void applyDirichletBCToMatrix(matrix_Type &matrix)
Update the matrices to take into account Dirichlet BC.
Int size() const
Return the size of the vector.
double Real
Generic real data.
Definition: LifeV.hpp:175
matrixPtrContainer_Type M_dFdUStiffnessMatrixPtr
tridiagonal stiffness matrices multiplied by diffFluxij
std::map< std::string, vectorPtr_Type > solution_Type
feSpacePtr_Type M_feSpacePtr
std::shared_ptr< source_Type > sourcePtr_Type
std::shared_ptr< linearSolver_Type > linearSolverPtr_Type
OneDFSISolver - Solver class for the 1D model.
vectorPtrContainer_Type M_fluxVector
Flux F(U) (in P1)
void resetOutput(const solution_Type &solution)
Reset the output files.
void setFESpace(const feSpacePtr_Type &feSpacePtr)
Set the FEspace.
vectorPtrContainer_Type M_rhs
Right hand sides of the linear system i: "mass * M_Ui = M_rhsi".
void updatedFdU(const solution_Type &solution)
Call _updateFlux and update the P0 derivative of flux vector from U:
void computeArea(solution_Type &solution)
Compute A from the area ratio: .
void setupSolution(solution_Type &solution, const MapEpetra &map, const bool &onlyMainQuantities=false)
Setup the solution using user defined FESpace map.
void updateFlux(const solution_Type &solution)
Update the P1 flux vector from U: M_fluxi = F_h(Un) i=1,2 (works only for P1Seg elements) ...
std::map< std::string, sourceTerm_Type > sourceMap
VectorEpetra(const VectorEpetra &vector)
Copy constructor.
std::shared_ptr< feSpace_Type > feSpacePtr_Type
void postProcess(const solution_Type &solution, const Real &time)
Save results on output files.
matrixPtr_Type M_homogeneousGradientMatrixPtr
tridiagonal gradient matrix
physicsPtr_Type M_physicsPtr
L2 Projection of the second derivative of Q over P1 space.
void computeW1W2(solution_Type &solution)
Update the Riemann variables.
vectorPtrContainer_Type M_sourceVector
Source term S (in P1)
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
void updateElementalMatrices(const Real &dFdU, const Real &dSdU)
Update the element matrices with the current element.
vector_Type inertialFlowRateCorrection(const vector_Type &)
Apply the inertial Flux correction: