GCC Code Coverage Report


Directory: ./
File: Model/bidomainDecoupledModel.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 0 149 0.0%
Branches: 0 172 0.0%

Line Branch Exec Source
1 // ______ ______ _ _ _____ ______
2 // | ____| ____| | (_)/ ____| | ____|
3 // | |__ | |__ | | _| (___ ___| |__
4 // | __| | __| | | | |\___ \ / __| __|
5 // | | | |____| |____| |____) | (__| |____
6 // |_| |______|______|_|_____/ \___|______|
7 // Finite Elements for Life Sciences and Engineering
8 //
9 // License: LGL2.1 License
10 // FELiScE default license: LICENSE in root folder
11 //
12 // Main authors: E. Schenone C. Corrado
13 //
14
15 // System includes
16
17 // External includes
18
19 // Project includes
20 #include "Model/bidomainDecoupledModel.hpp"
21
22 namespace felisce {
23 BidomainDecoupledModel::BidomainDecoupledModel():
24 BidomainModel(),
25 m_linearProblemBidomainTransMemb(nullptr),
26 m_linearProblemBidomainExtraCell(nullptr) {
27 m_name = "BidomainDecoupled";
28 }
29
30 BidomainDecoupledModel::~BidomainDecoupledModel() {
31 m_linearProblemBidomainTransMemb = nullptr;
32 m_linearProblemBidomainExtraCell = nullptr;
33 m_Ue_0.destroy();
34 m_extrapolatePotTransMemb.destroy();
35 if(!FelisceParam::instance().monodomain)
36 m_extrapolatePotExtraCell.destroy();
37 }
38
39 //! Define m_ionic and m_bdfEdp (used in linearProblem).
40 void BidomainDecoupledModel::initializeDerivedModel() {
41 BidomainModel::initializeDerivedModel();
42 //Define order for bdf used to calculate m_extrapolateExtraCell.
43 if(!FelisceParam::instance().monodomain)
44 m_bdfExtraCell.defineOrder(FelisceParam::instance().orderBdfEdp);
45 }
46
47 void BidomainDecoupledModel::initializeDerivedLinearProblem() {
48 m_linearProblemBidomainTransMemb = dynamic_cast<LinearProblemBidomainTransMemb*>(m_linearProblem[0]);
49 m_linearProblemBidomainExtraCell = dynamic_cast<LinearProblemBidomainExtraCell*>(m_linearProblem[1]);
50
51 initializeAppCurrent();
52 }
53
54 void BidomainDecoupledModel::initializeAppCurrent() {
55 m_iApp = new AppCurrent();
56 m_iApp->initialize(m_fstransient);
57 }
58
59
60 void BidomainDecoupledModel::evalIapp() {
61 m_iAppValue.clear();
62 if ( (FelisceParam::instance().typeOfAppliedCurrent == "zygote") || (FelisceParam::instance().typeOfAppliedCurrent == "heart") || (FelisceParam::instance().typeOfAppliedCurrent == "ellipseheart") ) {
63 m_linearProblemBidomainTransMemb->evalFunctionOnDof(*m_iApp,m_fstransient->time,m_iAppValue,m_linearProblemBidomainTransMemb->EndocardiumDistance());
64 } else {
65 m_linearProblemBidomainTransMemb->evalFunctionOnDof(*m_iApp,m_fstransient->time,m_iAppValue);
66 }
67 }
68
69 void BidomainDecoupledModel::finalizeRHSDP(int iProblem) {
70 if (iProblem == 0) {
71
72 int size = m_linearProblem[iProblem]->numDofLocalPerUnknown(potTransMemb);
73 double valueForPetsc[size];
74 felInt idLocalValue[size];
75 felInt idGlobalValue[size];
76
77 double coefAm = FelisceParam::instance().Am;
78 double coefCm = FelisceParam::instance().Cm;
79
80 // m_massRHS = Am * Cm * m_bdfEdp.RHS
81 m_linearProblemBidomainTransMemb->massRHS().axpy(coefAm*coefCm, m_bdfEdp.vector());
82
83 for (felInt i = 0; i < size; i++) {
84 idLocalValue[i] = i;
85 }
86 ISLocalToGlobalMappingApply(m_linearProblem[iProblem]->mappingDofLocalToDofGlobal(potTransMemb),size,&idLocalValue[0],&idGlobalValue[0]);
87
88 for (felInt i = 0; i < size; i++) {
89 valueForPetsc[i] = coefAm*m_iAppValue[idGlobalValue[i]];
90 }
91 // m_massRHS = m_massRHS + Am * Iapp
92 m_linearProblemBidomainTransMemb->massRHS().setValues(size,&idGlobalValue[0],&valueForPetsc[0],ADD_VALUES);
93 m_linearProblemBidomainTransMemb->massRHS().assembly();
94
95 // m_massRHS = m_massRHS + Am * Iion
96 m_linearProblemBidomainTransMemb->massRHS().axpy(coefAm,m_ionic->ion());
97
98 if(!FelisceParam::instance().monodomain) {
99 // _KsigmaiRHS = m_extrapolatePotExtraCell
100 m_linearProblemBidomainTransMemb->ksigmaiRHS().axpy(1.,m_extrapolatePotExtraCell);
101 }
102
103 } else if (iProblem == 1) {
104 m_linearProblemBidomainExtraCell->vector().axpy(1.0,m_linearProblem[0]->solution());
105 }
106
107 }
108
109 void BidomainDecoupledModel::preAssemblingMatrixRHS(std::size_t iProblem) {
110
111 // Initialize useful vectors of initial solution and initial extrapolate with a std::vector with same structure of _RHS for each linearProblem.
112
113 if (iProblem == 0) { // First problem solves first equation on potTransMemb
114 // Give _U_0 and m_W_0 values:
115 // initialize PotTransMemb with value Vmin
116 // and W_0 with 1/(vMax-vMin)^2.
117
118 // 1) copy structure in _U_0 and in m_extrapolatePotTransMemb.
119 m_U_0.duplicateFrom(m_linearProblem[iProblem]->vector());
120 m_U_0.set(FelisceParam::instance().vMin);
121
122 // 2) copy structure in m_W_0 (initialize solution at time 0 of EDO in schaf solver) - only for first equation.
123 m_W_0.resize(1);
124 m_W_0[0].duplicateFrom(m_linearProblem[iProblem]->vector());
125 double valueByDofW_0 = 1./((FelisceParam::instance().vMax - FelisceParam::instance().vMin)*(FelisceParam::instance().vMax - FelisceParam::instance().vMin));
126 m_W_0[0].set(valueByDofW_0);
127
128 // 3) copy structure in m_extrapolatePotTransMemb (contains extrapolate values of linearProblem[0] solution).
129 m_extrapolatePotTransMemb.duplicateFrom(m_linearProblem[iProblem]->vector());
130 m_extrapolatePotTransMemb.zeroEntries();
131
132 // 3) copy structure in m_massRHS and _KsigmaiRHS.
133 m_linearProblemBidomainTransMemb->massRHS().duplicateFrom(m_linearProblem[iProblem]->vector());
134 m_linearProblemBidomainTransMemb->massRHS().set(0.);
135 m_linearProblemBidomainTransMemb->ksigmaiRHS().duplicateFrom(m_linearProblem[iProblem]->vector());
136 m_linearProblemBidomainTransMemb->ksigmaiRHS().set(0.);
137
138 //Initialize solution for solver.
139 m_linearProblem[iProblem]->solution().copyFrom(m_U_0);
140
141 // Read fibers and distance mapp (for Zygote geometry).
142 m_linearProblem[iProblem]->readData(*io());
143
144 //Initialize heterogeneous parameters for schaf solver (useful only for first problem).
145 if (FelisceParam::instance().typeOfIonicModel == "schaf") {
146 initializeSchafParameter();
147 }
148
149 } else if (iProblem == 1) {
150 // 1) copy structure in _Ue_0.
151 m_Ue_0.duplicateFrom(m_linearProblem[iProblem]->vector());
152 m_Ue_0.set(0.0);
153
154 // 2) copy structure in m_extrapolatePotExtraCell (contains extrapolate values of linearProblem[1] solution).
155 if(!FelisceParam::instance().monodomain) {
156 m_extrapolatePotExtraCell.duplicateFrom(m_linearProblem[iProblem]->vector());
157 m_extrapolatePotExtraCell.set(0.);
158 }
159
160 //Initialize solution for solver.
161 m_linearProblem[iProblem]->solution().copyFrom(m_Ue_0);
162
163 // Read fibers and distance mapp (for Zygote geometry).
164 m_linearProblem[iProblem]->readData(*io());
165 }
166
167 //Debug print.
168 // /todo fix value of verbose
169 if (m_verbose > 2 && iProblem == 0) {
170 PetscPrintf(MpiInfo::petscComm(),"\n\t\t _U_0 (==m_sol (linearProblem[0]) at time == 0):\n");
171 m_U_0.view();
172 PetscPrintf(MpiInfo::petscComm(),"\n\t\t m_W_0 (==m_solEDO (ionicSolver) at time == 0):\n");
173 m_W_0[0].view();
174 } else if (m_verbose > 2 && iProblem == 1) {
175 PetscPrintf(MpiInfo::petscComm(),"\n\t\t m_Ue_0 (==m_sol (linearProblem[1]) at time == 0):\n");
176 m_Ue_0.view();
177 }
178 }
179
180 void BidomainDecoupledModel::postAssemblingMatrixRHS(std::size_t iProblem) {
181 // Evaluate applied current std::vector.
182 if (iProblem == 0) {
183 evalIapp();
184 }
185
186 // Calculate RHS std::vector (to be multiplied by mass matrix).
187 finalizeRHSDP(iProblem);
188 // Calculate _RHS :
189 // if model == 'Bidomain' => _RHS = mass * RHS.
190 // if model == 'BidomainDecoupled' :
191 // iProblem==0 => _RHS=mass*RHS+Ksigmai*u_e
192 // iProblem==1 => _RHS=Ksigmai*V_m
193 m_linearProblem[iProblem]->addMatrixRHS();
194
195 //RHS of Luenb. filter
196 if (FelisceParam::instance().stateFilter) {
197 if (iProblem == 0) {
198 double coefAm = FelisceParam::instance().Am;
199 m_luenbFlter.zeroEntries();
200 m_luenbFlter.copyFrom(m_linearProblem[iProblem]->matrix(1),SAME_NONZERO_PATTERN);
201 m_luenbFlter.assembly(MAT_FINAL_ASSEMBLY);
202 // copy diagonal stabiliz. matrix in luenberger matrix
203 m_luenbFlter.diagonalScale(PetscVector::null(),m_ionic->stabTerm());
204 m_luenbFlter.scale(coefAm);
205 m_linearProblem[iProblem]->matrix(0).axpy(1,m_luenbFlter,SAME_NONZERO_PATTERN);
206 }
207 }
208 }
209
210 void BidomainDecoupledModel::initializeSchafParameter() {
211 // Initialize TauClose.
212 if (FelisceParam::instance().hasHeteroTauClose) {
213 m_schaf->fctTauClose().initialize(m_fstransient);
214 if ( (FelisceParam::instance().typeOfAppliedCurrent == "zygote") || (FelisceParam::instance().typeOfAppliedCurrent == "heart") || (FelisceParam::instance().typeOfAppliedCurrent == "ellipseheart") ) {
215 m_linearProblemBidomainTransMemb->evalFunctionOnDof(m_schaf->fctTauClose(), m_schaf->tauClose(),m_linearProblemBidomainTransMemb->EndocardiumDistance());
216 }
217 else {
218 m_linearProblemBidomainTransMemb->evalFunctionOnDof(m_schaf->fctTauClose(), m_schaf->tauClose());
219 }
220 }
221 // Initialize TauOut : heterogeneous in case of infarct.
222 if (FelisceParam::instance().hasInfarct) {
223 m_schaf->fctTauOut().initialize(m_fstransient);
224 m_linearProblemBidomainTransMemb->evalFunctionOnDof(m_schaf->fctTauOut(), m_schaf->tauOut());
225 }
226 }
227
228 // Pay attention on the call of this :
229 // call BidomainModel::writeSolution() function instead of (non-virtual) Model::writeSolution() function
230 void BidomainDecoupledModel::writeSolution()
231 {
232 Model::writeSolution();
233 }
234
235 void BidomainDecoupledModel::forward() {
236 //Write solution with ensight.
237 BidomainDecoupledModel::writeSolution();
238 //Advance time step.
239 updateTime(FlagMatrixRHS::only_rhs);
240 printNewTimeIterationBanner();
241
242 if ( m_fstransient->iteration == 1) {
243 //Initialization of bdf solvers.
244 m_bdfEdp.initialize(m_linearProblem[0]->solution());
245 if(!FelisceParam::instance().monodomain)
246 m_bdfExtraCell.initialize(m_linearProblem[1]->solution());
247 m_linearProblemBidomainTransMemb->initializeTimeScheme(&m_bdfEdp);
248 //m_extrapolate = initial solution.
249 m_bdfEdp.extrapolate(m_extrapolatePotTransMemb);
250 if(!FelisceParam::instance().monodomain) {
251 m_bdfExtraCell.extrapolate(m_extrapolatePotExtraCell);
252 }
253 //Initialization of ionic solver.
254 m_ionic->defineSizeAndMappingOfIonicProblem(m_linearProblem[0]->numDofLocalPerUnknown(potTransMemb), m_linearProblem[0]->mappingDofLocalToDofGlobal(potTransMemb), m_linearProblemBidomain[0]->ao());
255 m_ionic->initializeExtrap(m_extrapolatePotTransMemb);
256 m_ionic->initialize(m_W_0[0]);
257 m_buildIonic = true;
258 } else {
259 m_bdfEdp.update(m_linearProblem[0]->solution());
260 if(!FelisceParam::instance().monodomain)
261 m_bdfExtraCell.update(m_linearProblem[1]->solution());
262 m_bdfEdp.extrapolate(m_extrapolatePotTransMemb);
263 if(!FelisceParam::instance().monodomain) {
264 m_bdfExtraCell.extrapolate(m_extrapolatePotExtraCell);
265 }
266 m_ionic->update(m_extrapolatePotTransMemb);
267 }
268
269 //Solve Mitchell and Schaeffer model and calculate Iion.
270 m_ionic->computeRHS();
271 m_ionic->solveEDO();
272 m_ionic->computeIon();
273 m_ionic->updateBdf();
274
275 m_bdfEdp.computeRHSTime(m_fstransient->timeStep);
276
277 // Assembling of matrices at first iteration (because of needs some coefficients not defined at iteration 0).
278 if ( m_fstransient->iteration == 1 ) {
279 if ( FelisceParam::instance().hasCoupledAtriaVent )
280 m_linearProblemBidomainTransMemb->assembleMatrixRHSCurrentAndCurvilinearElement(MpiInfo::rankProc());
281 else
282 m_linearProblemBidomainTransMemb->assembleMatrixRHS(MpiInfo::rankProc());
283 }
284
285 //Specific operations before solve the system : calculate _RHS std::vector used in solve().
286 postAssemblingMatrixRHS(0);
287
288 //Solve the system _Matrix[0]*_V_m=_RHS.
289 m_linearProblem[0]->solve(MpiInfo::rankProc(), MpiInfo::numProc());
290
291 // Assemble Matrix of linearProblem.
292 if ( m_fstransient->iteration == 1 ) {
293 if ( FelisceParam::instance().hasCoupledAtriaVent )
294 m_linearProblemBidomainExtraCell->assembleMatrixRHSCurrentAndCurvilinearElement(MpiInfo::rankProc());
295 else
296 m_linearProblemBidomainExtraCell->assembleMatrixRHS(MpiInfo::rankProc());
297 }
298
299 //Specific operations before solve the system : calculate _RHS std::vector used in solve().
300 postAssemblingMatrixRHS(1);
301
302 //Solve the system _Matrix[0]*m_u_e=_RHS.
303 m_linearProblem[1]->solve(MpiInfo::rankProc(), MpiInfo::numProc());
304
305 if ( FelisceParam::instance().hasCoupledAtriaVent == false )
306 m_linearProblem[1]->removeAverageFromSolution(potExtraCell, MpiInfo::rankProc());
307
308 }
309
310 }
311