sandbox/bderembl/libs/extra.h
Parameter Management Library
This library provides utilities for reading and managing input parameters from configuration files, creating output directories, and backing up files. It’s designed to work with Basilisk simulations and supports various parameter types including integers, doubles, and arrays.
The configuration file should contain one parameter per line in the format:
key = value‘value’ can be an int, double or array. Comments are allowed with # character
Example:
# parameter list
iterations = 1000
timestep = 0.01   # with comments
coefficients = [1.0,2.5,3.7]Global Variables and Data Structures
char dpath[80]; // name of output dir
char file_param[80] = "params.in"; // name param file
// for mkdir
#include <sys/stat.h>
#include <sys/types.h>String Utilities
- trim_whitespace: removes leading whitespace characters from a string in-place.
 - str2array: Parses a string containing comma-separated values enclosed in brackets and converts them to a double array.
 
void trim_whitespace(char* s) {
  const char* d = s;
  do {
    while (*d == ' ')
      ++d;
  } while ((*s++ = *d++));
  *s = '\0';
}
void str2array(char *tmps2, double *array){
  // overwrite newline character with string terminator
  char *newline = strchr( tmps2, '\n' );
  if ( newline )
    *newline = 0;
  char* p;
  int n = 0;
  p = strtok(tmps2,"[,]");
  while (p != NULL){
    array[n] = atof(p);
    fprintf (stderr, "array[%d] = %g \n", n, array[n]);
    p = strtok(NULL, ",");
    n += 1;
  }
}Params global variable
Array * params;
typedef struct {
  char * name;
  void * ptr;
  char * type;
  int len;
} ParamItem;
void add_param(char * name, void * ptr,  char * type, int len = 0)
{
  ParamItem p;
  p.name = strdup(name);
  p.ptr = ptr;
  p.type = strdup(type);
  p.len = len;
  array_append (params, &p, sizeof (ParamItem));
}
void read_params(char* path2file)
{
  FILE * fp;
  if ((fp = fopen(path2file, "rt"))) {
    char tempbuff[300];
    while(fgets(tempbuff,300,fp)) { // loop over file lines
      trim_whitespace(tempbuff);
      char* tmps1 = strtok(tempbuff, "=");
      char* tmps2 = strtok(NULL, "=");
  ParamItem * d2 = params->p;
  for (int i = 0; i < params->len/sizeof(ParamItem); i++, d2++) { // loop over parameters
    if (strcmp(d2->name, tmps1) == 0) {
      //check for type and assign value
    if (strcmp(d2->type, "int") == 0) {
      *( (int*) d2->ptr) = atoi(tmps2);
      fprintf (stderr, "scan param %s: %d\n", d2->name, *( (int*) d2->ptr));}
    else if (strcmp(d2->type, "double") == 0){
      *( (double*) d2->ptr) = atof(tmps2);
      fprintf (stderr, "scan param %s: %e\n", d2->name, *( (double*) d2->ptr));}
    else if (strcmp(d2->type, "array") == 0){
      fprintf (stderr, "scan param %s:\n", d2->name);
      str2array(tmps2, (double*) d2->ptr);
      }
    }
    }
    }
    fclose(fp);
  } else {
    fprintf(stdout, "file %s not found\n", path2file);
    exit(0);
  }
}Create output directory and copy input parameter file for backup
void create_outdir()
{
  if (pid() == 0) {
    for (int i=1; i<10000; i++) {
      sprintf(dpath, "outdir_%04d/", i);
      if (mkdir(dpath, 0777) == 0) {
        fprintf(stdout,"Writing output in %s\n",dpath);
        break;
      }
    }
  }
@if _MPI
  MPI_Bcast(&dpath, 80, MPI_CHAR, 0, MPI_COMM_WORLD);
@endif
}
void backup_config(char* path2file)
{
  fprintf(stdout, "Backup config\n");
  if (pid() == 0) {
    char ch;
    char name[90];
    sprintf (name,"%sparams.in", dpath);
    FILE * source = fopen(path2file, "r");
    FILE * target = fopen(name, "w");
    while ((ch = fgetc(source)) != EOF)
      fputc(ch, target);
    fclose(source);
    fclose(target);
  }
}Copy file from: https://stackoverflow.com/questions/29079011/copy-file-function-in-c
void backup_file(char FileSource[])
{
  if (pid() == 0) {
    char FileDestination[100];
    sprintf (FileDestination,"%s%s", dpath, FileSource);
    char    c[4096]; // or any other constant you like
    FILE    *stream_R = fopen(FileSource, "r");
    FILE    *stream_W = fopen(FileDestination, "w");   //create and write to file
    while (!feof(stream_R)) {
      size_t bytes = fread(c, 1, sizeof(c), stream_R);
      if (bytes) {
        fwrite(c, 1, bytes, stream_W);
      }
    }
    //close streams
    fclose(stream_R);
    fclose(stream_W);
  }
}