openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
LUT.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 
19 #include "LUT.h"
20 #include "basics.h"
21 #include "MULTI_ION_IF.h"
22 
23 #include <string.h>
24 #include <assert.h>
25 #include <cmath>
26 
27 namespace limpet {
28 
34 
35 /* create and initialize LUT
36  *
37  * \param p pointer to lookup table structure
38  * \param rows number of lookup variables
39  * \param mn lower boundary of LUT
40  * \param mx upper boundary of LUT
41  * \param res resolution of LUT
42  * \param name table name
43  *
44  */
45 void LUT_alloc(LUT *plut,int cols,float mn,float mx,float res,const char *name, Target target)
46 {
47  plut->name = dupstr(name);
48 
49  // table bounds
50  plut->cols = cols;
51  plut->mn = mn;
52  plut->mx = mx;
53  plut->res = res;
54  plut->step = 1/res;
55 
56  // in terms of indices
57  plut->mn_ind = (int)(mn * plut->step);
58  plut->mx_ind = (int)(mx * plut->step);
59  plut->rows = plut->mx_ind - plut->mn_ind + 1;
60 
61  // build a table and offset it
62  plut->tab = build_matrix_ns<LUT_data_t>( plut->rows, plut->cols, sizeof(LUT_data_t), target);
63  plut->tab -= plut->mn_ind;
64 }
65 
66 
67 /* dump LUT to file
68  *
69  * \param p pointer to lookup table structure
70  * \param fname filename to store LUT dump
71  *
72  * \return 0 if successull, -1 otherwise
73  */
74 int LUT_dump( LUT *plut, const char *fname )
75 {
76  FILE_SPEC fdump = f_open(fname, "wb");
77 
78  if (!fdump)
79  return -1;
80 
81  // write endianness and table dimensions first
82  int endian_flg = is_big_endian();
83  fwrite(&endian_flg, sizeof(int), 1, fdump->fd);
84  fwrite(&plut->rows, sizeof(plut->rows), 1, fdump->fd);
85  fwrite(&plut->cols, sizeof(plut->cols), 1, fdump->fd);
86 
87  for (int i=plut->mn_ind; i<=plut->mx_ind; i++)
88  for (int j=0; j<plut->cols; j++)
89  fwrite(&plut->tab[i][j], sizeof(LUT_data_t), 1, fdump->fd);
90 
91  f_close(fdump);
92 
93  return 0;
94 }
95 
96 
101 void destroy_lut( LUT *plut, Target target )
102 {
103  if ( plut != NULL && plut->tab != NULL ) {
104  if (plut->tab != NULL) {
105  plut->tab += plut->mn_ind;
106  deallocate_on_target<LUT_data_t>(target, plut->tab[0]);
107  deallocate_on_target(target, plut->tab);
108  }
109  free(plut->name);
110  }
111  if( plut )
112  memset( plut, 0, sizeof(LUT) );
113 }
114 
115 
116 
117 
127 #define MAX_LUT_NUMINF 10
128 
129 int check_LUT( LUT* lut )
130 {
131  int retval = 0;
132  int numinf = 0;
133 
134  for ( int i=lut->mn_ind; i<=lut->mx_ind; i++ )
135  for ( int j=0; j<lut->cols; j++ )
136  if ( ! std::isfinite(lut->tab[i][j])) {
137  log_msg(0, 2, 0, "LUT WARNING: %s=%g produces %g in entry number %d!\n",lut->name,i*lut->res,lut->tab[i][j],j);
138  retval = 1;
139  if( numinf++ > MAX_LUT_NUMINF ) {
140  log_msg(0, 3, 0, "suppressing further errors!!!\n" );
141  return retval;
142  }
143  }
144 
145  return retval;
146 }
147 
155 void IIF_warn(const int wv, const char error[]) {
156  // log_msg(_nc_logf, 2, 0, "danger [tm = %f]: %s : local node = %d, global node = %d\n",
157  // current_global_time(), error, wv, current_global_node(wv) ); //FIXME
158 }
159 
171 void LUT_problem( LUT *lt, double val, int wv, const char *tabname )
172 {
173  // struct exception_type except = { .exit=0 };
174  char error[5000]; //FIXME, replace me with a C++ string.
175 
176  if ( std::isfinite(val) ) {
177 #ifdef CHATTY_LUT
178  snprintf(error, sizeof error, "bounds exceeded for %s-table = %g (limits: %g - %g)",
179  tabname, val, lt->mn, lt->mx);
180  IIF_warn(wv, error);
181 #endif
182  return;
183  } else if (std::isinf(val)) {
184  snprintf(error, sizeof error, "inf passed to LUT_index() for %s-table", tabname);
185  IIF_warn(wv, error);
186  } else if ( std::isnan(val) ) {
187  snprintf(error, sizeof error, "NaN passed to LUT_index() for %s-table", tabname);
188  IIF_warn(wv, error);
189  }
190 }
191 
192 #ifndef IMP_FAST
193 int LUT_index( LUT *tab, GlobalData_t val, int locind )
194 {
195  int indx = (int)(tab->step*val);
196 
197  if (indx < tab->mn_ind) {
198  indx = tab->mn_ind;
199  } else if (indx > tab->mx_ind) {
200  indx = tab->mx_ind;
201  } else {
202  return indx;
203  }
204 
205  LUT_problem(tab, val, locind, tab->name );
206  return indx;
207 }
208 #endif
209 
211  return (val < tab->mn || val > tab->mx) ;
212 }
213 
223 inline LUT_data_t LUT_interp( LUT *t, int i, int j, GlobalData_t x )
224 {
225  return (1.-x)*t->tab[i][j] + x*t->tab[i+1][j];
226 }
227 
228 
242 inline LUT_data_t LUT_derror( LUT *t, int idx, GlobalData_t x )
243 {
244  return (x-idx*t->res)/t->res;
245 }
246 
259 {
260  int idx = LUT_index(tab, val, i);
261  GlobalData_t derr = LUT_derror(tab, idx, val);
262  if (LUT_out_of_bounds(tab, val)) {
263  for (int j=0;j<tab->cols;j++)
264  row[j] = tab->tab[idx][j];
265  } else {
266  for (int j=0;j<tab->cols;j++)
267  row[j] = LUT_interp(tab, idx, j, derr );
268  }
269  return derr;
270 }
271 
272 
279 LUT_data_t*
280 LUT_row( LUT *lut, GlobalData_t val, int locind )
281 {
282  return lut->tab[LUT_index( lut, val, locind )];
283 }
284 
285 #ifdef __cplusplus
286 extern "C"
287 {
288 #endif // ifdef __cplusplus
289 
290 
304 void LUT_interpRow_n_elements(char *table, char *val_ptr, int offset,
305  int distance, int index, int n, char* row_ptr,
306  int lut_numelements) {
307  if (n <= 0)
308  return;
309  LUT *tab = (LUT *)table;
310  GlobalData_t *val = (GlobalData_t *)(val_ptr + offset);
311  LUT_data_t* row = (LUT_data_t*)row_ptr;
312  if (distance == 1) {
313  for (unsigned i = 0; i < n; ++i)
314  LUT_interpRow(tab, *(val + i), i + index*n,
315  row + (i * (lut_numelements)));
316  } else {
317  for (unsigned i = 0; i < n; ++i)
318  LUT_interpRow(tab, *(val + i*distance + index*n), i + index*n,
319  row + (i * (lut_numelements)));
320  }
321 }
322 
323 #ifdef HAS_MLIR_CPU_MODEL
324 void compute_LUT_interpRow_mlir_8xf64(double , double, double, double, int, double, double*, double *, bool, int, double, char*);
325 void compute_LUT_interpRow_mlir_4xf64(double , double, double, double, int, double, double*, double *, bool, int, double, char*);
326 void compute_LUT_interpRow_mlir_2xf64(double , double, double, double, int, double, double*, double *, bool, int, double, char*);
327 
338 void LUT_interpRow_mlir(char *table, int i, char* row_ptr,
339  int lut_num_elements, int vector_size)
340 {
341  LUT *const tab = (LUT *const)table;
342  LUT_data_t* row = (LUT_data_t*)row_ptr;
343 
344  if (lut_num_elements > 0)
345  {
346  #ifndef IMP_FAST
347  if (vector_size == 8)
348  {
349  compute_LUT_interpRow_mlir_8xf64((double) tab->step, (double) tab->mn, (double) tab->mx, (double) tab->res, (int) tab->cols, (double) tab->mn_ind, (double*)tab->tab[tab->mn_ind], (double *) row, true, i, (double) tab->mx_ind, table);
350  }
351  else if (vector_size == 4)
352  {
353  compute_LUT_interpRow_mlir_4xf64((double) tab->step, (double) tab->mn, (double) tab->mx, (double) tab->res, (int) tab->cols, (double) tab->mn_ind, (double*)tab->tab[tab->mn_ind], (double *) row, true, i, (double) tab->mx_ind, table);
354  }
355  else if (vector_size == 2)
356  {
357  compute_LUT_interpRow_mlir_2xf64((double) tab->step, (double) tab->mn, (double) tab->mx, (double) tab->res, (int) tab->cols, (double) tab->mn_ind, (double*)tab->tab[tab->mn_ind], (double *) row, true, i, (double) tab->mx_ind, table);
358  }
359 
360  #else
361  if (vector_size == 8)
362  {
363  compute_LUT_interpRow_mlir_8xf64((double) tab->step, (double) tab->mn, (double) tab->mx, (double) tab->res, (int) tab->cols, (double) tab->mn_ind, (double*)tab->tab[tab->mn_ind], (double *) row, false, i, (double) tab->mx_ind, table);
364  }
365  else if (vector_size == 4)
366  {
367  compute_LUT_interpRow_mlir_4xf64((double) tab->step, (double) tab->mn, (double) tab->mx, (double) tab->res, (int) tab->cols, (double) tab->mn_ind, (double*)tab->tab[tab->mn_ind], (double *) row, false, i, (double) tab->mx_ind, table);
368  }
369  else if (vector_size == 2)
370  {
371  compute_LUT_interpRow_mlir_2xf64((double) tab->step, (double) tab->mn, (double) tab->mx, (double) tab->res, (int) tab->cols, (double) tab->mn_ind, (double*)tab->tab[tab->mn_ind], (double *) row, false, i, (double) tab->mx_ind, table);
372  }
373  #endif
374  }
375 
376 }
377 
378 
379 void LUT_problem_mlir( char *table, GlobalData_t val, int locind)
380 {
381  LUT *const tab = (LUT *const)table;
382  LUT_problem(tab, val, locind, tab->name );
383 }
384 #endif
385 
386 #ifdef __cplusplus
387 }
388 #endif // ifdef __cplusplus
389 
390 } // namespace limpet
int LUT_out_of_bounds(LUT *tab, GlobalData_t val)
Definition: LUT.cc:210
char * dupstr(const char *old_str)
Definition: basics.cc:44
int rows
Definition: LUT.h:48
bool is_big_endian()
Definition: basics.cc:290
void LUT_interpRow_n_elements(char *table, char *val_ptr, int offset, int distance, int index, int n, char *row_ptr, int lut_numelements)
Definition: LUT.cc:304
LUT_data_t * LUT_row(LUT *lut, GlobalData_t val, int locind)
Definition: LUT.cc:280
void destroy_lut(LUT *plut, Target target)
Definition: LUT.cc:101
double LUT_data_t
Definition: LUT.h:34
void LUT_problem_mlir(char *tab, GlobalData_t val, int locind)
int check_LUT(LUT *lut)
Definition: LUT.cc:129
void IIF_warn(const int wv, const char error[])
Definition: LUT.cc:155
void LUT_alloc(LUT *plut, int cols, float mn, float mx, float res, const char *name, Target target)
Definition: LUT.cc:45
LUT_data_t LUT_interpRow(LUT *const tab, GlobalData_t val, int i, LUT_data_t *row)
Definition: LUT.cc:258
int cols
Definition: LUT.h:49
LUT_data_t LUT_derror(LUT *t, int idx, GlobalData_t x)
Definition: LUT.cc:242
int LUT_index(LUT *tab, GlobalData_t val, int locind)
Definition: LUT.cc:193
int mn_ind
Definition: LUT.h:54
#define MAX_LUT_NUMINF
maximum # non-finite warnings to print
Definition: LUT.cc:127
float res
Definition: LUT.h:52
Define multiple ionic models to be used in different regions.
int mx_ind
Definition: LUT.h:55
double distance(const Point &a, const Point &b)
Definition: SF_container.h:149
LUT_data_t ** tab
Definition: LUT.h:57
int LUT_dump(LUT *plut, const char *fname)
Definition: LUT.cc:74
float mn
Definition: LUT.h:50
void LUT_problem(LUT *lt, double val, int wv, const char *tabname)
Definition: LUT.cc:171
LUT_data_t LUT_interp(LUT *t, int i, int j, GlobalData_t x)
Definition: LUT.cc:223
void LUT_interpRow_mlir(char *table, int i, char *row_ptr, int lut_num_elements, int vector_size)
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
Definition: basics.cc:72
char * name
Definition: LUT.h:47
Target
enum that represents different targets to run ionic models on.
Definition: target.h:45
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:162
float mx
Definition: LUT.h:51
lookup table structure
Definition: LUT.h:46
Basic utility structs and functions, mostly IO related.
file_desc * FILE_SPEC
Definition: basics.h:138
float step
Definition: LUT.h:53
void deallocate_on_target(Target target, T *ptr)
Utility function for deallocating memory on a target. See TargetAllocator.
Definition: target.h:318
SF_real GlobalData_t
Definition: limpet_types.h:27
FILE_SPEC f_open(const char *fname, const char *mode)
Open a FILE_SPEC.
Definition: basics.cc:135