39 #include <lifev/electrophysiology/solver/IonicModels/ElectroIonicModel.hpp> 47 ElectroIonicModel::ElectroIonicModel() :
48 M_numberOfEquations (0),
49 M_numberOfGatingVariables (0),
50 M_restingConditions (),
51 M_membraneCapacitance (1.),
52 M_appliedCurrent (0.),
53 M_appliedCurrentPtr(),
58 ElectroIonicModel::ElectroIonicModel (
int n ) :
59 M_numberOfEquations (n),
60 M_numberOfGatingVariables (0),
61 M_restingConditions (std::vector<Real> (M_numberOfEquations, 0.0) ),
62 M_membraneCapacitance (1.),
63 M_appliedCurrent (0.),
64 M_appliedCurrentPtr(),
69 ElectroIonicModel::ElectroIonicModel (
int n,
int g ) :
70 M_numberOfEquations (n),
71 M_numberOfGatingVariables (g),
72 M_restingConditions (std::vector<Real> (M_numberOfEquations, 0.0) ),
73 M_membraneCapacitance (1.),
74 M_appliedCurrent (0.),
75 M_appliedCurrentPtr(),
80 ElectroIonicModel::ElectroIonicModel (
const ElectroIonicModel& Ionic ) :
81 M_numberOfEquations ( Ionic.Size() ),
82 M_numberOfGatingVariables ( Ionic.numberOfGatingVariables() ),
83 M_restingConditions ( Ionic.restingConditions() ),
84 M_membraneCapacitance ( Ionic.M_membraneCapacitance ),
85 M_appliedCurrent ( Ionic.M_appliedCurrent ),
86 M_pacingProtocol (Ionic.M_pacingProtocol)
88 if (Ionic.M_appliedCurrentPtr)
90 M_appliedCurrentPtr.reset (
new vector_Type (*Ionic.M_appliedCurrentPtr) );
97 ElectroIonicModel& ElectroIonicModel::operator = (
const ElectroIonicModel& Ionic )
99 M_numberOfEquations = Ionic.M_numberOfEquations;
100 M_numberOfGatingVariables = Ionic.M_numberOfGatingVariables;
101 M_restingConditions = Ionic.M_restingConditions;
102 M_membraneCapacitance = Ionic.M_membraneCapacitance;
103 M_appliedCurrent = Ionic.M_appliedCurrent;
104 if (Ionic.M_appliedCurrent)
106 M_appliedCurrentPtr = Ionic.M_appliedCurrentPtr;
108 M_pacingProtocol = Ionic.M_pacingProtocol;
113 std::vector< std::vector<Real> > ElectroIonicModel::getJac (
const std::vector<Real>& v, Real h)
115 std::vector< std::vector<Real> > J ( M_numberOfEquations, std::vector<Real> (M_numberOfEquations, 0.0) );
116 std::vector<Real> f1 (M_numberOfEquations, 0.0);
117 std::vector<Real> f2 (M_numberOfEquations, 0.0);
118 std::vector<Real> y1 (M_numberOfEquations, 0.0);
119 std::vector<Real> y2 (M_numberOfEquations, 0.0);
121 for (
int i = 0; i < M_numberOfEquations; i++)
123 for (
int j = 0; j < M_numberOfEquations; j++)
125 y1[j] = v[j] + ( (
double) (i == j) ) * h;
126 y2[j] = v[j] - ( (
double) (i == j) ) * h;
128 this->computeRhs (y1, f1);
129 f1[0] += M_appliedCurrent;
130 this->computeRhs (y2, f2);
131 f2[0] += M_appliedCurrent;
133 for (
int j = 0; j < M_numberOfEquations; j++)
135 J[j][i] = (f1[j] - f2[j]) / (2.0 * h);
144 matrix_Type J (v.map(), M_numberOfEquations,
false);
188 void ElectroIonicModel::computeGatingRhs (
const std::vector<vectorPtr_Type>& v,
189 std::vector<vectorPtr_Type>& rhs )
192 int nodes = ( * (v.at (1) ) ).epetraVector().MyLength();
195 std::vector<Real> localVec ( M_numberOfEquations, 0.0 );
196 std::vector<Real> localRhs ( M_numberOfEquations - 1, 0.0 );
200 for (
int k = 0; k < nodes; k++ )
203 j = ( * (v.at (1) ) ).blockMap().GID (k);
205 for (
int i = 0; i < M_numberOfEquations; i++ )
207 localVec.at (i) = ( * ( v.at (i) ) ) [j];
210 if (M_appliedCurrentPtr)
212 M_appliedCurrent = (*M_appliedCurrentPtr) [j];
216 M_appliedCurrent = 0.0;
219 computeGatingRhs ( localVec, localRhs );
221 for (
int i = 1; i < M_numberOfEquations; i++ )
223 ( * ( rhs.at (i) ) ) [j] = localRhs.at (i - 1);
230 void ElectroIonicModel::computeNonGatingRhs (
const std::vector<vectorPtr_Type>& v,
231 std::vector<vectorPtr_Type>& rhs )
234 int nodes = ( * (v.at (1) ) ).epetraVector().MyLength();
237 std::vector<Real> localVec ( M_numberOfEquations, 0.0 );
238 int offset = 1 + M_numberOfGatingVariables;
239 std::vector<Real> localRhs ( M_numberOfEquations - offset, 0.0 );
243 for (
int k = 0; k < nodes; k++ )
246 j = ( * (v.at (1) ) ).blockMap().GID (k);
248 for (
int i = 0; i < M_numberOfEquations; i++ )
250 localVec.at (i) = ( * ( v.at (i) ) ) [j];
253 if (M_appliedCurrentPtr)
255 M_appliedCurrent = (*M_appliedCurrentPtr) [j];
259 M_appliedCurrent = 0.0;
262 computeNonGatingRhs ( localVec, localRhs );
264 for (
int i = offset; i < M_numberOfEquations; i++ )
266 ( * ( rhs.at (i) ) ) [j] = localRhs.at (i - offset);
274 void ElectroIonicModel::computeRhs (
const std::vector<vectorPtr_Type>& v,
275 std::vector<vectorPtr_Type>& rhs )
278 int nodes = ( * (v.at (1) ) ).epetraVector().MyLength();
281 std::vector<Real> localVec ( M_numberOfEquations, 0.0 );
282 std::vector<Real> localRhs ( M_numberOfEquations, 0.0 );
286 for (
int k = 0; k < nodes; k++ )
289 j = ( * (v.at (1) ) ).blockMap().GID (k);
291 for (
int i = 0; i < M_numberOfEquations; i++ )
293 localVec.at (i) = ( * ( v.at (i) ) ) [j];
297 if (M_appliedCurrentPtr)
299 M_appliedCurrent = (*M_appliedCurrentPtr) [j];
303 M_appliedCurrent = 0.0;
305 computeRhs ( localVec, localRhs );
306 addAppliedCurrent (localRhs);
308 for (
int i = 0; i < M_numberOfEquations; i++ )
310 ( * ( rhs.at (i) ) ) [j] = localRhs.at (i);
317 void ElectroIonicModel::computePotentialRhsICI (
const std::vector<vectorPtr_Type>& v,
318 std::vector<vectorPtr_Type>& rhs,
319 matrix_Type& massMatrix )
321 int nodes = ( * (v.at (0) ) ).epetraVector().MyLength();
323 ( * ( rhs.at (0) ) ) *= 0.0;
324 std::vector<Real> localVec ( M_numberOfEquations, 0.0 );
328 for (
int k = 0; k < nodes; k++ )
331 j = ( * (v.at (0) ) ).blockMap().GID (k);
333 for (
int i = 0; i < M_numberOfEquations; i++ )
335 localVec.at (i) = ( * ( v.at (i) ) ) [j];
338 if (M_appliedCurrentPtr)
340 M_appliedCurrent = (*M_appliedCurrentPtr) [j];
344 M_appliedCurrent = 0.0;
347 ( * ( rhs.at (0) ) ) [j] = computeLocalPotentialRhs ( localVec ) + M_appliedCurrent;
351 ( * ( rhs.at (0) ) ) = massMatrix * ( * ( rhs.at (0) ) );
356 void ElectroIonicModel::computePotentialRhsSVI (
const std::vector<vectorPtr_Type>& v,
357 std::vector<vectorPtr_Type>& rhs,
358 FESpace<mesh_Type,
MapEpetra>& uFESpace )
361 std::vector<Real> U (M_numberOfEquations, 0.0);
363 ( * ( rhs.at (0) ) ) *= 0.0;
365 std::vector<vectorPtr_Type> URepPtr;
366 for (
int k = 0; k < M_numberOfEquations; k++ )
368 URepPtr.push_back ( vectorPtr_Type (
new VectorEpetra ( * ( v.at (k) ) , Repeated ) ) );
371 VectorEpetra IappRep ( *M_appliedCurrentPtr, Repeated );
373 std::vector<elvecPtr_Type> elvecPtr;
374 for (
int k = 0; k < M_numberOfEquations; k++ )
376 elvecPtr.push_back ( elvecPtr_Type (
new VectorElemental ( uFESpace.fe().nbFEDof(), 1 ) ) );
382 for (UInt iVol = 0; iVol < uFESpace.mesh()->numVolumes(); ++iVol)
385 uFESpace.fe().updateJacQuadPt ( uFESpace.mesh()->volumeList ( iVol ) );
388 for (
int k = 0; k < M_numberOfEquations; k++ )
390 ( * ( elvecPtr.at (k) ) ).zero();
395 UInt eleIDu = uFESpace.fe().currentLocalId();
396 UInt nbNode = ( UInt ) uFESpace.fe().nbFEDof();
399 for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
402 Int ig = uFESpace.dof().localToGlobalMap ( eleIDu, iNode );
404 for (
int k = 0; k < M_numberOfEquations; k++ )
406 ( * ( elvecPtr.at (k) ) ).vec() [iNode] = ( * ( URepPtr.at (k) ) ) [ig];
409 elvec_Iapp.vec() [ iNode ] = IappRep[ig];
414 for ( UInt ig = 0; ig < uFESpace.fe().nbQuadPt(); ig++ )
417 for (
int k = 0; k < M_numberOfEquations; k++ )
423 for ( UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
426 for (
int k = 0; k < M_numberOfEquations; k++ )
428 U.at (k) += ( * ( elvecPtr.at (k) ) ) (i) * uFESpace.fe().phi ( i, ig );
431 I += elvec_Iapp (i) * uFESpace.fe().phi ( i, ig );
435 for ( UInt i = 0; i < uFESpace.fe().nbFEDof(); i++ )
438 elvec_Iion ( i ) += ( computeLocalPotentialRhs (U) + I ) * uFESpace.fe().phi ( i, ig ) * uFESpace.fe().weightDet ( ig );
445 for ( UInt i = 0 ; i < uFESpace.fe().nbFEDof(); i++ )
447 Int ig = uFESpace.dof().localToGlobalMap ( eleIDu, i );
448 ( * ( rhs.at (0) ) ).sumIntoGlobalValues (ig, elvec_Iion.vec() [i] );
451 rhs.at (0) -> globalAssemble();
454 if (M_appliedCurrentPtr)
456 M_appliedCurrentPtr -> setMapType (Unique);
461 void ElectroIonicModel::computePotentialRhsSVI (
const std::vector<vectorPtr_Type>& v,
462 std::vector<vectorPtr_Type>& rhs,
466 uFESpace.setQuadRule ( qr );
467 computePotentialRhsSVI (v, rhs, uFESpace);
471 void ElectroIonicModel::computeGatingVariablesWithRushLarsen ( std::vector<vectorPtr_Type>& v,
const Real dt )
473 int nodes = ( * (v.at (0) ) ).epetraVector().MyLength();
475 std::vector<Real> localVec ( M_numberOfEquations, 0.0 );
479 for (
int k = 0; k < nodes; k++ )
482 j = ( * (v.at (0) ) ).blockMap().GID (k);
484 for (
int i = 0; i < M_numberOfEquations; i++ )
486 localVec.at (i) = ( * ( v.at (i) ) ) [j];
489 computeGatingVariablesWithRushLarsen (localVec, dt);
491 for (
int i = 0; i < M_numberOfEquations; i++ )
493 ( * ( v.at (i) ) ) [j] = localVec.at (i);
501 void ElectroIonicModel::initialize ( std::vector<Real>& v )
503 for (
int i (0); i < M_numberOfEquations; i++ )
505 v.at (i) = M_restingConditions.at (i);
510 void ElectroIonicModel::initialize ( std::vector<vectorPtr_Type>& v )
512 for (
int i (0); i < M_numberOfEquations; i++ )
514 * ( v.at (i) ) = M_restingConditions.at (i);
VectorEpetra - The Epetra Vector format Wrapper.
void importFromHDF5(std::string const &fileName, std::string const &matrixName="matrix")
Read a matrix from a HDF5 (.h5) file.
void updateInverseJacobian(const UInt &iQuadPt)
Epetra_Import const & importer()
Getter for the Epetra_Import.
double Real
Generic real data.
QuadratureRule - The basis class for storing and accessing quadrature rules.