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