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 #pragma once
28 
29 #ifndef _EIKONAL_H
30 #define _EIKONAL_H
31 
32 #include <array>
33 
34 #include "SF_globals.h"
35 #include "electrics.h"
36 #include "physics_types.h"
37 #include "sim_utils.h"
38 #include "stimulate.h"
39 
40 #include "sf_interface.h"
41 #include "timers.h"
42 #include "ionics.h"
43 #include "basics.h"
44 
45 namespace opencarp
46 {
51 struct node_stats {
52  enum status { in = 1,
53  out = 0 };
54  enum reason { none = 0,
55  nbn = 1,
56  conv = 2,
57  stim = 3 };
61  SF_real T_A = std::numeric_limits<double>::quiet_NaN();
62  SF_real nbn_T_A = std::numeric_limits<double>::quiet_NaN();
63  SF_real T_A_ = std::numeric_limits<double>::quiet_NaN();
64  SF_real T_R = std::numeric_limits<double>::quiet_NaN();
65  SF_real D_I = std::numeric_limits<double>::quiet_NaN();
66  const char* status = "out";
67  const char* reasonIn = "-";
68  const char* reasonOut = "-";
69 
70  FILE_SPEC logger = NULL;
71 
73  {
74  f_close(logger);
75  }
76 
77  void init_logger(const char* filename);
78  void log_stats(double tm, bool cflg);
79  void update_status(enum status s, enum reason r);
80 };
81 
83 {
84  public:
85  eikonal_solver() : stimuliRef(nullptr) {}
86 
87  const double inf = std::numeric_limits<double>::infinity();
88 
89  // data to dump
91 
92  // Has to be kept in line with param_globals::eik_solve
93  enum Idiff_t { FOOT = 0,
94  GAUSS = 1 };
96 
99  SF_real A_F = 1;
111  };
112 
113  // Vectors
115  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
116  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
117  SF::vector<mesh_int_t> StimulusPoints; // Nodes that have initial stimulus
118  SF::vector<SF_real> StimulusTimes; // Times when the initial nodes are stimulated
119  mesh_int_t Index_currStim; // index of the row in the table of stimuli and points
121 
122  // mesh related data
123  mesh_int_t MESH_SIZE; // number of points per element
124  bool twoFib; // true if there is sheet information, false if there is only fiber orientation
125  size_t num_pts;
126  SF::vector<mesh_int_t> e2n_con; // Connectivity vector with nodes that belong to each element
127  SF::vector<mesh_int_t> elem_start; // For the i_th element elem_start[j] stores its starting position in the "connect" vector
128  std::vector<mesh_int_t> n2n_connect, n2n_dsp;
130 
131  // Element data storage for anisotropy and CV
132  std::vector<SF::dmat<double>> S;
133  std::vector<double> CV_L;
134 
135  // CV restitution parameters
137 
138  // export vectors
139  sf_vec* Idiff = nullptr;
140  sf_vec* AT = nullptr;
141  sf_vec* RT = nullptr;
142 
143  // eikonal solver statistics
145 
147  {
148  if (Idiff) delete Idiff;
149  if (AT) delete AT;
150  if (RT) delete RT;
151  if (stimuliRef) delete stimuliRef;
152  }
153 
155  void init();
156 
165  bool determine_model_to_run(double& time);
166 
168  void set_stimuli(SF::vector<stimulus>& stimuli) { stimuliRef = &stimuli; }
169 
184  void clean_list();
185 
197  void save_eikonal_state(const char* tsav_ext);
198 
210  void update_repolarization_times(const Ionics& ion);
211 
213  void cycFIM();
214 
216  void FIM();
217 
243  void update_repolarization_times_from_rd(sf_vec& Vmv, sf_vec& Vmv_old, double time);
244 
288  void compute_diffusion_current(const double& time, sf_vec& vm);
289 
321 
322  private:
323  // stimulus pointer
324  SF::vector<stimulus>* stimuliRef = nullptr;
325 
334  void compute_bc();
335 
371  void precompute_squared_anisotropy_metric();
372 
373  // --- Small helpers for active list management ---
374  inline void add_to_active(std::vector<mesh_int_t>& active,
375  std::vector<char>& in_active,
376  mesh_int_t node)
377  {
378  if (!in_active[node]) {
379  in_active[node] = 1;
380  active.push_back(node);
381  }
382  }
383 
384  inline void remove_from_active(std::vector<char>& in_active, mesh_int_t node)
385  {
386  in_active[node] = 0;
387  }
388 
397  void update_Ta_in_active_list();
398 
444  SF_real compute_H(mesh_int_t& indX, SF_real& tmpTA);
445 
476  SF_real compute_coherence(mesh_int_t& indX);
477 
504  SF_real update(mesh_int_t& indX, SF_real CVrest_factor = 1.0, bool isDREAM = false);
505 
539  template <int N>
540  SF_real update_impl(mesh_int_t& indX, SF_real CVrest_factor = 1.0, bool CheckValidity = false);
541 
572  template <int N>
573  bool is_not_valid_update(const std::array<int, N>& nodeIDs, double time);
574 
582  bool add_node_neighbor_to_list(SF_real& RT, SF_real& oldTA, SF_real& newTA);
583 
585  void translate_stim_to_eikonal();
586 
613  void create_node_to_node_graph();
614 
616  void load_state_file();
617 };
618 
619 class Eikonal : public Basic_physic
620 {
621  public:
628  enum grid_t { intra_grid = 0,
632 
635 
638 
640  sf_vec* phie_dummy = nullptr;
641 
645 
648 
651  // Has to be kept in line with param_globals::eik_solve
652  enum eikonal_t { EIKONAL = 0,
653  REp = 1,
654  REm = 2,
655  DREAM = 3 };
657 
660 
663 
667 
668  bool do_output_eikonal = false;
669 
671 
676  {
677  name = "Eikonal";
678  }
679 
688  void initialize();
689 
690  void destroy();
691  void compute_step();
692  void output_step();
693 
694  inline void output_timings()
695  {
696  // since ionics are included in electrics, we substract ionic timings from electric timings
699 
700  // now we call the base class timings output for Electrics
702  // and then for ionics
704  }
705 
707 
709  double timer_val(const int timer_id);
710 
712  std::string timer_unit(const int timer_id);
713 
714  private:
716  void solve_EIKONAL();
718  void solve_RE();
720  void solve_DREAM();
722  void solve_RD();
723 
725  void setup_stimuli();
727  void stimulate_intracellular();
730  void clamp_Vm();
731 
733  void setup_solvers();
734 
736  void setup_mappings();
737 
739  void setup_output();
740 
742  void dump_matrices();
743 
744  void checkpointing();
745 
752  void set_elec_tissue_properties(MaterialType* mtype, Eikonal::grid_t g, FILE_SPEC logger);
753 };
754 
755 template <int MESH_SIZE>
757 {
758  private:
759  SF::dmat<double>& D;
760  std::array<SF::Point, MESH_SIZE>& points;
761  std::array<double, MESH_SIZE>& values;
762 
781  double tsitsiklis_update_line(const std::array<SF::Point, 2>& base,
782  const SF::dmat<double>& D,
783  const double& value);
806  double tsitsiklis_update_triangle(const std::array<SF::Point, 3>& base,
807  const SF::dmat<double>& D,
808  const std::array<double, 2>& values);
832  double tsitsiklis_update_tetra(const std::array<SF::Point, 4>& base,
833  const SF::dmat<double>& D,
834  const std::array<double, 3>& values);
835 
836  public:
837  LocalSolver(SF::dmat<double>& D, std::array<SF::Point, MESH_SIZE>& points, std::array<double, MESH_SIZE>& values)
838  : D(D), points(points), values(values) {}
839 
840  // This function performs the local solver, returning the solution value for the last point with reference to
841  // point order of constructor input
842  double solve();
843 };
844 
845 template class LocalSolver<2>;
846 
847 template class LocalSolver<3>;
848 
849 template class LocalSolver<4>;
850 
851 } // namespace opencarp
852 
853 #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
LocalSolver(SF::dmat< double > &D, std::array< SF::Point, MESH_SIZE > &points, std::array< double, MESH_SIZE > &values)
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)
Updates node repolarization times based on transmembrane voltage crossing.
SF::vector< SF_real > T_R
void init_imp_region_properties()
Initializes diffusion current models and CV restitution parameters per mesh node.
SF::vector< mesh_int_t > n2e_dsp
SF::vector< SF_real > T_A
SF::vector< SF_real > TA_old
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
SF::vector< SF_real > rho_cvrest
std::vector< double > CV_L
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...
SF::vector< SF_real > denom_cvrest
void compute_diffusion_current(const double &time, sf_vec &vm)
Computes the stimulus-driven diffusion current at mesh nodes.
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< 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< SF_real > theta_cvrest
SF::vector< mesh_int_t > num_changes
std::vector< mesh_int_t > n2n_dsp
SF::vector< SF_real > StimulusTimes
SF::vector< SF_real > kappa_cvrest
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< mesh_int_t > List
std::vector< SF::dmat< double > > S
Tissue level electrics, main Electrics physics class.
Electrical ionics functions and LIMPET wrappers.
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)