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