39 #ifndef _IONICSOLVER_H_ 40 #define _IONICSOLVER_H_ 42 #include <lifev/core/array/MatrixElemental.hpp> 43 #include <lifev/core/array/VectorElemental.hpp> 44 #include <lifev/core/fem/Assembly.hpp> 45 #include <lifev/core/fem/AssemblyElemental.hpp> 46 #include <lifev/core/fem/BCManage.hpp> 47 #include <lifev/core/algorithm/SolverAztecOO.hpp> 48 #include <lifev/core/array/MapEpetra.hpp> 49 #include <lifev/core/array/MatrixEpetra.hpp> 50 #include <lifev/core/array/VectorEpetra.hpp> 51 #include <lifev/core/fem/SobolevNorms.hpp> 52 #include <lifev/core/fem/GeometricMap.hpp> 53 #include <lifev/heart/solver/HeartIonicData.hpp> 54 #include <lifev/core/util/LifeChrono.hpp> 55 #include <boost/shared_ptr.hpp> 56 #include <lifev/core/fem/FESpace.hpp> 57 #include <lifev/core/fem/TimeAdvanceBDF.hpp> 64 template <
typename Mesh,
65 typename SolverType = LifeV::SolverAztecOO >
147 const Real timeStep ) = 0;
152 VectorElemental& elvec,
153 VectorElemental& elvec_u,
194 template<
typename Mesh,
typename SolverType>
199 Epetra_Comm& comm ) :
210 template <
typename Mesh,
211 typename SolverType = LifeV::SolverAztecOO >
234 VectorElemental& elvec,
235 VectorElemental& elvec_u,
272 template<
typename Mesh,
typename SolverType>
277 Epetra_Comm& comm ) :
288 template<
typename Mesh,
typename SolverType>
294 template<
typename Mesh,
typename SolverType>
300 template<
typename Mesh,
typename SolverType>
306 for (
UInt iNode = 0 ; iNode <
HeartIonicSolver<Mesh, SolverType>::M_uFESpace.fe().nbFEDof() ; iNode++ )
308 ig =
HeartIonicSolver<Mesh, SolverType>::M_uFESpace.dof().localToGlobalMap ( eleID, iNode );
309 M_elvec.vec() [ iNode ] = M_solutionGatingWRepeated[ig];
313 template<
typename Mesh,
typename SolverType>
319 template<
typename Mesh,
typename SolverType>
323 const Real& z,
const ID& i)
const 328 template<
typename Mesh,
typename SolverType>
336 Real aux1 = 1.0 / (
M_BDFW.coefficientFirstDerivative (0) / timeStep +
337 1.0 /
this->M_data.MSTauOpen() );
338 Real aux = 1.0 / ( (
this->M_data.MSPotentialMaximum() -
339 this->M_data.MSPotentialMinimum() ) *
340 (
this->M_data.MSPotentialMaximum() -
341 this->M_data.MSPotentialMinimum() ) *
342 this->M_data.MSTauOpen() );
343 Real aux2 = 1.0 / (
M_BDFW.coefficientFirstDerivative (0) / timeStep +
344 1.0 /
this->M_data.MSTauClose() );
346 M_BDFW.updateRHSContribution (timeStep);
351 for (
Int i = 0 ; i < u.epetraVector().MyLength() ; ++i )
353 Int ig = u.blockMap().MyGlobalElements() [i];
359 if (u[ig] <
this->M_data.MSCriticalPotential() )
363 else if (
this->M_data.MSHasHeterogeneousTauClose() )
377 template<
typename Mesh,
typename SolverType>
379 VectorElemental& elvec,
380 VectorElemental& elvec_u,
383 for (
UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
385 elvec ( i ) =
this->M_data.MSReactionAmplitude() *
386 ( ( (M_elvec ( i ) /
this->M_data.MSTauIn() ) *
387 (elvec_u ( i ) -
this->M_data.MSPotentialMinimum() ) *
388 (elvec_u ( i ) -
this->M_data.MSPotentialMinimum() ) *
389 (
this->M_data.MSPotentialMaximum() - elvec_u ( i ) ) /
390 (
this->M_data.MSPotentialMaximum() -
this->M_data.MSPotentialMinimum() ) ) -
391 ( ( elvec_u ( i ) -
this->M_data.MSPotentialMinimum() ) /
392 (
this->M_data.MSTauOut() * (
this->M_data.MSPotentialMaximum() -
393 this->M_data.MSPotentialMinimum() ) ) ) ) ;
397 template<
typename Mesh,
typename SolverType>
402 ( (
this->M_data.MSPotentialMaximum() -
403 this->M_data.MSPotentialMinimum() ) *
404 (
this->M_data.MSPotentialMaximum() -
405 this->M_data.MSPotentialMinimum() ) ) );
410 template <
typename Mesh,
411 typename SolverType = LifeV::SolverAztecOO >
432 VectorElemental& elvec,
433 VectorElemental& elvec_u,
458 template<
typename Mesh,
typename SolverType>
463 Epetra_Comm& comm ) :
471 template<
typename Mesh,
typename SolverType>
477 template<
typename Mesh,
typename SolverType>
483 template<
typename Mesh,
typename SolverType>
488 for (
UInt iNode = 0 ;
489 iNode <
HeartIonicSolver<Mesh, SolverType>::M_uFESpace.fe().nbFEDof() ; iNode++ )
491 ig =
HeartIonicSolver<Mesh, SolverType>::M_uFESpace.dof().localToGlobalMap ( eleID, iNode );
492 M_elvec.vec() [ iNode ] = M_solutionGatingWRepeated[ig];
496 template<
typename Mesh,
typename SolverType>
500 Real G =
this->M_data.RMCParameterB() /
this->M_data.RMCPotentialAmplitude() /
this->M_data.RMCTimeUnit();
502 Real alpha = 1 / timeStep + G *
this -> M_data.RMCPotentialAmplitude() *
this -> M_data.RMCParameterD() ;
508 temp.epetraVector().PutScalar ( G *
this -> M_data.RMCRestPotential() );
517 template<
typename Mesh,
typename SolverType>
519 VectorElemental& elvec,
520 VectorElemental& elvec_u,
525 Real G1 =
this->M_data.RMCParameterC1() /
this->M_data.RMCTimeUnit() / std::pow (
this->M_data.RMCPotentialAmplitude(), 2.0);
526 Real G2 =
this->M_data.RMCParameterC2() /
this->M_data.RMCTimeUnit();
528 for (
UInt ig = 0; ig < uFESpace.fe().nbQuadPt(); ig++ )
531 for (
UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
533 u_ig += elvec_u ( i ) * uFESpace.fe().phi ( i, ig );
535 for (
UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
537 w_ig += M_elvec ( i ) * uFESpace.fe().phi ( i, ig );
540 for (
UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
542 elvec ( i ) -= Capacitance * ( G1 * ( u_ig -
this -> M_data.RMCRestPotential() ) *
543 (u_ig -
this->M_data.RMCRestPotential() -
544 this->M_data.RMCParameterA() *
this->M_data.RMCPotentialAmplitude() ) *
545 (u_ig -
this->M_data.RMCRestPotential() -
546 this->M_data.RMCPotentialAmplitude() ) + G2 *
547 (u_ig -
this->M_data.RMCRestPotential() ) * w_ig) *
548 uFESpace.fe().phi ( i, ig ) * uFESpace.fe().weightDet ( ig );
553 template<
typename Mesh,
typename SolverType>
560 template <
typename Mesh,
561 typename SolverType = LifeV::SolverAztecOO >
585 VectorElemental& elvec,
586 VectorElemental& elvec_u,
628 M_Ena,
M_Gk,
M_Ek,
M_Gk1,
M_Ek1,
M_Ekp,
M_Esi,
M_ah,
M_bh,
M_aj,
M_bj,
M_xii,
629 M_am,
M_bm,
M_ad,
M_bd,
M_af,
M_bf,
M_aX,
M_bX,
M_ak1,
M_bk1,
M_Kp,
M_K1inf,
630 M_hinf,
M_tauh,
M_jinf,
M_tauj,
M_minf,
M_taum,
M_dinf,
M_taud,
M_finf,
M_tauf,
694 template<
typename Mesh,
typename SolverType>
699 Epetra_Comm& comm ) :
743 template<
typename Mesh,
typename SolverType>
750 template<
typename Mesh,
typename SolverType>
753 M_elemVecIonicCurrent.zero();
756 for (
UInt iNode = 0 ; iNode <
HeartIonicSolver<Mesh, SolverType>::M_uFESpace.fe().nbFEDof() ; iNode++ )
758 ig =
HeartIonicSolver<Mesh, SolverType>::M_uFESpace.dof().localToGlobalMap ( eleID, iNode );
759 M_elemVecIonicCurrent.vec() [ iNode ] = M_ionicCurrentRepeated[ig];
765 template<
typename Mesh,
typename SolverType>
769 LifeChrono chronoionmodelsolve;
770 chronoionmodelsolve.start();
773 for (
Int i = 0 ; i < u.epetraVector().MyLength() ; i++ )
775 Int ig = u.blockMap().MyGlobalElements() [i];
778 M_Esi = 7.7 - 13.0287 * std::log (M_solutionGatingCa[ig]);
794 M_Iback = 0.03921 * (u_ig + 59.87);
801 M_vectorExponentialh.epetraVector().ReplaceGlobalValue (ig,
803 std::exp (-timeStep / M_tauh) );
804 M_vectorExponentialj.epetraVector().ReplaceGlobalValue (ig,
806 std::exp (-timeStep / M_tauj) );
807 M_vectorExponentialm.epetraVector().ReplaceGlobalValue (ig,
809 std::exp (-timeStep / M_taum) );
810 M_vectorExponentiald.epetraVector().ReplaceGlobalValue (ig,
812 std::exp (-timeStep / M_taud) );
813 M_vectorExponentialf.epetraVector().ReplaceGlobalValue (ig,
815 std::exp (-timeStep / M_tauf) );
816 M_vectorExponentialX.epetraVector().ReplaceGlobalValue (ig,
818 std::exp (-timeStep / M_tauX) );
905 chronoionmodelsolve.stop();
908 std::cout <<
"Total ionmodelsolve time " << chronoionmodelsolve.diff() <<
" s." << std::endl;
914 template<
typename Mesh,
typename SolverType>
920 M_bh = 1. / (0.13 * (1. + std::exp ( (u_ig + 10.66) / (-11.1) ) ) );
922 M_bj = 0.3 * std::exp (-2.535e-7 * u_ig) / (1. + std::exp (-0.1 * (u_ig + 32.) ) );
926 M_ah = 0.135 * std::exp ( (80. + u_ig) / -6.8);
927 M_bh = 3.56 * std::exp (0.079 * u_ig) + 3.1e5 * std::exp (0.35 * u_ig);
928 M_aj = (-1.2714e5 * std::exp (0.2444 * u_ig) - 3.474e-5 * std::exp (-0.04391 * u_ig) ) *
929 (u_ig + 37.78) / (1 + std::exp (0.311 * (u_ig + 79.23) ) );
930 M_bj = 0.1212 * std::exp (-0.01052 * u_ig) / (1. + std::exp (-0.1378 * (u_ig + 40.14) ) );
932 M_am = 0.32 * (u_ig + 47.13) / (1. - std::exp (-0.1 * (u_ig + 47.13) ) );
933 M_bm = 0.08 * std::exp (-u_ig / 11.);
936 M_ad = 0.095 * std::exp (-0.01 * (u_ig - 5.) ) / (1. + std::exp (-0.072 * (u_ig - 5.) ) );
937 M_bd = 0.07 * std::exp (-0.017 * (u_ig + 44.) ) / (1. + std::exp ( 0.05 * (u_ig + 44.) ) );
938 M_af = 0.012 * std::exp (-0.008 * (u_ig + 28.) ) / (1. + std::exp ( 0.15 * (u_ig + 28.) ) );
939 M_bf = 0.0065 * std::exp (-0.02 * (u_ig + 30.) ) / (1. + std::exp ( -0.2 * (u_ig + 30.) ) );
942 M_aX = 0.0005 * std::exp (0.083 * (u_ig + 50.) ) / (1. + std::exp (0.057 * (u_ig + 50.) ) );
943 M_bX = 0.0013 * std::exp (-0.06 * (u_ig + 20.) ) / (1. + std::exp (-0.04 * (u_ig + 20.) ) );
951 M_xii = 2.837 * (std::exp (0.04 * (u_ig + 77.) ) - 1.) / ( (u_ig + 77.) * std::exp (0.04 * (u_ig + 35.) ) );
953 M_ak1 = 1.02 / (1. + std::exp (0.2385 * (u_ig - M_Ek1 - 59.215) ) );
954 M_bk1 = (0.49124 * std::exp (0.08032 * (u_ig - M_Ek1 + 5.476) ) +
955 std::exp (0.06175 * (u_ig - M_Ek1 - 594.31) ) ) / (1. + std::exp (-0.5143 * (u_ig - M_Ek1 + 4.753) ) );
957 M_Kp = 1. / (1. + std::exp ( (7.488 - u_ig) / 5.98) );
974 template<
typename Mesh,
typename SolverType>
976 VectorElemental& elvec,
981 for (
UInt ig = 0; ig < uFESpace.fe().nbQuadPt(); ig++ )
984 for (
UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
986 Iion_ig += M_elemVecIonicCurrent ( i ) * uFESpace.fe().phi ( i, ig );
988 for (
UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
991 elvec ( i ) -= Iion_ig * Capacitance *
992 uFESpace.fe().phi ( i, ig ) * uFESpace.fe().weightDet ( ig );
997 template<
typename Mesh,
typename SolverType>
998 void LuoRudy<Mesh, SolverType>::
HeartIonicSolver< Mesh, SolverType >::function_Type function_Type
SolverType::vector_type vector_Type
vector_Type M_solutionGatingW
Global solution _w.
void computeIonicCurrent(Real Capacitance, VectorElemental &elvec, VectorElemental &elvec_u, FESpace< Mesh, MapEpetra > &uFESpace)
Computes the term -1/ u^n (G (1-u^n/vp) (1-u^n/v_th) + eta_1 v^{n+1}) for the PDE righthand side...
void solveIonicModel(const vector_Type &u, const Real timeStep)
Solves the ionic model.
void setHeteroTauClose(functorTauClose_Type)
SolverType::matrix_type matrix_Type
void updateElementSolution(UInt eleID)
Update the ionic model elvecs.
HeartIonicSolver< Mesh, SolverType >::data_Type data_Type
void computeIonicCurrent(Real Capacitance, VectorElemental &elvec, VectorElemental &elvec_u, FESpace< Mesh, MapEpetra > &uFESpace)
Computes the term -1/ u^n (G (1-u^n/vp) (1-u^n/v_th) + eta_1 v^{n+1}) for the PDE righthand side...
HeartIonicSolver< Mesh, SolverType >::function_Type function_Type
const vector_Type & solutionGatingJ() const
const vector_Type & solutionGatingX() const
SolverType::prec_type prec_Type
UInt solutionUDimension() const
vector_Type M_vectorExponentialf
vector_Type M_vectorInfimumj
HeartIonicSolver< Mesh, SolverType >::functorTauClose_Type functorTauClose_Type
virtual void solveIonicModel(const vector_Type &u, const Real timeStep)=0
Solves the ionic model.
FESpace - Short description here please!
FESpace< Mesh, MapEpetra > & recoveryFESpace()
Returns the recovery variable FE space.
std::function< Real(const markerID_Type &ref, const Real &x, const Real &y, const Real &z, const ID &i) > functorTauClose_Type
vector_Type M_vectorExponentialj
const vector_Type & solutionGatingH() const
Returns the local solution vector for each field.
vector_Type M_vectorInfimumf
vector_Type M_ionicCurrentRepeated
int32_type Int
Generic integer data.
RogersMcCulloch(const data_Type &dataType, const Mesh &mesh, FESpace< Mesh, MapEpetra > &uFEspace, Epetra_Comm &comm)
Constructor.
ID markerID_Type
markerID_Type is the type used to store the geometric entity marker IDs
TimeAdvanceBDF< vector_Type > M_BDFW
virtual void updateRepeated()=0
HeartIonicSolver(const data_Type &dataType, const Mesh &mesh, FESpace< Mesh, MapEpetra > &uFEspace, Epetra_Comm &comm)
Constructor.
HeartIonicSolver< Mesh, SolverType >::vector_Type vector_Type
HeartIonicSolver< Mesh, SolverType >::data_Type data_Type
void initialize()
Initialize.
HeartIonicSolver< Mesh, SolverType >::vector_Type vector_Type
MitchellSchaeffer(const data_Type &dataType, const Mesh &mesh, FESpace< Mesh, MapEpetra > &uFEspace, Epetra_Comm &comm)
Constructor.
Epetra_Import const & importer()
Getter for the Epetra_Import.
void updateElementSolution(UInt eleID)
Update the ionic model elvecs.
void initialize()
Initialize.
HeartIonicSolver< Mesh, SolverType >::function_Type function_Type
vector_Type M_solutionGatingF
Global solution f.
SolverType::prec_raw_type precRaw_Type
virtual ~HeartIonicSolver()
Destructor.
vector_Type M_solutionGatingWRepeated
vector_Type M_solutionGatingH
Global solution h.
vector_Type M_vectorExponentialm
vector_Type M_solutionGatingW
Global solution _w.
class TimeAdvanceBDF - Backward differencing formula time discretization for the first and the second...
vector_Type M_solutionGatingX
Global solution X.
Real functorTauClose(const markerID_Type &ref, const Real &x, const Real &y, const Real &z, const ID &i) const
void updateElementSolution(UInt eleID)
Update the ionic model elvecs.
void computeODECoefficients(const Real &u_ig)
HeartIonicSolver< Mesh, SolverType >::vector_Type vector_Type
virtual void computeIonicCurrent(Real Capacitance, VectorElemental &elvec, VectorElemental &elvec_u, FESpace< Mesh, MapEpetra > &uFESpace)=0
Computes the term -1/ u^n (G (1-u^n/vp) (1-u^n/v_th) + eta_1 v^{n+1}) for the PDE righthand side...
void solveIonicModel(const vector_Type &u, const Real timeStep)
Solves the ionic model.
double Real
Generic real data.
void initialize()
Initialize.
virtual void initialize()=0
Initialize.
functorTauClose_Type M_tauClose
void computeIonicCurrent(Real Capacitance, VectorElemental &elvec, VectorElemental &elvec_u, FESpace< Mesh, MapEpetra > &uFESpace)
Computes the term -1/ u^n (G (1-u^n/vp) (1-u^n/v_th) + eta_1 v^{n+1}) for the PDE righthand side...
virtual ~MitchellSchaeffer()
VectorElemental M_elemVecIonicCurrent
LuoRudy(const data_Type &dataType, const Mesh &mesh, FESpace< Mesh, MapEpetra > &uFEspace, Epetra_Comm &comm)
Constructor.
Epetra_Comm * M_comm
MPI communicator.
vector_Type M_vectorExponentialh
vector_Type M_solutionGatingJ
Global solution j.
vector_Type M_vectorInfimumd
vector_Type M_ionicCurrent
const vector_Type & solutionGatingM() const
bool M_verbose
Boolean that indicates if output is sent to cout.
const vector_Type & solutionGatingD() const
vector_Type M_solutionGatingD
Global solution d.
vector_Type M_vectorInfimumm
const vector_Type & solutionGatingW() const
vector_Type M_solutionGatingM
Global solution m.
vector_Type M_vectorExponentiald
vector_Type M_vectorIonicChange
const vector_Type & solutionGatingCa() const
const vector_Type & solutionGatingW() const
vector_Type M_solutionGatingCa
Global solution Ca_i.
virtual ~RogersMcCulloch()
vector_Type M_solutionGatingWRepeated
FESpace< Mesh, MapEpetra > & M_uFESpace
const vector_Type & solutionGatingF() const
virtual void updateElementSolution(UInt eleIDw)=0
Update the ionic model elvecs.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
vector_Type M_vectorInfimumX
void solveIonicModel(const vector_Type &u, const Real timeStep)
Solves the ionic model.
vector_Type M_vectorExponentialX
vector_Type M_vectorInfimumh
HeartIonicSolver< Mesh, SolverType >::data_Type data_Type