openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
basics.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: Apache-2.0
3 
12 #include "basics.h"
13 
14 #include "petsc_utils.h" // TODO: PETSc dependency, for FPRINTF_SYNC, etc
15 
16 namespace opencarp {
17 
18 void sltlst_append( Salt_list* sl, void *p, int quantum )
19 {
20  if( !sl->chunk ) sl->chunk = 1;
21 
22  if( !(sl->nitems%sl->chunk) )
23  sl->data = realloc( sl->data, sl->chunk*(quantum*(sl->nitems/sl->chunk+1)+1) );
24  memcpy( (char*)sl->data+sl->nitems*quantum, p, quantum );
25  sl->nitems++;
26  sl->size = quantum;
27 }
28 
29 char* dupstr(const char* old_str) {
30  if (!old_str) return NULL;
31 
32  size_t len = strlen(old_str);
33  char *new_str = (char *)calloc(len+1, sizeof(char));
34  strcpy(new_str, old_str);
35 
36  return new_str;
37 }
38 
39 char* stringify(double r)
40 {
41  char *rs = (char *)malloc(256);
42  snprintf(rs, 255, "%.1f", r);
43  return rs;
44 }
45 
46 std::string get_basename(const std::string & path)
47 {
48  char sep = '/';
49  size_t i = path.rfind(sep, path.length());
50  if (i != std::string::npos) {
51  return path.substr(i+1, path.length() - i);
52  }
53 
54  return path;
55 }
56 
57 void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt, ...)
58 {
59  assert(level>=0 && level<=MAX_LOG_LEVEL);
60 
61  if(!out)
62  flag |= ECHO;
63 
64  const bool mpi_ready = mpi_runtime_ready();
65  const int rank = mpi_ready ? get_rank() : 0;
66 
67  // create the message string
68  char fmsg[MAX_MESG_LEN] = "";
69  if(level)
70  snprintf(fmsg, sizeof fmsg, "L%d ", level );
71  if((flag&LOCAL) || (flag&SYNCED))
72  snprintf(fmsg+strlen(fmsg), sizeof fmsg, "[P%d] ", rank );
73  if(level || (flag&LOCAL) || (flag&SYNCED))
74  strcat(fmsg, ": ");
75 
76  if(fmt) {
77  va_list ap;
78  va_start(ap, fmt);
79  vsnprintf(fmsg+strlen(fmsg), MAX_MESG_LEN-strlen(fmsg)-1, fmt, ap);
80  if(!(flag&NONL))
81  strcat(fmsg, "\n");
82  }
83 
84  // write to file
85  if(out && fmt) {
86  if(flag&SYNCED && mpi_ready && out->fd)
87  FPRINTF_SYNC(WORLD out->fd, "%s", fmsg);
88  else if(!mpi_ready || !rank || (flag&LOCAL)) {
89  fprintf(out->fd, "%s", fmsg);
90  }
91  }
92 
93  // flush file
94  if(out && flag & FLUSH) {
95  if(flag&SYNCED && mpi_ready && out->fd)
96  PRINTF_FLUSH(COMM_W, out->fd);
97  else
98  fflush(out->fd);
99  }
100 
101  // write to screen
102  if((flag&ECHO) && fmt) {
103  if(flag&SYNCED && mpi_ready)
104  FPRINTF_SYNC(WORLD level ? stderr : stdout, "%s", fmsg);
105  else if(!mpi_ready || !rank || (flag&LOCAL))
106  fprintf(level ? stderr : stdout, "%s", fmsg);
107  }
108 
109  // flush screen
110  if((flag&ECHO) && ((flag & FLUSH) || level == MAX_LOG_LEVEL)) {
111  if(flag&SYNCED && mpi_ready)
112  PRINTF_FLUSH(COMM_W, level ? stderr : stdout);
113  else
114  fflush(level ? stderr : stdout);
115  }
116 }
117 
118 bool f_exist(const char *fname)
119 {
120  return access(fname, F_OK) != -1;
121 }
122 
123 FILE_SPEC f_open(const char *fname, const char *mode)
124 {
125  FILE_SPEC f = new file_desc();
126  f->name = dupstr(fname);
127 
128  bool openfail = false;
129  int error = 0;
130 
131  f->fd = fopen(fname,mode);
132  if(f->fd == NULL) {
133  openfail = true;
134  error = errno;
135  }
136 
137  if(openfail) {
138  char current_workdir[2048]; getcwd(current_workdir, 2048);
139 
140  fprintf(stderr, "Error, failed to open file: \"%s/%s\"!\n", current_workdir, fname);
141  fprintf(stderr, "%s\n", strerror(error));
142 
143  delete f;
144  return NULL;
145  }
146 
147  return f;
148 }
149 
151 {
152  if(f != NULL) {
153  fclose(f->fd);
154  delete f;
155  f = NULL;
156  }
157 }
158 
159 void f_read_par(void *ptr, size_t size, size_t nmemb, FILE_SPEC stream, MPI_Comm comm)
160 {
161  if(!get_rank())
162  fread(ptr, size, nmemb, stream->fd);
163 
164  MPI_Bcast(ptr, size*nmemb, MPI_BYTE, 0, comm);
165 }
166 
167 void f_write_par(void* ptr, size_t size, size_t nmemb, int source_pid, FILE_SPEC stream,
168  MPI_Comm comm)
169 {
170  int rank = get_rank();
171 
172  if(rank == source_pid) {
173  MPI_Send(&nmemb, sizeof(size_t), MPI_BYTE, 0, 100, comm);
174  MPI_Send(ptr, nmemb*size, MPI_BYTE, 0, 100, comm);
175  }
176 
177  if(rank == 0) {
178  MPI_Status status;
179 
180  MPI_Recv(&nmemb, sizeof(size_t), MPI_BYTE, source_pid, 100, comm, &status);
181  SF::vector<char> wbuff(nmemb*size);
182  MPI_Recv(wbuff.data(), size*nmemb, MPI_BYTE, source_pid, 100, comm, &status);
183  fwrite(wbuff.data(), size, nmemb, stream->fd);
184  }
185 }
186 
187 char* f_gets_par(char* s, int size, FILE_SPEC stream, MPI_Comm comm)
188 {
189  int rank = get_rank();
190 
191  // we want to be able to detect if a read happend by only evaluating s, not also the
192  // return type of fgets. as such we make sure that strlen(s) == 0 if no read occured.
193  s[0] = '\0';
194 
195  if(rank == 0) {
196  fgets(s, size, stream->fd);
197  }
198 
199  MPI_Bcast(s, size, MPI_CHAR, 0, comm);
200 
201  int str_len = strlen(s);
202 
203  if(str_len) return s;
204  else return NULL;
205 }
206 
207 void write_bin_string(FILE_SPEC out, const char *s)
208 {
209  if( !s ) return;
210 
211  int len = strlen(s);
212  fwrite( &len, sizeof(int), 1, out->fd);
213  fwrite( s, sizeof(char), len, out->fd);
214 }
215 
217 {
218  int len;
219  fread( &len, sizeof(int), 1, in->fd );
220  char *s = (char*)malloc( len+1 );
221  fread( s, sizeof(char), len, in->fd );
222  s[len] = '\0';
223 
224  return s;
225 }
226 
228 {
229  int len;
230  f_read_par(&len, sizeof(int), 1, in);
231  char *s = (char*) malloc(len+1);
232  f_read_par(s, sizeof(char), len, in);
233  s[len] = '\0';
234 
235  return s;
236 }
237 
238 bool point_in_shape(const Point & p, const geom_shape & shape)
239 {
240  switch(shape.type) {
241  case geom_shape::block: {
242  bool inside_x = p.x >= shape.p0.x && p.x <= shape.p1.x;
243  bool inside_y = p.y >= shape.p0.y && p.y <= shape.p1.y;
244  bool inside_z = p.z >= shape.p0.z && p.z <= shape.p1.z;
245  return (inside_x && inside_y && inside_z);
246  }
247 
248  case geom_shape::sphere:
249  return (dist_2(p, shape.p0) <= (shape.radius * shape.radius));
250 
252  {
253  Point height = shape.p1 - shape.p0;
254  Point center_to_point = p - shape.p0;
255 
256  double h = mag(height);
257  height /= h;
258 
259  double height_projection = dot(height, center_to_point);
260 
261  if(height_projection >= 0 && height_projection <= h) {
262  center_to_point -= (height * height_projection);
263  return (mag2(center_to_point) <= (shape.radius * shape.radius));
264  }
265  else
266  return false;
267  }
268 /*
269  default:
270  log_msg(0,5,0, "%s error: Shape type not yet implemented.", __func__);
271  EXIT(1);
272 */
273  }
274 
275  return false;
276 }
277 
279 {
280  int i = 1;
281  char *p = (char *)&i;
282 
283  if (p[0] == 1)
284  return false;
285  else
286  return true;
287 }
288 
289 bool file_can_be_opened(const char* file)
290 {
291  int rank = get_rank();
292  int did_open = 0;
293 
294  if(rank == 0) {
295  FILE* fd = fopen(file, "r");
296  if(fd != NULL) {
297  did_open = 1;
298  fclose(fd);
299  }
300  }
301 
302  did_open = get_global(did_open, MPI_SUM);
303 
304  return did_open > 0;
305 }
306 
307 bool path_is_absolute(const char* path)
308 {
309  // we can be here more fancy / platform specific. -Aurel Jan. 27 2021
310  if(strlen(path) && path[0] == '/') return true;
311 
312  return false;
313 }
314 
315 
316 #ifdef USE_FMEM_WRAPPER
324 static fpos_t SeekFn(void *handler, fpos_t offset, int whence) {
325  size_t pos = 0;
326  fmem_t *mem = (fmem_t*)handler;
327 
328  switch (whence) {
329  case SEEK_SET:
330  if (offset > 0 && (size_t)offset <= mem->size)
331  return mem->pos = offset;
332  break;
333  case SEEK_CUR:
334  if (mem->pos + offset <= mem->size)
335  return mem->pos = offset;
336  break;
337  case SEEK_END:
338  /* must be negative */
339  if (mem->size + offset <= mem->size)
340  return pos = mem->size + offset;
341  break;
342  }
343 
344  return -1;
345 }
346 
354 static int ReadFn(void *handler, char *buf, int size) {
355  size_t count = 0;
356  fmem_t *mem = (fmem_t*)handler;
357  size_t available = mem->size - mem->pos;
358 
359  if (size < 0) return - 1;
360 
361  if ((size_t)size > available)
362  size = available;
363 
364  while (count < (size_t)size)
365  buf[count++] = mem->buffer[mem->pos++];
366 
367  return count;
368 }
369 
377 static int WriteFn(void *handler, const char *buf, int size) {
378  size_t count = 0;
379  fmem_t *mem = (fmem_t*)handler;
380  size_t available = mem->size - mem->pos;
381 
382  if (size < 0) return - 1;
383 
384  if ((size_t)size > available)
385  size = available;
386 
387  while (count < (size_t)size)
388  mem->buffer[mem->pos++] = buf[count++];
389 
390  return count;
391 }
392 
398 static int CloseFn(void *handler) {
399  free (handler);
400  return 0;
401 }
402 
403 
411 FILE *fmemopen_(void *buf, size_t size, const char *mode) {
412  fmem_t *mem = (fmem_t *) malloc(sizeof(fmem_t));
413 
414  memset(mem, 0, sizeof(fmem_t));
415  mem->size = size, mem->buffer = (char*)buf;
416 
417  return funopen(mem, ReadFn, WriteFn, SeekFn, CloseFn);
418 }
419 
420 #endif // USE_FMEM_WRAPPER
421 
422 } // namespace opencarp
Basic utility structs and functions, mostly IO related.
#define FLUSH
Definition: basics.h:304
#define MAX_LOG_LEVEL
Definition: basics.h:308
#define LOCAL
Definition: basics.h:302
#define MAX_MESG_LEN
Definition: basics.h:307
#define SYNCED
Definition: basics.h:303
#define ECHO
Definition: basics.h:301
#define NONL
Definition: basics.h:305
#define fmemopen_
Definition: basics.h:426
A vector storing arbitrary data.
Definition: SF_vector.h:28
T * data()
Pointer to the vector's start.
Definition: SF_vector.h:76
class to store shape definitions
Definition: basics.h:374
void count(const vector< T > &data, vector< S > &cnt)
Count number of occurrences of indices.
Definition: SF_vector.h:317
bool is_big_endian()
Definition: basics.cc:278
void sltlst_append(Salt_list *sl, void *p, int quantum)
Definition: basics.cc:18
char * f_gets_par(char *s, int size, FILE_SPEC stream, MPI_Comm comm)
Definition: basics.cc:187
V dot(const vec3< V > &p1, const vec3< V > &p2)
Definition: vect.h:110
bool point_in_shape(const Point &p, const geom_shape &shape)
test if a point is inside a simple geometric shape
Definition: basics.cc:238
char * stringify(double r)
Definition: basics.cc:39
char * read_bin_string(FILE_SPEC in)
Definition: basics.cc:216
void f_read_par(void *ptr, size_t size, size_t nmemb, FILE_SPEC stream, MPI_Comm comm)
Parallel fread. Root reads, then broadcasts.
Definition: basics.cc:159
bool file_can_be_opened(const char *file)
Check wheterh a file can be opened for reading.
Definition: basics.cc:289
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
Definition: basics.h:269
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
Definition: basics.h:218
void write_bin_string(FILE_SPEC out, const char *s)
Definition: basics.cc:207
void f_write_par(void *ptr, size_t size, size_t nmemb, int source_pid, FILE_SPEC stream, MPI_Comm comm)
Write in parallel. Data comes from one rank, rank 0 writes.
Definition: basics.cc:167
FILE_SPEC f_open(const char *fname, const char *mode)
Open a FILE_SPEC.
Definition: basics.cc:123
bool path_is_absolute(const char *path)
check whether path is absolute
Definition: basics.cc:307
V mag(const vec3< V > &vect)
Definition: vect.h:116
char * read_bin_string_par(FILE_SPEC in)
Definition: basics.cc:227
bool mpi_runtime_ready()
Definition: basics.h:253
char * dupstr(const char *old_str)
Definition: basics.cc:29
V dist_2(const vec3< V > &p1, const vec3< V > &p2)
Definition: vect.h:87
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
Definition: basics.cc:57
bool f_exist(const char *fname)
Definition: basics.cc:118
std::string get_basename(const std::string &path)
Definition: basics.cc:46
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:150
V mag2(const vec3< V > &vect)
Definition: vect.h:123
bool available
Definition: sim_utils.cc:63
saltatory list – memory is allocated in chunks
Definition: basics.h:44
int chunk
allocate memory to hold this many items
Definition: basics.h:46
void * data
the buffer
Definition: basics.h:45
int size
size of list items
Definition: basics.h:48
int nitems
number of items
Definition: basics.h:47
File descriptor struct.
Definition: basics.h:120
const char * name
Definition: basics.h:122