37 #include <Epetra_ConfigDefs.h> 40 #include <Epetra_MpiComm.h> 42 #include <Epetra_SerialComm.h> 48 using namespace LifeV;
74 const std::string data_file_name = command_line.follow (
"data", 2,
"-f",
"--file");
75 GetPot dataFile (data_file_name);
78 M_heart_fct.reset (
new HeartFunctors ( dataFile) );
80 M_heart_fct->M_comm.reset (
new Epetra_MpiComm ( MPI_COMM_WORLD ) );
82 if (!M_heart_fct->M_comm->MyPID() )
84 std::cout <<
"My PID = " << M_heart_fct->M_comm->MyPID() << std::endl;
97 typedef std::shared_ptr<feSpace_Type> feSpacePtr_Type;
99 LifeChrono chronoinitialsettings;
100 LifeChrono chronototaliterations;
101 chronoinitialsettings.start();
111 HeartBidomainData _data (M_heart_fct);
116 meshData.setup (M_heart_fct->M_dataFile,
"electric/space_discretization");
117 std::shared_ptr<mesh_Type > fullMeshPtr (
new mesh_Type ( M_heart_fct->M_comm ) );
118 readMesh (*fullMeshPtr, meshData);
119 bool verbose = (M_heart_fct->M_comm->MyPID() == 0);
122 BCFunctionBase uZero ( zero_scalar );
124 bcH.addBC (
"Endo", ENDOCARDIUM, Natural, Full, uZero, 1 );
125 bcH.addBC (
"Epi", EPICARDIUM, Natural, Full, uZero, 1 );
126 bcH.addBC (
"Trunc", TRUNC_SEC, Natural, Full, uZero, 1 );
138 std::shared_ptr<mesh_Type> localMeshPtr;
141 localMeshPtr = meshPart.meshPartition();
143 std::string uOrder = M_heart_fct->M_dataFile (
"electric/space_discretization/u_order",
"P1");
146 if ( uOrder.compare (
"P1") == 0 )
150 std::cout <<
"P1 potential " << std::flush;
152 refFE_u = &feTetraP1;
158 cout <<
"\n " << uOrder <<
" finite element not implemented yet \n";
162 std::string wOrder = M_heart_fct->M_dataFile (
"electric/space_discretization/w_order",
"P1");
163 if ( wOrder.compare (
"P1") == 0 )
167 std::cout <<
"P1 recovery variable " << std::flush;
169 refFE_w = &feTetraP1;
175 cout <<
"\n " << wOrder <<
" finite element not implemented yet \n";
182 std::cout <<
"Building the potential FE space ... " << std::flush;
185 feSpacePtr_Type uFESpacePtr (
new feSpace_Type ( localMeshPtr,
190 M_heart_fct->M_comm) );
193 feSpacePtr_Type _FESpacePtr (
new feSpace_Type (localMeshPtr,
198 M_heart_fct->M_comm) );
202 std::cout <<
"ok." << std::endl;
206 std::cout <<
"Building the recovery variable FE space ... " << std::flush;
210 std::cout <<
"ok." << std::endl;
213 UInt totalUDof = uFESpacePtr->map().map (Unique)->NumGlobalElements();
216 std::cout <<
"Total Potential DOF = " << totalUDof << std::endl;
220 std::cout <<
"Calling the electric model constructor ... ";
224 HeartMonodomainSolver< mesh_Type > electricModel (_data, *uFESpacePtr, bcH, M_heart_fct->M_comm);
226 HeartBidomainSolver< mesh_Type > electricModel (_data, *_FESpacePtr, *uFESpacePtr, bcH, M_heart_fct->M_comm);
231 std::cout <<
"ok." << std::endl;
233 MapEpetra fullMap (electricModel.getMap() );
235 electricModel.setup ( M_heart_fct->M_dataFile );
236 std::cout <<
"setup ok" << std::endl;
240 std::cout <<
"Calling the ionic model constructor ... ";
242 std::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel;
247 std::cout <<
"Ion Model = Rogers-McCulloch" << std::endl << std::flush;
249 ionicModel.reset (
new RogersMcCulloch< mesh_Type > (_dataIonic,
252 *M_heart_fct->M_comm) );
258 std::cout <<
"Ion Model = Luo-Rudy" << std::endl << std::flush;
260 ionicModel.reset (
new LuoRudy< mesh_Type > (_dataIonic,
263 *M_heart_fct->M_comm) );
269 std::cout <<
"Ion Model = Mitchell-Schaeffer" << std::endl << std::flush;
271 ionicModel.reset (
new MitchellSchaeffer< mesh_Type > (_dataIonic,
274 *M_heart_fct->M_comm) );
278 electricModel.initialize ( M_heart_fct->initialScalar() );
280 electricModel.initialize ( M_heart_fct->initialScalar(),
281 M_heart_fct->zeroScalar() );
286 std::cout <<
"ok." << std::endl;
289 ionicModel->initialize( );
292 electricModel.buildSystem( );
293 std::cout <<
"buildsystem ok" << std::endl;
295 Real dt = _data.timeStep();
297 Real tFinal = _data.endTime();
298 MPI_Barrier (MPI_COMM_WORLD);
302 std::cout <<
"Setting the initial solution ... " << std::endl << std::endl;
305 electricModel.resetPreconditioner();
308 std::cout <<
" ok " << std::endl;
312 std::shared_ptr< Exporter<mesh_Type > > exporter;
313 std::string
const exporterType = M_heart_fct->M_dataFile (
"exporter/type",
"ensight");
315 if (exporterType.compare (
"hdf5") == 0)
317 exporter.reset (
new ExporterHDF5<mesh_Type > ( M_heart_fct->M_dataFile,
319 exporter->setPostDir (
"./" );
320 exporter->setMeshProcId ( localMeshPtr, M_heart_fct->M_comm->MyPID() );
325 if (exporterType.compare (
"none") == 0)
327 exporter.reset (
new ExporterEmpty<mesh_Type > ( M_heart_fct->M_dataFile,
330 M_heart_fct->M_comm->MyPID() ) );
334 exporter.reset (
new ExporterEnsight<mesh_Type > ( M_heart_fct->M_dataFile,
337 M_heart_fct->M_comm->MyPID() ) );
342 vectorPtr_Type Uptr (
new vector_Type (electricModel.solutionTransmembranePotential(), Repeated ) );
344 exporter->addVariable ( ExporterData<mesh_Type>::ScalarField,
"potential", uFESpacePtr,
348 vectorPtr_Type Ueptr (
new vector_Type (electricModel.solutionExtraPotential(), Repeated ) );
349 exporter->addVariable ( ExporterData<mesh_Type>::ScalarField,
"potential_e", _FESpacePtr,
353 vectorPtr_Type Fptr (
new vector_Type (electricModel.fiberVector(), Repeated ) );
355 if (_data.hasFibers() )
356 exporter->addVariable ( ExporterData<mesh_Type>::VectorField,
361 exporter->postProcess ( 0 );
363 MPI_Barrier (MPI_COMM_WORLD);
364 chronoinitialsettings.stop();
369 chronototaliterations.start();
370 for (
Real time = t0 + dt ; time <= tFinal + dt / 2.; time += dt, iter++)
372 _data.setTime (time);
375 std::cout << std::endl;
376 std::cout <<
"We are now at time " << _data.time() <<
" s. " << std::endl;
377 std::cout << std::endl;
380 MPI_Barrier (MPI_COMM_WORLD);
381 ionicModel->solveIonicModel ( electricModel.solutionTransmembranePotential(), _data.timeStep() );
383 computeRhs ( rhs, electricModel, ionicModel, _data );
384 electricModel.updatePDESystem ( rhs );
385 electricModel.PDEiterate ( bcH );
386 normu = electricModel.solutionTransmembranePotential().norm2();
387 electricModel.solutionTransmembranePotential().epetraVector().MeanValue (&meanu);
388 electricModel.solutionTransmembranePotential().epetraVector().MaxValue (&minu);
391 std::cout <<
"norm u " << normu << std::endl;
392 std::cout <<
"mean u " << meanu << std::endl;
393 std::cout <<
"max u " << minu << std::endl << std::flush;
396 *Uptr = electricModel.solutionTransmembranePotential();
398 *Ueptr = electricModel.solutionExtraPotential();
401 exporter->postProcess ( time );
402 MPI_Barrier (MPI_COMM_WORLD);
406 std::cout <<
"Total iteration time " << chrono.diff() <<
" s." << std::endl;
408 chronototaliterations.stop();
413 std::cout <<
"Total iterations time " << chronototaliterations.diff() <<
" s." << std::endl;
417 std::cout <<
"Total initial settings time " << chronoinitialsettings.diff() <<
" s." << std::endl;
421 std::cout <<
"Total execution time " << chronoinitialsettings.diff() + chronototaliterations.diff() <<
" s." << std::endl;
427 HeartMonodomainSolver< mesh_Type >& electricModel,
428 std::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel,
431 bool verbose = (M_heart_fct->M_comm->MyPID() == 0);
434 std::cout <<
" f- Computing Rhs ... " <<
"\n" << std::flush;
440 vector_Type uVecRep (electricModel.solutionTransmembranePotential(), Repeated);
441 ionicModel->updateRepeated();
442 VectorElemental elvec_Iapp ( electricModel.potentialFESpace().fe().nbFEDof(), 2 ),
443 elvec_u ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ),
444 elvec_Iion ( electricModel.potentialFESpace().fe().nbFEDof(), 1 );
446 for (UInt iVol = 0; iVol < electricModel.potentialFESpace().mesh()->numVolumes(); ++iVol)
448 electricModel.potentialFESpace().fe().updateJacQuadPt ( electricModel.potentialFESpace().mesh()->volumeList ( iVol ) );
453 UInt eleIDu = electricModel.potentialFESpace().fe().currentLocalId();
454 UInt nbNode = ( UInt ) electricModel.potentialFESpace().fe().nbFEDof();
457 for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
459 Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode );
460 elvec_u.vec() [ iNode ] = uVecRep[ig];
463 ionicModel->updateElementSolution (eleIDu);
464 ionicModel->computeIonicCurrent (data.membraneCapacitance(), elvec_Iion, elvec_u, electricModel.potentialFESpace() );
467 AssemblyElemental::source (M_heart_fct->stimulus(),
469 electricModel.potentialFESpace().fe(),
472 AssemblyElemental::source (M_heart_fct->stimulus(),
474 electricModel.potentialFESpace().fe(),
479 for ( UInt i = 0 ; i < electricModel.potentialFESpace().fe().nbFEDof() ; i++ )
481 Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, i );
482 rhs.sumIntoGlobalValues (ig, (data.conductivityRatio() * elvec_Iapp.vec() [i] +
483 elvec_Iapp.vec() [i + nbNode]) /
484 (1 + data.conductivityRatio() ) + data.volumeSurfaceRatio() * elvec_Iion.vec() [i] );
487 rhs.globalAssemble();
488 Real coeff = data.volumeSurfaceRatio() * data.membraneCapacitance() / data.timeStep();
489 vector_Type tmpvec (electricModel.solutionTransmembranePotential() );
491 rhs += electricModel.massMatrix() * tmpvec;
492 MPI_Barrier (MPI_COMM_WORLD);
496 std::cout <<
"done in " << chrono.diff() <<
" s." << std::endl;
500 void Heart::computeRhs ( vector_Type& rhs,
501 HeartBidomainSolver< mesh_Type >& electricModel,
502 std::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel,
503 HeartBidomainData& data )
505 bool verbose = (M_heart_fct->M_comm->MyPID() == 0);
508 std::cout <<
" f- Computing Rhs ... " <<
"\n" << std::flush;
514 vector_Type uVecRep (electricModel.solutionTransmembranePotential(), Repeated);
515 ionicModel->updateRepeated();
517 VectorElemental elvec_Iapp ( electricModel.potentialFESpace().fe().nbFEDof(), 2 ),
518 elvec_u ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ),
519 elvec_Iion ( electricModel.potentialFESpace().fe().nbFEDof(), 1 );
520 for (UInt iVol = 0; iVol < electricModel.potentialFESpace().mesh()->numVolumes(); ++iVol)
522 electricModel.potentialFESpace().fe().updateJacQuadPt ( electricModel.potentialFESpace().mesh()->volumeList ( iVol ) );
527 UInt eleIDu = electricModel.potentialFESpace().fe().currentLocalId();
528 UInt nbNode = ( UInt ) electricModel.potentialFESpace().fe().nbFEDof();
529 for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
531 Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode );
532 elvec_u.vec() [ iNode ] = uVecRep[ig];
535 UInt eleID = electricModel.potentialFESpace().fe().currentLocalId();
536 ionicModel->updateElementSolution (eleID);
537 ionicModel->computeIonicCurrent (data.membraneCapacitance(), elvec_Iion, elvec_u, electricModel.potentialFESpace() );
540 AssemblyElemental::source (M_heart_fct->stimulus(),
542 electricModel.potentialFESpace().fe(),
544 AssemblyElemental::source (M_heart_fct->stimulus(),
546 electricModel.potentialFESpace().fe(),
549 UInt totalUDof = electricModel.potentialFESpace().map().map (Unique)->NumGlobalElements();
551 for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
553 Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode );
554 rhs.sumIntoGlobalValues (ig, elvec_Iapp.vec() [iNode] +
555 data.volumeSurfaceRatio() * elvec_Iion.vec() [iNode] );
556 rhs.sumIntoGlobalValues (ig + totalUDof,
557 -elvec_Iapp.vec() [iNode + nbNode] -
558 data.volumeSurfaceRatio() * elvec_Iion.vec() [iNode] );
561 rhs.globalAssemble();
563 rhs += electricModel.matrMass() * data.volumeSurfaceRatio() *
564 data.membraneCapacitance() * electricModel.BDFIntraExtraPotential().time_der (data.timeStep() );
566 MPI_Barrier (MPI_COMM_WORLD);
571 std::cout <<
"done in " << chrono.diff() <<
" s." << std::endl;
Real zero_scalar(const Real &, const Real &, const Real &, const Real &, const ID &)
Null function used to define the boundary conditions.
FESpace - Short description here please!
const QuadratureRule quadRuleTetra15pt(pt_tetra_15pt, 5, "Quadrature rule 15 points on a tetraedra", TETRA, 15, 5)
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
const QuadratureRule quadRuleTetra4pt(pt_tetra_4pt, 2, "Quadrature rule 4 points on a tetraedra", TETRA, 4, 2)
int32_type Int
Generic integer data.
void computeRhs(vector_Type &rhs, HeartMonodomainSolver< RegionMesh< LinearTetra > > &electricModel, std::shared_ptr< HeartIonicSolver< RegionMesh< LinearTetra > > > ionicModel, HeartMonodomainData &dataMonodomain)
To compute the righthand side of the system.
Epetra_Import const & importer()
Getter for the Epetra_Import.
Heart(Int argc, char **argv)
Constructors.
std::shared_ptr< std::vector< Int > > M_isOnProc
MeshData - class for handling spatial discretization.
RegionMesh< LinearTetra > mesh_Type
double Real
Generic real data.
const QuadratureRule quadRuleTria3pt(pt_tria_3pt, 2, "Quadrature rule 3 points on a triangle", TRIANGLE, 3, 2)
The class for a reference Lagrangian finite element.
void run()
To build the system and iterate.
std::shared_ptr< vector_Type > vectorPtr_Type
int operator()(const char *VarName, int Default) const
HeartMonodomainSolver< RegionMesh< LinearTetra > >::vector_Type vector_Type
QuadratureRule - The basis class for storing and accessing quadrature rules.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
const Int EPICARDIUM
Identifiers for heart boundaries.