diff --git a/src/configuration.c b/src/configuration.c new file mode 100644 index 0000000000000000000000000000000000000000..b740bf6893c3c16268593792d5de7b1b3a190dd9 --- /dev/null +++ b/src/configuration.c @@ -0,0 +1,847 @@ +/** @file configuration.c + * @brief Module for input/output of parameters + */ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/** @brief Looks in a libconfig file *.cfg for a parameter of type 'int', with + * name 'sstring' and add its value to the global variable with the same name. + * If already initialized, its value will be overwritten. + * + * @param[in] name name of the parameter (see e.g., input file default.cfg) + * @param[in] type type of parameter (see e.g., input file default.cfg) + * @param[in] comment comment to be added (see e.g., input file default.cfg) + * @param[in] sstring name to be found + * @param[out] *par global 'int' variable named 'name'; + * on return *par will have value 'value' + * @param[in] value of type 'int' + * @param[in] count number of elements in array 'parameter_names' to examine + * @param[in] *change if TRUE then value in setting_default will be changed + * @param[in] setting_default related to default configuration file + * @param[out] i position in global array 'parameter_names' + * defined in configuration.h + * + */ +bool +change_cfg_integer(const char* name, + const char *type, + const char *comment, + const char *sstring, + int *par, + int value, + int count, + bool *change, + config_setting_t *setting_default, + int i) +{ + int j; + config_setting_t *elem,*setting_value,*setting_comment; + + if(!(strncmp(name,sstring,COMPARE_LIMIT))) { + if(!(strncmp(type,"int",COMPARE_LIMIT))) { + *par = value; + if(change) { + /* Find the corresponding index in the file default.cfg */ + for(j=0; j You should use something smaller. + */ + if(change_cfg_integer (name,type,comment,"max_disk_space_mb",&max_disk_space_mb,ivalue,count,change,setting,ii)) + return; + + /************************ + * Numerical parameters * + ************************/ + + /* Number of gridpoints in r direction at level 0. */ + if(change_cfg_integer (name,type,comment,"gridpoints_r",&gridpoints_r,ivalue,count,change,setting,ii)) + return; + + /* Number of gridpoints in z direction at level 0. */ + if(change_cfg_integer (name,type,comment,"gridpoints_z",&gridpoints_z,ivalue,count,change,setting,ii)) + return; + + /* Number of azimuthal modes. */ + if(change_cfg_integer (name,type,comment,"max_ntheta",&max_ntheta,ivalue,count,change,setting,ii)) + return; + + /* Initial time may be away from 0 */ + if(change_cfg_double(name,type,comment,"start_t",&start_t,dvalue,count,change,setting,ii)) + return; + + /* End time of simulation, originally 500.0 */ + if(change_cfg_double(name,type,comment,"end_t",&end_t,dvalue,count,change,setting,ii)) + return; + + /* The actual timestep may be smaller that this one, if it is needed + * to satisfy the Courant constraint. + */ + if(change_cfg_double(name,type,comment,"attempt_dt",&attempt_dt,dvalue,count,change,setting,ii)) + return; + + /* Number of levels that are used for the Poisson equation + * but NOT for the cdr integrator. + */ + if(change_cfg_integer (name,type,comment,"extra_pois_levels",&extra_pois_levels,ivalue,count,change,setting,ii)) + return; + + /* Maximum nesting depth */ + if(change_cfg_integer (name,type,comment,"max_levels",&max_levels,ivalue,count,change,setting,ii)) + return; + + /* Total number of species */ + if(change_cfg_integer (name,type,comment,"no_species",&no_species,ivalue,count,change,setting,ii)) + return; + + /* Maximum error allowed in the Poisson solver. + * Cells with larger errors will be further refined. + */ + if(change_cfg_double(name,type,comment,"pois_max_error",&pois_max_error,dvalue,count,change,setting,ii)) + return; + + /* Maximum refinement level for the Poisson solver. */ + if(change_cfg_integer(name,type,comment,"pois_max_level",&pois_max_level,ivalue,count,change,setting,ii)) + return; + + /* These are photo-ionization parameters equivalent to the Poisson ones. + * If extra_photo_levels < 0, then these parameters are ignored and the + * poisson-parameters are used. If extra_photo_levels_2 < 0 then the + * parameters for the second term are ignored and the parameters for the + * first term are used for both terms. + */ + + /* First photo-ionization term */ + if(change_cfg_integer (name,type,comment,"extra_photo_levels",&extra_photo_levels,ivalue,count,change,setting,ii)) + return; + + /* Maximum level of refinement in the photo-ionization solver.*/ + if(change_cfg_integer (name,type,comment,"photo_max_level",&photo_max_level,ivalue,count,change,setting,ii)) + return; + + /* Error threshold that leads to refinement in the photo-ionization code. */ + if(change_cfg_double(name,type,comment,"photo_max_error",&photo_max_error,dvalue,count,change,setting,ii)) + return; + + /* Photo-ionization boundary condition at r = L_r + * 1 means homogeneous Neumann boundary conditions + * -1 means homogeneous Dirichlet boundary conditions. + */ + if(change_cfg_integer(name,type,comment,"photo_bnd_right" ,&photo_bnd_right ,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"photo_bnd_bottom",&photo_bnd_bottom,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"photo_bnd_top" ,&photo_bnd_top ,ivalue,count,change,setting,ii)) + return; + + + /* Second photo-ionization term: Extra levels for the photo-ionization solver. */ + if(change_cfg_integer(name,type,comment,"extra_photo_levels_2",&extra_photo_levels_2,ivalue,count,change,setting,ii)) + return; + + /* Maximum level of refinement in the photo-ionization solver.*/ + if(change_cfg_integer(name,type,comment,"photo_max_level_2",&photo_max_level_2,ivalue,count,change,setting,ii)) + return; + + + /* Error threshold that leads to refinement in the photo-ionization code.*/ + if(change_cfg_double(name,type,comment,"photo_max_error_2",&photo_max_error_2,dvalue,count,change,setting,ii)) + return; + + /* Photo-ionization boundary condition at r = L_r. + * 1 for homogeneous Neumann, + * -1 for homogeneous Dirichlet + */ + if(change_cfg_integer(name,type,comment,"photo_bnd_right_2",&photo_bnd_right_2,ivalue,count,change,setting,ii)) + return; + + /* Photo-ionization boundary condition at z = 0. + * 1 for homogeneous Neumann, + * -1 for homogeneous Dirichlet + */ + if(change_cfg_integer(name,type,comment,"photo_bnd_bottom_2",&photo_bnd_bottom_2,ivalue,count,change,setting,ii)) + return; + + /* Photo-ionization boundary condition at z = L_z. + * 1 for homogeneous Neumann, + * -1 for homogeneous Dirichlet + */ + if(change_cfg_integer(name,type,comment,"photo_bnd_top_2",&photo_bnd_top_2,ivalue,count,change,setting,ii)) + return; + + /* Boundary conditions for the CDR system. */ + if(change_cfg_integer(name,type,comment,"cdr_bnd_bottom",&cdr_bnd_bottom,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"cdr_bnd_top",&cdr_bnd_top,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"cdr_bnd_right",&cdr_bnd_right,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"pois_bnd_right",&pois_bnd_right,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"pois_bnd_bottom",&pois_bnd_bottom,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"pois_bnd_top",&pois_bnd_top,ivalue,count,change,setting,ii)) + return; + + /* Courant numbers. */ + if(change_cfg_double(name,type,comment,"nu_a",&nu_a,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"nu_d",&nu_d,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"nu_rt",&nu_rt,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"nu_f",&nu_f,dvalue,count,change,setting,ii)) + return; + + /* Refinement criteria for the CDR equation. */ + if(change_cfg_double(name,type,comment,"ref_threshold_eabs",&ref_threshold_eabs,dvalue,count,change,setting,ii)) + return; + + /* Refinement criteria for the CDR equation. */ + if(change_cfg_integer(name,type,comment,"ref_level_eabs",&ref_level_eabs,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"ref_threshold_charge",&ref_threshold_charge,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"ref_threshold_dens",&ref_threshold_dens,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"ref_threshold_edge",&ref_threshold_edge,dvalue,count,change,setting,ii)) + return; + + /* r- and z-length of the minimal refinement area in the cdr equation*/ + if(change_cfg_integer(name,type,comment,"cdr_brick_dr",&cdr_brick_dr,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"cdr_brick_dz",&cdr_brick_dz,ivalue,count,change,setting,ii)) + return; + + /* Maximum refinement level for the cdr solver. */ + if(change_cfg_integer(name,type,comment,"cdr_max_level",&cdr_max_level,ivalue,count,change,setting,ii)) + return; + + /* Interpolation method. */ + if(change_cfg_integer(name,type,comment,"cdr_interp_in",&cdr_interp_in,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"cdr_interp_bnd",&cdr_interp_bnd,ivalue,count,change,setting,ii)) + return; + + /*********************** + * Physical parameters * + ***********************/ + if(change_cfg_double(name,type,comment,"L_r",&L_r,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"L_z",&L_z,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"diffusion_coeff",&diffusion_coeff,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"attachment_rate",&attachment_rate,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"attachment_E0",&attachment_E0,dvalue,count,change,setting,ii)) + return; + + /* Constant external electric field. */ + if(change_cfg_double(name,type,comment,"E0_x",&E0_x,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"E0_y",&E0_y,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"E0_z",&E0_z,dvalue,count,change,setting,ii)) + return; + + /* Constant external electric field. */ + if(change_cfg_double(name,type,comment,"rise_time",&rise_time,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"off_time",&off_time,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"has_photoionization",&has_photoionization,ivalue,count,change,setting,ii)) + return; + + /* Width of the initial seed in x-, y- and z-direction */ + if(change_cfg_double(name,type,comment,"seed_sigma_x",&seed_sigma_x,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"seed_sigma_y",&seed_sigma_y,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"seed_sigma_z",&seed_sigma_z,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"seed_N",&seed_N,dvalue,count,change,setting,ii)) + return; + + /* Initial background ionization */ + if(change_cfg_double(name,type,comment,"background_ionization",&background_ionization,dvalue,count,change,setting,ii)) + return; + + /* Length of exponential increase of the pre-ionization for atmospherical + * models + */ + if(change_cfg_double(name,type,comment,"background_increase_length",&background_increase_length, + dvalue,count,change,setting,ii)) + return; + + /* Use the point-plane geometry? */ + if(change_cfg_integer(name,type,comment,"pois_inhom",&pois_inhom,ivalue,count,change,setting,ii)) + return; + + /* Number of mirror charges to use*/ + if(change_cfg_integer(name,type,comment,"pois_inhom_reflections",&pois_inhom_reflections,ivalue,count,change,setting,ii)) + return; + + /* Length of the needle */ + if(change_cfg_double(name,type,comment,"needle_length",&needle_length,dvalue,count,change,setting,ii)) + return; + + /* Radius of the needle */ + if(change_cfg_double(name,type,comment,"needle_radius",&needle_radius,dvalue,count,change,setting,ii)) + return; + + /* If nonzero, the charge is fixed, not floating + * Simulation of charged clouds close to the earth surface. + */ + if(change_cfg_double(name,type,comment,"pois_inhom_fixed_q",&pois_inhom_fixed_q,dvalue,count,change,setting,ii)) + return; + + /* Constant ionization rate. */ + if(change_cfg_double(name,type,comment,"constant_source",&constant_source,dvalue,count,change,setting,ii)) + return; + + /* Random perturbations for stability analysis. */ + if(change_cfg_double(name,type,comment,"perturb_epsilon",&perturb_epsilon,dvalue,count,change,setting,ii)) + return; + + /* Perturb only modes up to perturb_max_k, i.e. large number to perturb all */ + if(change_cfg_integer(name,type,comment,"perturb_max_k",&perturb_max_k,ivalue,count,change,setting,ii)) + return; + + /****************** + * Sprites module * + ******************/ + if(change_cfg_integer(name,type,comment,"sprite_module",&sprite_module,ivalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"dens_decay_len",&dens_decay_len,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"sprite_dens_0",&sprite_dens_0,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_double(name,type,comment,"sprite_dens_q",&sprite_dens_q,dvalue,count,change,setting,ii)) + return; + + if(change_cfg_integer(name,type,comment,"sprite_sign",&sprite_sign,ivalue,count,change,setting,ii)) + return; + +} + +/* @brief Read just one parameter from configuration file connected + * to setting2. + * + * In case setting1 and setting2 are different then + * the value in setting1 will be overwritten by the value of setting2. + * + * In case setting1 and setting2 are the same then + * the value in setting1 will be added. + * + * @param[in] config_setting_t *setting1 represents s configuration setting + * @param[in] config_setting_t *setting2 represents s configuration setting + * @param[in] ii position in array 'parameter_names' + * @param[in] count number of elements in parameter array to examine + * @param[in] *change if TRUE then value in setting_default will be changed + * + */ +bool +read_parameter(config_setting_t *setting1, + config_setting_t *setting2, + int ii, + int count, + bool *change) +{ + const char *type,*name,*comment; + double dvalue; + int ivalue; + int bbool; + const char* astring; + config_setting_t *elem = config_setting_get_elem(setting2,ii); + + /* Only output the record if all of the expected fields are present. */ + if(config_setting_lookup_string(elem, "type", &type) && + config_setting_lookup_string(elem, "name", &name) && + config_setting_lookup_string(elem, "comment",&comment) && + (config_setting_lookup_float (elem,"value", &dvalue) || + config_setting_lookup_int (elem,"value", &ivalue) || + config_setting_lookup_bool (elem,"value", &bbool ) || + config_setting_lookup_string(elem,"value", &astring)) + ) { + printf("\n# %s\n",comment); + if(!(strncmp(type,"string",COMPARE_LIMIT))) + printf("(%s) %s=%s\n",type,name,astring); + if(!(strncmp(type,"double",COMPARE_LIMIT))) + printf("(%s) %s=%g\n",type,name,dvalue); + if(!(strncmp(type,"int",COMPARE_LIMIT))) + printf("(%s) %s=%i\n",type,name,ivalue); + if(!(strncmp(type,"bool",COMPARE_LIMIT))) + printf("(%s) %s=%i\n",type,name,bbool); + } else { + printf("read_parameter: type is no string, double, int or bool but something else\n"); + return(FALSE); + } + + change_cfg_parameters(name,type,comment,ii,ivalue,dvalue,bbool,astring, + setting1,count,change); + return(TRUE); +} + +/* @brief Reads the specifications of specie number 'ii' in the configuration + * file related to *setting. Initializes the fields of *temp_s. + * + * @param[in] *setting Of type config_setting_t. It represents a configuration + * setting + * @param[in] ii position in global 'parameter_names' array + * @param[out] *temp_s Of type 'species_t'. Its fields will be initialized + * with values "name","mass" and "charge" read + * from setting connected to configuration file + */ +bool +read_specie(config_setting_t *setting, + int ii, + species_t *temp_s) +{ + config_setting_t *elem = config_setting_get_elem(setting,ii); + + /* Only output the record if all of the expected fields are present. */ + if (!(config_setting_lookup_string(elem,"name",&temp_s->name) && + config_setting_lookup_float (elem,"mass",&temp_s->mass) && + config_setting_lookup_float (elem,"charge",&temp_s->charge))) + { + printf("wrong types in kinetic file for species\n"); + return(FALSE); + } + return(TRUE); +} + +/* @brief Read the specifications of seed number 'ii' in the configuration + * file related to *setting. Initialize *temp_se. + * + * @param[in] *setting of type config_setting_t. It represents a configuration + * setting + * @param[in] ii position in global array '*seed_index' + * @param[out] *temp_se of type 'seed_t' describing a seed + */ +bool +read_seed(config_setting_t *setting, + int ii, + seed_t *temp_se) +{ + config_setting_t *elem = config_setting_get_elem(setting,ii); + + /* Only output the record if all of the expected fields are present. */ + if (!(config_setting_lookup_string(elem,"species",&temp_se->kind_species) && + config_setting_lookup_float (elem,"value",&temp_se->value) && + config_setting_lookup_string(elem,"type",&temp_se->kind_type))) + { + printf("wrong types in kinetic file for seed: species,value or type\n"); + return(FALSE); + } + + /* Find the position in the species-array of a given species */ + temp_se->species = find_species_by_name(temp_se->kind_species); + + /* Translate string 'kind_type' into integer value, + * temp_se->type = -1 denotes unknown */ + if (strcmp(temp_se->kind_type,"gaussian") == 0) + temp_se->type = 0; + else if (strcmp(temp_se->kind_type,"constant") == 0) + temp_se->type = 1; + else + temp_se->type = -1; + + if (!(config_setting_lookup_float(elem,"x0",&temp_se->x0))) + { temp_se->x0=0.0; } + if (!(config_setting_lookup_float(elem,"y0",&temp_se->y0))) + { temp_se->y0=0.0; } + if (!(config_setting_lookup_float(elem,"z0",&temp_se->z0))) + { temp_se->z0=0.0; } + + if (!(config_setting_lookup_float (elem,"sigma_x",&temp_se->sigma_x))) + { temp_se->sigma_x=0.0; } + if (!(config_setting_lookup_float(elem,"sigma_y",&temp_se->sigma_y))) + { temp_se->sigma_y=0.0; } + if (!(config_setting_lookup_float(elem,"sigma_z",&temp_se->sigma_z))) + { temp_se->sigma_z=0.0; } + + return(TRUE); +} + +/* @brief Read the specifications of reaction number 'ii' in the configuration + * file related to *setting. Initialize *temp_r. + * + * @param[in] *setting of type config_setting_t. It represents a configuration + * setting + * @param[in] ii position in global array '*reaction_index' + * @param[out] *temp_r of type 'reaction_t' describing a reaction + */ +bool +read_reaction(config_setting_t *setting, + int ii, + reaction_t *temp_r) +{ + config_setting_t *elem = config_setting_get_elem(setting,ii); + const char *table; + const char *error; + int cnt; + + /* Only output the record if fields nin and nout are present. */ + if (!(config_setting_lookup_string(elem,"reacttable",&table))) + { + printf("wrong types in kinetic file for reaction.reacttable\n"); + return(FALSE); + } else + temp_r->tablefile = (char *) table; + + /* Only output the record if fields nin and nout are present. */ + if (!(config_setting_lookup_int(elem,"nin",&temp_r->nin) && + config_setting_lookup_int(elem,"nout",&temp_r->nout))) + { + printf("wrong types in kinetic file for reactions\n"); + return(FALSE); + } + + error="not_init"; + for(cnt = 0; cnt < REACTION_MAX_IN; ++cnt) { + temp_r->input[cnt] = -1; + temp_r->inname[cnt]=error; + } + + config_setting_lookup_string(elem,"specin0",&temp_r->inname[0]); + config_setting_lookup_string(elem,"specin1",&temp_r->inname[1]); + config_setting_lookup_string(elem,"specin2",&temp_r->inname[2]); + config_setting_lookup_string(elem,"specin3",&temp_r->inname[3]); + + /* Find the position in the species-array of a given species */ + for(cnt = 0; cnt < temp_r->nin; cnt++) { + if(strcmp(temp_r->inname[cnt],error)==0) + { + printf("NOT all reaction.specin initialized for reaction %d and specie %d\n",ii,cnt); + exit(1); + } + else + temp_r->input[cnt] = find_species_by_name(temp_r->inname[cnt]); + } + + for(cnt = 0; cnt < REACTION_MAX_OUT; ++cnt) { + temp_r->output[cnt] = -1; + temp_r->outname[cnt]=error; + } + + config_setting_lookup_string(elem,"specout0",&temp_r->outname[0]); + config_setting_lookup_string(elem,"specout1",&temp_r->outname[1]); + config_setting_lookup_string(elem,"specout2",&temp_r->outname[2]); + config_setting_lookup_string(elem,"specout3",&temp_r->outname[3]); + config_setting_lookup_string(elem,"specout4",&temp_r->outname[4]); + config_setting_lookup_string(elem,"specout5",&temp_r->outname[5]); + + /* Find the position in the species-array of a given species */ + for(cnt = 0; cnt < temp_r->nout; cnt++) { + if(strcmp(temp_r->outname[cnt],error)==0) + { + debug(1,"temp_r->outname[%d]=%s; error=%s\n",cnt,temp_r->outname[cnt],error); + printf("NOT all reaction.specout initialized for reaction %d and specie %d\n",ii,cnt); + exit(1); + } + else + temp_r->output[cnt] = find_species_by_name(temp_r->outname[cnt]); + } + + return(TRUE); +}