GCC Code Coverage Report


Directory: ./
File: Solver/PaciSolver.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 0 438 0.0%
Branches: 0 238 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: F. Raphel
13 //
14
15 // System includes
16
17 // External includes
18
19 // Project includes
20 #include "Solver/PaciSolver.hpp"
21
22
23 //************************************
24 //Constants
25 //************************************
26
27 static constexpr double R = 8.314472; // [J/mol/K] Gas constant
28 static constexpr double F = 96485.3415; // [C/mol] Faraday constant
29 static constexpr double T = 310.0; // [K] Temperature
30 static constexpr double Q = 2.3;
31 static constexpr double Lo = 0.025; //[dimensionless]
32 static constexpr double Nao = 151.; // [mM]
33 static constexpr double Ko = 5.4; // [mM]
34 static constexpr double Cao = 1.8; // [mM]
35 static constexpr double Ki = 150.; // [mM]//150 doc---- 140 Matlab
36 static constexpr double gCaL = 8.635702e-5; //[m3/F.s]
37 static constexpr double gKr = 29.8667; //[S/F]
38 static constexpr double gKs = 2.041;
39 static constexpr double gf = 30.10312;
40 static constexpr double arel = 16.464; //[mM/s]
41 static constexpr double brel = 0.25;
42 static constexpr double crel = 8.232;
43 static constexpr double Vleak = 4.4444e-4;
44 static constexpr double gpCa = 0.4125; //[A/F]
45 static constexpr double gbNa = 0.9; //[S/F]
46 static constexpr double gbCa = 0.69264;
47 static constexpr double Bufc = 0.25; //[mM]
48 static constexpr double Bufsr = 10.;
49 static constexpr double Kbufc = 0.001; //[mM]
50 static constexpr double Kbufsr = 0.3;
51 static constexpr double Kup = 0.00025; //[mM]
52 static constexpr double KpCa = 0.0005;
53 static constexpr double Pkna = 0.03;
54 static constexpr double Ksat = 0.1;
55 static constexpr double KmCa = 1.38; //[mM]
56 static constexpr double KmNai = 87.5;
57 static constexpr double alpha = 2.8571432; //[dimensionless]
58 static constexpr double gamma_value = 0.35;
59 static constexpr double KmNa = 40.; //[mM]
60 static constexpr double Kmk = 1.;
61
62 #ifdef FELISCE_WITH_SUNDIALS
63
64 #define Ith(v,i) NV_Ith_S(v,i-1) /* Ith numbers components 1..NEQ */
65 #define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
66
67 static constexpr double Y0 = RCONST(0.0); /* initial y components */
68 static constexpr double Y1 = RCONST(1.0);
69 static constexpr double Y075 = RCONST(0.75);
70 static constexpr double Y01 = RCONST(0.1);
71 static constexpr double Ycai = RCONST(0.0002);
72 static constexpr double Ycasr = RCONST(0.3);
73 static constexpr double Ynai = RCONST(10.);
74 static constexpr double Y0bis = RCONST(1e-15); /* initial y components */
75
76 static constexpr double YmORd = RCONST(0.0074621);//minfORd
77 static constexpr double YjORd = RCONST( 0.692477);//jinfORd
78 static constexpr double Yhslow = RCONST(0.692574);//hslow
79 static constexpr double Yhfast = RCONST(0.692591);//hfast
80 static constexpr double Yhl = RCONST(0.496116);//hl
81 static constexpr double Yml = RCONST(0.000194015);//ml
82
83 //static constexpr double RTOL = RCONST(1.0e-6); /* scalar relative tolerance ----- 1e-6: doc Sundials */
84 //static constexpr double RTOL = RCONST(1.0e-4); //Nouveau test: avant: spontane
85
86 //static constexpr double RTOL = RCONST(1.0e-1); //Non sponta ok!
87 //static constexpr double RTOL = RCONST(1.0e-4);
88 static constexpr double RTOL = RCONST(1.0e0); //Non sponta ok!
89
90
91
92 //static constexpr double ATOL4 = RCONST(1.0e-4); /* std::vector absolute tolerance components */
93 static constexpr double ATOL4 = RCONST(1.0e-4); /* std::vector absolute tolerance components */
94 static constexpr double ATOL6 = RCONST(1.0e-6);
95 static constexpr double ATOL8 = RCONST(1.0e-8);
96 static constexpr double ATOL10 = RCONST(1.0e-10);
97 static constexpr double ATOL12 = RCONST(1.0e-12);
98 static constexpr double ATOL14 = RCONST(1.0e-14);
99
100 //static constexpr double RTOL = RCONST(1.0e-4); /* scalar relative tolerance 1e-4: 0.01% */
101 //static constexpr double ATOL = RCONST(1.0e-4); /* std::vector absolute tolerance components */
102
103 #endif
104
105 namespace felisce {
106
107 /////////////////
108 // Constructor //
109 /////////////////
110
111 PaciSolver::PaciSolver(FelisceTransient::Pointer fstransient):
112 IonicSolver(fstransient) {
113 m_nComp = 42;
114 }
115
116 /////////////////
117 /////////////////
118
119
120 ////////////////
121 // Destructor //
122 ////////////////
123
124 PaciSolver::~PaciSolver() = default;
125
126 ////////////////
127 ////////////////
128
129
130 //////////////////////////////////////////////////////////////
131 // ComputeRHS: useless in the non Spontaneous model (cvode) //
132 //////////////////////////////////////////////////////////////
133
134 void PaciSolver::computeRHS() {
135
136 #ifndef FELISCE_WITH_SUNDIALS
137 //Only spontaneous model
138 double& dt = m_fstransient->timeStep;
139
140 m_bdf.computeRHSTime(dt, m_vecRHS);
141
142
143 felInt pos;
144 double value_uExtrap,value_Cai,value_df1,value_fCa,value_g;
145
146
147 std::vector<double> values_RHS;
148 std::vector<double> valuem_solEDO;
149
150
151 values_RHS.resize(42);
152 valuem_solEDO.resize(42);
153
154
155 values_RHS.clear();
156 valuem_solEDO.clear();
157
158 int& numIt = m_fstransient->iteration;
159
160 for (felInt i = 0; i < m_size; i++) {
161 ISLocalToGlobalMappingApply(m_localDofToGlobalDof,1,&i,&pos);
162 m_uExtrap.getValues(1,&pos,&value_uExtrap);
163
164 //Initialization
165 m_vecSolEDO[4].getValues(1,&pos,&value_fCa);
166 m_vecSolEDO[13].getValues(1,&pos,&value_g);
167 m_vecSolEDO[14].getValues(1,&pos,&value_Cai);
168 m_vecSolEDO[17].getValues(1,&pos,&value_df1);
169
170 for(int iEDO=0; iEDO<42; iEDO++) {
171 m_vecSolEDO[iEDO].getValues(1,&pos,&valuem_solEDO[iEDO]);//value_RHS = _RHS(i)
172 }
173
174 if(numIt == 1) {
175 value_fCa = 1.;
176 value_g = 1.;
177 value_Cai = 0.0002;
178 value_df1 = 0.;
179 }
180
181 double hinf,tauh;
182 PaciSolver::hgate(hinf,tauh,value_uExtrap);
183
184 double jinf,tauj;
185 PaciSolver::jgate(jinf,tauj,value_uExtrap);
186
187 double minf,taum;
188 PaciSolver::mgate(minf,taum,value_uExtrap);
189
190 double dinf,taud;
191 PaciSolver::dgate(dinf,taud,value_uExtrap);
192
193 double fCainf,taufCa,constfCa;
194 PaciSolver::fcagate(fCainf,taufCa,constfCa,value_uExtrap,value_Cai,value_fCa);
195
196 double f1inf,tauf1;
197 PaciSolver::f1gate(f1inf,tauf1,value_uExtrap,value_df1,value_Cai);
198
199 double f2inf,tauf2;
200 PaciSolver::f2gate(f2inf,tauf2,value_uExtrap);
201
202 double rinf,taur;
203 PaciSolver::rgate(rinf,taur,value_uExtrap);
204
205 double qinf,tauq;
206 PaciSolver::qgate(qinf,tauq,value_uExtrap);
207
208 double xr1inf,tauxr1;
209 PaciSolver::xr1gate(xr1inf,tauxr1,value_uExtrap);
210
211 double xr2inf,tauxr2;
212 PaciSolver::xr2gate(xr2inf,tauxr2,value_uExtrap);
213
214 double xsinf,tauxs;
215 PaciSolver::xsgate(xsinf,tauxs,value_uExtrap);
216
217 double xfinf,tauf;
218 PaciSolver::xfgate(xfinf,tauf,value_uExtrap);
219
220 double ginf,taug,constg;
221 PaciSolver::ggate(ginf,taug,constg,value_uExtrap,value_Cai,value_g);
222
223
224 //! For non spontaneous AP
225 double minfORd,taumORd;
226 PaciSolver::mgateORd(minfORd, taumORd,value_uExtrap);
227
228 double jinfORd,taujORd;
229 PaciSolver::jgateORd(jinfORd, taujORd,value_uExtrap);
230
231 double hslowinf,tauhslow;
232 PaciSolver::hslowgateORd(hslowinf, tauhslow,value_uExtrap);
233
234 double hfastinf,tauhfast;
235 PaciSolver::hfastgateORd(hfastinf, tauhfast,value_uExtrap);
236
237 double hlinf,tauhl;
238 PaciSolver::hlgateORd(hlinf, tauhl,value_uExtrap);
239
240 double mlinf,tauml;
241 PaciSolver::mlgateORd(mlinf, tauml,value_uExtrap);
242
243
244 //RHS:
245 values_RHS[0]=hinf/tauh;
246 values_RHS[1]=jinf/tauj;
247 values_RHS[2]=minf/taum;
248 values_RHS[3]=dinf/taud;
249 values_RHS[4]=constfCa*fCainf/taufCa;
250 values_RHS[5]=f1inf/tauf1;
251 values_RHS[6]=f2inf/tauf2;
252 values_RHS[7]=rinf/taur;
253 values_RHS[8]=qinf/tauq;
254 values_RHS[9]=xr1inf/tauxr1;
255 values_RHS[10]=xr2inf/tauxr2;
256 values_RHS[11]=xsinf/tauxs;
257 values_RHS[12]=xfinf/tauf;
258 values_RHS[13]=constg*ginf/taug;
259 values_RHS[14]=0.;
260 values_RHS[15]=0.;
261 values_RHS[16]=0.;
262 values_RHS[17]=0.;
263 values_RHS[18]=0.;
264 values_RHS[19]=0.;
265 values_RHS[20]=0.;
266 values_RHS[21]=0.;
267 values_RHS[22]=0.;
268 values_RHS[23]=0.;
269 values_RHS[24]=0.;
270 values_RHS[25]=0.;
271 values_RHS[26]=0.;
272 values_RHS[27]=0.;
273 values_RHS[28]=0.;
274 values_RHS[29]=0.;
275 values_RHS[30]=0.;
276 values_RHS[31]=0.;
277 values_RHS[32]=0.;
278 values_RHS[33]=0.;
279 values_RHS[34]=0.;
280 values_RHS[35]=0.;
281
282
283 //! For non spontaneous AP: ORd
284
285 values_RHS[36]=minfORd/taumORd;
286 values_RHS[37]=jinfORd/taujORd;
287 values_RHS[38]=hslowinf/tauhslow;
288 values_RHS[39]=hfastinf/tauhfast;
289 values_RHS[40]=hlinf/tauhl;
290 values_RHS[41]=mlinf/tauml;
291
292 for (std::size_t index = 0 ; index < 42 ; ++index)
293 m_vecRHS[index].setValue(pos,values_RHS[index], ADD_VALUES);
294
295
296 }
297
298
299 for(int index =0 ; index < 42 ; ++index) {
300 m_vecRHS[index].assembly();
301 }
302
303 #endif
304
305 }
306
307
308 void PaciSolver::solveEDO() {
309
310
311 //################//
312 //Ionic parameters//
313 //################//
314
315 const double Cm = 98.7109;
316 const double Vc = 8800.;
317 const double Vsr = 583.73;
318 const double gNa = 3.6712302e3;
319 const double PNaK = 1.841424;
320 const double KNaCa = 4900.;
321 const double Vmaxup = 0.56064;
322
323
324 //##################
325 //##################
326
327
328
329 double value_uExtrap;
330 std::vector<double> values_RHS;
331 std::vector<double> valuem_solEDO;
332
333 values_RHS.resize(42);
334 valuem_solEDO.resize(42);
335
336 values_RHS.clear();
337 valuem_solEDO.clear();
338
339 double& dt = m_fstransient->timeStep;
340 double& coeffDeriv = m_bdf.coeffDeriv0();
341
342
343 double betaEDOh,betaEDOj,betaEDOm,betaEDOd,betaEDOfca,betaEDOf1,betaEDOf2,betaEDOr,betaEDOq,betaEDOxr1,betaEDOxr2,betaEDOxs,betaEDOxf,betaEDOg,betaEDOcai,betaEDOcasr,betaEDOnai;
344 double Cai,fca,df1,g,Casr,Nai,f1;
345
346 int& numIt = m_fstransient->iteration;
347 felInt pos;
348
349 #ifdef FELISCE_WITH_SUNDIALS
350
351 if(numIt == 1) { //resizes
352 M_userData.M_u_extrap.resize(m_size);
353 M_userData.value_df1.resize(m_size);
354 M_userData.vINaCa.resize(m_size);
355 M_userData.vIPCa.resize(m_size);
356 M_userData.vIbCa.resize(m_size);
357 M_userData.vENa.resize(m_size);
358 M_userData.vEKs.resize(m_size);
359 M_userData.vECa.resize(m_size);
360 M_userData.vINa.resize(m_size);
361 M_userData.vICaL.resize(m_size);
362 M_userData.vINaK.resize(m_size);
363 M_userData.vIrel.resize(m_size);
364 M_userData.vIup.resize(m_size);
365 M_userData.vIleak.resize(m_size);
366 M_userData.vIbNa.resize(m_size);
367 cvode_mem.resize(m_size);
368 initvalue.resize(m_size);
369 abstol.resize(m_size);
370 }
371
372 #endif
373
374 for (felInt i = 0; i < m_size; i++) {
375
376 ISLocalToGlobalMappingApply(m_localDofToGlobalDof,1,&i,&pos);
377 m_uExtrap.getValues(1,&pos,&value_uExtrap);//value_uExtrap = m_uExtrap(i)
378
379
380
381 #ifdef FELISCE_WITH_SUNDIALS
382
383 double time = m_fstransient->time;
384 int flag;
385
386 M_userData.M_u_extrap[i] = value_uExtrap;
387 M_userData.pos = i;
388
389 if(numIt == 1) { //1st iteration --> initializations for each Dof
390
391
392 M_userData.value_df1[i] = 0.;
393
394 cvode_mem[i] = NULL;
395 initvalue[i] = N_VNew_Serial(23);
396 abstol[i] = N_VNew_Serial(23);
397
398
399 Ith(initvalue[i],1) = Y075;//h
400 Ith(initvalue[i],2) = Y075;//j
401 Ith(initvalue[i],3) = Y0bis;//m
402 Ith(initvalue[i],4) = Y0bis;//d
403 Ith(initvalue[i],5) = Y1;//fca
404 Ith(initvalue[i],6) = Y1;//f1
405 Ith(initvalue[i],7) = Y1;//f2
406 Ith(initvalue[i],8) = Y0bis;//r
407 Ith(initvalue[i],9) = Y1;//q
408 Ith(initvalue[i],10) = Y0bis;//xr1
409 Ith(initvalue[i],11) = Y1;//xr2
410 Ith(initvalue[i],12) = Y0bis;//xs
411 Ith(initvalue[i],13) = Y01;//xf
412 Ith(initvalue[i],14) = Y1;//g
413 Ith(initvalue[i],15) = Ycai;//Cai
414 Ith(initvalue[i],16) = Ycasr;//Casr
415 Ith(initvalue[i],17) = Ynai;//Nai
416
417
418 Ith(initvalue[i],18) = YmORd;//minfORd
419 Ith(initvalue[i],19) = YjORd;//jinfORd
420 Ith(initvalue[i],20) = Yhslow;//hslow
421 Ith(initvalue[i],21) = Yhfast;//hfast
422 Ith(initvalue[i],22) = Yhl;//hl
423 Ith(initvalue[i],23) = Yml;//ml
424
425
426 Ith(abstol[i],1) = ATOL4;
427 Ith(abstol[i],2) = ATOL4;
428 Ith(abstol[i],3) = ATOL4;
429 Ith(abstol[i],4) = ATOL4;
430 Ith(abstol[i],5) = ATOL4;
431 Ith(abstol[i],6) = ATOL4;
432 Ith(abstol[i],7) = ATOL4;
433 Ith(abstol[i],8) = ATOL4;
434 Ith(abstol[i],9) = ATOL4;
435 Ith(abstol[i],10) = ATOL4;
436 Ith(abstol[i],11) = ATOL4;
437 Ith(abstol[i],12) = ATOL4;
438 Ith(abstol[i],13) = ATOL4;
439 Ith(abstol[i],14) = ATOL4;
440 Ith(abstol[i],15) = ATOL4;
441 Ith(abstol[i],16) = ATOL4;
442 Ith(abstol[i],17) = ATOL4;
443
444 Ith(abstol[i],18) = ATOL4;
445 Ith(abstol[i],19) = ATOL4;
446 Ith(abstol[i],20) = ATOL4;
447 Ith(abstol[i],21) = ATOL4;
448 Ith(abstol[i],22) = ATOL4;
449 Ith(abstol[i],23) = ATOL4;
450
451 cvode_mem[i] = CVodeCreate(CV_BDF,CV_NEWTON);//CV_BDF or CV_ADAMS and CV_NEWTON or CV_FUNCTIONAL || (CV_BDF,CV_NEWTON) for stiff pb
452
453 datatest = &M_userData;
454 flag = CVodeSetUserData(cvode_mem[i],datatest);
455 flag = CVodeInit(cvode_mem[i],M_f,0.0,initvalue[i]);
456
457
458 //Tolerances************
459 //
460 flag = CVodeSVtolerances(cvode_mem[i],RTOL,abstol[i]);
461 //flag = CVodeWFtolerances(cvode_mem, ewt);
462
463 //**********************
464
465
466 //Optional inputs********************
467 //
468 //flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
469 //flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS);
470 //flag = CVodeRootInit(cvode_mem,2,g);//Optional
471 //
472 //************************************
473
474 flag = CVDense(cvode_mem[i],23);//--->if ORd? else 17?
475
476
477 //Optional inputs******************
478 //
479
480 //flag = CVodeSetMaxNumSteps(cvode_mem[i],500);//default: 500
481 //flag = CVodeSetMaxNumSteps(cvode_mem[i],1000);//ok!
482 flag = CVodeSetMaxNumSteps(cvode_mem[i],1000);//default: 500
483
484
485 flag = CVodeSetMaxStep(cvode_mem[i],0.1);//if 0: inf
486
487 //---------------
488 //
489 //For more informations, print flag
490 //
491 // If flag = 0: SUCCESS
492 // If flag = 1: TSTOP_RETURN
493 //....see cvode.h
494
495
496 realtype tout;
497 int flag;
498
499
500 flag = CVode(cvode_mem[i], time, initvalue[i], &tout, CV_NORMAL);
501
502
503 if ( flag != CV_SUCCESS ) {
504 std::cout << "CVODE solver failed " << std::endl;
505 exit(1);
506 }
507
508 } else {
509
510 double df1;
511 m_vecSolEDO[17].getValues(1,&pos,&df1);
512 M_userData.value_df1[i] = df1;
513 double f1;
514 m_vecSolEDO[5].getValues(1,&pos,&f1);
515
516 realtype tout;
517 int flag;
518
519
520 flag = CVode(cvode_mem[i], time, initvalue[i], &tout, CV_NORMAL);
521
522 if ( flag != CV_SUCCESS ) {
523 std::cout << "CVODE solver failed " << std::endl;
524 exit(1);
525 }
526 }
527
528 for(int j=0; j<17; j++) {
529 valuem_solEDO[j] = Ith (initvalue[i],j+1);
530 }
531
532 valuem_solEDO[17] = (valuem_solEDO[5]-f1)/dt;
533 valuem_solEDO[18] = M_userData.vINaCa[i];
534 valuem_solEDO[19] = M_userData.vIPCa[i];
535 valuem_solEDO[20] = M_userData.vIbCa[i];
536 valuem_solEDO[21] = M_userData.vENa[i];
537 valuem_solEDO[22] = M_userData.vEKs[i];
538 valuem_solEDO[23] = M_userData.vECa[i];
539 valuem_solEDO[24] = M_userData.vINa[i];
540 valuem_solEDO[25] = M_userData.vICaL[i];
541 valuem_solEDO[31] = M_userData.vINaK[i];
542 valuem_solEDO[32] = M_userData.vIrel[i];
543 valuem_solEDO[33] = M_userData.vIup[i];
544 valuem_solEDO[34] = M_userData.vIleak[i];
545 valuem_solEDO[35] = M_userData.vIbNa[i];
546
547 for(int j=0; j<6; j++) {
548 valuem_solEDO[36+j] = Ith (initvalue[i],j+18);
549 }
550
551
552
553 #else
554
555 for(int iEDO=0; iEDO<36; iEDO++)
556 m_vecRHS[iEDO].getValues(1,&pos,&values_RHS[iEDO]);//value_RHS
557
558
559 m_vecSolEDO[4].getValues(1,&pos,&fca);
560 m_vecSolEDO[5].getValues(1,&pos,&f1);
561 m_vecSolEDO[13].getValues(1,&pos,&g);
562 m_vecSolEDO[14].getValues(1,&pos,&Cai);
563 m_vecSolEDO[15].getValues(1,&pos,&Casr);
564 m_vecSolEDO[16].getValues(1,&pos,&Nai);
565 m_vecSolEDO[17].getValues(1,&pos,&df1);
566
567
568 if(numIt==1) {
569 fca = 1.;
570 g = 1.;
571 Cai = 0.0002;
572 Casr = 0.3;
573 Nai = 10.;
574 f1 = 1.;
575 df1 = 0.;
576 }
577
578 double hinf,tauh;
579 PaciSolver::hgate(hinf,tauh,value_uExtrap);
580
581 double jinf,tauj;
582 PaciSolver::jgate(jinf,tauj,value_uExtrap);
583
584 double minf,taum;
585 PaciSolver::mgate(minf,taum,value_uExtrap);
586
587 double dinf,taud;
588 PaciSolver::dgate(dinf,taud,value_uExtrap);
589
590 double fCainf,taufCa,constfCa;
591 PaciSolver::fcagate(fCainf,taufCa,constfCa,value_uExtrap,Cai,fca);
592 double f1inf,tauf1;
593 PaciSolver::f1gate(f1inf,tauf1,value_uExtrap,df1,Cai);
594
595 double f2inf,tauf2;
596 PaciSolver::f2gate(f2inf,tauf2,value_uExtrap);
597
598 double rinf,taur;
599 PaciSolver::rgate(rinf,taur,value_uExtrap);
600
601 double qinf,tauq;
602 PaciSolver::qgate(qinf,tauq,value_uExtrap);
603
604 double xr1inf,tauxr1;
605 PaciSolver::xr1gate(xr1inf,tauxr1,value_uExtrap);
606
607 double xr2inf,tauxr2;
608 PaciSolver::xr2gate(xr2inf,tauxr2,value_uExtrap);
609
610 double xsinf,tauxs;
611 PaciSolver::xsgate(xsinf,tauxs,value_uExtrap);
612
613 double xfinf,tauf;
614 PaciSolver::xfgate(xfinf,tauf,value_uExtrap);
615
616 double ginf,taug,constg;
617 PaciSolver::ggate(ginf,taug,constg,value_uExtrap,Cai,g);
618
619
620
621 //! For non spontaneous AP
622 double minfORd,taumORd;
623 PaciSolver::mgateORd(minfORd, taumORd,value_uExtrap);
624
625 double jinfORd,taujORd;
626 PaciSolver::jgateORd(jinfORd, taujORd,value_uExtrap);
627
628 double hslowinf,tauhslow;
629 PaciSolver::hslowgateORd(hslowinf, tauhslow,value_uExtrap);
630
631 double hfastinf,tauhfast;
632 PaciSolver::hfastgateORd(hfastinf, tauhfast,value_uExtrap);
633
634 double hlinf,tauhl;
635 PaciSolver::hlgateORd(hlinf, tauhl,value_uExtrap);
636
637 double mlinf,tauml;
638 PaciSolver::mlgateORd(mlinf, tauml,value_uExtrap);
639
640
641
642
643 //h
644 betaEDOh = coeffDeriv/dt+1./tauh;
645 valuem_solEDO[0] = values_RHS[0]/betaEDOh;
646
647 //j
648 betaEDOj = coeffDeriv/dt+1./tauj;
649 valuem_solEDO[1] = values_RHS[1]/betaEDOj;
650
651 //m
652 betaEDOm = coeffDeriv/dt+1./taum;
653 valuem_solEDO[2] = values_RHS[2]/betaEDOm;
654
655 //d
656 betaEDOd = coeffDeriv/dt+1./taud;
657 valuem_solEDO[3] = values_RHS[3]/betaEDOd;
658
659 //fCa
660 betaEDOfca = coeffDeriv/dt+constfCa/taufCa;
661 valuem_solEDO[4] = values_RHS[4]/betaEDOfca;
662
663 //f1
664 betaEDOf1 = coeffDeriv/dt+1./tauf1;
665 valuem_solEDO[5] = values_RHS[5]/betaEDOf1;
666
667 //f2
668 betaEDOf2 = coeffDeriv/dt+1./tauf2;
669 valuem_solEDO[6] = values_RHS[6]/betaEDOf2;
670
671 //r
672 betaEDOr = coeffDeriv/dt+1./taur;
673 valuem_solEDO[7] = values_RHS[7]/betaEDOr;
674
675 //q
676 betaEDOq = coeffDeriv/dt+1./tauq;
677 valuem_solEDO[8] = values_RHS[8]/betaEDOq;
678
679 //xr1
680 betaEDOxr1 = coeffDeriv/dt+1./tauxr1;
681 valuem_solEDO[9] = values_RHS[9]/betaEDOxr1;
682
683 //xr2
684 betaEDOxr2 = coeffDeriv/dt+1./tauxr2;
685 valuem_solEDO[10] = values_RHS[10]/betaEDOxr2;
686
687 //xs
688 betaEDOxs = coeffDeriv/dt+1./tauxs;
689 valuem_solEDO[11] = values_RHS[11]/betaEDOxs;
690
691 //xf
692 betaEDOxf = coeffDeriv/dt+1./tauf;
693 valuem_solEDO[12] = values_RHS[12]/betaEDOxf;
694
695 //g
696 betaEDOg = coeffDeriv/dt+constg/taug;
697 valuem_solEDO[13] = values_RHS[13]/betaEDOg;
698
699
700
701 //! For non spontaneous AP
702
703 //mORd
704 const double betaEDOmORd = coeffDeriv/dt+1./taumORd;
705 valuem_solEDO[18] = values_RHS[18]/betaEDOmORd;
706
707 //jORd
708 const double betaEDOjORd = coeffDeriv/dt+1./taujORd;
709 valuem_solEDO[19] = values_RHS[19]/betaEDOjORd;
710
711 //hslow
712 const double betaEDOhslow = coeffDeriv/dt+1./tauhslow;
713 valuem_solEDO[20] = values_RHS[20]/betaEDOhslow;
714
715 //hfast
716 const double betaEDOhfast = coeffDeriv/dt+1./tauhfast;
717 valuem_solEDO[21] = values_RHS[21]/betaEDOhfast;
718
719 //hl
720 const double betaEDOhl = coeffDeriv/dt+constfCa/tauhl;
721 valuem_solEDO[22] = values_RHS[22]/betaEDOhl;
722
723 //ml
724 const double betaEDOml = coeffDeriv/dt+1./tauml;
725 valuem_solEDO[23] = values_RHS[23]/betaEDOml;
726
727
728
729 //Calcul des courants pour les concentrations
730 double value_iup = Vmaxup/(1.+std::pow(Kup/Cai,2));
731 double value_ileak = Vleak*(Casr-Cai);
732
733
734 double value_irel = (crel+(arel*std::pow(Casr,2))/(std::pow(brel,2)+std::pow(Casr,2)))*valuem_solEDO[3]*valuem_solEDO[13];
735 value_irel = value_irel*0.0411;//ventricular
736 //Atrial
737 //value_irel = value_irel*0.0556;
738
739
740
741 //iNaK
742 const double num1 = PNaK*Ko*Nai/(Ko+Kmk);
743 const double num2 = num1/(Nai+KmNa);
744 double value_iNaK = num2/(1.+0.1245*std::exp(-0.1*value_uExtrap*F/(R*T))+0.0353*std::exp(-value_uExtrap*F/(R*T)));
745
746 //iNaCa
747 const double prodnum1 = std::pow(Nai,3)*Cao*std::exp(gamma_value*value_uExtrap*F/(R*T));
748 const double prodnum2 = alpha*std::pow(Nao,3)*Cai*std::exp((gamma_value-1.)*value_uExtrap*F/(R*T));
749 const double numINaCa = KNaCa*(prodnum1-prodnum2);
750 const double prodden1 = std::pow(KmNai,3)+std::pow(Nao,3);
751 const double prodden2 = KmCa+Cao;
752 const double prodden3 = 1.+Ksat*std::exp((gamma_value-1.)*value_uExtrap*F/(R*T));
753 const double denINaCa = prodden1*prodden2*prodden3;
754 double value_iNaCa = numINaCa/denINaCa;
755
756 valuem_solEDO[18] = value_iNaCa;
757
758 //iCaL
759 const double term1 = (gCaL*4.*value_uExtrap*F*F)/(R*T);
760 const double term2 = (Cai*std::exp((2.*value_uExtrap*F)/(R*T))-0.341*Cao)/(std::expm1((2.*value_uExtrap*F)/(R*T)));
761
762 double value_iCaL = term1*term2*valuem_solEDO[3]*valuem_solEDO[5]*valuem_solEDO[6]*valuem_solEDO[4];
763
764
765 //ipCa
766 double value_iPCa = gpCa*Cai/(Cai+KpCa);
767
768 valuem_solEDO[19] = value_iPCa;
769
770
771 const double ENa = (R*T/F)*std::log(Nao/Nai);
772 const double ECa = 0.5*(R*T/F)*std::log(Cao/Cai);
773
774
775
776 //iNa
777 const double m3 = valuem_solEDO[2]*valuem_solEDO[2]*valuem_solEDO[2];
778 double value_iNa=gNa*m3*valuem_solEDO[0]*valuem_solEDO[1]*(value_uExtrap-ENa);
779
780 //ibNa-ibCa
781 double value_ibNa=gbNa*(value_uExtrap-ENa);
782 double value_ibCa=gbCa*(value_uExtrap-ECa);
783
784 valuem_solEDO[20] = value_ibCa;
785
786 double Caibufc = 1./(1.+(Bufc*Kbufc)/std::pow(Cai+Kbufc,2));
787 double Casrbufsr = 1./(1.+(Bufsr*Kbufsr)/std::pow(Casr+Kbufsr,2));
788
789
790 //Cai
791 const double valCai = Caibufc*(value_ileak-value_iup+value_irel-Cm*(value_iCaL+value_ibCa+value_iPCa-2.*value_iNaCa)/(2.*Vc*F));
792
793 //Casr
794 const double valCasr = (Casrbufsr*Vc)*(value_iup-(value_irel+value_ileak))/Vsr;
795
796 //Nai
797 const double valNai = -Cm*(value_iNa+value_ibNa+3.*value_iNaK+3.*value_iNaCa)/(F*Vc);
798
799
800 //Cai
801 betaEDOcai = coeffDeriv/dt;
802 values_RHS[14] += valCai;
803 valuem_solEDO[14] = values_RHS[14]/betaEDOcai;
804
805 //Casr
806 betaEDOcasr = coeffDeriv/dt;
807 values_RHS[15] += valCasr;
808 valuem_solEDO[15] = values_RHS[15]/betaEDOcasr;
809
810 //Nai
811 betaEDOnai = coeffDeriv/dt;
812 values_RHS[16] += valNai;
813 valuem_solEDO[16] = values_RHS[16]/betaEDOnai;
814
815
816 //Calcul de df1
817 valuem_solEDO[17] = (valuem_solEDO[5]-f1)/dt;
818
819
820 //Calcul de ENa EKs et ECa
821 valuem_solEDO[21] = (R*T/F)*std::log(Nao/Nai);
822 valuem_solEDO[22] = (R*T/F)*std::log((Ko+Pkna*Nao)/(Ki+Pkna*Nai));
823 valuem_solEDO[23] = 0.5*(R*T/F)*std::log(Cao/Cai);
824
825
826
827 #endif
828
829
830 for(int iEDO=0; iEDO<17; iEDO++) {
831 m_vecSolEDO[iEDO].setValue(pos,valuem_solEDO[iEDO], INSERT_VALUES);
832 }
833
834 m_vecSolEDO[17].setValue(pos,valuem_solEDO[17], INSERT_VALUES);
835 m_vecSolEDO[18].setValue(pos,valuem_solEDO[18], INSERT_VALUES);
836 m_vecSolEDO[19].setValue(pos,valuem_solEDO[19], INSERT_VALUES);
837 m_vecSolEDO[20].setValue(pos,valuem_solEDO[20], INSERT_VALUES);
838
839
840 //ENa EKs ECa
841 m_vecSolEDO[21].setValue(pos,valuem_solEDO[21], INSERT_VALUES);
842 m_vecSolEDO[22].setValue(pos,valuem_solEDO[22], INSERT_VALUES);
843 m_vecSolEDO[23].setValue(pos,valuem_solEDO[23], INSERT_VALUES);
844
845
846
847 //Currennts Iup,Ileak,Irel,INaK,INaCa,ICaL,IpCa,INa,IbNa,IbCa
848
849 #ifdef FELISCE_WITH_SUNDIALS
850 m_vecSolEDO[24].setValue(pos,valuem_solEDO[24], INSERT_VALUES);
851 m_vecSolEDO[25].setValue(pos,valuem_solEDO[25], INSERT_VALUES);
852 m_vecSolEDO[31].setValue(pos,valuem_solEDO[31], INSERT_VALUES);
853 m_vecSolEDO[32].setValue(pos,valuem_solEDO[32], INSERT_VALUES);
854 m_vecSolEDO[33].setValue(pos,valuem_solEDO[33], INSERT_VALUES);
855 m_vecSolEDO[34].setValue(pos,valuem_solEDO[34], INSERT_VALUES);
856 m_vecSolEDO[35].setValue(pos,valuem_solEDO[35], INSERT_VALUES);
857
858 //! For non spontaneous AP
859 m_vecSolEDO[36].setValue(pos,valuem_solEDO[18], INSERT_VALUES);
860 m_vecSolEDO[37].setValue(pos,valuem_solEDO[19], INSERT_VALUES);
861 m_vecSolEDO[38].setValue(pos,valuem_solEDO[20], INSERT_VALUES);
862 m_vecSolEDO[39].setValue(pos,valuem_solEDO[21], INSERT_VALUES);
863 m_vecSolEDO[40].setValue(pos,valuem_solEDO[22], INSERT_VALUES);
864 m_vecSolEDO[41].setValue(pos,valuem_solEDO[23], INSERT_VALUES);
865
866 #else
867 m_vecSolEDO[24].setValue(pos,value_iNa, INSERT_VALUES);
868 m_vecSolEDO[25].setValue(pos,value_iCaL, INSERT_VALUES);
869 m_vecSolEDO[31].setValue(pos,value_iNaK, INSERT_VALUES);
870 m_vecSolEDO[32].setValue(pos,value_irel, INSERT_VALUES);
871 m_vecSolEDO[33].setValue(pos,value_iup, INSERT_VALUES);
872 m_vecSolEDO[34].setValue(pos,value_ileak, INSERT_VALUES);
873 m_vecSolEDO[35].setValue(pos,value_ibNa, INSERT_VALUES);
874 #endif
875
876 }
877
878 for (std::size_t index = 0 ; index < 42; ++index)
879 m_vecSolEDO[index].assembly();
880
881
882 }
883
884
885
886
887
888 void PaciSolver::computeIon() {
889
890 //################//
891 //Ionic parameters//
892 //################//
893
894 const double gNa = 3.6712302e3;
895 const double gto = 29.9038;
896 const double gK1 = 28.1492;
897 const double PNaK = 1.841424;
898 const double KNaCa = 4900.;
899
900 //##################
901 //##################
902
903 //*******************************************************//
904 //Declaration des variables: courants et concentrations
905 //*******************************************************//
906
907 double value_ion;
908 double value_uExtrap;
909
910 double value_iCaL;
911 double value_iPCa;
912 double value_iNaCa;
913 double value_iNaK;
914 double value_ik1;
915 double value_ito;
916 double value_ikr;
917 double value_iks;
918 double value_if;
919 double value_iNa;
920
921 //gates:
922 std::vector<double> valuem_solEDO;
923 valuem_solEDO.resize(42);
924
925
926 valuem_solEDO.clear();
927
928 felInt pos;
929
930 //*****************************************//
931 //******** Calculation ******************//
932 //*****************************************//
933
934 for(felInt i = 0 ; i < m_size; i++) {
935
936
937 ISLocalToGlobalMappingApply(m_localDofToGlobalDof,1,&i,&pos);
938 m_uExtrap.getValues(1,&pos,&value_uExtrap);//value_uExtrap = m_uExtrap(i)
939
940 for(int iEDO=0; iEDO<42; iEDO++) {
941 m_vecSolEDO[iEDO].getValues(1,&pos,&valuem_solEDO[iEDO]);
942 }
943
944
945 //******************************************
946 //Reversal potential: Nernst equation
947 //
948 const double Ef = -17e-3; //[mV]
949 const double EK = (R*T/F)*std::log(Ko/Ki);
950 const double ENa = valuem_solEDO[21];
951 const double EKs = valuem_solEDO[22];
952 const double ECa = valuem_solEDO[23];
953
954 //******************************************
955 //******************************************
956
957
958
959 //*************
960 //Na+ current
961 //
962 const double m3sponta = valuem_solEDO[2]*valuem_solEDO[2]*valuem_solEDO[2];
963 //-------------------------------------
964 //value_iNa=gNa*m3*valuem_solEDO[0]*valuem_solEDO[1]*(value_uExtrap-ENa);
965 //-------------------------------------
966
967 //! For non spontaneous AP
968
969 const double hORd = 0.99*valuem_solEDO[39]+0.01*valuem_solEDO[38];
970 const double m3 = valuem_solEDO[36]*valuem_solEDO[36]*valuem_solEDO[36];
971 const double iNafast = 75.*(value_uExtrap-ENa)*m3*valuem_solEDO[37]*hORd;
972 const double iNalate = 0.0075*(value_uExtrap-ENa)*valuem_solEDO[41]*valuem_solEDO[40];
973
974 if(FelisceParam::instance().spontaneous == false) {
975 value_iNa = iNafast+iNalate;
976 } else {
977 value_iNa=gNa*m3sponta*valuem_solEDO[0]*valuem_solEDO[1]*(value_uExtrap-ENa);
978 }
979
980
981 //*********************
982 //L-Type Ca2+ current
983 //
984 const double term1 = (gCaL*4.*value_uExtrap*F*F)/(R*T);
985 const double term2 = (valuem_solEDO[14]*std::exp((2.*value_uExtrap*F)/(R*T))-0.341*Cao)/(std::expm1((2.*value_uExtrap*F)/(R*T)));
986 //------------------------------------------
987 value_iCaL = term1*term2*valuem_solEDO[3]*valuem_solEDO[5]*valuem_solEDO[6]*valuem_solEDO[4];
988 //------------------------------------------
989
990
991
992 //***************************
993 //Transient outward current
994 //---------------------------------
995 value_ito = gto*valuem_solEDO[7]*valuem_solEDO[8]*(value_uExtrap-EK);
996 //---------------------------------
997
998 //************************************
999 //Rapid delayed rectifier K+ current
1000 //--------------------------------------------------
1001 value_ikr = gKr*std::sqrt(Ko/5.4)*valuem_solEDO[9]*valuem_solEDO[10]*(value_uExtrap-EK);
1002 //--------------------------------------------------
1003
1004
1005 //***********************************
1006 //Slow delayed rectifier K+ current
1007 //--------------------------------------------------------------------------
1008 value_iks = gKs*std::pow(valuem_solEDO[11],2)*(1.+0.6/(1.+std::pow(3.8e-5/valuem_solEDO[14],1.4)))*(value_uExtrap-EKs);
1009 //--------------------------------------------------------------------------
1010
1011
1012 //*****************************
1013 //Inward rectifier K+ current
1014 //
1015 const double alphak1 = 3.91/(1.+std::exp(1000.*0.5942*(value_uExtrap-EK-200e-3)));
1016 const double betak1 = (-1.509*std::exp(1000.*0.0002*(value_uExtrap-EK+100e-3))+std::exp(1000.*0.5886*(value_uExtrap-EK-10e-3)))/(1.+std::exp(1000.*0.4547*(value_uExtrap-EK)));
1017 const double xK1inf = alphak1/(alphak1+betak1);
1018 //-------------------------------------------------
1019 value_ik1 = gK1*xK1inf*std::sqrt(Ko/5.4)*(value_uExtrap-EK);
1020 //-------------------------------------------------
1021
1022
1023 //*******************************************
1024 //Hyperpolarization activated funny current
1025 //------------------------------
1026 value_if = gf*valuem_solEDO[12]*(value_uExtrap-Ef);
1027 //------------------------------
1028
1029
1030
1031 //********************
1032 //Na+K+ pump current
1033 //
1034 const double num1 = PNaK*Ko*valuem_solEDO[16]/(Ko+Kmk);
1035 const double num2 = num1/(valuem_solEDO[16]+KmNa);
1036 //--------------------------------------------------------------------------------
1037 value_iNaK = num2/(1.+0.1245*std::exp(-0.1*value_uExtrap*F/(R*T))+0.0353*std::exp(-value_uExtrap*F/(R*T)));
1038 //--------------------------------------------------------------------------------
1039
1040
1041
1042 //***************************
1043 //Na+Ca2+ exchanger current
1044 //
1045 const double prodnum1 = std::pow(valuem_solEDO[16],3)*Cao*std::exp(gamma_value*value_uExtrap*F/(R*T));
1046 const double prodnum2 = alpha*std::pow(Nao,3)*valuem_solEDO[14]*std::exp((gamma_value-1.)*value_uExtrap*F/(R*T));
1047 const double numINaCa = KNaCa*(prodnum1-prodnum2);
1048 const double prodden1 = std::pow(KmNai,3)+std::pow(Nao,3);
1049 const double prodden2 = KmCa+Cao;
1050 const double prodden3 = 1.+Ksat*std::exp((gamma_value-1.)*value_uExtrap*F/(R*T));
1051 const double denINaCa = prodden1*prodden2*prodden3;
1052 //-------------------------------
1053 value_iNaCa = numINaCa/denINaCa;
1054 //-------------------------------
1055
1056
1057
1058 //*******************
1059 //Ca2+ pump current
1060 //--------------------------------------
1061 value_iPCa = gpCa*valuem_solEDO[14]/(valuem_solEDO[14]+KpCa);
1062 //--------------------------------------
1063
1064
1065
1066 //*********************
1067 //Background currents
1068 //--------------------------------------
1069 double value_ibNa=gbNa*(value_uExtrap-ENa);
1070 double value_ibCa=gbCa*(value_uExtrap-ECa);
1071 //--------------------------------------
1072
1073
1074 //********************
1075 //Membrane potential
1076 //********************
1077
1078 value_iNaCa = valuem_solEDO[18];
1079 value_iPCa = valuem_solEDO[19];
1080 value_ibCa = valuem_solEDO[20];
1081
1082 //Currents Ito,IKr,IKs,IK1,If
1083 m_vecSolEDO[26].setValue(pos,value_ito, INSERT_VALUES);
1084 m_vecSolEDO[27].setValue(pos,value_ikr, INSERT_VALUES);
1085 m_vecSolEDO[28].setValue(pos,value_iks, INSERT_VALUES);
1086 m_vecSolEDO[29].setValue(pos,value_ik1, INSERT_VALUES);
1087 m_vecSolEDO[30].setValue(pos,value_if, INSERT_VALUES);
1088
1089 value_ion = -(value_ik1+value_ito+value_ikr+value_iks+value_iCaL+value_iNaK+value_iNa+value_iNaCa+value_iPCa+value_if+value_ibNa+value_ibCa);
1090 m_ion.setValue(pos,value_ion, INSERT_VALUES);
1091
1092 }
1093
1094 m_ion.assembly();
1095
1096 m_vecSolEDO[26].assembly();
1097 m_vecSolEDO[27].assembly();
1098 m_vecSolEDO[28].assembly();
1099 m_vecSolEDO[29].assembly();
1100 m_vecSolEDO[30].assembly();
1101
1102
1103 //********************
1104 //********************
1105
1106
1107 }
1108
1109 //****************************************************************************************************
1110 //****************************************************************************************************
1111
1112 //Gates functions
1113
1114 //****************************************************************************************************
1115 //****************************************************************************************************
1116
1117
1118 void PaciSolver::hgate(double& hinf,double& tauh, double u) {
1119
1120 hinf = 1./std::sqrt(1.+std::exp(1000.*(u+72.1e-3)/5.7));
1121 double alphah,betah;
1122
1123 if(u<-40e-3) {
1124 alphah = 0.057*std::exp(-1000.*(u+80e-3)/6.8);
1125 betah = 2.7*std::exp(0.079*u*1000.)+(3.1e5)*std::exp(0.3485*u*1000.);
1126 tauh = 1.5/(alphah+betah);
1127 } else {
1128 alphah = 0.;
1129 betah = 0.77/(0.13*(1.+std::exp(-1000.*(u+10.66e-3)/11.1)));
1130 tauh = 2.542;
1131 }
1132 }
1133
1134 void PaciSolver::jgate(double& jinf,double& tauj, double u) {
1135
1136 jinf = 1./std::sqrt(1.+std::exp(1000.*(u+72.1e-3)/5.7));
1137 double alphaj,betaj;
1138
1139 if(u<-40e-3) {
1140 const double numalphaj = 1000.*(u+37.78e-3)*(-25428.*std::exp(1000.*0.2444*u)-(6.948e-6)*std::exp(-0.04391*u*1000.));
1141 const double denalphaj = 1./(1.+std::exp(0.311*(u+79.23e-3)*1000.));
1142
1143 alphaj = numalphaj/denalphaj;
1144 betaj = (0.02424*std::exp(-0.01052*u*1000.))/(1.+std::exp(-0.1378*(u+40.14e-3)*1000.));
1145 } else {
1146 alphaj = 0.;
1147 betaj = (0.6*std::exp(0.057*u*1000.))/(1.+std::exp(-0.1*(u+32.e-3)*1000.));
1148 }
1149 tauj = 7./(alphaj+betaj);
1150 }
1151
1152 void PaciSolver::mgate(double& minf,double& taum, double u) {
1153
1154 const double minfradicand = 1.+std::exp(1000.*(-u-34.1e-3)/5.9);
1155 minf = 1./std::pow(minfradicand,1./3.);
1156 const double alpham = 1./(1.+std::exp(1000.*(-u-60e-3)/5.));
1157 const double betam = (0.1/(1.+std::exp(1000.*(u+35e-3)/5.)))+(0.1/(1.+std::exp(1000.*(u-50e-3)/200.)));
1158 taum = alpham*betam;
1159 }
1160
1161 void PaciSolver::dgate(double& dinf,double& taud, double u) {
1162
1163 dinf = 1./(1.+std::exp(-1000.*(u+9.1e-3)/7.));
1164 //Atrial
1165 //dinf = 1./(1.+std::exp(-1000.*(value_uExtrap+5.986e-3)/7.));
1166 const double alphad = (1.4/(1.+std::exp(1000.*(-u-35e-3)/13.)))+0.25;
1167 const double betad = 1.4/(1.+std::exp(1000.*(u+5e-3)/5.));
1168 const double gammad = 1./(1.+std::exp(1000.*(-u+50e-3)/20.));
1169 taud = (alphad*betad)+gammad;
1170 }
1171
1172 void PaciSolver::fcagate(double& fcainf,double& taufca, double& constfca, double u, double Cai, double fCa) {
1173
1174 const double alphafCa = 1./(1.+std::pow(Cai/0.0006,8));
1175 const double betafCa = 0.1/(1.+std::exp((Cai-0.0009)/0.0001));
1176 const double gammafCa = 0.3/(1.+std::exp((Cai-0.00075)/0.0008));
1177 fcainf = (alphafCa+betafCa+gammafCa)/1.3156;
1178 taufca = 2.;//[ms]
1179 constfca = 1.;
1180 if(fcainf>fCa && u>-60e-3) {
1181 constfca = 0.;
1182 }
1183 }
1184
1185 void PaciSolver::f1gate(double& f1inf,double& tauf1, double u, double df1, double Cai) {
1186
1187 f1inf = 1./(1.+std::exp(1000.*(u+26e-3)/3.));//ventricular
1188 //Atrial
1189 //f1inf = 1./(1.+std::exp(-1000.*(value_uExtrap+25.266e-3)/3.));
1190
1191 const double sum1 = 1102.5*std::exp(-std::pow(std::pow(1000.*(u+27e-3),2.)/15.,2.));
1192 const double sum2 = 200./(1.+std::exp(1000.*(-u+13e-3)/10.));
1193 const double sum3 = 180./(1.+std::exp(1000.*(u+30e-3)/10.));
1194 tauf1 = sum1+sum2+sum3+20.;
1195 if(df1>0.) {
1196 tauf1 = tauf1*(1.+1433*(Cai-(50e-6)));
1197 }
1198 }
1199
1200 void PaciSolver::f2gate(double& f2inf,double& tauf2, double u) {
1201
1202 const double sum12 = 600.*std::exp(-std::pow(1000.*(u+25e-3),2.)/170.);
1203 const double sum22 = 31./(1.+std::exp(1000.*(-u+25e-3)/10.));
1204 const double sum32 = 16./(1.+std::exp(1000.*(u+30e-3)/10.));
1205 tauf2 = sum12+sum22+sum32;
1206 f2inf = (0.67/(1.+std::exp(1000.*(u+35e-3)/4.)))+0.33;
1207 }
1208
1209 void PaciSolver::rgate(double& rinf,double& taur, double u) {
1210 rinf = 1./(1.+std::exp(1000.*(-u+22.3e-3)/18.75));
1211 taur = (14.40516/(1.037*std::exp(1000.*0.09*(u+30.61e-3))+0.369*std::exp(-0.12*(u+23.84e-3)*1000.)))+2.75352;
1212 }
1213
1214 void PaciSolver::qgate(double& qinf,double& tauq, double u) {
1215 qinf = 1./(1.+std::exp(1000.*(u+53e-3)/13.));
1216 tauq = (39.102/(0.57*std::exp(-0.08*(u+44e-3)*1000.)+0.065*std::exp(1000.*0.1*(u+45.93e-3))))+6.06;
1217 }
1218
1219 void PaciSolver::xr1gate(double& xr1inf,double& tauxr1, double u) {
1220 const double V05 = (-((R*T)/(F*Q))*std::log(std::pow(1.+Cao/2.6,4)/(Lo*std::pow(1.+Cao/0.58,4)))-0.019);
1221 xr1inf = 1./(1.+std::exp(1000.*(V05-u)/4.9));
1222 const double alphaxr1 = 450./(1.+std::exp(1000.*(-u-45e-3)/10.));
1223 const double betaxr1 = 6./(1.+std::exp(1000.*(u+30e-3)/11.5));
1224 tauxr1 = alphaxr1*betaxr1;
1225 }
1226
1227 void PaciSolver::xr2gate(double& xr2inf,double& tauxr2, double u) {
1228 xr2inf = 1./(1.+std::exp(1000.*(u+88e-3)/50.));
1229 const double alphaxr2 = 3./(1.+std::exp(1000.*(-u-60e-3)/20.));
1230 const double betaxr2 = 1.12/(1.+std::exp(1000.*(u-60e-3)/20.));
1231 tauxr2 = alphaxr2*betaxr2;
1232 }
1233
1234 void PaciSolver::xsgate(double& xsinf,double& tauxs, double u) {
1235 xsinf = 1./(1.+std::exp(1000.*(-u-20e-3)/16.));
1236 const double alphaxs = 1100./std::sqrt((1.+std::exp(1000.*(-u-10e-3)/6.)));
1237 const double betaxs = 1./(1.+std::exp(1000.*(u-60e-3)/20.));
1238 tauxs = alphaxs*betaxs;
1239 }
1240
1241 void PaciSolver::xfgate(double& xfinf,double& tauf, double u) {
1242 xfinf = 1./(1.+std::exp(1000.*(u+77.85e-3)/5.));
1243 tauf = 1900./(1.+std::exp(1000.*(u+15e-3)/10.));
1244 }
1245
1246 void PaciSolver::ggate(double& ginf,double& taug,double& constg, double u, double Cai, double g) {
1247
1248 if(Cai<=0.00035) {
1249 ginf = 1./(1.+std::pow(Cai/0.00035,6));
1250 } else {
1251 ginf = 1./(1.+std::pow(Cai/0.00035,16));
1252 }
1253
1254 taug = 2.; //[ms]
1255 constg = 1.;
1256
1257 if(ginf>g && u>-60e-3) {
1258 constg = 0.;
1259 }
1260 }
1261
1262 //For non spontaneous AP, only used for INa
1263
1264 void PaciSolver::mgateORd(double& minf, double& taum, double u) {
1265 minf = 1./(1.+std::exp(-1000.*(u+39.57e-3)/9.871));
1266 const double exp1 = 6.765*std::exp(1000.*(u+11.64e-3)/34.77);
1267 const double exp2 = 8.552*std::exp(-1000.*(u+77.42e-3)/5.955);
1268 taum = 1./(exp1+exp2);
1269 }
1270
1271 void PaciSolver::jgateORd(double& jinf, double& tauj, double u) {
1272 jinf = 1./(1.+std::exp(1000.*(u+82.9e-3)/6.086));
1273 const double exp1 = 0.02136*std::exp(-1000.*(u+100.6e-3)/8.281);
1274 const double exp2 = 0.3052*std::exp(1000.*(u+0.9941e-3)/38.45);
1275 tauj = 2.038+1./(exp1+exp2);
1276 }
1277
1278 void PaciSolver::hslowgateORd(double& hslowinf, double& tauhslow, double u) {
1279 hslowinf = 1./(1.+std::exp(1000.*(u+82.9e-3)/6.086));
1280 const double exp1 = 0.009764*std::exp(-1000.*(u+17.95e-3)/28.05);
1281 const double exp2 = 0.3343*std::exp(1000.*(u+5.730e-3)/56.66);
1282 tauhslow = 1./(exp1+exp2);
1283 }
1284
1285 void PaciSolver::hfastgateORd(double& hfastinf, double& tauhfast, double u) {
1286 hfastinf = 1./(1.+std::exp(1000.*(u+82.9e-3)/6.086));
1287 const double exp1 = 1.432e-5*std::exp(-1000.*(u+1.196e-3)/6.285);
1288 const double exp2 = 6.149*std::exp(1000.*(u+0.5096e-3)/20.27);
1289 tauhfast = 1./(exp1+exp2);
1290
1291 }
1292
1293 void PaciSolver::hlgateORd(double& hlinf, double& tauhl, double u) {
1294 hlinf = 1./(1.+std::exp(1000.*(u+87.61e-3)/7.488));
1295 tauhl = 200.;
1296 }
1297
1298 void PaciSolver::mlgateORd(double& mlinf, double& tauml, double u) {
1299 mlinf = 1./(1.+std::exp(-1000.*(u+42.85e-3)/5.264));
1300 const double exp1 = 6.765*std::exp(1000.*(u+11.64e-3)/34.77);
1301 const double exp2 = 8.552*std::exp(-1000.*(u+77.42e-3)/5.955);
1302 tauml = 1./(exp1+exp2);
1303 }
1304
1305
1306
1307 //****************************************************************************************************
1308 //****************************************************************************************************
1309
1310 // CVODE: y' = f(y)
1311
1312 //****************************************************************************************************
1313 //****************************************************************************************************
1314
1315
1316 #ifdef FELISCE_WITH_SUNDIALS
1317
1318 //for each node
1319 int PaciSolver::M_f(realtype t, N_Vector y, N_Vector ydot, void *f_data) {
1320
1321 //-----------------------------------------------------//
1322 // RHS
1323 //-----------------------------------------------------//
1324
1325
1326 UserData* data = static_cast< UserData* >(f_data);
1327 const int pos = data->pos;
1328 const double UExtrap_forM_f = data->M_u_extrap[pos];
1329 const double value_df1 = data->value_df1[pos];
1330
1331 double hinf,tauh;
1332 PaciSolver::hgate(hinf,tauh,UExtrap_forM_f);
1333
1334 double jinf,tauj;
1335 PaciSolver::jgate(jinf,tauj,UExtrap_forM_f);
1336
1337 double minf,taum;
1338 PaciSolver::mgate(minf,taum,UExtrap_forM_f);
1339
1340 double dinf,taud;
1341 PaciSolver::dgate(dinf,taud,UExtrap_forM_f);
1342
1343 double fcainf,taufca,constfca;
1344 PaciSolver::fcagate(fcainf,taufca,constfca,UExtrap_forM_f,Ith(y,15),Ith(y,5));
1345
1346 double f1inf,tauf1;
1347 PaciSolver::f1gate(f1inf,tauf1,UExtrap_forM_f,value_df1,Ith(y,15));
1348
1349 double f2inf,tauf2;
1350 PaciSolver::f2gate(f2inf,tauf2,UExtrap_forM_f);
1351
1352 double rinf,taur;
1353 PaciSolver::rgate(rinf,taur,UExtrap_forM_f);
1354
1355 double qinf,tauq;
1356 PaciSolver::qgate(qinf,tauq,UExtrap_forM_f);
1357
1358 double xr1inf,tauxr1;
1359 PaciSolver::xr1gate(xr1inf,tauxr1,UExtrap_forM_f);
1360
1361 double xr2inf,tauxr2;
1362 PaciSolver::xr2gate(xr2inf,tauxr2,UExtrap_forM_f);
1363
1364 double xsinf,tauxs;
1365 PaciSolver::xsgate(xsinf,tauxs,UExtrap_forM_f);
1366
1367 double xfinf,tauf;
1368 PaciSolver::xfgate(xfinf,tauf,UExtrap_forM_f);
1369
1370 double ginf,taug,constg;
1371 PaciSolver::ggate(ginf,taug,constg,UExtrap_forM_f,Ith(y,15),Ith(y,14));
1372
1373
1374 //! Non spontaneous (ORd)
1375 double minfORd,taumORd;
1376 PaciSolver::mgateORd(minfORd, taumORd,UExtrap_forM_f);
1377
1378 double jinfORd,taujORd;
1379 PaciSolver::jgateORd(jinfORd, taujORd,UExtrap_forM_f);
1380
1381 double hslowinf,tauhslow;
1382 PaciSolver::hslowgateORd(hslowinf, tauhslow,UExtrap_forM_f);
1383
1384 double hfastinf,tauhfast;
1385 PaciSolver::hfastgateORd(hfastinf, tauhfast,UExtrap_forM_f);
1386
1387 double hlinf,tauhl;
1388 PaciSolver::hlgateORd(hlinf, tauhl,UExtrap_forM_f);
1389
1390 double mlinf,tauml;
1391 PaciSolver::mlgateORd(mlinf, tauml,UExtrap_forM_f);
1392
1393
1394
1395 //------------------------------------
1396 // Calculations for Cai, Casr and Nai
1397 //------------------------------------
1398
1399 const double Cm = 98.7109;
1400 const double Vc = 8800.;
1401 const double Vsr = 583.73;
1402 const double gNa = 3.6712302e3;
1403 const double PNaK = 1.841424;
1404 const double KNaCa = 4900.;
1405 const double Vmaxup = 0.56064;
1406
1407
1408 const double Ileak = Vleak*(Ith(y,16)-Ith(y,15));
1409 const double Iup = Vmaxup/(1.+std::pow(Kup/Ith(y,15),2));
1410 double Irel = (crel+(arel*std::pow(Ith(y,16),2))/(std::pow(brel,2)+std::pow(Ith(y,16),2)))*Ith(y,4)*Ith(y,14);
1411 Irel = Irel*0.0411;//ventricular
1412
1413 //Atrial
1414 //Irel = value_irel*0.0556;
1415
1416 //iNaK
1417 const double num1 = PNaK*Ko*Ith(y,17)/(Ko+Kmk);
1418 const double num2 = num1/(Ith(y,17)+KmNa);
1419 const double INaK = num2/(1.+0.1245*std::exp(-0.1*UExtrap_forM_f*F/(R*T))+0.0353*std::exp(-UExtrap_forM_f*F/(R*T)));
1420
1421
1422 //iNaCa
1423 const double prodnum1 = std::pow(Ith(y,17),3)*Cao*std::exp(gamma_value*UExtrap_forM_f*F/(R*T));
1424 const double prodnum2 = alpha*std::pow(Nao,3)*Ith(y,15)*std::exp((gamma_value-1.)*UExtrap_forM_f*F/(R*T));
1425 const double numINaCa = KNaCa*(prodnum1-prodnum2);
1426 const double prodden1 = std::pow(KmNai,3)+std::pow(Nao,3);
1427 const double prodden2 = KmCa+Cao;
1428 const double prodden3 = 1.+Ksat*std::exp((gamma_value-1.)*UExtrap_forM_f*F/(R*T));
1429 const double denINaCa = prodden1*prodden2*prodden3;
1430 const double INaCa = numINaCa/denINaCa;
1431
1432
1433 //iCaL
1434 const double term1 = (gCaL*4.*UExtrap_forM_f*F*F)/(R*T);
1435 const double term2 = (Ith(y,15)*std::exp((2.*UExtrap_forM_f*F)/(R*T))-0.341*Cao)/(std::expm1((2.*UExtrap_forM_f*F)/(R*T)));
1436 const double ICaL = term1*term2*Ith(y,4)*Ith(y,5)*Ith(y,6)*Ith(y,7);
1437
1438
1439 //ipCa
1440 const double IPCa = gpCa*Ith(y,15)/(Ith(y,15)+KpCa);
1441
1442
1443 const double ENa = (R*T/F)*std::log(Nao/Ith(y,17));
1444 const double EKs = (R*T/F)*std::log((Ko+Pkna*Nao)/(Ki+Pkna*Ith(y,17)));
1445 const double ECa = 0.5*(R*T/F)*std::log(Cao/Ith(y,15));
1446
1447
1448 //iNa
1449 //const double m3 = std::pow(Ith(y,3),3.);
1450 //const double INa=gNa*m3*Ith(y,1)*Ith(y,2)*(UExtrap_forM_f-ENa);
1451
1452 //! For non spontaneous AP
1453 const double hORd = 0.99*Ith(y,21)+0.01*Ith(y,20);
1454 const double m3 = std::pow(Ith(y,18),3.);
1455 const double iNafast = 75.*(UExtrap_forM_f-ENa)*m3*Ith(y,19)*hORd;
1456 const double iNalate = 0.0075*(UExtrap_forM_f-ENa)*Ith(y,23)*Ith(y,22);
1457
1458 const double INa = iNafast+iNalate;
1459
1460
1461 //ibNa-ibCa
1462 const double IbNa=gbNa*(UExtrap_forM_f-ENa);
1463 const double IbCa=gbCa*(UExtrap_forM_f-ECa);
1464
1465
1466 const double Caibufc = 1./(1.+(Bufc*Kbufc)/std::pow(Ith(y,15)+Kbufc,2));
1467 const double Casrbufsr = 1./(1.+(Bufsr*Kbufsr)/std::pow(Ith(y,16)+Kbufsr,2));
1468
1469 //Cai-Casr-Nai
1470 double cstteCai = Caibufc*(Ileak-Iup+Irel-Cm*(ICaL+IbCa+IPCa-2.*INaCa)/(2.*Vc*F));
1471 double cstteCasr = (Casrbufsr*Vc)*(Iup-(Irel+Ileak))/Vsr;
1472 double cstteNai = -Cm*(INa+IbNa+3.*INaK+3.*INaCa)/(F*Vc);
1473
1474
1475 //Add currents in data
1476 data->vINaCa[pos] = INaCa;
1477 data->vIPCa[pos] = IPCa;
1478 data->vIbCa[pos] = IbCa;
1479 data->vENa[pos] = ENa;
1480 data->vEKs[pos] = EKs;
1481 data->vECa[pos] = ECa;
1482 data->vINa[pos] = INa;
1483 data->vICaL[pos] = ICaL;
1484 data->vINaK[pos] = INaK;
1485 data->vIrel[pos] = Irel;
1486 data->vIup[pos] = Iup;
1487 data->vIleak[pos] = Ileak;
1488 data->vIbNa[pos] = IbNa;
1489
1490
1491 //-----------------------------------------------------//
1492 // Derivates
1493 //-----------------------------------------------------//
1494
1495 Ith(ydot,1) = (hinf-Ith(y,1))/tauh;//h
1496 Ith(ydot,2) = (jinf-Ith(y,2))/tauj;//j
1497 Ith(ydot,3) = (minf-Ith(y,3))/taum;//m
1498 Ith(ydot,4) = (dinf-Ith(y,4))/taud;//d
1499 Ith(ydot,5) = constfca*(fcainf-Ith(y,5))/taufca;//fca
1500 Ith(ydot,6) = (f1inf-Ith(y,6))/tauf1;//f1
1501 Ith(ydot,7) = (f2inf-Ith(y,7))/tauf2;//f2
1502 Ith(ydot,8) = (rinf-Ith(y,8))/taur;//r
1503 Ith(ydot,9) = (qinf-Ith(y,9))/tauq;//q
1504 Ith(ydot,10) = (xr1inf-Ith(y,10))/tauxr1;//xr1
1505 Ith(ydot,11) = (xr2inf-Ith(y,11))/tauxr2;//xr2
1506 Ith(ydot,12) = (xsinf-Ith(y,12))/tauxs;//xs
1507 Ith(ydot,13) = (xfinf-Ith(y,13))/tauf;//xf
1508 Ith(ydot,14) = constg*(ginf-Ith(y,14))/taug;//g
1509 Ith(ydot,15) = cstteCai;//Cai
1510 Ith(ydot,16) = cstteCasr;//Casr
1511 Ith(ydot,17) = cstteNai;//Nai
1512
1513 //! For non spontaneous AP
1514 Ith(ydot,18) = (minfORd-Ith(y,18))/taumORd;//mORd
1515 Ith(ydot,19) = (jinfORd-Ith(y,19))/taujORd;//jORd
1516 Ith(ydot,20) = (hslowinf-Ith(y,20))/tauhslow;//hslow
1517 Ith(ydot,21) = (hfastinf-Ith(y,21))/tauhfast;//hfast
1518 Ith(ydot,22) = (hlinf-Ith(y,22))/tauhl;//hl
1519 Ith(ydot,23) = (mlinf-Ith(y,23))/tauml;//ml
1520
1521 return(0);
1522 }
1523
1524
1525
1526
1527
1528 static int ewt(N_Vector y, N_Vector w, void *user_data) {
1529 int i;
1530 realtype yy, ww, rtol, atol[17];
1531
1532 rtol = RTOL;
1533 atol[0] = ATOL8;
1534 atol[1] = ATOL8;
1535 atol[2] = ATOL8;
1536 atol[3] = ATOL8;
1537 atol[4] = ATOL8;
1538 atol[5] = ATOL8;
1539 atol[6] = ATOL8;
1540 atol[7] = ATOL8;
1541 atol[8] = ATOL8;
1542 atol[9] = ATOL8;
1543 atol[10] = ATOL8;
1544 atol[11] = ATOL8;
1545 atol[12] = ATOL8;
1546 atol[13] = ATOL8;
1547 atol[14] = ATOL8;
1548 atol[15] = ATOL8;
1549 atol[16] = ATOL8;
1550 atol[17] = ATOL8;
1551
1552
1553 for (i=1; i<=17; i++) {
1554 yy = Ith(y,i);
1555 ww = rtol * ABS(yy) + atol[i-1];
1556 if (ww <= 0.0) return (-1);
1557 Ith(w,i) = 1.0/ww;
1558 }
1559
1560 return(0);
1561 }
1562
1563
1564
1565
1566
1567 void PaciSolver::PrintOutput(realtype t, realtype y1, realtype y2, realtype y3, realtype y4, realtype y5, realtype y6) {
1568 #if defined(SUNDIALS_EXTENDED_PRECISION)
1569 printf("At t = %0.4Le y =%14.6Le %14.6Le %14.6Le %14.6Le %14.6Le %14.6Le\n", t, y1, y2, y3, y4, y5, y6);
1570 #elif defined(SUNDIALS_DOUBLE_PRECISION)
1571 printf("At t = %0.4le y =%14.6le %14.6le %14.6le %14.6le %14.6le %14.6le\n", t, y1, y2, y3, y4, y5, y6);
1572 #else
1573 printf("At t = %0.4e y =%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n", t, y1, y2, y3, y4, y5, y6);
1574 #endif
1575
1576 return;
1577 }
1578
1579 #endif
1580
1581
1582
1583
1584 }
1585
1586
1587
1588
1589 /*
1590 Stock std::cout and others informations
1591
1592
1593
1594 if(pos==700){
1595 std::cout << "Iion: " << value_ion << std::endl;
1596 }
1597 */
1598 /*
1599 if(pos==700){
1600 std::cout << " " << std::endl;
1601 std::cout << "ik1: " << value_ik1 << std::endl;
1602 std::cout << "ito: " << value_ito << std::endl;
1603 std::cout << "ikr: " << value_ikr << std::endl;
1604 std::cout << "iks: " << value_iks << std::endl;
1605 std::cout << "iCaL: " << value_iCaL << std::endl;
1606 std::cout << "iNaK: " << value_iNaK << std::endl;
1607 std::cout << "iNa: " << value_iNa << std::endl;
1608 std::cout << "iNaCa: " << value_iNaCa << std::endl;
1609 std::cout << "iPCa: " << value_iPCa << std::endl;
1610 std::cout << "if: " << value_if << std::endl;
1611 std::cout << "ibNa: " << value_ibNa << std::endl;
1612 std::cout << "ibCa: " << value_ibCa << std::endl;
1613 std::cout << " " << std::endl;
1614 std::cout << "Iion: " << value_ion << " sans Cm: " << value_ion*Cm << std::endl;
1615 std::cout << "u: " << value_uExtrap << std::endl;
1616 std::cout << " " << std::endl;
1617 }
1618 */
1619
1620 //const double coefCm = FelisceParam::instance().Cm;//Test pour recuperer la valeur Cm du data
1621 /*
1622 if(coefCm == 98.7109){
1623 //Ventricular
1624 Vc = 8800.;
1625 Vsr = 583.73;
1626 gNa = 3.6712302e3;
1627 gto = 29.9038;
1628 gk1 = 28.1492;
1629 PNaK = 1.841424;
1630 KNaCa = 4900.;
1631 Vmaxup = 0.56064;
1632 }
1633 else if(coefCm == 78.6671){
1634 //Atrial
1635 Vc = 7012.;
1636 Vsr = 465.20;
1637 gNa = 6.646185e3;
1638 gto = 59.8077;
1639 gk1 = 19.1925;
1640 PNaK = 1.4731392;
1641 KNaCa = 2450.;
1642 Vmaxup = 0.22;
1643 }
1644 */
1645
1646
1647 /*
1648 if(pos==700){
1649 std::cout << "avant: " << std::endl;
1650 PaciSolver::PrintOutput(time-dt, Ith(initvalue,1), Ith(initvalue,2), Ith(initvalue,3), Ith(initvalue,4), Ith(initvalue,5), Ith(initvalue,6));
1651 PaciSolver::PrintOutput(time-dt, Ith(initvalue,7), Ith(initvalue,8), Ith(initvalue,9), Ith(initvalue,10), Ith(initvalue,11), Ith(initvalue,12));
1652 PaciSolver::PrintOutput(time-dt, Ith(initvalue,13), Ith(initvalue,14), Ith(initvalue,15), Ith(initvalue,16), Ith(initvalue,17), Ith(initvalue,18));
1653 std::cout << " " << std::endl;
1654 }
1655 */
1656
1657
1658