openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
ION_IF.cc
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 
28 /*
29  * Specify an interface for an IMP
30  *
31  * To use an IMP by itself outside of MULTI_IF.h, one must \n
32  * -# alloc_IIF()
33  * -# set the rdata pointers in the ::IMPDataStruct
34  * -# initialize_params()
35  * -# initialize_IIF()
36  * -# call the compute() method of the IMP
37  *
38  * The IMP library tries to avoid undo computation by using lookup
39  * tables to avoid computation of costly mathematical functions.
40  * Tables indices may be computed based on vltage, calcium concentrations,
41  * or any other quantity.
42  *
43  * One common scenario is commonly encountered with first-order differential
44  * equations:
45  * \f[ \frac{dz}{dt} = \frac{z_{\infty}(x) - z}{\tau_z(x)} \f]
46  *
47  * Using an exponential solution assuming that
48  * \f$z_{\inf}(x)\f$ and \f$\tau_z(x)\f$ constant over a time step:
49  *
50  * \f[ \begin{split}
51  * z_{i+1} & = z_{\infty}(x) - (z_{\infty}(x)-z_i)
52  * \exp\Large (-\Delta t/\tau_z(x) \Large ) \\
53  * & = A(x) + B(x) z_i
54  * \end{split}\f]
55  * where A(x) and B(x) are entered into a look up table which is
56  * indexed by \em x:
57  * \f[ \begin{split}
58  * A(x) &= z_{\infty}(x)\Large ( 1 - \exp(-\Delta t/\tau_z(x)\Large ) \\
59  * &= -z_{\infty}(x) expm1\Large ( -\Delta t/\tau_z(x) \Large ) \\
60  * B(x) &= \exp(-\Delta t/\tau_z(x))
61  * \end{split}\f]
62  *
63  */
64 #include "limpet_types.h"
65 #include "ION_IF.h"
66 #include "petsc_utils.h" // for EXIT
67 #include <stdarg.h>
68 
69 #ifdef USE_CVODE
70 #include <nvector/nvector_serial.h>
71 #include <cvode/cvode.h>
72 #include <cvode/cvode_diag.h>
73 #endif
74 
75 namespace limpet {
76 
80 using ::opencarp::Salt_list;
81 
82 #ifdef USE_HDF5
83 FILE_SPEC _nc_logf = (FILE_SPEC)calloc(1, sizeof(fileptr));
84 #else
86 #endif
87 
88 
89 char* tokstr_r(char *s1, const char *s2, char **lasts)
90 {
91  char *ret;
92 
93  if (s1 == NULL)
94  s1 = *lasts;
95  while(*s1 && strchr(s2, *s1))
96  ++s1;
97  if(*s1 == '\0')
98  return NULL;
99  ret = s1;
100  while(*s1 && !strchr(s2, *s1))
101  ++s1;
102  if(*s1)
103  *s1++ = '\0';
104  *lasts = s1;
105  return ret;
106 }
107 
108 
109 #ifndef offsetof
110 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
111 #endif
112 
113 // struct exception_context the_exception_context[1];
114 
116 
117 IonIfBase::IonIfBase(const IonType& type, Target target, node_count_t num_node, const std::vector<std::reference_wrapper<IonType>>& plugins)
118  : _type(type), _target(type.select_target(target)), _num_node(num_node) {
119  this->_tstp = {};
120  this->_reqdat = type.reqdat();
121  this->_moddat = type.moddat();
122  this->_plugins = {};
123 
124  for (const auto& plugin : plugins) {
125  auto child = plugin.get().make_ion_if(target, num_node, {});
126  child->_parent = this;
127  this->_plugins.push_back(child);
128 
129  this->_reqdat |= child->_reqdat;
130  this->_moddat |= child->_moddat;
131  }
132 }
133 
135  for (auto plugin : this->_plugins) {
136  plugin->get_type().destroy_ion_if(plugin);
137  }
138 
139  this->_type.destroy(*this);
140  if (this->_tables_d != nullptr) {
141  deallocate_on_target<LUT>(this->_target, this->_tables_d);
142  }
143 }
144 
145 const IonType& IonIfBase::get_type() const {
146  return this->_type;
147 }
148 
150  return this->_num_node;
151 }
152 
153 std::size_t IonIfBase::get_num_threads() const {
154  std::size_t num_threads = 0;
155  switch (this->_target) {
156  // CPU target threads number depends on wether OpenMP is enabled or not
157  case Target::CPU:
158  case Target::MLIR_CPU:
159 #ifdef _OPENMP
160  num_threads = omp_get_max_threads();
161 #else
162  num_threads = 1;
163 #endif
164  break;
165  // GPU targets threads numbers is the number of cells
166  case Target::MLIR_CUDA:
167  case Target::MLIR_ROCM:
168  num_threads = this->get_num_node();
169  break;
170  default:
171  throw std::logic_error("The IonIf execution target " + std::to_string(this->_target) + " is invalid");
172  break;
173  }
174  return num_threads;
175 }
176 
178  return this->_parent;
179 }
180 
182  this->_parent = parent;
183 }
184 
185 std::vector<IonIfBase*>& IonIfBase::plugins() {
186  return this->_plugins;
187 }
188 
189 uint32_t IonIfBase::get_reqdat() const {
190  return this->_reqdat;
191 }
192 
193 uint32_t IonIfBase::get_moddat() const {
194  return this->_moddat;
195 }
196 
197 void IonIfBase::set_moddat(uint32_t data) {
198  this->_moddat = data;
199 }
200 
201 float IonIfBase::get_dt() const {
202  return this->dt;
203 }
204 
205 void IonIfBase::set_dt(float dt) {
206  this->dt = dt;
207 }
208 
210  return this->_tstp;
211 }
212 
213 std::vector<LUT>& IonIfBase::tables() {
214  return this->_tables;
215 }
216 
218  return this->_n_tables_d;
219 }
220 
222  if (is_concrete(this->get_type().select_target(target))) {
223  this->_target = target;
224  }
225  else {
226  throw std::invalid_argument("new target set for IMP is unavailable or not concrete (AUTO, UNKNWOWN, ...)");
227  }
228 }
229 
231  this->_type.initialize_params(*this);
232 
233  for (auto& plugin : this->_plugins) {
234  plugin->initialize_params();
235  }
236 }
237 
238 void IonIfBase::initialize(double dt, GlobalData_t **impdat) {
245  this->dt = dt;
246 
247  if (this->_num_node) {
248  this->_type.construct_tables(*this);
249  // If this is a GPU target, we need to copy the LUT definitions to the
250  // device
251  if (is_gpu(this->get_target()) && this->tables().size() > 0) {
252  // Allocate on device and copy
253  this->_tables_d = allocate_on_target<LUT>(this->get_target(), this->tables().size());
254  // TODO replace this with some kind of memcpy (needs to be adjusted
255  // depending on CUDA / HIP
256  for (size_t i = 0; i < this->tables().size(); ++i) {
257  this->_tables_d[i] = this->tables()[i];
258  }
259  this->_n_tables_d = this->tables().size();
260  }
261  }
262 
263  this->_type.initialize_sv(*this, impdat);
264  this->ldata = impdat;
265 
266  for (auto& plugin : this->_plugins) {
267  plugin->initialize(dt, impdat);
268  }
269 }
270 
272  this->_type.compute(this->_target, start, end, *this, data);
273 }
274 
275 char* IonIfBase::fill_buf(char *buf, int* n, opencarp::Salt_list *l) const {
276  int iif_sz = this->get_sv_size();
277 
278  for (auto& plugin : this->_plugins) {
279  iif_sz += plugin->get_sv_size();
280  }
281 
282  buf = (char *) realloc(buf, *n + l->nitems*iif_sz) + *n;
283  *n += l->nitems * iif_sz;
284 
285  return buf - *n + l->nitems * iif_sz;
286 }
287 
289  size_t *offset, IMPinfo *impinfo, const global_node_index_t* loc2canon) {
290  if( !impinfo->compatible )
291  return n;
292 
293  char *ptr = (char *)(this->get_sv_address());
294  long base = ftell(in->fd);
295  node_count_t mismatch = 0;
296 
297  // Restoration of the model data need to take care of the data layout
298  // optimization. (if it is disabled, the vector size should be 1 anyways
299  std::size_t vec_size = this->get_type().dlo_vector_size();
300  for( node_index_t i=0; i<n; i+=vec_size ) {
301  node_index_t index = i / vec_size;
302  global_node_index_t canon = loc2canon[pos[i]];
303  if(mask[canon] == this->miifIdx) {
304  fseek(in->fd, base+offset[canon], SEEK_SET);
305  fread(ptr+index*impinfo->sz, impinfo->sz, 1, in->fd);
306 
307  for(int j=0; j<impinfo->nplug; j++) {
308  if(impinfo->plug[j].compatible) {
309  fread((char*)(this->_plugins[impinfo->plug[j].map]->get_sv_address())+index*impinfo->plug[j].sz,
310  impinfo->plug[j].sz, 1, in->fd);
311  }
312  else
313  fseek(in->fd, impinfo->plug[j].sz, SEEK_CUR);
314  }
315  }
316  else
317  mismatch++;
318  }
319  return mismatch;
320 }
321 
322 const std::vector<IonIfBase::sv_field>& IonIfBase::sv_layout() const {
323  if (!_sv_layout_valid) {
324  char** list = NULL;
325  int nsv = this->get_type().get_sv_list(&list);
326  _sv_layout.reserve(nsv);
327  for (int i = 0; i < nsv; i++) {
328  int off = 0, sz = 0, type = 0;
329  char* type_name = NULL;
330  this->get_type().get_sv_offset(list[i], &off, &sz);
331  this->get_type().get_sv_type(list[i], &type, &type_name);
332  free(type_name);
333  _sv_layout.push_back({list[i], off, sz, type});
334  free(list[i]);
335  }
336  free(list);
337  _sv_layout_valid = true;
338  }
339  return _sv_layout;
340 }
341 
342 void IonIfBase::get_sv_layout(std::vector<std::pair<int, int>>& fields) const {
343  const std::vector<sv_field>& layout = this->sv_layout();
344  fields.clear();
345  fields.reserve(layout.size());
346  for (const auto& f : layout)
347  fields.emplace_back(f.off, f.sz);
348 }
349 
351  size_t total = 0;
352  for (const auto& f : this->sv_layout())
353  total += static_cast<size_t>(f.sz);
354  return total;
355 }
356 
357 uint64_t IonIfBase::sv_fingerprint() const {
358  constexpr uint64_t kFNVOffsetBasis = 0xcbf29ce484222325ULL; // 14695981039346656037
359  constexpr uint64_t kFNVPrime = 0x100000001b3ULL; // 1099511628211
360  uint64_t h = kFNVOffsetBasis;
361  auto mix = [&h](unsigned char b) { h ^= b; h *= kFNVPrime; };
362  for (const auto& f : this->sv_layout()) {
363  for (unsigned char c : f.name) mix(c);
364  mix(0); // name terminator, so {"ab","c"} and {"a","bc"} differ
365  for (int b = 0; b < 4; b++)
366  mix((static_cast<uint32_t>(f.sz) >> (8 * b)) & 0xff);
367  for (int b = 0; b < 4; b++)
368  mix((static_cast<uint32_t>(f.type) >> (8 * b)) & 0xff);
369  }
370  return h;
371 }
372 
374  IIF_Mask_t *mask, size_t *offset, IMPinfo *impinfo,
375  const global_node_index_t* loc2canon) {
376  if( !impinfo->compatible )
377  return n;
378 
379  long base = ftell(in->fd);
380  node_count_t mismatch = 0;
381 
382  // field layouts are model properties: gather them once, not per node
383  std::vector<std::pair<int, int>> main_fields;
384  this->get_sv_layout(main_fields);
385 
386  std::vector<std::vector<std::pair<int, int>>> plug_fields(impinfo->nplug);
387  for (int j = 0; j < impinfo->nplug; j++)
388  if (impinfo->plug[j].compatible)
389  this->_plugins[impinfo->plug[j].map]->get_sv_layout(plug_fields[j]);
390 
391  for( node_index_t i=0; i<n; i++ ) {
392  global_node_index_t canon = loc2canon[pos[i]];
393  if(mask[canon] == this->miifIdx) {
394  fseek(in->fd, base+offset[canon], SEEK_SET);
395  // a short read means the checkpoint is truncated within the state payload,
396  // which the header-level checks in restore_state cannot catch; abort rather
397  // than scatter stale bytes into the state. A zero-width field (e.g. a
398  // placeholder SV whose per-lane size rounds to 0 under DLO) reads nothing;
399  // fread reports 0 items for size 0, which must not be read as truncation.
400  auto scatter = [&](char* dst, std::size_t sz) {
401  if (sz && fread(dst, sz, 1, in->fd) != 1) {
402  log_msg(NULL, 5, 0, "Truncated ionic-state checkpoint during restore");
403  EXIT(EXIT_FAILURE);
404  }
405  };
406 
407  this->for_each_sv_field(i, main_fields, scatter);
408  for(int j=0; j<impinfo->nplug; j++) {
409  if(impinfo->plug[j].compatible)
410  this->_plugins[impinfo->plug[j].map]->for_each_sv_field(i, plug_fields[j], scatter);
411  else
412  fseek(in->fd, impinfo->plug[j].sz, SEEK_CUR);
413  }
414  }
415  else
416  mismatch++;
417  }
418  return mismatch;
419 }
420 
421 int IonIfBase::dump_luts(bool zipped) {
422  std::string name;
423  std::string ext = zipped ? ".gz" : "";
424 
425  int dcnt = 0;
426  for (int i=0; i < this->_tables.size(); i++) {
427  // determine file name
428  if (strcmp(this->_tables[i].name, ""))
429  name = this->_type.get_name() + "_LUT_" + this->_tables[i].name + ".bin" + ext;
430  else
431  name = this->_type.get_name() + "_LUT_" + std::to_string(i) + ".bin" + ext;
432 
433  // dump table
434  int err = LUT_dump(&this->_tables[i], name.c_str());
435  if (!err) dcnt++;
436  }
437  return dcnt;
438 }
439 
441  for (auto& lut : this->_tables) {
442  destroy_lut(&lut, this->_target);
443  }
444 
445  std::vector<LUT>().swap(this->_tables);
446 }
447 
448 void IonIfBase::tune(const char *im_par, const char *plugs, const char *plug_par) {
449  char *opar, *oplg, *plg, *nplg, *parlst, *nparlst;
450 
451  if( im_par && *im_par != '\0' ) {
452  log_msg( _nc_logf, 0, 0, "Ionic model: %s", this->_type.get_name().c_str());
453  this->_type.tune(*this, im_par);
454  }
455  opar = parlst = dupstr(plug_par);
456  oplg = plg = dupstr(plugs);
457 
458  while( plg!=NULL && *plg!='\0' ) {
459  nparlst = get_next_list( parlst, ':' );
460  nplg = get_next_list( plg, ':' );
461 
462  log_msg( _nc_logf, 0, 0, "Plug-in: %s", plg );
463 
464  if( parlst==NULL || *parlst=='\0' ) {
465  parlst = nparlst;
466  plg = nplg;
467  continue;
468  }
469 
470  // find apropriate plugin
471  IonType* plugin = get_ion_type(plg);
472  int j;
473 
474  for(j = 0; j < this->_plugins.size(); j++) {
475  if(this->_plugins[j]->get_type() == *plugin) break;
476  }
477 
478  if(j == this->_plugins.size()) {
479  log_msg( _nc_logf, 2, 0, "Plugin %s not used with IM", plg );
480  plg = nplg;
481  parlst = nparlst;
482  continue;
483  }
484 
485  plugin->tune(*this->_plugins[j], parlst);
486  plg = nplg;
487  parlst = nparlst;
488  }
489 
490  log_msg( _nc_logf, 0, 0, "" );
491  free( opar );
492  free( oplg );
493 }
494 
495 int IonIfBase::read_svs(FILE* file) {
496  if(this->get_num_node())
497  return this->_type.read_svs(*this, file);
498  else
499  return 1;
500 }
501 
502 int IonIfBase::write_svs(FILE* file, node_index_t node) {
503  return this->_type.write_svs(*this, file, node);
504 }
505 
507  this->_plugins = {};
508 
509  for (auto& plugin : other.plugins()) {
510  auto copy = plugin->get_type().make_ion_if(this->_target, plugin->get_num_node(), {});
511  copy->_parent = this;
512  this->_plugins.push_back(copy);
513  copy->copy_SVs_from(*plugin, true);
514  }
515 }
516 
517 void IonIfBase::for_each(const std::function<void(IonIfBase&)>& consumer) {
518  consumer(*this);
519 
520  for (auto& plugin : this->_plugins) {
521  consumer(*plugin);
522  }
523 }
524 
536 // Is this ever used?
537 void initialize_ts(Target target, ts *tstp, int ng, int *skp, double dt)
538 {
539  // initialize step counter that will run linearly as long the
540  // simulation goes
541  tstp->cnt = -1;
542  tstp->ng = ng;
543  tstp->tcg = allocate_on_target<tc_grp>(target, ng);
544 
545  // initialize time constant grouping
546  // fast variables, use dt=dt
547  tstp->tcg[0].skp = 1;
548  tstp->tcg[0].dt = dt;
549  tstp->tcg[0].update = 1;
550 
551  for (int i=1;i<ng;i++) {
552  tstp->tcg[i].skp = skp[i];
553  tstp->tcg[i].dt = tstp->tcg[i].skp*dt;
554  }
555 }
556 
557 
566 void update_ts(ts *ptstp)
567 {
568  ptstp->cnt++;
569 
570  tc_grp *ptcg = ptstp->tcg;
571  for (int i=1;i<ptstp->ng;i++)
572  ptcg[i].update = !(ptstp->cnt%ptcg[i].skp);
573 }
574 
575 
576 #ifndef _GNU_SOURCE
586 void *memmem( void *haystack, int sz_hay, void *needle, int sz_n )
587 {
588  if( !sz_n ) return NULL;
589 
590  char *h = (char *)haystack;
591 
592  for( int i=0; i>sz_hay-sz_n+1; i++, h++ )
593  if( !memcmp( h, needle, sz_n ) )
594  return (void *)h;
595  break;
596 
597  return NULL;
598 }
599 #endif
600 
601 
612 char *get_next_list( char *lst, char delimiter )
613 {
614  if( lst == NULL || *lst == '\0' )
615  return NULL;
616 
617  while( *lst != delimiter && *lst != '\0' )
618  lst++;
619 
620  if( *lst != '\0' ) {
621  *lst = '\0';
622  return lst+1;
623  } else
624  return lst;
625 }
626 
627 
635  bool verify_flags( const char *flags, const char* given )
636  {
637  char *flag, *ptr, *gvn_cp = dupstr( given );
638 
639  flag = tokstr_r( gvn_cp, "|", &ptr );
640  while( flag ) {
641  if( !flag_set( flags, flag ) )
642  break;
643  flag = tokstr_r( NULL, "|", &ptr );
644  }
645 
646  free( gvn_cp );
647  return flag ? false : true;
648 }
649 
657 bool flag_set( const char *flags, const char *target )
658 {
659  if( !flags ) return false;
660 
661  char *f = dupstr( flags ), *last, *pos;
662 
663  pos = tokstr_r( f, "|", &last );
664  while( pos && strcmp( pos, target ) ) {
665  pos = tokstr_r( NULL, "|", &last );
666  }
667  free( f );
668 
669  return pos? true : false;
670 }
671 
672 
673 #ifdef USE_CVODE
674 
677 void __bogus_function_for_cvode() {
678 
679  int flag;
680  int N_CVODE = 1;
681 #if SUNDIALS_VERSION_MAJOR < 4
682  void* cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
683 #elif SUNDIALS_VERSION_MAJOR < 6
684  void* cvode_mem = CVodeCreate(CV_BDF);
685 #elif SUNDIALS_VERSION_MAJOR < 7
686  SUNContext sunctx;
687  MPI_Comm comm = PETSC_COMM_WORLD;
688  if( SUNContext_Create(&comm, &sunctx )<0 ){
689  assert(0);
690  }
691  void* cvode_mem = CVodeCreate(CV_BDF, sunctx);
692 #else // version from 7.0.0
693  SUNContext sunctx;
694  SUNComm comm = PETSC_COMM_WORLD;
695  if( SUNContext_Create( comm, &sunctx )<0 ){
696  assert(0);
697  }
698  void* cvode_mem = CVodeCreate(CV_BDF, sunctx);
699 #endif
700  assert(cvode_mem != NULL);
701 #if SUNDIALS_VERSION_MAJOR >= 6
702  N_Vector cvode_y = N_VNew_Serial(N_CVODE, sunctx);
703 #else
704  N_Vector cvode_y = N_VNew_Serial(N_CVODE);
705 #endif
706  flag = CVodeInit(cvode_mem, NULL, 0, cvode_y);
707  assert(flag == CV_SUCCESS);
708  N_VDestroy(cvode_y);
709 
710  flag = CVodeSStolerances(cvode_mem, 1e-5, 1e-6);
711  assert(flag == CV_SUCCESS);
712  flag = CVodeSetMaxStep(cvode_mem, 1);
713  assert(flag == CV_SUCCESS);
714  flag = CVodeSetUserData(cvode_mem, NULL);
715  assert(flag == CV_SUCCESS);
716  flag = CVDiag(cvode_mem);
717  assert(flag == CV_SUCCESS);
718 
719  NV_Ith_S(cvode_y,0) = 0;
720 
721  {
722  int CVODE_flag;
723  CVODE_flag = CVodeReInit(NULL, 1, NULL);
724  assert(CVODE_flag == CV_SUCCESS);
725  CVODE_flag = CVodeSetInitStep(NULL, 1);
726  assert(CVODE_flag == CV_SUCCESS);
727 #if SUNDIALS_VERSION_MAJOR >= 7
728  sunrealtype tret;
729 #else
730  realtype tret;
731 #endif
732  CVODE_flag = CVode(cvode_mem, 1, NULL, &tret, CV_NORMAL);
733  assert(CVODE_flag == CV_SUCCESS);
734  }
735 }
736 #endif
737 
738 } // namespace limpet
Represents the ionic model and plug-in (IMP) data structure.
Definition: ION_IF.h:142
virtual void initialize(double dt, GlobalData_t **impdat)
Initializes lookup table and state variable tables.
Definition: ION_IF.cc:238
void tune(const char *im_par, const char *plugs, const char *plug_par)
Tunes specific IMP parameters from files.
Definition: ION_IF.cc:448
Target _target
execution target for this IMP
Definition: ION_IF.h:155
void set_parent(IonIfBase *parent)
Definition: ION_IF.cc:181
node_count_t restore_per_node(opencarp::FILE_SPEC in, node_count_t n, const node_index_t *pos, IIF_Mask_t *mask, size_t *offset, IMPinfo *impinfo, const global_node_index_t *loc2canon)
Reads in the state variables for an IMP from a per-node (format >= 3) dump.
Definition: ION_IF.cc:373
virtual void set_target(Target target)
Definition: ION_IF.cc:221
const IonType & get_type() const
Gets this IMP's model type.
Definition: ION_IF.cc:145
char * fill_buf(char *buf, int *n, opencarp::Salt_list *l) const
Appends the state variables to a buffer.
Definition: ION_IF.cc:275
float get_dt() const
Gets the basic integration time step.
Definition: ION_IF.cc:201
int read_svs(FILE *file)
Reads state variable values for one cell from a file.
Definition: ION_IF.cc:495
void for_each_sv_field(node_index_t node, const std::vector< std::pair< int, int >> &fields, Fn &&fn)
Visits each state-variable field of one node, in storage order.
Definition: ION_IF.h:469
std::vector< LUT > & tables()
Gets the array of state variables.
Definition: ION_IF.cc:213
ts _tstp
control time stepping
Definition: ION_IF.h:157
std::vector< IonIfBase * > & plugins()
Returns a vector containing the plugins of this IMP.
Definition: ION_IF.cc:185
int dump_luts(bool zipped)
Dumps array of LUTs to file.
Definition: ION_IF.cc:421
void get_sv_layout(std::vector< std::pair< int, int >> &fields) const
Describes the per-node memory layout of this IMP's state variables.
Definition: ION_IF.cc:342
void compute(node_index_t start, node_index_t end, GlobalData_t **data)
Perform ionic model computation for 1 time step.
Definition: ION_IF.cc:271
virtual ~IonIfBase()
Virtual destructor declaration.
Definition: ION_IF.cc:134
int write_svs(FILE *file, node_index_t node)
Definition: ION_IF.cc:502
size_t get_sv_per_node_size() const
Size in bytes of one node's de-interleaved state-variable record.
Definition: ION_IF.cc:350
uint64_t sv_fingerprint() const
Fingerprint of this IMP's state-variable layout.
Definition: ION_IF.cc:357
void set_moddat(uint32_t data)
Set the data flag for this IMP's modified data.
Definition: ION_IF.cc:197
void set_dt(float dt)
Sets the basic integration time step.
Definition: ION_IF.cc:205
ts & get_tstp()
Gets the time stepper.
Definition: ION_IF.cc:209
void for_each(const std::function< void(IonIfBase &)> &consumer)
Executes the consumer functions on this IMP and each of its plugins.
Definition: ION_IF.cc:517
size_t get_n_tables_d() const
Gets the size of the array returned by IonIf::tables_d.
Definition: ION_IF.cc:217
IonIfBase * parent() const
Gets the parent IMP.
Definition: ION_IF.cc:177
void destroy_luts()
Destroys array of LUTs.
Definition: ION_IF.cc:440
Target get_target() const
Definition: ION_IF.h:352
node_count_t restore(opencarp::FILE_SPEC in, node_count_t n, const node_index_t *pos, IIF_Mask_t *mask, size_t *offset, IMPinfo *impinfo, const global_node_index_t *loc2canon)
Reads in the state variables for an IMP.
Definition: ION_IF.cc:288
uint32_t get_moddat() const
Gets the data flags for this IMP's modified data.
Definition: ION_IF.cc:193
int miifIdx
imp index within miif
Definition: ION_IF.h:154
virtual std::size_t get_sv_size() const =0
Gets the size of the structure this IMP uses for state variables.
void copy_plugins_from(IonIfBase &other)
Copies the plugins of an IMP.
Definition: ION_IF.cc:506
virtual void * get_sv_address()=0
Gets the raw address of the state variables for this IMP.
void initialize_params()
Initializes user modifiable parameters with default values defined in the respective ionic models.
Definition: ION_IF.cc:230
IonIfBase(const IonType &type, Target target, node_count_t num_node, const std::vector< std::reference_wrapper< IonType >> &plugins)
Constructor for IonIfBase.
Definition: ION_IF.cc:117
uint32_t get_reqdat() const
Gets the data flags for this IMP's required data.
Definition: ION_IF.cc:189
node_count_t get_num_node() const
Gets the number of nodes handled by this IMP.
Definition: ION_IF.cc:149
std::size_t get_num_threads() const
Gets the number of threads used for running this IMP.
Definition: ION_IF.cc:153
Abstract class representing an ionic model type.
Definition: ion_type.h:59
const std::string & get_name() const
Gets the model name.
Definition: ion_type.cc:23
virtual void initialize_params(IonIfBase &imp) const =0
Initializes the parameters in the given IMP.
virtual SVgetfcn get_sv_offset(const char *svname, int *off, int *sz) const =0
Get the offset and size of a state variable of the model, as well as an access function.
virtual int get_sv_list(char ***list) const =0
Returns a list of SVs.
virtual uint32_t moddat() const =0
Gets data flags for this IMP's modified data.
virtual int read_svs(IonIfBase &imp, FILE *file) const =0
Reads state variable values for one cell from a file.
virtual void tune(IonIfBase &imp, const char *im_par) const =0
Handles setting of this model's parameters.
virtual int get_sv_type(const char *svname, int *type, char **type_name) const =0
Determines the type of a SV.
virtual void compute(Target target, node_index_t start, node_index_t end, IonIfBase &imp, GlobalData_t **data) const =0
Performs computation for 1 time step.
virtual void initialize_sv(IonIfBase &imp, GlobalData_t **data) const =0
Initializes the state variables of the given IMP.
virtual int write_svs(IonIfBase &imp, FILE *file, node_index_t node) const =0
Write state variable values for one cell to a file/.
virtual uint32_t reqdat() const =0
Gets data flags for this IMP's required data.
virtual void construct_tables(IonIfBase &imp) const =0
Contructs lookup tables.
virtual void destroy(IonIfBase &imp) const =0
Destroys the given IMP.
virtual size_t dlo_vector_size() const =0
Gets the vector size when using data layout optimization (DLO).
#define log_msg(F, L, O,...)
Definition: filament.h:8
node_index_t * curr_node_list
needed to determine the global node number
Definition: ION_IF.cc:115
bool is_concrete(Target const target)
Checks if target is a real, concrete target.
Definition: target.cc:71
Target
enum that represents different targets to run ionic models on.
Definition: target.h:45
@ MLIR_ROCM
ROCM code for AMD GPUs generated with MLIR.
Definition: target.h:50
@ CPU
baseline CPU model generated with the original opencarp code generator
Definition: target.h:48
@ MLIR_CUDA
CUDA code for NVIDIA GPUs generated with MLIR.
Definition: target.h:51
@ MLIR_CPU
vectorized CPU code generated with MLIR
Definition: target.h:49
bool flag_set(const char *flags, const char *target)
Definition: ION_IF.cc:657
IonType * get_ion_type(const std::string &name)
SF_real GlobalData_t
Definition: limpet_types.h:27
int LUT_dump(LUT *plut, const char *fname)
Definition: LUT.cc:74
bool is_gpu(Target const target)
Checks if this is a GPU target.
Definition: target.cc:67
bool verify_flags(const char *flags, const char *given)
Definition: ION_IF.cc:635
FILE_SPEC _nc_logf
Definition: ION_IF.cc:85
void destroy_lut(LUT *plut, Target target)
Definition: LUT.cc:101
void update_ts(ts *ptstp)
Definition: ION_IF.cc:566
opencarp::local_index_t node_count_t
Definition: limpet_types.h:29
char * get_next_list(char *lst, char delimiter)
Definition: ION_IF.cc:612
char IIF_Mask_t
Definition: ion_type.h:50
opencarp::global_index_t global_node_index_t
Definition: limpet_types.h:30
void * memmem(void *haystack, int sz_hay, void *needle, int sz_n)
Definition: ION_IF.cc:586
opencarp::local_index_t node_index_t
Definition: limpet_types.h:28
char * tokstr_r(char *s1, const char *s2, char **lasts)
Definition: ION_IF.cc:89
void initialize_ts(Target target, ts *tstp, int ng, int *skp, double dt)
Definition: ION_IF.cc:537
char * dupstr(const char *old_str)
Definition: basics.cc:44
file_desc * FILE_SPEC
Definition: basics.h:140
int sz
storage required
Definition: ION_IF.h:130
int map
which plugin does this IMO match
Definition: ION_IF.h:134
IMPinfo * plug
plugins
Definition: ION_IF.h:132
bool compatible
does IM match stored IM
Definition: ION_IF.h:133
int nplug
number of plugins
Definition: ION_IF.h:131
time constant groups
Definition: ION_IF.h:77
int update
Definition: ION_IF.h:81
float dt
Definition: ION_IF.h:78
time stepper
Definition: ION_IF.h:88
int cnt
Definition: ION_IF.h:89
int ng
Definition: ION_IF.h:90
tc_grp * tcg
Definition: ION_IF.h:91
saltatory list – memory is allocated in chunks
Definition: basics.h:59
int nitems
number of items
Definition: basics.h:62