openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
electrics_eikonal.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: Apache-2.0
3 
12 #pragma once
13 
14 #ifndef _EIKONAL_H
15 #define _EIKONAL_H
16 
17 #include <array>
18 
19 #include "SF_globals.h"
20 #include "electrics.h"
21 #include "physics_types.h"
22 #include "sim_utils.h"
23 #include "stimulate.h"
24 
25 #include "sf_interface.h"
26 #include "timers.h"
27 #include "ionics.h"
28 #include "basics.h"
29 
30 namespace opencarp
31 {
36 struct node_stats {
37  enum status { in = 1,
38  out = 0 };
39  enum reason { none = 0,
40  nbn = 1,
41  conv = 2,
42  stim = 3 };
46  SF_real T_A = std::numeric_limits<double>::quiet_NaN();
47  SF_real nbn_T_A = std::numeric_limits<double>::quiet_NaN();
48  SF_real T_A_ = std::numeric_limits<double>::quiet_NaN();
49  SF_real T_R = std::numeric_limits<double>::quiet_NaN();
50  SF_real D_I = std::numeric_limits<double>::quiet_NaN();
51  const char* status = "out";
52  const char* reasonIn = "-";
53  const char* reasonOut = "-";
54 
55  FILE_SPEC logger = NULL;
56 
58  {
59  f_close(logger);
60  }
61 
62  void init_logger(const char* filename);
63  void log_stats(double tm, bool cflg);
64  void update_status(enum status s, enum reason r);
65 };
66 
68 {
69  public:
70  eikonal_solver() : stimuliRef(nullptr) {}
71 
72  const double inf = std::numeric_limits<double>::infinity();
73 
74  // data to dump
76 
77  // Has to be kept in line with param_globals::eik_solve
78  enum Idiff_t { FOOT = 0,
79  GAUSS = 1 };
81 
84  SF_real A_F = 1;
96  };
97 
98  // Vectors
100  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
101  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
102  SF::vector<mesh_int_t> StimulusPoints; // Nodes that have initial stimulus
103  SF::vector<SF_real> StimulusTimes; // Times when the initial nodes are stimulated
104  mesh_int_t Index_currStim; // index of the row in the table of stimuli and points
106 
107  // mesh related data
108  mesh_int_t MESH_SIZE; // number of points per element
109  bool twoFib; // true if there is sheet information, false if there is only fiber orientation
110  size_t num_pts;
111  SF::vector<mesh_int_t> e2n_con; // Connectivity vector with nodes that belong to each element
112  SF::vector<mesh_int_t> elem_start; // For the i_th element elem_start[j] stores its starting position in the "connect" vector
113  std::vector<mesh_int_t> n2n_connect, n2n_dsp;
115 
116  // Element data storage for anisotropy and CV
117  std::vector<SF::dmat<double>> S;
118  std::vector<double> CV_L;
119 
120  // CV restitution parameters
122 
123  // export vectors
124  sf_vec* Idiff = nullptr;
125  sf_vec* AT = nullptr;
126  sf_vec* RT = nullptr;
127 
128  // eikonal solver statistics
130 
132  {
133  if (Idiff) delete Idiff;
134  if (AT) delete AT;
135  if (RT) delete RT;
136  if (stimuliRef) delete stimuliRef;
137  }
138 
140  void init();
141 
150  bool determine_model_to_run(double& time);
151 
153  void set_stimuli(SF::vector<stimulus>& stimuli) { stimuliRef = &stimuli; }
154 
169  void clean_list();
170 
182  void save_eikonal_state(const char* tsav_ext);
183 
195  void update_repolarization_times(const Ionics& ion);
196 
198  void cycFIM();
199 
201  void FIM();
202 
228  void update_repolarization_times_from_rd(sf_vec& Vmv, sf_vec& Vmv_old, double time);
229 
273  void compute_diffusion_current(const double& time, sf_vec& vm);
274 
306 
307  private:
308  // stimulus pointer
309  SF::vector<stimulus>* stimuliRef = nullptr;
310 
319  void compute_bc();
320 
356  void precompute_squared_anisotropy_metric();
357 
358  // --- Small helpers for active list management ---
359  inline void add_to_active(std::vector<mesh_int_t>& active,
360  std::vector<char>& in_active,
361  mesh_int_t node)
362  {
363  if (!in_active[node]) {
364  in_active[node] = 1;
365  active.push_back(node);
366  }
367  }
368 
369  inline void remove_from_active(std::vector<char>& in_active, mesh_int_t node)
370  {
371  in_active[node] = 0;
372  }
373 
382  void update_Ta_in_active_list();
383 
429  SF_real compute_H(mesh_int_t& indX, SF_real& tmpTA);
430 
461  SF_real compute_coherence(mesh_int_t& indX);
462 
489  SF_real update(mesh_int_t& indX, SF_real CVrest_factor = 1.0, bool isDREAM = false);
490 
524  template <int N>
525  SF_real update_impl(mesh_int_t& indX, SF_real CVrest_factor = 1.0, bool CheckValidity = false);
526 
557  template <int N>
558  bool is_not_valid_update(const std::array<int, N>& nodeIDs, double time);
559 
567  bool add_node_neighbor_to_list(SF_real& RT, SF_real& oldTA, SF_real& newTA);
568 
570  void translate_stim_to_eikonal();
571 
598  void create_node_to_node_graph();
599 
601  void load_state_file();
602 };
603 
604 class Eikonal : public Basic_physic
605 {
606  public:
613  enum grid_t { intra_grid = 0,
617 
620 
623 
625  sf_vec* phie_dummy = nullptr;
626 
630 
633 
636  // Has to be kept in line with param_globals::eik_solve
637  enum eikonal_t { EIKONAL = 0,
638  REp = 1,
639  REm = 2,
640  DREAM = 3 };
642 
645 
648 
652 
653  bool do_output_eikonal = false;
654 
656 
661  {
662  name = "Eikonal";
663  }
664 
673  void initialize();
674 
675  void destroy();
676  void compute_step();
677  void output_step();
678 
679  inline void output_timings()
680  {
681  // since ionics are included in electrics, we substract ionic timings from electric timings
684 
685  // now we call the base class timings output for Electrics
687  // and then for ionics
689  }
690 
692 
694  double timer_val(const int timer_id);
695 
697  std::string timer_unit(const int timer_id);
698 
699  private:
701  void solve_EIKONAL();
703  void solve_RE();
705  void solve_DREAM();
707  void solve_RD();
708 
710  void setup_stimuli();
712  void stimulate_intracellular();
715  void clamp_Vm();
716 
718  void setup_solvers();
719 
721  void setup_mappings();
722 
724  void setup_output();
725 
727  void dump_matrices();
728 
729  void checkpointing();
730 
737  void set_elec_tissue_properties(MaterialType* mtype, Eikonal::grid_t g, FILE_SPEC logger);
738 };
739 
740 template <int MESH_SIZE>
742 {
743  private:
744  SF::dmat<double>& D;
745  std::array<SF::Point, MESH_SIZE>& points;
746  std::array<double, MESH_SIZE>& values;
747 
766  double tsitsiklis_update_line(const std::array<SF::Point, 2>& base,
767  const SF::dmat<double>& D,
768  const double& value);
791  double tsitsiklis_update_triangle(const std::array<SF::Point, 3>& base,
792  const SF::dmat<double>& D,
793  const std::array<double, 2>& values);
817  double tsitsiklis_update_tetra(const std::array<SF::Point, 4>& base,
818  const SF::dmat<double>& D,
819  const std::array<double, 3>& values);
820 
821  public:
822  LocalSolver(SF::dmat<double>& D, std::array<SF::Point, MESH_SIZE>& points, std::array<double, MESH_SIZE>& values)
823  : D(D), points(points), values(values) {}
824 
825  // This function performs the local solver, returning the solution value for the last point with reference to
826  // point order of constructor input
827  double solve();
828 };
829 
830 template class LocalSolver<2>;
831 
832 template class LocalSolver<3>;
833 
834 template class LocalSolver<4>;
835 
836 } // namespace opencarp
837 
838 #endif
opencarp::local_index_t mesh_int_t
Definition: SF_container.h:31
opencarp::real_t SF_real
Global scalar type.
Definition: SF_globals.h:18
Basic utility structs and functions, mostly IO related.
A vector storing arbitrary data.
Definition: SF_vector.h:28
The abstract physics interface we can use to trigger all physics.
Definition: physics_types.h:44
virtual void output_timings()
Definition: physics_types.h:61
FILE_SPEC logger
The logger of the physic, each physic should have one.
Definition: physics_types.h:49
const char * name
The name of the physic, each physic should have one.
Definition: physics_types.h:47
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:18
@ intra_elec_msh
Definition: sf_interface.h:45
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:150
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:106
for analysis of the computations done to solve the eikonal model
Definition: timers.h:39
File descriptor struct.
Definition: basics.h:120
for analysis of the #iterations to solve CG
Definition: timers.h:72
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)