openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
electrics_eikonal.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
27 #ifndef _EIKONAL_H
28 #define _EIKONAL_H
29 
30 #include "SF_globals.h"
31 #include "electrics.h"
32 #include "physics_types.h"
33 #include "sim_utils.h"
34 #include "stimulate.h"
35 
36 #include "sf_interface.h"
37 #include "timers.h"
38 #include "ionics.h"
39 #include "basics.h"
40 
41 namespace opencarp
42 {
47 struct node_stats {
48  enum status { in = 1,
49  out = 0 };
50  enum reason { none = 0,
51  nbn = 1,
52  conv = 2,
53  stim = 3 };
57  SF_real T_A = std::numeric_limits<double>::quiet_NaN();
58  SF_real nbn_T_A = std::numeric_limits<double>::quiet_NaN();
59  SF_real T_A_ = std::numeric_limits<double>::quiet_NaN();
60  SF_real T_R = std::numeric_limits<double>::quiet_NaN();
61  SF_real D_I = std::numeric_limits<double>::quiet_NaN();
62  const char* status = "out";
63  const char* reasonIn = "-";
64  const char* reasonOut = "-";
65 
66  FILE_SPEC logger = NULL;
67 
69  {
70  f_close(logger);
71  }
72 
73  void init_logger(const char* filename);
74  void log_stats(double tm, bool cflg);
75  void update_status(enum status s, enum reason r);
76 };
77 
79 {
80  public:
81  eikonal_solver() : stimuliRef(nullptr) {}
82 
83  size_t num_pts;
84 
85  mesh_int_t numPtsxElem; // number of points per element
86  SF_real time2stop_eikonal; // time before the fim stops iterating and assess
87  SF_real CV_l; // Variable to store the conduction velocity in each update
88  mesh_int_t Index_currStim; // index of the row in the table of stimuli and points
89 
90  const double inf = std::numeric_limits<double>::infinity(); // infinity
91 
92  // Variables for solver for triangles
93  SF_real A, B, C;
99  SF_real Num, Frac;
101  SF_real p1, p2;
102 
103  // data to dump
105 
106  // Variables for solver for tetrahedra
107  SF_real c1, c2, c3, c4, c5, c6;
108  SF_real a1, s1, s2, s3, a2, s4, b1, b2;
109  SF_real R1, R2, R3, R4, R5;
110  SF_real asol, bsol;
111  SF_real a, b;
112  SF_real derivat_a, derivat_b;
113 
114  double DI; // diastolic interval
115 
116  // Has to be kept in line with param_globals::eik_solve
117  enum Idiff_t { FOOT = 0,
118  GAUSS = 1 };
119  Idiff_t Idiff_tech = FOOT;
120 
122  Idiff_t model = FOOT;
123  SF_real A_F = 1;
124  SF_real tau_F = 1;
125  SF_real V_th = 1;
126  SF_real alpha_1 = 1;
127  SF_real beta_1 = 1;
128  SF_real gamma_1 = 1;
129  SF_real alpha_2 = 1;
130  SF_real beta_2 = 1;
131  SF_real gamma_2 = 1;
132  SF_real alpha_3 = 1;
133  SF_real beta_3 = 1;
134  SF_real gamma_3 = 1;
135  };
136 
137  // Vectors
139  SF::vector<SF_real> T_A, T_R, TA_old, D_I; // Time of activation, time of repolarization, time of activation previously calculated, diastolic interval, final conduction velocity
140  SF::vector<mesh_int_t> List, num_changes, nReadded2List, stim_status; // List of active nodes (L), number of changes per node to enter iterate in the list, number of times reentering the list per node, status per node after stimulus
141  SF::vector<mesh_int_t> StimulusPoints; // Nodes that have initial stimulus
142  SF::vector<SF_real> StimulusTimes; // Times when the initial nodes are stimulated
143 
144  SF::vector<mesh_int_t> e2n_con; // Connectivity vector with nodes that belong to each element
145  SF::vector<mesh_int_t> elem_start; // For the i_th element elem_start[j] stores its starting position in the "connect" vector
146  bool twoFib; // true if there is sheet information, false if there is only fiber orientation
147 
148  SF::vector<SF_real> fiber_node, sheet_node; // Fiber and sheet orientation per node
149  SF::vector<SF_real> x_coord, y_coord, z_coord; // x,y,z coordinates of each node
150  SF::vector<SF_real> CVnodes, CVnodes_mod, p_cvrest, k_cvrest, j_cvrest, l_cvrest, cv_ar_t, cv_ar_n; // CV restitution parameters
151  sf_vec* Idiff = nullptr;
152  sf_vec* AT = nullptr;
153  sf_vec* RT = nullptr;
154 
155  std::vector<mesh_int_t> n2n_connect, n2n_dsp;
156  SF::vector<mesh_int_t> e2n_cnt, n2e_cnt, n2e_con, n2e_dsp;
157 
159 
160  SF_real actMIN = 0, actMAX = 0;
161 
162  // eikonal solver stats
164 
165  bool condign1, condign2, condign3, condign4;
166 
168  {
169  if (Idiff) delete Idiff;
170  if (AT) delete AT;
171  if (RT) delete RT;
172  if (stimuliRef) delete stimuliRef;
173  }
174 
176  void init();
177 
186  bool determine_model_to_run(double& time);
187 
198  void set_initial_cv();
199 
201  void set_stimuli(SF::vector<stimulus>& stimuli) { stimuliRef = &stimuli; }
202 
217  void clean_list();
218 
230  void save_eikonal_state(const char* tsav_ext);
231 
243  void update_repolarization_times(const Ionics& ion);
244 
246  void cycFIM();
247 
249  void FIM();
250 
261  void update_repolarization_times_from_rd(sf_vec& Vmv, sf_vec& Vmv_old, double time);
262 
270  void compute_diffusion_current(const double& time, sf_vec& vm);
271 
280  void compute_bc();
281 
282  private:
283  // stimulus pointer
284  SF::vector<stimulus>* stimuliRef = nullptr;
285 
297  void bubble_sort(SF::vector<SF_real>& Array, SF::vector<mesh_int_t>& IndexArray, int& length);
298 
307  void update_Ta_in_active_list();
308 
317  SF_real compute_H(mesh_int_t& indX, SF_real& T_A_indX);
318 
328  SF_real compute_coherence(mesh_int_t& indX);
329 
338  SF_real compute_F(mesh_int_t& indX, SF_real& T_A_indX);
339 
347  SF_real solve_tet(mesh_int_t& indx3, std::vector<mesh_int_t>& Elem_cur);
348 
356  SF_real solve_tri(mesh_int_t& indx, std::vector<mesh_int_t>& Elem_cur);
357 
365  SF_real solve_edges(mesh_int_t& indX, mesh_int_t& indY);
366 
378 
390  SF_real compute_AT_at_node(SF_real& pp, mesh_int_t& indxf1, mesh_int_t& indyf1, mesh_int_t& indzf1);
391 
403  SF_real compute_AT_at_node_in_tet(SF_real& pf2, SF_real& qf2, mesh_int_t indxf2, mesh_int_t indyf2, mesh_int_t indzf2, mesh_int_t indwf2);
404 
413  bool add_node_neighbor_to_list(SF_real& RT, SF_real& oldTA, SF_real& newTA);
414 
416  void translate_stim_to_eikonal();
417 
419  void create_node_to_node_graph();
420 
422  void load_state_file();
423 
425  void init_diffusion_current();
426 };
427 
428 class Eikonal : public Basic_physic
429 {
430  public:
437  enum grid_t { intra_grid = 0,
438  extra_grid };
439  enum linsys_t { elliptic_sys,
440  parabolic_sys };
441 
443  MaterialType mtype[2];
444 
447 
449  sf_vec* phie_dummy = nullptr;
450 
454 
457 
460  // Has to be kept in line with param_globals::eik_solve
461  enum eikonal_t { EIKONAL = 0,
462  REp = 1,
463  REm = 2,
464  DREAM = 3 };
465  eikonal_t eik_tech = EIKONAL;
466 
469 
472 
476 
477  bool do_output_eikonal = false;
478 
480 
485  {
486  name = "Eikonal";
487  }
488 
497  void initialize();
498 
499  void destroy();
500  void compute_step();
501  void output_step();
502 
503  inline void output_timings()
504  {
505  // since ionics are included in electrics, we substract ionic timings from electric timings
506  compute_time -= ion.compute_time;
507  initialize_time -= ion.initialize_time;
508 
509  // now we call the base class timings output for Electrics
511  // and then for ionics
512  ion.output_timings();
513  }
514 
515  ~Eikonal();
516 
518  double timer_val(const int timer_id);
519 
521  std::string timer_unit(const int timer_id);
522 
523  private:
525  void solve_EIKONAL();
527  void solve_RE();
529  void solve_DREAM();
530 
532  void solve_RD();
533 
535  void setup_stimuli();
536 
538  void stimulate_intracellular();
541  void clamp_Vm();
542 
544  void setup_solvers();
545 
547  void setup_mappings();
548 
550  void setup_output();
551 
553  void dump_matrices();
554 
555  void checkpointing();
556 
557  void prepace();
558 
566 };
567 
568 } // namespace opencarp
569 
570 #endif
constexpr T min(T a, T b)
Definition: ion_type.h:33
SF::vector< SF_real > TA_old
description of materal properties in a mesh
Definition: fem_types.h:110
SF::vector< mesh_int_t > e2n_con
eikonal_solver eik_solver
Solver for the eikonal equation.
LAT_detector lat
the activation time detector
void set_stimuli(SF::vector< stimulus > &stimuli)
Simple setter for stimulus vector.
igb_output_manager output_manager_cycle
parabolic_solver parab_solver
Solver for the parabolic bidomain equation.
SF_real nbn_T_A
activation time of neighboring node
void update_status(enum status s, enum reason r)
eikonal_solver_stats stats
mesh_int_t idX
node index
SF::vector< SF_real > sheet_node
void log_stats(double tm, bool cflg)
SF_real T_A
current activation time
const char * reasonIn
reason for list entry
SF::vector< SF_real > z_coord
generic_timing_stats IO_stats
Tissue level electrics, main Electrics physics class.
int mesh_int_t
Definition: SF_container.h:46
SF::vector< SF_real > StimulusTimes
for analysis of the #iterations to solve CG
Definition: timers.h:69
SF_real T_R
repolarization time
The abstract physics interface we can use to trigger all physics.
Definition: physics_types.h:59
SF::vector< SF_real > p_cvrest
SF::vector< mesh_int_t > n2e_dsp
SF::vector< stimulus > stimuli
the electrical stimuli
Electrical ionics functions and LIMPET wrappers.
void set_elec_tissue_properties(MaterialType *mtype, Electrics::grid_t g, FILE_SPEC logger)
Fill the RegionSpec of an electrics grid with the associated inputs from the param parameters...
Definition: electrics.cc:100
gvec_data gvec
datastruct holding global IMP state variable output
for analysis of the computations done to solve the eikonal model
Definition: timers.h:36
mesh_int_t idXNB
neighboring node index responsible for list entry
Interface to SlimFem.
SF::vector< mesh_int_t > elem_start
File descriptor struct.
Definition: basics.h:133
const char * reasonOut
reason for list entry
SF::vector< mesh_int_t > StimulusPoints
virtual void output_timings()
Definition: physics_types.h:76
SF_real D_I
diastolic interval
SF::vector< mesh_int_t > stim_status
Electrical stimulation functions.
A vector storing arbitrary data.
Definition: SF_vector.h:42
igb_output_manager output_manager_time
class handling the igb output
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:162
struct opencarp::List List
Eikonal()
Most of the initialization is done with initialize()
mesh_int_t cycle
DREAM cycle.
double SF_real
Use the general double as real type.
Definition: SF_globals.h:38
SF::vector< diffusion_current > diff_cur
Basic utility structs and functions, mostly IO related.
void init_logger(const char *filename)
std::vector< mesh_int_t > n2n_dsp
SF_real T_A_
previous activation time
Simulator-level utility execution control functions.
grid_t
An electrics grid identifier to distinguish between intra and extra grids.
Basic physics types.
Struct used for debugging purposes.