CEPS  24.01
Cardiac ElectroPhysiology Simulator
CardiacSolver.cpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
31 
33  HeatSolver (problem),
34  m_activationTracker (nullptr),
35  m_ionSolvers ({}),
36  m_ionSolvOpts ("RL 2"),
37  m_stopAtCompleteActivation (false),
38  m_stopAtCompleteRepolarization(false)
39 {
40  m_hasRegSrc = true; // Ionic models
41 
42  this->m_scaleSystem = 1.; // Reverted from 1/dt in HeatSolver
43  m_activationTracker = ceps::getNew<ActivationTracker>(this);
44 
45  // Check parameters
46  InputParameters* params = problem->getParameters();
47  if (ceps::isValidPtr(params))
48  {
49  m_stopAtCompleteActivation = params->isActiveOption("stop at complete activation");
50  CEPS_WARNS_IF(m_stopAtCompleteActivation and not params->hasKey ("activation time data"),
51  "Cannot enable simulation stop at complete activation since no activation time data\n" <<
52  "has been provided. Simulation will stop at time " << m_timeStepper->getEndTime()
53  );
54 
55  m_ionSolvOpts = params->getString("ionic model solver",m_ionSolvOpts);
56  }
57 
58  // Initialize ionic solvers
59  if (ceps::isProfiling())
60  getProfiler()->logMemoryUsage("\"PDE solver - before allocation of ionic data arrays\"");
61 
62  for (AbstractIonicModel* model: problem->getIonicModels())
63  m_ionSolvers.push_back(ceps::getNew<IonicSolver>(m_ionSolvOpts,model,m_fe));
64 
65 
66  if (ceps::isProfiling())
67  getProfiler()->logMemoryUsage("\"PDE solver - end of initialization\"");
68 
69 }
70 
72 {
74  for (auto solver : m_ionSolvers)
75  ceps::destroyObject(solver);
76 }
77 
78 void
80 {
82 
84 }
85 
88 {
89  return m_activationTracker;
90 }
91 
92 
95 {
96  CepsBool ended = m_timeStepper->atEnd();
98 
99  return ended or allActiv;
100 }
101 
104 {
105  return ceps::runtimeCast<CardiacProblem*>(m_problem);
106 }
107 
108 void
110 {
112 
113  if (ceps::isProfiling())
114  getProfiler()->start("iion","computing ionic currents (CardiacSolver)");
115  for (IonicSolver* solver: m_ionSolvers)
116  {
117  // if (m_type == "RK")
118  // solver->takeOneSubStep(tn,dt,m_uNm[0]);
119  // else
120  solver->takeOneStep(m_timeStepper->getTime(),m_timeStepper->getTimeStep(),m_uNm[0]);
121  }
122  if (ceps::isProfiling())
123  getProfiler()->stop("iion");
124 }
125 
126 void
128 {
129  auto cpb = getCardiacProblem();
130 
131  // Add all non ionic sources (regular and stiffness source terms)
133 
134  // Divide by AmCm
135  auto vecUs = cpb->getCardiacUnknowns();
136  CepsSet<Unknown*> us(vecUs.begin(),vecUs.end());
137 
138  scaleByField(m_regSourcesNm[0].get(),*cpb->getCm(),{},us,tn,true);
139  scaleByField(m_regSourcesNm[0].get(),*cpb->getAm(),{},us,tn,true);
140 
141  // Add ionic currents and stim. Ionic models compute directly (iIon+iApp)/cm
142  for (IonicSolver* solver: m_ionSolvers)
143  {
144  solver->addDtv(m_regSourcesNm[0]);
145 
146  // Advance the ionic model for next step
147 
148  // if (ceps::isProfiling())
149  // getProfiler()->start("iion","computing ionic currents (CardiacSolver)");
150  // if (m_type == "RK")
151  // solver->takeOneSubStep(tn,dt,m_uNm[0]);
152  // else
153  // solver->takeOneStep(tn,dt,m_uNm[0]);
154  // if (ceps::isProfiling())
155  // getProfiler()->stop("iion");
156  }
157 
158 }
159 
160 void
161 CardiacSolver::output(DHVecPtr solution, CepsBool immediatWriting)
162 {
163  auto pb = getCardiacProblem();
164 
165  HeatSolver::output(solution, false);
166 
168  {
169  auto vec = m_discretization->newDofHaloVector();
170  vec->zero();
171  for (IonicSolver* solver: m_ionSolvers)
172  {
173  solver->addDtv(vec);
174  }
175 
177  if (ceps::contains(pb->getTMVUnknowns(), u))
178  m_writer->addScalarData(vec, "IIon (uA) [" + u->getName() + "]", u);
179 
180  if (immediatWriting)
182  }
183 
187 }
#define CEPS_WARNS_IF(condition, message)
If condition is true, writes a warning in the debug log and in the terminal (stderr).
std::set< _Type, _Compare, _Alloc > CepsSet
C++ set.
Definition: CepsTypes.hpp:209
bool CepsBool
Booleans.
Definition: CepsTypes.hpp:124
float CepsReal
Need single precision floating point.
Definition: CepsTypes.hpp:100
std::shared_ptr< DistributedHaloVector > DHVecPtr
Typedef for pointer on Distributed Halo CepsVector.
void scaleByField(DistributedVector *vec, ScalarField< _SupportType > &f, CepsReal t=0., CepsBool divide=false)
Multiplies or divides given vector by coeff value. (default behaviour)
DHVecPtr newDofHaloVector() const
Get a new vector from the factory, with halo data.
Represents a ionic model for a group of cells, i.e. multiple systems of ODEs.
CepsVector< Unknown * > getSpatialUnknowns() const
A vector of all unknowns of pb defined on cells or points.
VtkWriter * m_writer
Manages output.
AbstractDiscretization * m_discretization
Link to PDE discretization.
CepsBool m_doOutput
Enables/disables outputs.
AbstractPdeProblem * m_problem
Link to PDE to solve.
TimeStepper * m_timeStepper
Monitors time evolution.
void solve() override
Solves the all PDE (all iterations)
CepsVector< DHVecPtr > m_regSourcesNm
Sources at previous steps (if problem has source terms)
CepsVector< DHVecPtr > m_uNm
Solution vectors at different time steps. Several vectors are needed for multi-step methods....
CepsUInt m_nbIterSnapshot
Output perdiodicity.
virtual void output(DHVecPtr solution, CepsBool immediateWriting=true)
Prints the solution.
DHVecPtr m_uNp1
Vectors of unknowns at time t^n+1.
virtual void fillSourceTermsVector(CepsReal tn)
Adds contributions from all source terms into m_regSourcesNm[0].
Class managing computations from potential to outputs.
CepsBool allPointsHaveBeenActivated() const
Tells if all points have seen AP start (checked with activation threshold)
void writeActivationMap()
Writes activation times and probe points data.
void update(CepsInt iter, CepsReal time, DHVecPtr solution, DHVecPtr prevSolution)
Writes the solution (optionnally currents) every m_nbIterSnapshot steps only. Also updates activation...
A abstract class that regroups common parameters of cardiac problems.
CepsBool m_stopAtCompleteActivation
stop when all points have activation time computed
ActivationTracker * getActivationTracker() const
Link to activation tracker.
void output(DHVecPtr dummy, CepsBool immediatWriting=true) override
Calls the appropriate post-processing and writing methods.
void assembleAndSolve() override
Performs one iteration of the solver.
CardiacProblem * getCardiacProblem() const
Converts own pointer to abstract pde problem to cardiac problem.
void fillSourceTermsVector(CepsReal tn) override
Computes all contributions to source terms (ionic current, stimcurrent, field sources) with a loop on...
virtual ~CardiacSolver()
Destructor.
CepsVector< IonicSolver * > m_ionSolvers
One solver per ionic model in the problem.
void solve() override
Performs all iterations of the PDE solver.
CardiacSolver(CardiacProblem *problem)
Constructor with associated PDE problem.
ActivationTracker * m_activationTracker
Output computation and writing.
CepsBool finished() const override
Tells if simulation reached end time or, if enabled, all points have seen an AP.
Profiler * getProfiler() const
Access to profiler.
Definition: CepsObject.cpp:46
void assembleAndSolve() override
Main routine used during solving, assemble the system depending on the scheme and solve the linear sy...
Solve heat equation.
Definition: HeatSolver.hpp:39
Reads and stores simulation configuration.
CepsBool hasKey(const keyType &key) const
Tells if key exists in input file.
CepsBool isActiveOption(const keyType &key) const
Tells if key exists in configuration and is of "1","YES","ON" or "TRUE".
CepsString getString(const keyType &key) const
Reads a CepsString from configuration.
Groups two ODE solvers for ionic variables and interacts with cardiac problem.
Definition: IonicSolver.hpp:44
void stop(CepsString lbl)
Stops the measure of a labeled chronometer.
void start(CepsString lbl, CepsString dspl="")
Creates or continue a labeled chronometer.
CepsReal getTimeStep() const
Time step.
Definition: TimeStepper.cpp:95
virtual CepsReal getTime()
current simulation time
CepsBool atEnd()
Whether time stepper has reached the end time or not.
CepsUInt getNbTakenTimeSteps() const
Number of time steps performed until now.
A class used to defined an unknown of a PDE problem The unknown can be defined on a specific region,...
Definition: Unknown.hpp:45
void addScalarData(const DHVecPtr &v, const CepsVector< CepsString > &fieldNames, const CepsVector< Unknown * > &us)
Set multiple scalar fields to be output by this writer. addScalarData for several unknowns.
Definition: VtkWriter.cpp:101
void write(CepsReal time=0., CepsBool writeXmlEntry=true)
Write all stored data.
Definition: VtkWriter.cpp:176
constexpr CepsHash get(_Type const &i)
get a hash from a single value
CepsBool contains(const CepsVector< _Type, _Alloc > &vec, const _Type &item)
Tells if vectors contains a given item.
Definition: CepsVector.hpp:56
CepsBool isValidPtr(_Type *ptr)
Tells if pointer is not null.
Definition: CepsMemory.hpp:61
CepsBool isProfiling()
Check if we are currently profiling on the master proc (always false on slave procs).
Definition: CepsFlags.cpp:257
void destroyObject(_Type &)
Destroy[delete] any type.
Definition: CepsMemory.hpp:116