/****************************************************************************** * @brief Parse units string in format of "<units> since <origin (YYYY-MM-DD)>" *****************************************************************************/ void parse_nc_time_units(char *nc_unit_chars, unsigned short int *units, dmy_struct *dmy) { int status; char unit_chars[MAXSTRING]; int hours = 0; int minutes = 0; int seconds = 0; // Parse standard netCDF time units string. Note that sscanf return the // number of variables parsed and that not all variables will be parsed status = sscanf(nc_unit_chars, "%s since %d-%hu-%hu %d:%d:%d", unit_chars, &dmy->year, &dmy->month, &dmy->day, &hours, &minutes, &seconds); if (status < 4) { log_err("Unable to parse netcdf time units as specified: %s", nc_unit_chars); } // dayseconds, this will be zero when the last part of the format // string is not present dmy->dayseconds = hours * SEC_PER_HOUR + minutes * SEC_PER_MIN + seconds; *units = str_to_timeunits(unit_chars); }
/****************************************************************************** * @brief Read the VIC model global control file, getting values for * global parameters, model options, and debugging controls. *****************************************************************************/ void get_global_param(FILE *gp) { extern option_struct options; extern global_param_struct global_param; extern param_set_struct param_set; extern filenames_struct filenames; char cmdstr[MAXSTRING]; char optstr[MAXSTRING]; char flgstr[MAXSTRING]; char flgstr2[MAXSTRING]; /** Read through global control file to find parameters **/ rewind(gp); fgets(cmdstr, MAXSTRING, gp); while (!feof(gp)) { if (cmdstr[0] != '#' && cmdstr[0] != '\n' && cmdstr[0] != '\0') { sscanf(cmdstr, "%s", optstr); /* Handle case of comment line in which '#' is indented */ if (optstr[0] == '#') { fgets(cmdstr, MAXSTRING, gp); continue; } /************************************* Get Model Global Parameters *************************************/ if (strcasecmp("NLAYER", optstr) == 0) { sscanf(cmdstr, "%*s %zu", &options.Nlayer); } else if (strcasecmp("NODES", optstr) == 0) { sscanf(cmdstr, "%*s %zu", &options.Nnode); } else if (strcasecmp("OUT_TIME_UNITS", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); global_param.time_units = str_to_timeunits(flgstr); } else if (strcasecmp("FULL_ENERGY", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.FULL_ENERGY = str_to_bool(flgstr); if (options.FULL_ENERGY == false) { log_warn("FULL_ENERGY is set to FALSE. Please double check " "that this is the setting you intended."); } } else if (strcasecmp("FROZEN_SOIL", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.FROZEN_SOIL = str_to_bool(flgstr); // TODO: move these steps to a option validation if (options.FROZEN_SOIL) { options.QUICK_FLUX = false; } else { options.IMPLICIT = false; options.EXP_TRANS = false; } } else if (strcasecmp("QUICK_FLUX", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.QUICK_FLUX = str_to_bool(flgstr); } else if (strcasecmp("QUICK_SOLVE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.QUICK_SOLVE = str_to_bool(flgstr); } else if ((strcasecmp("NOFLUX", optstr) == 0) || (strcasecmp("NO_FLUX", optstr) == 0)) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("TRUE", flgstr) == 0) { options.NOFLUX = str_to_bool(flgstr); } } else if (strcasecmp("IMPLICIT", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.IMPLICIT = str_to_bool(flgstr); } else if (strcasecmp("EXP_TRANS", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.EXP_TRANS = str_to_bool(flgstr); } else if (strcasecmp("SNOW_DENSITY", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("DENS_SNTHRM", flgstr) == 0) { options.SNOW_DENSITY = DENS_SNTHRM; } else if (strcasecmp("DENS_BRAS", flgstr) == 0) { options.SNOW_DENSITY = DENS_BRAS; } else { log_err("Unknown SNOW_DENSITY option: %s", flgstr); } } else if (strcasecmp("BLOWING", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.BLOWING = str_to_bool(flgstr); } else if (strcasecmp("BLOWING_VAR_THRESHOLD", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.BLOWING_VAR_THRESHOLD = str_to_bool(flgstr); } else if (strcasecmp("BLOWING_CALC_PROB", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.BLOWING_CALC_PROB = str_to_bool(flgstr); } else if (strcasecmp("BLOWING_SIMPLE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.BLOWING_SIMPLE = str_to_bool(flgstr); } else if (strcasecmp("BLOWING_FETCH", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.BLOWING_FETCH = str_to_bool(flgstr); } else if (strcasecmp("BLOWING_SPATIAL_WIND", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.BLOWING_SPATIAL_WIND = str_to_bool(flgstr); } else if (strcasecmp("CORRPREC", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.CORRPREC = str_to_bool(flgstr); } else if (strcasecmp("CLOSE_ENERGY", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.CLOSE_ENERGY = str_to_bool(flgstr); } else if (strcasecmp("COMPUTE_TREELINE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("FALSE", flgstr) == 0) { options.COMPUTE_TREELINE = false; } else { options.COMPUTE_TREELINE = true; options.AboveTreelineVeg = atoi(flgstr); } } else if (strcasecmp("AERO_RESIST_CANSNOW", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("AR_406", flgstr) == 0) { options.AERO_RESIST_CANSNOW = AR_406; } else if (strcasecmp("AR_406_LS", flgstr) == 0) { options.AERO_RESIST_CANSNOW = AR_406_LS; } else if (strcasecmp("AR_406_FULL", flgstr) == 0) { options.AERO_RESIST_CANSNOW = AR_406_FULL; } else if (strcasecmp("AR_410", flgstr) == 0) { options.AERO_RESIST_CANSNOW = AR_410; } else { log_err("Unknown AERO_RESIST_CANSNOW option: %s", flgstr); } } else if (strcasecmp("GRND_FLUX_TYPE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("GF_406", flgstr) == 0) { options.GRND_FLUX_TYPE = GF_406; } else if (strcasecmp("GF_410", flgstr) == 0) { options.GRND_FLUX_TYPE = GF_410; } else { log_err("Unknown GRND_FLUX_TYPE option: %s", flgstr); } } else if (strcasecmp("SPATIAL_FROST", optstr) == 0) { sscanf(cmdstr, "%*s %s %s", flgstr, flgstr2); if (strcasecmp("TRUE", flgstr) == 0) { options.SPATIAL_FROST = true; options.Nfrost = atoi(flgstr2); } else { options.SPATIAL_FROST = false; } } else if (strcasecmp("SPATIAL_SNOW", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.SPATIAL_SNOW = str_to_bool(flgstr); } else if (strcasecmp("TFALLBACK", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.TFALLBACK = str_to_bool(flgstr); } else if (strcasecmp("SHARE_LAYER_MOIST", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.SHARE_LAYER_MOIST = str_to_bool(flgstr); } else if (strcasecmp("CANOPY_LAYERS", optstr) == 0) { sscanf(cmdstr, "%*s %zu", &options.Ncanopy); } else if (strcasecmp("CARBON", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.CARBON = str_to_bool(flgstr); } else if (strcasecmp("RC_MODE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("RC_PHOTO", flgstr) == 0) { options.RC_MODE = RC_PHOTO; } else if (strcasecmp("RC_JARVIS", flgstr) == 0) { options.RC_MODE = RC_JARVIS; } else { log_err("Unknown RC_MODE option: %s", flgstr); } } /************************************* Define log directory *************************************/ else if (strcasecmp("LOG_DIR", optstr) == 0) { sscanf(cmdstr, "%*s %s", filenames.log_path); } else if (strcasecmp("INIT_STATE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("FALSE", flgstr) == 0) { options.INIT_STATE = false; } else { options.INIT_STATE = true; strcpy(filenames.init_state.nc_filename, flgstr); } } // Define state file format else if (strcasecmp("STATE_FORMAT", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("NETCDF3_CLASSIC", flgstr) == 0) { options.STATE_FORMAT = NETCDF3_CLASSIC; } else if (strcasecmp("NETCDF3_64BIT_OFFSET", flgstr) == 0) { options.STATE_FORMAT = NETCDF3_64BIT_OFFSET; } else if (strcasecmp("NETCDF4_CLASSIC", flgstr) == 0) { options.STATE_FORMAT = NETCDF4_CLASSIC; } else if (strcasecmp("NETCDF4", flgstr) == 0) { options.STATE_FORMAT = NETCDF4; } else { log_err("STATE_FORMAT must be either NETCDF3_CLASSIC, " "NETCDF3_64BIT_OFFSET, NETCDF4_CLASSIC, or NETCDF4."); } } /************************************* Define parameter files *************************************/ else if (strcasecmp("CONSTANTS", optstr) == 0) { sscanf(cmdstr, "%*s %s", filenames.constants); } else if (strcasecmp("DOMAIN", optstr) == 0) { sscanf(cmdstr, "%*s %s", filenames.domain.nc_filename); } else if (strcasecmp("DOMAIN_TYPE", optstr) == 0) { get_domain_type(cmdstr); } else if (strcasecmp("PARAMETERS", optstr) == 0) { sscanf(cmdstr, "%*s %s", filenames.params.nc_filename); } else if (strcasecmp("ARNO_PARAMS", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("TRUE", flgstr) == 0) { log_err("Please change \"ARNO_PARAMS TRUE\" to \"BASEFLOW " "NIJSSEN2001\" in your global parameter file."); } else { log_err("Please change \"ARNO_PARAMS FALSE\" to \"BASEFLOW " "ARNO\" in your global parameter file."); } } else if (strcasecmp("NIJSSEN2001_BASEFLOW", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("TRUE", flgstr) == 0) { log_err("Please change \"NIJSSEN2001_BASEFLOW TRUE\" to " "\"BASEFLOW NIJSSEN2001\" in your global " "parameter file."); } else { log_err("Please change \"NIJSSEN2001_BASEFLOW FALSE\" to " "\"BASEFLOW ARNO\" in your global parameter file."); } } else if (strcasecmp("BASEFLOW", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("NIJSSEN2001", flgstr) == 0) { options.BASEFLOW = NIJSSEN2001; } else if (strcasecmp("ARNO", flgstr) == 0) { options.BASEFLOW = ARNO; } else { log_err("Unknown BASEFLOW option: %s", flgstr); } } else if (strcasecmp("JULY_TAVG_SUPPLIED", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.JULY_TAVG_SUPPLIED = str_to_bool(flgstr); } else if (strcasecmp("ORGANIC_FRACT", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.ORGANIC_FRACT = str_to_bool(flgstr); } else if (strcasecmp("VEGLIB_PHOTO", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.VEGLIB_PHOTO = str_to_bool(flgstr); } else if (strcasecmp("LAI_SRC", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("FROM_VEGHIST", flgstr) == 0) { options.LAI_SRC = FROM_VEGHIST; } else if (strcasecmp("FROM_VEGPARAM", flgstr) == 0) { options.LAI_SRC = FROM_VEGPARAM; } else if (strcasecmp("FROM_VEGLIB", flgstr) == 0) { options.LAI_SRC = FROM_VEGLIB; } else { log_err("Unrecognized value of LAI_SRC in the global " "control file."); } } else if (strcasecmp("FCAN_SRC", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("FROM_VEGHIST", flgstr) == 0) { options.FCAN_SRC = FROM_VEGHIST; } else if (strcasecmp("FROM_VEGPARAM", flgstr) == 0) { options.FCAN_SRC = FROM_VEGPARAM; } else if (strcasecmp("FROM_VEGLIB", flgstr) == 0) { options.FCAN_SRC = FROM_VEGLIB; } else if (strcasecmp("FROM_DEFAULT", flgstr) == 0) { options.FCAN_SRC = FROM_DEFAULT; } else { log_err("Unrecognized value of FCAN_SRC in the global " "control file."); } } else if (strcasecmp("ALB_SRC", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("FROM_VEGHIST", flgstr) == 0) { options.ALB_SRC = FROM_VEGHIST; } else if (strcasecmp("FROM_VEGPARAM", flgstr) == 0) { options.ALB_SRC = FROM_VEGPARAM; } else if (strcasecmp("FROM_VEGLIB", flgstr) == 0) { options.ALB_SRC = FROM_VEGLIB; } else { log_err("Unrecognized value of ALB_SRC in the global " "control file."); } } else if (strcasecmp("SNOW_BAND", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (str_to_bool(flgstr)) { options.SNOW_BAND = SNOW_BAND_TRUE_BUT_UNSET; } } else if (strcasecmp("LAKES", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp("FALSE", flgstr) == 0) { options.LAKES = false; } else { options.LAKES = true; } } else if (strcasecmp("LAKE_PROFILE", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); options.LAKE_PROFILE = str_to_bool(flgstr); } /************************************* Define output files *************************************/ else if (strcasecmp("RESULT_DIR", optstr) == 0) { sscanf(cmdstr, "%*s %s", filenames.result_dir); } /************************************* Define output file contents *************************************/ else if (strcasecmp("OUTFILE", optstr) == 0) { ; // do nothing } else if (strcasecmp("OUTVAR", optstr) == 0) { ; // do nothing } else if (strcasecmp("AGGFREQ", optstr) == 0) { ; // do nothing } else if (strcasecmp("OUTPUT_STEPS_PER_DAY", optstr) == 0) { ; // do nothing } else if (strcasecmp("SKIPYEAR", optstr) == 0) { ; // do nothing } else if (strcasecmp("COMPRESS", optstr) == 0) { ; // do nothing } else if (strcasecmp("OUT_FORMAT", optstr) == 0) { ; // do nothing } // vegetation history not yet implemented in image mode // TBD: feature in VIC 4.2 that has been ported to classic // mode, but that does not exist in image mode (yet) else if (strcasecmp("ALBEDO", optstr) == 0 || strcasecmp("LAI", optstr) == 0 || strcasecmp("FCANOPY", optstr) == 0) { log_err("Time-varying vegetation parameters not implemented " "in CESM driver"); } /*********************************** Unrecognized Global Parameter Flag ***********************************/ else { log_warn("Unrecognized option in the global parameter file: %s" "\n - check your spelling", optstr); } } fgets(cmdstr, MAXSTRING, gp); } // Output major options display_current_settings(DISP_VERSION); }