openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
LUT.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: LicenseRef-APL-1.1
3 
4 #include "LUT.h"
5 #include "basics.h"
6 #include "MULTI_ION_IF.h"
7 
8 #include <string.h>
9 #include <assert.h>
10 #include <cmath>
11 
12 namespace limpet {
13 
19 
20 /* create and initialize LUT
21  *
22  * \param p pointer to lookup table structure
23  * \param rows number of lookup variables
24  * \param mn lower boundary of LUT
25  * \param mx upper boundary of LUT
26  * \param res resolution of LUT
27  * \param name table name
28  *
29  */
30 void LUT_alloc(LUT *plut,int cols,float mn,float mx,float res,const char *name, Target target)
31 {
32  plut->name = dupstr(name);
33 
34  // table bounds
35  plut->cols = cols;
36  plut->mn = mn;
37  plut->mx = mx;
38  plut->res = res;
39  plut->step = 1/res;
40 
41  // in terms of indices
42  plut->mn_ind = (int)(mn * plut->step);
43  plut->mx_ind = (int)(mx * plut->step);
44  plut->rows = plut->mx_ind - plut->mn_ind + 1;
45 
46  // build a table and offset it
47  plut->tab = build_matrix_ns<LUT_data_t>( plut->rows, plut->cols, sizeof(LUT_data_t), target);
48  plut->tab -= plut->mn_ind;
49 }
50 
51 
52 /* dump LUT to file
53  *
54  * \param p pointer to lookup table structure
55  * \param fname filename to store LUT dump
56  *
57  * \return 0 if successull, -1 otherwise
58  */
59 int LUT_dump( LUT *plut, const char *fname )
60 {
61  FILE_SPEC fdump = f_open(fname, "wb");
62 
63  if (!fdump)
64  return -1;
65 
66  // write endianness and table dimensions first
67  int endian_flg = is_big_endian();
68  fwrite(&endian_flg, sizeof(int), 1, fdump->fd);
69  fwrite(&plut->rows, sizeof(plut->rows), 1, fdump->fd);
70  fwrite(&plut->cols, sizeof(plut->cols), 1, fdump->fd);
71 
72  for (int i=plut->mn_ind; i<=plut->mx_ind; i++)
73  for (int j=0; j<plut->cols; j++)
74  fwrite(&plut->tab[i][j], sizeof(LUT_data_t), 1, fdump->fd);
75 
76  f_close(fdump);
77 
78  return 0;
79 }
80 
81 
86 void destroy_lut( LUT *plut, Target target )
87 {
88  if ( plut != NULL && plut->tab != NULL ) {
89  if (plut->tab != NULL) {
90  plut->tab += plut->mn_ind;
91  deallocate_on_target<LUT_data_t>(target, plut->tab[0]);
92  deallocate_on_target(target, plut->tab);
93  }
94  free(plut->name);
95  }
96  if( plut )
97  memset( plut, 0, sizeof(LUT) );
98 }
99 
100 
101 
102 
112 #define MAX_LUT_NUMINF 10
113 
114 int check_LUT( LUT* lut )
115 {
116  int retval = 0;
117  int numinf = 0;
118 
119  for ( int i=lut->mn_ind; i<=lut->mx_ind; i++ )
120  for ( int j=0; j<lut->cols; j++ )
121  if ( ! std::isfinite(lut->tab[i][j])) {
122  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);
123  retval = 1;
124  if( numinf++ > MAX_LUT_NUMINF ) {
125  log_msg(0, 3, 0, "suppressing further errors!!!\n" );
126  return retval;
127  }
128  }
129 
130  return retval;
131 }
132 
140 void IIF_warn(const int wv, const char error[]) {
141  // log_msg(_nc_logf, 2, 0, "danger [tm = %f]: %s : local node = %d, global node = %d\n",
142  // current_global_time(), error, wv, current_global_node(wv) ); //FIXME
143 }
144 
156 void LUT_problem( LUT *lt, double val, int wv, const char *tabname )
157 {
158  // struct exception_type except = { .exit=0 };
159  char error[5000]; //FIXME, replace me with a C++ string.
160 
161  if ( std::isfinite(val) ) {
162 #ifdef CHATTY_LUT
163  snprintf(error, sizeof error, "bounds exceeded for %s-table = %g (limits: %g - %g)",
164  tabname, val, lt->mn, lt->mx);
165  IIF_warn(wv, error);
166 #endif
167  return;
168  } else if (std::isinf(val)) {
169  snprintf(error, sizeof error, "inf passed to LUT_index() for %s-table", tabname);
170  IIF_warn(wv, error);
171  } else if ( std::isnan(val) ) {
172  snprintf(error, sizeof error, "NaN passed to LUT_index() for %s-table", tabname);
173  IIF_warn(wv, error);
174  }
175 }
176 
177 #ifndef IMP_FAST
178 int LUT_index( LUT *tab, GlobalData_t val, int locind )
179 {
180  int indx = (int)(tab->step*val);
181 
182  if (indx < tab->mn_ind) {
183  indx = tab->mn_ind;
184  } else if (indx > tab->mx_ind) {
185  indx = tab->mx_ind;
186  } else {
187  return indx;
188  }
189 
190  LUT_problem(tab, val, locind, tab->name );
191  return indx;
192 }
193 #endif
194 
196  return (val < tab->mn || val > tab->mx) ;
197 }
198 
208 inline LUT_data_t LUT_interp( LUT *t, int i, int j, GlobalData_t x )
209 {
210  return (1.-x)*t->tab[i][j] + x*t->tab[i+1][j];
211 }
212 
213 
227 inline LUT_data_t LUT_derror( LUT *t, int idx, GlobalData_t x )
228 {
229  return (x-idx*t->res)/t->res;
230 }
231 
244 {
245  int idx = LUT_index(tab, val, i);
246  GlobalData_t derr = LUT_derror(tab, idx, val);
247  if (LUT_out_of_bounds(tab, val)) {
248  for (int j=0;j<tab->cols;j++)
249  row[j] = tab->tab[idx][j];
250  } else {
251  for (int j=0;j<tab->cols;j++)
252  row[j] = LUT_interp(tab, idx, j, derr );
253  }
254  return derr;
255 }
256 
257 
264 LUT_data_t*
265 LUT_row( LUT *lut, GlobalData_t val, int locind )
266 {
267  return lut->tab[LUT_index( lut, val, locind )];
268 }
269 
270 #ifdef __cplusplus
271 extern "C"
272 {
273 #endif // ifdef __cplusplus
274 
275 
289 void LUT_interpRow_n_elements(char *table, char *val_ptr, int offset,
290  int distance, int index, int n, char* row_ptr,
291  int lut_numelements) {
292  if (n <= 0)
293  return;
294  LUT *tab = (LUT *)table;
295  GlobalData_t *val = (GlobalData_t *)(val_ptr + offset);
296  LUT_data_t* row = (LUT_data_t*)row_ptr;
297  if (distance == 1) {
298  for (unsigned i = 0; i < n; ++i)
299  LUT_interpRow(tab, *(val + i), i + index*n,
300  row + (i * (lut_numelements)));
301  } else {
302  for (unsigned i = 0; i < n; ++i)
303  LUT_interpRow(tab, *(val + i*distance + index*n), i + index*n,
304  row + (i * (lut_numelements)));
305  }
306 }
307 
308 #ifdef HAS_MLIR_CPU_MODEL
309 void compute_LUT_interpRow_mlir_8xf64(double , double, double, double, int, double, double*, double *, bool, int, double, char*);
310 void compute_LUT_interpRow_mlir_4xf64(double , double, double, double, int, double, double*, double *, bool, int, double, char*);
311 void compute_LUT_interpRow_mlir_2xf64(double , double, double, double, int, double, double*, double *, bool, int, double, char*);
312 
323 void LUT_interpRow_mlir(char *table, int i, char* row_ptr,
324  int lut_num_elements, int vector_size)
325 {
326  LUT *const tab = (LUT *const)table;
327  LUT_data_t* row = (LUT_data_t*)row_ptr;
328 
329  if (lut_num_elements > 0)
330  {
331  #ifndef IMP_FAST
332  if (vector_size == 8)
333  {
334  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);
335  }
336  else if (vector_size == 4)
337  {
338  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);
339  }
340  else if (vector_size == 2)
341  {
342  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);
343  }
344 
345  #else
346  if (vector_size == 8)
347  {
348  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);
349  }
350  else if (vector_size == 4)
351  {
352  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);
353  }
354  else if (vector_size == 2)
355  {
356  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);
357  }
358  #endif
359  }
360 
361 }
362 
363 
364 void LUT_problem_mlir( char *table, GlobalData_t val, int locind)
365 {
366  LUT *const tab = (LUT *const)table;
367  LUT_problem(tab, val, locind, tab->name );
368 }
369 #endif
370 
371 #ifdef __cplusplus
372 }
373 #endif // ifdef __cplusplus
374 
375 } // namespace limpet
#define MAX_LUT_NUMINF
maximum # non-finite warnings to print
Definition: LUT.cc:112
Define multiple ionic models to be used in different regions.
Basic utility structs and functions, mostly IO related.
#define log_msg(F, L, O,...)
Definition: filament.h:8
double distance(const Point &a, const Point &b)
Definition: SF_container.h:146
int LUT_out_of_bounds(LUT *tab, GlobalData_t val)
Definition: LUT.cc:195
void IIF_warn(const int wv, const char error[])
Definition: LUT.cc:140
Target
enum that represents different targets to run ionic models on.
Definition: target.h:30
void LUT_alloc(LUT *plut, int cols, float mn, float mx, float res, const char *name, Target target)
Definition: LUT.cc:30
LUT_data_t LUT_interp(LUT *t, int i, int j, GlobalData_t x)
Definition: LUT.cc:208
void LUT_problem_mlir(char *tab, GlobalData_t val, int locind)
SF_real GlobalData_t
Definition: limpet_types.h:12
LUT_data_t LUT_interpRow(LUT *const tab, GlobalData_t val, int i, LUT_data_t *row)
Definition: LUT.cc:243
double LUT_data_t
Definition: LUT.h:19
int LUT_dump(LUT *plut, const char *fname)
Definition: LUT.cc:59
LUT_data_t * LUT_row(LUT *lut, GlobalData_t val, int locind)
Definition: LUT.cc:265
int LUT_index(LUT *tab, GlobalData_t val, int locind)
Definition: LUT.cc:178
void destroy_lut(LUT *plut, Target target)
Definition: LUT.cc:86
void deallocate_on_target(Target target, T *ptr)
Utility function for deallocating memory on a target. See TargetAllocator.
Definition: target.h:303
void LUT_interpRow_mlir(char *table, int i, char *row_ptr, int lut_num_elements, int vector_size)
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:289
void LUT_problem(LUT *lt, double val, int wv, const char *tabname)
Definition: LUT.cc:156
int check_LUT(LUT *lut)
Definition: LUT.cc:114
LUT_data_t LUT_derror(LUT *t, int idx, GlobalData_t x)
Definition: LUT.cc:227
bool is_big_endian()
Definition: basics.cc:278
FILE_SPEC f_open(const char *fname, const char *mode)
Open a FILE_SPEC.
Definition: basics.cc:123
char * dupstr(const char *old_str)
Definition: basics.cc:29
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:150
file_desc * FILE_SPEC
Definition: basics.h:125
lookup table structure
Definition: LUT.h:31
float res
Definition: LUT.h:37
float mx
Definition: LUT.h:36
int mn_ind
Definition: LUT.h:39
float mn
Definition: LUT.h:35
int rows
Definition: LUT.h:33
int cols
Definition: LUT.h:34
LUT_data_t ** tab
Definition: LUT.h:42
float step
Definition: LUT.h:38
int mx_ind
Definition: LUT.h:40
char * name
Definition: LUT.h:32