sandbox/acastillo/frozen_waves/without_walls/sim_parameters.h
sim_parameters.h
Clean struct-based parameter reading for main_json.c. Replaces preprocessor defines with runtime JSON configuration.
Feature detection for cJSON library
#if __has_include(<cjson/cJSON.h>)
#define HAVE_CJSON 1
#pragma autolink -lcjson
#include <cjson/cJSON.h>Helper macro to safely extract double values from JSON
#define GET_DOUBLE(parent, name, dest) do { \
cJSON *item = cJSON_GetObjectItem(parent, #name); \
if (item && cJSON_IsNumber(item)) { \
dest = item->valuedouble; \
} \
} while(0)Helper macro to safely extract integer values from JSON
#define GET_INT(parent, name, dest) do { \
cJSON *item = cJSON_GetObjectItem(parent, #name); \
if (item && cJSON_IsNumber(item)) { \
dest = (int)item->valuedouble; \
} \
} while(0)Helper macro to safely extract boolean values from JSON
#define GET_BOOL(parent, name, dest) do { \
cJSON *item = cJSON_GetObjectItem(parent, #name); \
if (item && cJSON_IsBool(item)) { \
dest = cJSON_IsTrue(item); \
} \
} while(0)
#else
#define HAVE_CJSON 0
#warning "cJSON library not found. Using hardcoded default parameters."
#endifSimulation parameters structure
typedef struct {Domain parameters
double width; // Domain width
double height; // Domain height
double depth; // Domain depth
double aspectratio_x; // Aspect ratio (nx dimension multiplier)
double aspectratio_y; // Aspect ratio (ny dimension multiplier)
double aspectratio_z; // Aspect ratio (nz dimension multiplier)Dimensionless parameters
double atwood; // Atwood number
double reynolds; // Reynolds number
double froude; // Froude number
double weber; // Weber number
double viscosity; // Viscosity ratio (upsilon)Forcing parameters
double ramp_start; // Time when ramp starts
double ramp_slope; // Slope of sigmoid rampInitial conditions
double amplitude; // RMS amplitude of initial perturbation
double kmin; // Minimum wavenumber
double kmax; // Maximum wavenumberContact angle
double theta0; // Contact angle in degreesNumerical parameters
int level; // Grid refinement level
double cfl; // CFL number
double dt; // Time step
double tolerance; // Solver tolerance
int nitermin; // Minimum iterationsRuntime parameters
double walltime; // Maximum wall time (seconds)
double endtime; // Simulation end time
} SimParams;Initialize parameters with default values
void init_default_params(SimParams *p) {Domain parameters
p->width = 300.0;
p->height = 300.0;
p->depth = 75.0;
p->aspectratio_x = 1.0;
p->aspectratio_y = 1.0;
#if dimension == 3
p->aspectratio_z = 1.0;
#endifDimensionless parameters
p->atwood = 0.5;
p->reynolds = 43.62;
p->froude = 64.05;
p->weber = 604.80;
p->viscosity = 11.5;Forcing parameters
p->ramp_start = 100.0;
p->ramp_slope = 0.04;Initial conditions
p->amplitude = 0.50;
p->kmin = 15.0;
p->kmax = 30.0;Contact angle
p->theta0 = 90.0;Numerical parameters
p->level = 9;
p->cfl = 0.25;
p->dt = 0.1;
p->tolerance = 1e-4;
p->nitermin = 1;Runtime parameters
p->walltime = 3600.0;
p->endtime = 1000.0;
}
#if HAVE_CJSONParse domain parameters from JSON object
void parse_domain_section(cJSON *domain, SimParams *p) {
if (!domain) return;
GET_DOUBLE(domain, width, p->width);
GET_DOUBLE(domain, height, p->height);
GET_DOUBLE(domain, depth, p->depth);
#if dimension == 2
double min_dim = p->width < p->height ? p->width : p->height;
p->aspectratio_x = p->width / min_dim;
p->aspectratio_y = p->height / min_dim;
#else
double min_dim = p->depth;
p->aspectratio_x = p->width / min_dim;
p->aspectratio_y = p->depth / min_dim;
p->aspectratio_z = p->height / min_dim;
#endif
}Parse dimensionless parameters from JSON object
void parse_dimensionless_section(cJSON *dimless, SimParams *p) {
if (!dimless) return;
GET_DOUBLE(dimless, atwood, p->atwood);
GET_DOUBLE(dimless, reynolds, p->reynolds);
GET_DOUBLE(dimless, froude, p->froude);
GET_DOUBLE(dimless, weber, p->weber);
GET_DOUBLE(dimless, viscosity, p->viscosity);
}Parse forcing parameters from JSON object
void parse_forcing_section(cJSON *forcing, SimParams *p) {
if (!forcing) return;
GET_DOUBLE(forcing, ramp_start, p->ramp_start);
GET_DOUBLE(forcing, ramp_slope, p->ramp_slope);
}Parse initial condition parameters from JSON object
void parse_initial_conditions_section(cJSON *ic, SimParams *p) {
if (!ic) return;
GET_DOUBLE(ic, amplitude, p->amplitude);
GET_DOUBLE(ic, kmin, p->kmin);
GET_DOUBLE(ic, kmax, p->kmax);
}Parse contact angle from JSON object
void parse_contact_section(cJSON *contact, SimParams *p) {
if (!contact) return;
GET_DOUBLE(contact, theta0, p->theta0);
}Parse runtime parameters from JSON object
void parse_runtime_section(cJSON *runtime, SimParams *p) {
if (!runtime) return;
GET_DOUBLE(runtime, walltime, p->walltime);
GET_DOUBLE(runtime, endtime, p->endtime);
}Parse numerical parameters from JSON object
void parse_numerics_section(cJSON *numerics, SimParams *p) {
if (!numerics) return;
GET_INT(numerics, level, p->level);
GET_DOUBLE(numerics, cfl, p->cfl);
GET_DOUBLE(numerics, dt, p->dt);
GET_DOUBLE(numerics, tolerance, p->tolerance);
GET_INT(numerics, nitermin, p->nitermin);
}
#endifRead and parse JSON file into SimParams structure
Returns 0 on success, -1 on error. If the file cannot be read or parsed, default parameters are used and a warning is printed.
int read_sim_params(const char *filename, SimParams *params) {Initialize with defaults first
init_default_params(params);
#if !HAVE_CJSON
fprintf(stderr, "Warning: cJSON not available, using default parameters\n");
return -1;
#elseRead file
FILE *file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "Warning: Could not open file '%s'\n", filename);
fprintf(stderr, "Using default parameters\n");
return -1;
}Get file size
fseek(file, 0, SEEK_END);
long length = ftell(file);
fseek(file, 0, SEEK_SET);Read content
char *content = (char *)malloc(length + 1);
if (!content) {
fprintf(stderr, "Error: Memory allocation failed\n");
fclose(file);
return -1;
}
fread(content, 1, length, file);
content[length] = '\0';
fclose(file);Parse JSON
cJSON *json = cJSON_Parse(content);
free(content);
if (!json) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr) {
fprintf(stderr, "Error: JSON parse error before: %s\n", error_ptr);
}
fprintf(stderr, "Using default parameters\n");
return -1;
}Parse sections
parse_domain_section(cJSON_GetObjectItem(json, "domain"), params);
parse_dimensionless_section(cJSON_GetObjectItem(json, "dimensionless"), params);
parse_forcing_section(cJSON_GetObjectItem(json, "forcing"), params);
parse_initial_conditions_section(cJSON_GetObjectItem(json, "initial_conditions"), params);
parse_contact_section(cJSON_GetObjectItem(json, "contact"), params);
parse_numerics_section(cJSON_GetObjectItem(json, "numerics"), params);
parse_runtime_section(cJSON_GetObjectItem(json, "runtime"), params);
cJSON_Delete(json);
return 0;
#endif
}MPI-aware version: only rank 0 reads, then broadcasts
void read_sim_params_mpi(const char *filename, SimParams *params) {
if (pid() == 0) {
read_sim_params(filename, params);
}
@if _MPIBroadcast the entire struct
MPI_Bcast(params, sizeof(SimParams), MPI_BYTE, 0, MPI_COMM_WORLD);
@endif
}Print parameters for verification
void print_sim_params(const SimParams *p) {
fprintf(stderr, "\n=== SIMULATION PARAMETERS ===\n");
fprintf(stderr, "Domain:\n");
fprintf(stderr, " Width : %g\n", p->width);
fprintf(stderr, " Height : %g\n", p->height);
fprintf(stderr, " Depth : %g\n", p->depth);
fprintf(stderr, " Aspect Ratio: %g\n", p->aspectratio_x);
fprintf(stderr, " Aspect Ratio: %g\n", p->aspectratio_y);
fprintf(stderr, " Aspect Ratio: %g\n", p->aspectratio_z);
fprintf(stderr, "\nDimensionless:\n");
fprintf(stderr, " Atwood : %g\n", p->atwood);
fprintf(stderr, " Reynolds : %g\n", p->reynolds);
fprintf(stderr, " Froude : %g\n", p->froude);
fprintf(stderr, " Weber : %g\n", p->weber);
fprintf(stderr, " Viscosity : %g\n", p->viscosity);
fprintf(stderr, "\nForcing:\n");
fprintf(stderr, " Ramp Start : %g\n", p->ramp_start);
fprintf(stderr, " Ramp Slope : %g\n", p->ramp_slope);
fprintf(stderr, "\nInitial Conditions:\n");
fprintf(stderr, " Amplitude : %g\n", p->amplitude);
fprintf(stderr, " kmin : %g\n", p->kmin);
fprintf(stderr, " kmax : %g\n", p->kmax);
fprintf(stderr, "\nContact:\n");
fprintf(stderr, " Theta0 : %g°\n", p->theta0);
fprintf(stderr, "\nNumerics:\n");
fprintf(stderr, " Level : %d\n", p->level);
fprintf(stderr, " CFL : %g\n", p->cfl);
fprintf(stderr, " DT : %g\n", p->dt);
fprintf(stderr, " Tolerance : %g\n", p->tolerance);
fprintf(stderr, " NITERMIN : %d\n", p->nitermin);
fprintf(stderr, "\nRuntime:\n");
fprintf(stderr, " Wall Time : %g s\n", p->walltime);
fprintf(stderr, " End Time : %g\n", p->endtime);
fprintf(stderr, "=============================\n\n");
}