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  // restore_state aborts on an incompatible model or plugin before reaching this point
291  assert(impinfo->compatible);
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  assert(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  }
313  else
314  mismatch++;
315  }
316  return mismatch;
317 }
318 
319 const std::vector<IonIfBase::sv_field>& IonIfBase::sv_layout() const {
320  if (!_sv_layout_valid) {
321  char** list = NULL;
322  int nsv = this->get_type().get_sv_list(&list);
323  _sv_layout.reserve(nsv);
324  for (int i = 0; i < nsv; i++) {
325  int off = 0, sz = 0, type = 0;
326  char* type_name = NULL;
327  this->get_type().get_sv_offset(list[i], &off, &sz);
328  this->get_type().get_sv_type(list[i], &type, &type_name);
329  free(type_name);
330  _sv_layout.push_back({list[i], off, sz, type});
331  free(list[i]);
332  }
333  free(list);
334  _sv_layout_valid = true;
335  }
336  return _sv_layout;
337 }
338 
339 void IonIfBase::get_sv_layout(std::vector<std::pair<int, int>>& fields) const {
340  const std::vector<sv_field>& layout = this->sv_layout();
341  fields.clear();
342  fields.reserve(layout.size());
343  for (const auto& f : layout)
344  fields.emplace_back(f.off, f.sz);
345 }
346 
348  size_t total = 0;
349  for (const auto& f : this->sv_layout())
350  total += static_cast<size_t>(f.sz);
351  return total;
352 }
353 
354 uint64_t IonIfBase::sv_fingerprint() const {
355  constexpr uint64_t kFNVOffsetBasis = 0xcbf29ce484222325ULL; // 14695981039346656037
356  constexpr uint64_t kFNVPrime = 0x100000001b3ULL; // 1099511628211
357  uint64_t h = kFNVOffsetBasis;
358  auto mix = [&h](unsigned char b) { h ^= b; h *= kFNVPrime; };
359  for (const auto& f : this->sv_layout()) {
360  for (unsigned char c : f.name) mix(c);
361  mix(0); // name terminator, so {"ab","c"} and {"a","bc"} differ
362  for (int b = 0; b < 4; b++)
363  mix((static_cast<uint32_t>(f.sz) >> (8 * b)) & 0xff);
364  for (int b = 0; b < 4; b++)
365  mix((static_cast<uint32_t>(f.type) >> (8 * b)) & 0xff);
366  }
367  return h;
368 }
369 
371  IIF_Mask_t *mask, size_t *offset, IMPinfo *impinfo,
372  const global_node_index_t* loc2canon) {
373  // restore_state aborts on an incompatible model or plugin before reaching this point
374  assert(impinfo->compatible);
375 
376  long base = ftell(in->fd);
377  node_count_t mismatch = 0;
378 
379  // field layouts are model properties: gather them once, not per node
380  std::vector<std::pair<int, int>> main_fields;
381  this->get_sv_layout(main_fields);
382 
383  std::vector<std::vector<std::pair<int, int>>> plug_fields(impinfo->nplug);
384  for (int j = 0; j < impinfo->nplug; j++) {
385  assert(impinfo->plug[j].compatible);
386  this->_plugins[impinfo->plug[j].map]->get_sv_layout(plug_fields[j]);
387  }
388 
389  for( node_index_t i=0; i<n; i++ ) {
390  global_node_index_t canon = loc2canon[pos[i]];
391  if(mask[canon] == this->miifIdx) {
392  fseek(in->fd, base+offset[canon], SEEK_SET);
393  // a short read means the checkpoint is truncated within the state payload,
394  // which the header-level checks in restore_state cannot catch; abort rather
395  // than scatter stale bytes into the state. A zero-width field (e.g. a
396  // placeholder SV whose per-lane size rounds to 0 under DLO) reads nothing;
397  // fread reports 0 items for size 0, which must not be read as truncation.
398  auto scatter = [&](char* dst, std::size_t sz) {
399  if (sz && fread(dst, sz, 1, in->fd) != 1) {
400  log_msg(NULL, 5, 0, "Truncated ionic-state checkpoint during restore");
401  EXIT(EXIT_FAILURE);
402  }
403  };
404 
405  this->for_each_sv_field(i, main_fields, scatter);
406  for(int j=0; j<impinfo->nplug; j++)
407  this->_plugins[impinfo->plug[j].map]->for_each_sv_field(i, plug_fields[j], scatter);
408  }
409  else
410  mismatch++;
411  }
412  return mismatch;
413 }
414 
415 int IonIfBase::dump_luts(bool zipped) {
416  std::string name;
417  std::string ext = zipped ? ".gz" : "";
418 
419  int dcnt = 0;
420  for (int i=0; i < this->_tables.size(); i++) {
421  // determine file name
422  if (strcmp(this->_tables[i].name, ""))
423  name = this->_type.get_name() + "_LUT_" + this->_tables[i].name + ".bin" + ext;
424  else
425  name = this->_type.get_name() + "_LUT_" + std::to_string(i) + ".bin" + ext;
426 
427  // dump table
428  int err = LUT_dump(&this->_tables[i], name.c_str());
429  if (!err) dcnt++;
430  }
431  return dcnt;
432 }
433 
435  for (auto& lut : this->_tables) {
436  destroy_lut(&lut, this->_target);
437  }
438 
439  std::vector<LUT>().swap(this->_tables);
440 }
441 
442 void IonIfBase::tune(const char *im_par, const char *plugs, const char *plug_par) {
443  char *opar, *oplg, *plg, *nplg, *parlst, *nparlst;
444 
445  if( im_par && *im_par != '\0' ) {
446  log_msg( _nc_logf, 0, 0, "Ionic model: %s", this->_type.get_name().c_str());
447  this->_type.tune(*this, im_par);
448  }
449  opar = parlst = dupstr(plug_par);
450  oplg = plg = dupstr(plugs);
451 
452  while( plg!=NULL && *plg!='\0' ) {
453  nparlst = get_next_list( parlst, ':' );
454  nplg = get_next_list( plg, ':' );
455 
456  log_msg( _nc_logf, 0, 0, "Plug-in: %s", plg );
457 
458  if( parlst==NULL || *parlst=='\0' ) {
459  parlst = nparlst;
460  plg = nplg;
461  continue;
462  }
463 
464  // find apropriate plugin
465  IonType* plugin = get_ion_type(plg);
466  int j;
467 
468  for(j = 0; j < this->_plugins.size(); j++) {
469  if(this->_plugins[j]->get_type() == *plugin) break;
470  }
471 
472  if(j == this->_plugins.size()) {
473  log_msg( _nc_logf, 2, 0, "Plugin %s not used with IM", plg );
474  plg = nplg;
475  parlst = nparlst;
476  continue;
477  }
478 
479  plugin->tune(*this->_plugins[j], parlst);
480  plg = nplg;
481  parlst = nparlst;
482  }
483 
484  log_msg( _nc_logf, 0, 0, "" );
485  free( opar );
486  free( oplg );
487 }
488 
489 int IonIfBase::read_svs(FILE* file) {
490  if(this->get_num_node())
491  return this->_type.read_svs(*this, file);
492  else
493  return 1;
494 }
495 
496 int IonIfBase::write_svs(FILE* file, node_index_t node) {
497  return this->_type.write_svs(*this, file, node);
498 }
499 
501  this->_plugins = {};
502 
503  for (auto& plugin : other.plugins()) {
504  auto copy = plugin->get_type().make_ion_if(this->_target, plugin->get_num_node(), {});
505  copy->_parent = this;
506  this->_plugins.push_back(copy);
507  copy->copy_SVs_from(*plugin, true);
508  }
509 }
510 
511 void IonIfBase::for_each(const std::function<void(IonIfBase&)>& consumer) {
512  consumer(*this);
513 
514  for (auto& plugin : this->_plugins) {
515  consumer(*plugin);
516  }
517 }
518 
530 // Is this ever used?
531 void initialize_ts(Target target, ts *tstp, int ng, int *skp, double dt)
532 {
533  // initialize step counter that will run linearly as long the
534  // simulation goes
535  tstp->cnt = -1;
536  tstp->ng = ng;
537  tstp->tcg = allocate_on_target<tc_grp>(target, ng);
538 
539  // initialize time constant grouping
540  // fast variables, use dt=dt
541  tstp->tcg[0].skp = 1;
542  tstp->tcg[0].dt = dt;
543  tstp->tcg[0].update = 1;
544 
545  for (int i=1;i<ng;i++) {
546  tstp->tcg[i].skp = skp[i];
547  tstp->tcg[i].dt = tstp->tcg[i].skp*dt;
548  }
549 }
550 
551 
560 void update_ts(ts *ptstp)
561 {
562  ptstp->cnt++;
563 
564  tc_grp *ptcg = ptstp->tcg;
565  for (int i=1;i<ptstp->ng;i++)
566  ptcg[i].update = !(ptstp->cnt%ptcg[i].skp);
567 }
568 
569 
570 #ifndef _GNU_SOURCE
580 void *memmem( void *haystack, int sz_hay, void *needle, int sz_n )
581 {
582  if( !sz_n ) return NULL;
583 
584  char *h = (char *)haystack;
585 
586  for( int i=0; i>sz_hay-sz_n+1; i++, h++ )
587  if( !memcmp( h, needle, sz_n ) )
588  return (void *)h;
589  break;
590 
591  return NULL;
592 }
593 #endif
594 
595 
606 char *get_next_list( char *lst, char delimiter )
607 {
608  if( lst == NULL || *lst == '\0' )
609  return NULL;
610 
611  while( *lst != delimiter && *lst != '\0' )
612  lst++;
613 
614  if( *lst != '\0' ) {
615  *lst = '\0';
616  return lst+1;
617  } else
618  return lst;
619 }
620 
621 
629  bool verify_flags( const char *flags, const char* given )
630  {
631  char *flag, *ptr, *gvn_cp = dupstr( given );
632 
633  flag = tokstr_r( gvn_cp, "|", &ptr );
634  while( flag ) {
635  if( !flag_set( flags, flag ) )
636  break;
637  flag = tokstr_r( NULL, "|", &ptr );
638  }
639 
640  free( gvn_cp );
641  return flag ? false : true;
642 }
643 
651 bool flag_set( const char *flags, const char *target )
652 {
653  if( !flags ) return false;
654 
655  char *f = dupstr( flags ), *last, *pos;
656 
657  pos = tokstr_r( f, "|", &last );
658  while( pos && strcmp( pos, target ) ) {
659  pos = tokstr_r( NULL, "|", &last );
660  }
661  free( f );
662 
663  return pos? true : false;
664 }
665 
666 
667 #ifdef USE_CVODE
668 
671 void __bogus_function_for_cvode() {
672 
673  int flag;
674  int N_CVODE = 1;
675 #if SUNDIALS_VERSION_MAJOR < 4
676  void* cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
677 #elif SUNDIALS_VERSION_MAJOR < 6
678  void* cvode_mem = CVodeCreate(CV_BDF);
679 #elif SUNDIALS_VERSION_MAJOR < 7
680  SUNContext sunctx;
681  MPI_Comm comm = PETSC_COMM_WORLD;
682  if( SUNContext_Create(&comm, &sunctx )<0 ){
683  assert(0);
684  }
685  void* cvode_mem = CVodeCreate(CV_BDF, sunctx);
686 #else // version from 7.0.0
687  SUNContext sunctx;
688  SUNComm comm = PETSC_COMM_WORLD;
689  if( SUNContext_Create( comm, &sunctx )<0 ){
690  assert(0);
691  }
692  void* cvode_mem = CVodeCreate(CV_BDF, sunctx);
693 #endif
694  assert(cvode_mem != NULL);
695 #if SUNDIALS_VERSION_MAJOR >= 6
696  N_Vector cvode_y = N_VNew_Serial(N_CVODE, sunctx);
697 #else
698  N_Vector cvode_y = N_VNew_Serial(N_CVODE);
699 #endif
700  flag = CVodeInit(cvode_mem, NULL, 0, cvode_y);
701  assert(flag == CV_SUCCESS);
702  N_VDestroy(cvode_y);
703 
704  flag = CVodeSStolerances(cvode_mem, 1e-5, 1e-6);
705  assert(flag == CV_SUCCESS);
706  flag = CVodeSetMaxStep(cvode_mem, 1);
707  assert(flag == CV_SUCCESS);
708  flag = CVodeSetUserData(cvode_mem, NULL);
709  assert(flag == CV_SUCCESS);
710  flag = CVDiag(cvode_mem);
711  assert(flag == CV_SUCCESS);
712 
713  NV_Ith_S(cvode_y,0) = 0;
714 
715  {
716  int CVODE_flag;
717  CVODE_flag = CVodeReInit(NULL, 1, NULL);
718  assert(CVODE_flag == CV_SUCCESS);
719  CVODE_flag = CVodeSetInitStep(NULL, 1);
720  assert(CVODE_flag == CV_SUCCESS);
721 #if SUNDIALS_VERSION_MAJOR >= 7
722  sunrealtype tret;
723 #else
724  realtype tret;
725 #endif
726  CVODE_flag = CVode(cvode_mem, 1, NULL, &tret, CV_NORMAL);
727  assert(CVODE_flag == CV_SUCCESS);
728  }
729 }
730 #endif
731 
732 } // 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:442
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:370
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:489
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:415
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:339
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:496
size_t get_sv_per_node_size() const
Size in bytes of one node's de-interleaved state-variable record.
Definition: ION_IF.cc:347
uint64_t sv_fingerprint() const
Fingerprint of this IMP's state-variable layout.
Definition: ION_IF.cc:354
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:511
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:434
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:500
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:651
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:629
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:560
opencarp::local_index_t node_count_t
Definition: limpet_types.h:29
char * get_next_list(char *lst, char delimiter)
Definition: ION_IF.cc:606
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:580
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:531
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