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;
102 
103  // data to dump
105 
106  // Variables for solver for tetrahedra
108  SF_real a1, s1, s2, s3, a2, s4, b1, b2;
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 };
120 
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
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;
157 
159 
161 
162  // eikonal solver stats
164 
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,
441 
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 };
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
508 
509  // now we call the base class timings output for Electrics
511  // and then for ionics
513  }
514 
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 
565  void set_elec_tissue_properties(MaterialType* mtype, Eikonal::grid_t g, FILE_SPEC logger);
566 };
567 
568 } // namespace opencarp
569 
570 #endif
int mesh_int_t
Definition: SF_container.h:46
double SF_real
Use the general double as real type.
Definition: SF_globals.h:38
Basic utility structs and functions, mostly IO related.
A vector storing arbitrary data.
Definition: SF_vector.h:43
The abstract physics interface we can use to trigger all physics.
Definition: physics_types.h:59
virtual void output_timings()
Definition: physics_types.h:76
FILE_SPEC logger
The logger of the physic, each physic should have one.
Definition: physics_types.h:64
const char * name
The name of the physic, each physic should have one.
Definition: physics_types.h:62
std::string timer_unit(const int timer_id)
figure out units of a signal linked to a given timer
Eikonal()
Most of the initialization is done with initialize()
SF::vector< stimulus > stimuli
the electrical stimuli
parabolic_solver parab_solver
Solver for the parabolic bidomain equation.
MaterialType mtype[2]
the material types of intra_grid and extra_grid grids.
void destroy()
Currently we only need to close the file logger.
double timer_val(const int timer_id)
figure out current value of a signal linked to a given timer
sf_vec * phie_dummy
no elliptic solver needed, but we need a dummy for phie to use parabolic solver
eikonal_solver eik_solver
Solver for the eikonal equation.
LAT_detector lat
the activation time detector
gvec_data gvec
datastruct holding global IMP state variable output
generic_timing_stats IO_stats
grid_t
An electrics grid identifier to distinguish between intra and extra grids.
igb_output_manager output_manager_cycle
void initialize()
Initialize the Eikonal class.
igb_output_manager output_manager_time
class handling the igb output
SF::vector< SF_real > j_cvrest
void FIM()
Standard fast iterative method to solve eikonal equation with active list approach.
void update_repolarization_times_from_rd(sf_vec &Vmv, sf_vec &Vmv_old, double time)
Checks if Vm crosses the repolarization threshold during each time step of the parabolic solver and u...
SF::vector< SF_real > fiber_node
SF::vector< SF_real > cv_ar_t
SF::vector< SF_real > T_R
SF::vector< mesh_int_t > n2e_dsp
SF::vector< SF_real > T_A
SF::vector< SF_real > CVnodes
SF::vector< SF_real > k_cvrest
SF::vector< SF_real > z_coord
SF::vector< SF_real > p_cvrest
SF::vector< SF_real > TA_old
SF::vector< SF_real > cv_ar_n
SF::vector< SF_real > sheet_node
void set_initial_cv()
Set the initial conduction velocity (CV) parameters for the nodes in the mesh.
SF::vector< SF_real > x_coord
SF::vector< diffusion_current > diff_cur
void init()
Initialize vectors and variables in the eikonal_solver class.
SF::vector< mesh_int_t > e2n_con
bool determine_model_to_run(double &time)
Determine the next model to run in the alternation between RD and Eikonal.
SF::vector< mesh_int_t > stim_status
SF::vector< mesh_int_t > elem_start
SF::vector< mesh_int_t > StimulusPoints
void save_eikonal_state(const char *tsav_ext)
Save the current state of variables related to the Eikonal simulation to a file to initialize a futur...
void compute_bc()
Computes and updates boundary counditions in cycFIM.
void compute_diffusion_current(const double &time, sf_vec &vm)
Compute the diffusion current approximation I_diff in all activated nodes. Only converged nodes are c...
std::vector< mesh_int_t > n2n_connect
void set_stimuli(SF::vector< stimulus > &stimuli)
Simple setter for stimulus vector.
SF::vector< mesh_int_t > e2n_cnt
SF::vector< SF_real > y_coord
SF::vector< mesh_int_t > n2e_con
void clean_list()
Clean the list of nodes by resetting their status and tracking changes based on the time step of the ...
SF::vector< SF_real > D_I
SF::vector< mesh_int_t > nReadded2List
SF::vector< mesh_int_t > num_changes
std::vector< mesh_int_t > n2n_dsp
SF::vector< SF_real > l_cvrest
SF::vector< SF_real > StimulusTimes
SF::vector< mesh_int_t > n2e_cnt
void cycFIM()
Implementation of the cyclical fast iterative method used in step A of the DREAM model.
void update_repolarization_times(const Ionics &ion)
Estimates initial repolarization times (T_R) in Step D of DREAM.
eikonal_solver_stats stats
SF::vector< SF_real > CVnodes_mod
SF::vector< mesh_int_t > List
Tissue level electrics, main Electrics physics class.
Electrical ionics functions and LIMPET wrappers.
@ X
Definition: kdpart.hpp:64
@ Y
Definition: kdpart.hpp:64
constexpr T min(T a, T b)
Definition: ion_type.h:33
@ intra_elec_msh
Definition: sf_interface.h:59
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:162
Basic physics types.
Interface to SlimFem.
Simulator-level utility execution control functions.
Electrical stimulation functions.
description of materal properties in a mesh
Definition: fem_types.h:110
for analysis of the computations done to solve the eikonal model
Definition: timers.h:36
File descriptor struct.
Definition: basics.h:133
for analysis of the #iterations to solve CG
Definition: timers.h:69
Struct used for debugging purposes.
const char * reasonOut
reason for list entry
SF_real T_R
repolarization time
void init_logger(const char *filename)
void log_stats(double tm, bool cflg)
SF_real D_I
diastolic interval
mesh_int_t idXNB
neighboring node index responsible for list entry
const char * reasonIn
reason for list entry
SF_real T_A_
previous activation time
SF_real T_A
current activation time
SF_real nbn_T_A
activation time of neighboring node
mesh_int_t cycle
DREAM cycle.
mesh_int_t idX
node index
void update_status(enum status s, enum reason r)