CEPS  24.01
Cardiac ElectroPhysiology Simulator
ExtendedBidomainProblem.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 
35 
37  BidomainProblem(g, params),
38  m_extMediaAttrsOpts(""),
39  m_extMediaAttrs({}),
40  m_biElecStimOpts(""),
41  m_robinCoeffs(""),
42  m_anodeAttrsOpts(""),
43  m_anodeAttrs({}),
44  m_cathodeAttrsOpts(""),
45  m_cathodeAttrs({})
46 {
47  setProblemName("Extended Bidomain");
48 
49  if (ceps::isValidPtr(params))
51 
52  // Set electrode attributes
53  m_anodeAttrs = ceps::toInts(m_anodeAttrsOpts);
54  m_cathodeAttrs = ceps::toInts(m_cathodeAttrsOpts);
55 
56  m_extMediaAttrs = ceps::toInts(m_extMediaAttrsOpts);
57  if (m_extMediaAttrs.empty())
58  m_extMediaAttrs = {-1};
59 
60  m_extMediaAttrs.insert(m_anodeAttrs.begin(), m_anodeAttrs.end());
61  m_extMediaAttrs.insert(m_cathodeAttrs.begin(), m_cathodeAttrs.end());
62 
63  // CEPS_ABORT_IF(
64  // m_extMediaAttrs.empty(),
65  // "missing blood/torso/extracardiac attributes to run an extended bidomain model"
66  // );
67 }
68 
69 void
71 {
73  addUnknown(UnknownsName::ue, getWholeDomainAttributes()); // ue is defined everywhere
74 
76 
77  if (requireNullMean())
78  {
79  // and a lagrangian unknown
82  }
83 }
84 
85 
86 void
88 {
89  if (ceps::isProfiling())
90  getProfiler()->start("whole", "solving the bidomain problem");
91 
93 
94  // Solve the static problem
95  if (hasAnodalCathodalStimulation() and m_parameters->isActiveOption("compute electric field"))
96  {
98  spb.getFunctionDictionary()->deleteTensor("physCoeffSigma");
99  spb.getFunctionDictionary()->add("sigma_i", m_sigmaIOptions);
100  spb.getFunctionDictionary()->add("sigma_e", m_sigmaEOptions);
101  spb.getFunctionDictionary()->add("physCoeffSigma", "OPERATOR sigma_i + sigma_e");
102  spb.setOutputFileBase(spb.getOutputFileBase() + "_elec_field");
103  spb.initializeEquation();
104 
105  FluxAnodeCathodeSolver ssolver(&spb);
106  ssolver.solve();
107  }
108 
109  ExtendedBidomainSolver solver(this);
110 
111  solver.solve();
112 
113  if (hasAnalyticSolution())
114  m_errors = solver.getErrors();
115 
116  if (ceps::isProfiling())
117  getProfiler()->stop("whole");
118 }
119 
122 {
123  return m_extMediaAttrs;
124 }
125 
128 {
129  auto tissue = getTissueAttributes();
130  auto extra = getExtracardiacAttributes();
131 
132  CepsSet<CepsAttribute> res = {};
133  res.insert(tissue.begin(),tissue.end());
134  res.insert(extra .begin(),extra .end());
135  return res;
136 }
137 
140 {
141  return m_anodeAttrs;
142 }
143 
146 {
147  return m_cathodeAttrs;
148 }
149 
150 CepsBool
152 {
153  CepsBool res = true;
154  res = res and not m_biElecStimOpts.empty();
155  res = res and m_anodeAttrs .size() > 0;
156  res = res and m_cathodeAttrs.size() > 0;
157  return res;
158 }
159 
160 void
162 {
164  {
165 
166  m_functions->add("bielec_stim", CepsString("FUNCTION TIME ") + m_biElecStimOpts);
167 
168  m_functions->add("anode_stim", "OPERATOR 1.0 * bielec_stim");
169  m_functions->add("cathode_stim", "OPERATOR -1.0 * bielec_stim");
170 
172  "anode NEUMANN anode_stim "
173  "UNKNOWN 1 ATTRIBUTES " +
175  );
177  "cathode NEUMANN cathode_stim "
178  "UNKNOWN 1 ATTRIBUTES " +
180  );
181 
182  for (auto definition : ceps::split(m_robinCoeffs, ","))
183  {
184  auto options = ceps::split(definition);
185  CEPS_ABORT_IF(options.size() != 2, "robin coefficient entry requires a scalar and an attribute");
186  m_boundaryConditions->add("boundary ROBIN 0.0 UNKNOWN 1 ATTRIBUTES " + options[1] + " ROBINCOEFF " + options[0]);
187  }
188 
189  /*
190  m_boundaryConditions->add(
191  "anode DIRICHLET bielec_stim "
192  "UNKNOWN 1 ATTRIBUTES " +
193  m_anodeAttrsOpts
194  );
195  m_boundaryConditions->add(
196  "cathode DIRICHLET 0. "
197  "UNKNOWN 1 ATTRIBUTES " +
198  m_cathodeAttrsOpts
199  );
200  */
201 
202 
203 
204  }
205 }
206 
207 CepsBool
209 {
210  return m_robinCoeffs.empty();
211 }
212 
213 void
215 {
216  // blood medium
217  m_extMediaAttrsOpts += params->getString("blood attributes", "");
218  // torso attributes, large domain usually
219  m_extMediaAttrsOpts += " " + params->getString("torso attributes", "");
220  // generic extracardiac attributes
221  m_extMediaAttrsOpts += " " + params->getString("extracardiac attributes", "");
222 
223  // anodal and cathodal stimulation
224  m_biElecStimOpts = params->getString("electrodes stimulation", m_biElecStimOpts);
225 
226  m_anodeAttrsOpts = params->getString("anode attributes", m_anodeAttrsOpts);
227  m_cathodeAttrsOpts = params->getString("cathode attributes", m_cathodeAttrsOpts);
228 
229  m_robinCoeffs = params->getString("robin coefficients", "");
230 
231  return;
232 }
#define CEPS_ABORT_IF(condition, message)
Stops the execution with a message if condition is true. If testing is enabled, only throws a runtime...
std::basic_string< CepsChar > CepsString
C++ format string.
Definition: CepsTypes.hpp:128
std::set< _Type, _Compare, _Alloc > CepsSet
C++ set.
Definition: CepsTypes.hpp:209
bool CepsBool
Booleans.
Definition: CepsTypes.hpp:124
CepsBool hasAnalyticSolution() const
Tells if there is an analytic or reference solution.
CepsString getOutputFileBase() const
Output file name includes the directory.
FunctionDictionary * getFunctionDictionary() const
Get functions manager.
void addUnknown(const CepsString &label, CepsSet< CepsAttribute > attrs={}, CepsLocationFlag flag=CepsLocationFlag::Point, const CepsString &unit="")
Register a new unknown.
void addZeroDUnknown(CepsString label, const CepsString &unit="")
Register a new unknown, defined outside of geometry.
void addUnknownInteraction(CepsString label1, CepsString label2, CepsSet< CepsAttribute > attrs={})
Register interaction between unknowns. Also sets the interaction within Unknown instances label1 and ...
InputParameters * m_parameters
Input file data.
void setOutputFileBase(CepsString fileName)
Output file name includes the directory.
Geometry * m_geom
Link to geometry on which the pb is defined.
BoundaryConditionManager * m_boundaryConditions
All BCs should be there.
FunctionDictionary * m_functions
Collection of custom functions.
void initializeEquation() override
Initializes equations (unknowns, bc, source term) and creates the spatial discretization This method ...
CepsArray2< CepsArray3< CepsArray3< CepsReal > > > m_errors
Will store Linf, L1 and L2 relative errors.
CepsArray2< CepsArray3< CepsArray3< CepsReal > > > getErrors() const
Gets the currently computed errors. First index selects absolute(0) or relative(1) second index selec...
Bidomain equation main class.
void add(const CepsString &params)
Add a boundary condition term from parameters.
CepsString m_sigmaIOptions
Options for intracellular conductivity.
CepsString m_sigmaEOptions
Options for extracellulat conductivity.
const CepsSet< CepsAttribute > & getTissueAttributes() const
All attributes that localize tissue.
void initializeEquation() override
Initializes all the elements of the PDE from options.
void solve() override
Performs all iterations of the PDE solver.
Profiler * getProfiler() const
Access to profiler.
Definition: CepsObject.cpp:46
virtual CepsSet< CepsAttribute > getAnodeAttributes() const
Get cathode attributes if set.
CepsBool hasAnodalCathodalStimulation() const
Has anodal and cathodal stimulation ?
CepsSet< CepsAttribute > m_extMediaAttrs
Extracardiac regions attributes.
void run() override
Run the simulation.
void defineUnknowns() override
Transmembrane voltage (mV) and Extracellular potential (mV)
CepsSet< CepsAttribute > getWholeDomainAttributes() const
Get all attributes: tissue and extracardiac.
void defineBoundaryConditions() override
Define the boundary conditions.
ExtendedBidomainProblem(Geometry *g, InputParameters *=nullptr)
Constructor from geometry and possibly parameters.
CepsString m_cathodeAttrsOpts
Text input for cathode attributes.
CepsString m_extMediaAttrsOpts
Text input for extracardiac regions attributes.
CepsSet< CepsAttribute > m_cathodeAttrs
Cathode attributes.
CepsSet< CepsAttribute > m_anodeAttrs
Anode attributes.
CepsString m_robinCoeffs
Robin coefficients.
virtual CepsSet< CepsAttribute > getCathodeAttributes() const
Get cathode attributes if set.
CepsBool requireNullMean() const
Tells if this problem requires a null mean constraint.
void setupWithParameters(InputParameters *params) override
Sets options from the parameters.
CepsString m_anodeAttrsOpts
Text input for anode attributes.
const CepsSet< CepsAttribute > & getExtracardiacAttributes() const
Get extracardiac attributes.
CepsString m_biElecStimOpts
Anodal and cathodal stimulation parameters, disabled if empty.
Solves bidomain extended problem with FBE, SBDF RK or CN schemes.
Poisson equation with Neumann 1 on anode, -1 on cathode. Neumann 0 elsewhere. Functional tensorial co...
Solver for a Poisson equation with Neumann BC (using 0 mean constraint)
void solve() override
Solve and postprocess.
void add(const CepsString &label, const CepsString &params, Geometry *geom=nullptr)
Add an object from parameters.
void deleteTensor(const CepsString &label)
Delete a single tensor entry. Be careful if the functor was created outside dictionary.
Encapsulates all the geometrical data.
Definition: Geometry.hpp:50
Reads and stores simulation configuration.
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.
void stop(CepsString lbl)
Stops the measure of a labeled chronometer.
void start(CepsString lbl, CepsString dspl="")
Creates or continue a labeled chronometer.
CepsSet< CepsInt > toInts(const CepsString &s)
Cast CepsString to a set of CepsInt.
Definition: CepsString.cpp:284
CepsBool isValidPtr(_Type *ptr)
Tells if pointer is not null.
Definition: CepsMemory.hpp:61
CepsVector< CepsString > split(const CepsString &s, const CepsString &delimiters=CepsString(" \t"))
Splits a string using mulitple delimiters in a single string.
Definition: CepsString.cpp:38
CepsBool isProfiling()
Check if we are currently profiling on the master proc (always false on slave procs).
Definition: CepsFlags.cpp:257
static constexpr const char * vm
Transmembrane voltage.
static constexpr const char * lag
Lagrangian (null mean constraint)
static constexpr const char * ue
Extracellular and extracardiac potential.