int main(int argc, char *argv[]) /********************************************************************** vicNl.c Dag Lohmann January 1996 This program controls file I/O and variable initialization as well as being the primary driver for the model. For details about variables, input files and subroutines check: http://ce.washington.edu/~hydro/Lettenmaier/Models/VIC/VIC_home.html UNITS: unless otherwise marked: all water balance components are in mm all energy balance components are in mks depths, and lengths are in m modifications: 1997-98 Model was updated from simple 2 layer water balance to an extension of the full energy and water balance 3 layer model. KAC 02-27-01 added controls for lake model KAC 11-18-02 Updated storage of lake water for water balance calculations. LCB 03-12-03 Modifed to add AboveTreeLine to soil_con_struct so that the model can make use of the computed treeline. KAC 04-10-03 Modified to initialize storm parameters using the state file. KAC 04-10-03 Modified to start the model by skipping records until the state file date is found. This replaces the previous method of modifying the global file start date, which can change the interpolation of atmospheric forcing data. KAC 04-15-03 Modified to store wet and dry fractions when intializing water balance storage. This accounts for changes in model state initialization, which now stores wet and dry fractions rather than just averagedvalues. KAC 29-Oct-03 Modified the version display banner to print the version string defined in global.h. TJB 01-Nov-04 Updated arglist for make_dist_prcp(), as part of fix for QUICK_FLUX state file compatibility. TJB 02-Nov-04 Updated arglist for read_lakeparam(), as part of fix for lake fraction readjustment. TJB 2005-Apr-13 OUTPUT_FORCE option now calls close_files(). TJB 2006-Sep-23 Implemented flexible output configuration; uses the new out_data, out_data_files, and save_data structures. TJB 2006-Oct-16 Merged infiles and outfiles structs into filep_struct; This included merging builtnames into filenames. TJB 2006-Nov-07 Removed LAKE_MODEL option. TJB 2006-Nov-07 Changed statefile to init_state in call to check_state_file(). TJB 2007-Jan-15 Added PRT_HEADER option; added call to write_header(). TJB 2007-Apr-04 Added option to continue run after a cell fails. GCT/KAC 2007-Apr-21 Added calls to free_dmy(), free_out_data_files(), free_out_data(), and free_veglib(). Added closing of all parameter files. TJB 2007-Aug-21 Return ErrorFlag from initialize_model_state. JCA 2007-Sep-14 Excluded calls to free_veglib() and closing of parameter files other than the soil param file for the case when OUTPUT_FORCE=TRUE. TJB 2007-Nov-06 Moved computation of cell_area from read_lakeparam() to read_soilparam() and read_soilparam_arc(). TJB 2008-May-05 Added prcp fraction (mu) to initial water storage computation. This solves water balance errors for the case where DIST_PRCP is TRUE. TJB 2009-Jan-16 Added soil_con.avgJulyAirTemp to argument list of initialize_atmos(). TJB 2009-Jun-09 Modified to use extension of veg_lib structure to contain bare soil information. TJB 2009-Jul-07 Added soil_con.BandElev[] to read_snowband() arg list. TJB 2009-Jul-31 Replaced references to N+1st veg tile with references to index of lake/wetland tile. TJB 2009-Sep-28 Replaced initial water/energy storage computations and calls to calc_water_balance_error/calc_energy_balance_error with an initial call to put_data. Modified the call to read_snowband(). TJB 2009-Dec-11 Removed save_data structure from argument list of initialize_model_state(). TJB 2010-Mar-31 Added cell_area to initialize_atmos(). TJB 2010-Apr-28 Removed individual soil_con variables from argument list of initialize_atmos() and replaced with *soil_con. TJB 2010-Nov-10 Added closing of state files. TJB 2011-Jan-04 Made read_soilparam_arc() a sub-function of read_soilparam(). TJB 2012-Jan-16 Removed LINK_DEBUG code BN **********************************************************************/ { extern veg_lib_struct *veg_lib; extern option_struct options; extern Error_struct Error; extern global_param_struct global_param; /** Variable Declarations **/ char NEWCELL; char LASTREC; char MODEL_DONE; char RUN_MODEL; char *init_STILL_STORM; char ErrStr[MAXSTRING]; int rec, i, j; int veg; int dist; int band; int Ndist; int Nveg_type; int cellnum; int index; int *init_DRY_TIME; int Ncells; int cell_cnt; int startrec; int ErrorFlag; float mu; double storage; double veg_fract; double band_fract; double Clake; dmy_struct *dmy; atmos_data_struct *atmos; veg_con_struct *veg_con; soil_con_struct soil_con; dist_prcp_struct prcp; /* stores information about distributed precipitation */ filenames_struct filenames; filep_struct filep; lake_con_struct lake_con; out_data_file_struct *out_data_files; out_data_struct *out_data; save_data_struct save_data; /** Read Model Options **/ initialize_global(); filenames = cmd_proc(argc, argv); #if VERBOSE display_current_settings(DISP_VERSION,(filenames_struct*)NULL,(global_param_struct*)NULL); #endif /** Read Global Control File **/ filep.globalparam = open_file(filenames.global,"r"); global_param = get_global_param(&filenames, filep.globalparam); /** Set up output data structures **/ out_data = create_output_list(); out_data_files = set_output_defaults(out_data); fclose(filep.globalparam); filep.globalparam = open_file(filenames.global,"r"); parse_output_info(&filenames, filep.globalparam, &out_data_files, out_data); /** Check and Open Files **/ check_files(&filep, &filenames); #if !OUTPUT_FORCE /** Read Vegetation Library File **/ veg_lib = read_veglib(filep.veglib,&Nveg_type); #endif // !OUTPUT_FORCE /** Initialize Parameters **/ if(options.DIST_PRCP) Ndist = 2; else Ndist = 1; cellnum = -1; /** Make Date Data Structure **/ dmy = make_dmy(&global_param); /** allocate memory for the atmos_data_struct **/ alloc_atmos(global_param.nrecs, &atmos); /** Initial state **/ startrec = 0; #if !OUTPUT_FORCE if ( options.INIT_STATE ) filep.init_state = check_state_file(filenames.init_state, dmy, &global_param, options.Nlayer, options.Nnode, &startrec); /** open state file if model state is to be saved **/ if ( options.SAVE_STATE && strcmp( filenames.statefile, "NONE" ) != 0 ) filep.statefile = open_state_file(&global_param, filenames, options.Nlayer, options.Nnode); else filep.statefile = NULL; #endif // !OUTPUT_FORCE /************************************ Run Model for all Active Grid Cells ************************************/ MODEL_DONE = FALSE; cell_cnt=0; while(!MODEL_DONE) { soil_con = read_soilparam(filep.soilparam, filenames.soil_dir, &cell_cnt, &RUN_MODEL, &MODEL_DONE); if(RUN_MODEL) { #if QUICK_FS /** Allocate Unfrozen Water Content Table **/ if(options.FROZEN_SOIL) { for(i=0;i<MAX_LAYERS;i++) { soil_con.ufwc_table_layer[i] = (double **)malloc((QUICK_FS_TEMPS+1)*sizeof(double *)); for(j=0;j<QUICK_FS_TEMPS+1;j++) soil_con.ufwc_table_layer[i][j] = (double *)malloc(2*sizeof(double)); } for(i=0;i<MAX_NODES;i++) { soil_con.ufwc_table_node[i] = (double **)malloc((QUICK_FS_TEMPS+1)*sizeof(double *)); for(j=0;j<QUICK_FS_TEMPS+1;j++) soil_con.ufwc_table_node[i][j] = (double *)malloc(2*sizeof(double)); } } #endif /* QUICK_FS */ NEWCELL=TRUE; cellnum++; #if !OUTPUT_FORCE /** Read Grid Cell Vegetation Parameters **/ veg_con = read_vegparam(filep.vegparam, soil_con.gridcel, Nveg_type); calc_root_fractions(veg_con, &soil_con); if ( options.LAKES ) lake_con = read_lakeparam(filep.lakeparam, soil_con, veg_con); #endif // !OUTPUT_FORCE /** Build Gridded Filenames, and Open **/ make_in_and_outfiles(&filep, &filenames, &soil_con, out_data_files); if (options.PRT_HEADER) { /** Write output file headers **/ write_header(out_data_files, out_data, dmy, global_param); } #if !OUTPUT_FORCE /** Read Elevation Band Data if Used **/ read_snowband(filep.snowband, &soil_con); /** Make Precipitation Distribution Control Structure **/ prcp = make_dist_prcp(veg_con[0].vegetat_type_num); #endif // !OUTPUT_FORCE /************************************************** Initialize Meteological Forcing Values That Have not Been Specifically Set **************************************************/ #if VERBOSE fprintf(stderr,"Initializing Forcing Data\n"); #endif /* VERBOSE */ initialize_atmos(atmos, dmy, filep.forcing, #if OUTPUT_FORCE &soil_con, out_data_files, out_data); #else /* OUTPUT_FORCE */ &soil_con); #endif /* OUTPUT_FORCE */ #if !OUTPUT_FORCE /************************************************** Initialize Energy Balance and Snow Variables **************************************************/ #if VERBOSE fprintf(stderr,"Model State Initialization\n"); #endif /* VERBOSE */ ErrorFlag = initialize_model_state(&prcp, dmy[0], &global_param, filep, soil_con.gridcel, veg_con[0].vegetat_type_num, options.Nnode, Ndist, atmos[0].air_temp[NR], &soil_con, veg_con, lake_con, &init_STILL_STORM, &init_DRY_TIME); if ( ErrorFlag == ERROR ) { if ( options.CONTINUEONERROR == TRUE ) { // Handle grid cell solution error fprintf(stderr, "ERROR: Grid cell %i failed in record %i so the simulation has not finished. An incomplete output file has been generated, check your inputs before rerunning the simulation.\n", soil_con.gridcel, rec); break; } else { // Else exit program on cell solution error as in previous versions sprintf(ErrStr, "ERROR: Grid cell %i failed in record %i so the simulation has ended. Check your inputs before rerunning the simulation.\n", soil_con.gridcel, rec); vicerror(ErrStr); } } #if VERBOSE fprintf(stderr,"Running Model\n"); #endif /* VERBOSE */ /** Update Error Handling Structure **/ Error.filep = filep; Error.out_data_files = out_data_files; /** Initialize the storage terms in the water and energy balances **/ /** Sending a negative record number (-global_param.nrecs) to dist_prec() will accomplish this **/ ErrorFlag = dist_prec(&atmos[0], &prcp, &soil_con, veg_con, &lake_con, dmy, &global_param, &filep, out_data_files, out_data, &save_data, -global_param.nrecs, cellnum, NEWCELL, LASTREC, init_STILL_STORM, init_DRY_TIME); /****************************************** Run Model in Grid Cell for all Time Steps ******************************************/ for ( rec = startrec ; rec < global_param.nrecs; rec++ ) { if ( rec == global_param.nrecs - 1 ) LASTREC = TRUE; else LASTREC = FALSE; ErrorFlag = dist_prec(&atmos[rec], &prcp, &soil_con, veg_con, &lake_con, dmy, &global_param, &filep, out_data_files, out_data, &save_data, rec, cellnum, NEWCELL, LASTREC, init_STILL_STORM, init_DRY_TIME); if ( ErrorFlag == ERROR ) { if ( options.CONTINUEONERROR == TRUE ) { // Handle grid cell solution error fprintf(stderr, "ERROR: Grid cell %i failed in record %i so the simulation has not finished. An incomplete output file has been generated, check your inputs before rerunning the simulation.\n", soil_con.gridcel, rec); break; } else { // Else exit program on cell solution error as in previous versions sprintf(ErrStr, "ERROR: Grid cell %i failed in record %i so the simulation has ended. Check your inputs before rerunning the simulation.\n", soil_con.gridcel, rec); vicerror(ErrStr); } } NEWCELL=FALSE; for ( veg = 0; veg <= veg_con[0].vegetat_type_num; veg++ ) init_DRY_TIME[veg] = -999; } /* End Rec Loop */ #endif /* !OUTPUT_FORCE */ close_files(&filep,out_data_files,&filenames); #if !OUTPUT_FORCE #if QUICK_FS if(options.FROZEN_SOIL) { for(i=0;i<MAX_LAYERS;i++) { for(j=0;j<6;j++) free((char *)soil_con.ufwc_table_layer[i][j]); free((char *)soil_con.ufwc_table_layer[i]); } for(i=0;i<MAX_NODES;i++) { for(j=0;j<6;j++) free((char *)soil_con.ufwc_table_node[i][j]); free((char *)soil_con.ufwc_table_node[i]); } } #endif /* QUICK_FS */ free_dist_prcp(&prcp,veg_con[0].vegetat_type_num); free_vegcon(&veg_con); free((char *)soil_con.AreaFract); free((char *)soil_con.BandElev); free((char *)soil_con.Tfactor); free((char *)soil_con.Pfactor); free((char *)soil_con.AboveTreeLine); free((char*)init_STILL_STORM); free((char*)init_DRY_TIME); #endif /* !OUTPUT_FORCE */ } /* End Run Model Condition */ } /* End Grid Loop */ /** cleanup **/ free_atmos(global_param.nrecs, &atmos); free_dmy(&dmy); free_out_data_files(&out_data_files); free_out_data(&out_data); #if !OUTPUT_FORCE free_veglib(&veg_lib); #endif /* !OUTPUT_FORCE */ fclose(filep.soilparam); #if !OUTPUT_FORCE fclose(filep.vegparam); fclose(filep.veglib); if (options.SNOW_BAND>1) fclose(filep.snowband); if (options.LAKES) fclose(filep.lakeparam); if ( options.INIT_STATE ) fclose(filep.init_state); if ( options.SAVE_STATE && strcmp( filenames.statefile, "NONE" ) != 0 ) fclose(filep.statefile); #endif /* !OUTPUT_FORCE */ return EXIT_SUCCESS; } /* End Main Program */
/****************************************************************************** * @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); }
int main(int argc, char * argv[]) { int UCODE; /* file descriptor for ucode file */ int DEV; /* file descriptor for em8300 device*/ struct stat s; em8300_microcode_t em8300_microcode; int opened_one,i,optindex; char * opt; char ucode_file[200]; // bad hardcoded value ;-) /* Vars to hold desired setings - init to -1 so we can see which were requested to be set explicitly by the user and which should be left alone */ int tvmode=-1, aspect=-1, audio=-1, spu=-1, upload=0, display_only=0; char * devs[] = {"/dev/em8300-0","/dev/em8300-1","/dev/em8300-2","/dev/em8300-3"}; int number_of_devs=4; /* Populate with default location - user can override below. */ sprintf(ucode_file,FIRMWARE_DIR "/em8300.bin"); /* Read microcode file */ if (argc == 1) { /* behave as em8300init with no arguments */ /* just upload the microcode from the default location and exit */ upload=1; } else { /* parse the command line arguments here */ optindex = 1; while (optindex < argc) { opt = argv[optindex++]; if (opt[0] == '-' && opt[1] != '\0') { switch(opt[1]) { case 'p': if(opt[2]=='6') tvmode = EM8300_VIDEOMODE_PAL60; else tvmode = EM8300_VIDEOMODE_PAL; break; case 'n': tvmode = EM8300_VIDEOMODE_NTSC; break; case 'd': audio = EM8300_AUDIOMODE_DIGITALPCM; break; case 'a': audio = EM8300_AUDIOMODE_ANALOG; break; case '3': audio = EM8300_AUDIOMODE_DIGITALAC3; break; case 'w': aspect = EM8300_ASPECTRATIO_16_9; break; case 'o': aspect = EM8300_ASPECTRATIO_4_3; break; case 'S': spu = EM8300_SPUMODE_ON; break; case 's': spu = EM8300_SPUMODE_OFF; break; case 'q': display_only=1; break; case 'f': if(opt[2] == '\0') sprintf(ucode_file,"%s", argv[optindex++]); else sprintf(ucode_file,"%s",opt+2); upload=1; printf("Using microcode file %s\n",ucode_file); break; default: printf("Unknown option -%c \n\n",opt[1]); printf("Usage: em8300setup [-q]|[all other options]\n\nWhere options are one of the following (latter options will override previously\nspecified options for the same control):\n\n"); printf(" -p, -p6, -n\tSet display mode to pal, pal60, ntsc\n"); printf(" -a, -d, -3\tSet audio mode to analog, digitalpcm, digital ac3\n"); printf(" -o, -w\tSet aspect ratio to normal[4:3], widescreen[16:9]\n"); printf(" -S, -s\tSet spu mode On(S), Off(s)\n"); printf(" -f <filename>\tSpecify alternate location of microcode\n\t\t(Defaults to " FIRMWARE_DIR "/em8300.bin)\n"); printf(" -q\t\tQuery the current settings for all of the above and\n\t\texit without making any changes\n"); printf(" <none>\tPassing no option (except -f) causes the microcode\n\t\tto be loaded\n"); exit(1); } } } } if(upload && !display_only) { UCODE = open(ucode_file,O_RDONLY); if(UCODE <0) { printf("Unable to open microcode file \"%s\" for reading\n", ucode_file); exit(1); } if(fstat(UCODE, &s ) <0) { printf("Unable to fstat ucode file\n"); exit(1); } /* Alloc space for microcode and length structure */ em8300_microcode.ucode = (char*) malloc(s.st_size * sizeof(char) ); if (em8300_microcode.ucode == NULL) { printf("Unable to malloc() space for ucode\n"); exit(1); } if ((i=read(UCODE,em8300_microcode.ucode,s.st_size)) < 1) { printf("Unable to read data from microcode file\n"); } close(UCODE); } /* Open the device */ opened_one = 0; for (i=0 ; i<number_of_devs; i++) { if ((DEV=open(devs[i],O_RDWR))== -1) { if (!opened_one) { printf("Can't open %s\n",devs[i]); exit(1); } /* exit normally if at least one card has been initialized */ exit(0); } opened_one = 1; if(upload && !display_only) { /* Prepare ioctl */ em8300_microcode.ucode_size = s.st_size; if(ioctl(DEV, EM8300_IOCTL_INIT, &em8300_microcode) == -1) { printf("Microcode upload to %s failed: \n",devs[i]); close(DEV); exit(1); } printf("Microcode uploaded to %s\n",devs[i]); } if(display_only) { display_current_settings(DEV); close(DEV); exit(0); } if(tvmode!=-1) { printf("Setting tvmode = %i\n",tvmode); if(ioctl(DEV, EM8300_IOCTL_SET_VIDEOMODE, &tvmode) == -1) check_errno("Unable to set videomode"); } if(aspect!=-1) { printf("Setting aspect = %i\n",aspect); if(ioctl(DEV, EM8300_IOCTL_SET_ASPECTRATIO, &aspect) == -1) check_errno("Unable to set aspect ratio"); } if(audio!=-1) { printf("Setting audio = %i\n",audio); if(ioctl(DEV, EM8300_IOCTL_SET_AUDIOMODE, &audio) == -1) check_errno("Unable to set audio mode"); } if(spu!=-1) { printf("Setting spu = %i\n",spu); if(ioctl(DEV, EM8300_IOCTL_SET_SPUMODE, &spu) == -1) check_errno("Unable to set spu mode"); } printf("Current settings are:\n"); display_current_settings(DEV); close(DEV); } exit(0); }
filenames_struct cmd_proc(int argc, char *argv[]) /********************************************************************** cmd_proc Keith Cherkauer 1997 This routine checks the command line for valid program options. If no options are found, or an invalid combination of them appear, the routine calls usage() to print the model usage to the screen, before exiting execution. Modifications: 11-18-98 Added comment block to cmd_proc() and fixed routine so that it will exit if global command file is not defined using the "-g" flag. KAC 30-Oct-03 Added -v option to display version information. TJB **********************************************************************/ { extern option_struct options; #if LINK_DEBUG extern debug_struct debug; #endif extern int getopt(); extern char *optarg; extern char *optstring; filenames_struct names; int optchar; char GLOBAL_SET; if(argc==1) { usage(argv[0]); exit(1); } GLOBAL_SET = FALSE; while((optchar = getopt(argc, argv, optstring)) != EOF) { switch((char)optchar) { case 'v': /** Version information **/ display_current_settings(DISP_VERSION,(filenames_struct*)NULL,(global_param_struct*)NULL); exit(0); break; case 'o': /** Compile-time options information **/ display_current_settings(DISP_COMPILE_TIME,(filenames_struct*)NULL,(global_param_struct*)NULL); exit(0); break; case 'g': /** Global Parameters File **/ strcpy(names.global, optarg); GLOBAL_SET = TRUE; break; default: /** Print Usage if Invalid Command Line Arguments **/ usage(argv[0]); exit(1); break; } } if(!GLOBAL_SET) { fprintf(stderr,"ERROR: Must set global control file using the '-g' flag\n"); usage(argv[0]); exit(1); } return names; }
global_param_struct get_global_param(filenames_struct *names, FILE *gp) /********************************************************************** get_global_param Keith Cherkauer March 1998 This routine reads the VIC model global control file, getting values for global parameters, model options, and debugging controls. Modifications: 7-19-96 Modified to read time step KAC 4-5-98 Modified to read model options and debugging controls from a single file KAC 01-20-00 modified to work with new radiation estimation routines, new simplified frozen soil moisture, and new new open format forcing file rad routines. KAC 06-03-03 modified to handle both ASCII and BINARY state files. KAC 09-02-2003 Moved COMPUTE_TREELINE flag from user_def.h to the options structure. Now when not set to FALSE, the value indicates the default above treeline vegetation if no usable vegetation types are in the grid cell (i.e. everything has a canopy). A negative value will cause the model to use bare soil. Make sure that positive index value refer to a non-canopied vegetation type in the vegetation library. KAC 10-Oct-03 Modified to understand the ARNO_PARAMS option. TJB 10-May-04 Modified to display compile-time and run-time options if VERBOSE is set to TRUE. TJB 2005-11-09 Checked for missing STATEMONTH and STATEDAY GCT 2005-11-09 (Port from 4.1.0) Added validation for Nnodes with QUICK_FLUX option, as part of fix for QUICK_FLUX state file compatibility.GCT 2005-11-10 Moved setting of statename from open_state_file to here. GCT 2005-11-21 Added checks for range of STATEMONTH and STATEDAY GCT 2005-11-21 (Port from 4.1.0) Changed ARNO_PARAMS to NIJSSEN2001_BASEFLOW. GCT 2005-11-23 Allow user to use NO_FLUX in addition to NOFLUX for NOFLUX in global.param.file GCT 2006-Jan-22 Replaced NIJSSEN2001_BASEFLOW with BASEFLOW option. TJB 2006-Sep-01 (Port from 4.1.0) Added support for OUTPUT_FORCE option. TJB 2006-Sep-11 Implemented flexible output configuration; uses new N_OUTFILES, OUTFILE, and OUTVAR flags; removed the OPTIMIZE and LDAS_OUTPUT options. TJB 2006-Sep-18 Implemented aggregation of output variables. TJB 2006-Oct-26 Merged infiles and outfiles structs into filep_struct; This included moving global->statename to filenames->statefile; also added f_path_pfx to store forcing file path and prefix. TJB 2007-Jan-03 Added ALMA_INPUT option. TJB 2007-Jan-15 Added PRT_HEADER option. TJB 2007-Apr-23 Added initialization of some global parameters. TJB 2007-Sep-14 Added initialization of names->soil_dir. TJB 2007-Oct-10 Added validation of dt, start date, end date, and nrecs. TJB 2007-Oct-31 Added validation of input/output files. TJB 2008-Jan-19 Removed setting of SNOW_STEP = global.dt for OUTPUT_FORCE == TRUE. TJB **********************************************************************/ { extern option_struct options; extern param_set_struct param_set; #if LINK_DEBUG extern debug_struct debug; #endif extern int NF, NR; char cmdstr[MAXSTRING]; char optstr[MAXSTRING]; char flgstr[MAXSTRING]; char ErrStr[MAXSTRING]; int file_num; int field; int i; int lastvalidday; int lastday[] = { 31, /* JANUARY */ 28, /* FEBRUARY */ 31, /* MARCH */ 30, /* APRIL */ 31, /* MAY */ 30, /* JUNE */ 31, /* JULY */ 31, /* AUGUST */ 30, /* SEPTEMBER */ 31, /* OCTOBER */ 30, /* NOVEMBER */ 31, /* DECEMBER */ } ; global_param_struct global; int outfilenum; int fn; char varname[20]; int outvarnum; int format; char formatstr[10]; int type; char typestr[10]; float multiplier; /** Initialize global parameters (that aren't part of the options struct) **/ global.dt = MISSING; global.startyear = MISSING; global.startmonth = MISSING; global.startday = MISSING; global.starthour = MISSING; global.endyear = MISSING; global.endmonth = MISSING; global.endday = MISSING; global.nrecs = MISSING; global.resolution = MISSING; global.MAX_SNOW_TEMP = 0; global.MIN_RAIN_TEMP = 0; global.measure_h = 2.0; global.wind_h = 10.0; for(i = 0; i < 2; i++) { global.forceyear[i] = MISSING; global.forcemonth[i] = 1; global.forceday[i] = 1; global.forcehour[i] = 0; global.forceskip[i] = 0; strcpy(names->f_path_pfx[i],"MISSING"); } file_num = 0; global.skipyear = 0; strcpy(names->init_state, "MISSING"); global.stateyear = MISSING; global.statemonth = MISSING; global.stateday = MISSING; strcpy(names->statefile, "MISSING"); strcpy(names->soil, "MISSING"); strcpy(names->soil_dir, "MISSING"); strcpy(names->veg, "MISSING"); strcpy(names->veglib, "MISSING"); strcpy(names->snowband, "MISSING"); strcpy(names->result_dir, "MISSING"); global.out_dt = MISSING; /** Read through global control file to find parameters **/ fgets(cmdstr,MAXSTRING,gp); while(!feof(gp)) { if(cmdstr[0]!='#' && cmdstr[0]!='\n' && cmdstr[0]!='\0') { sscanf(cmdstr,"%s",optstr); /******************************* Get Model Global Parameters *****************************/ if(strcasecmp("NLAYER",optstr)==0) { sscanf(cmdstr,"%*s %d",&options.Nlayer); } else if(strcasecmp("TIME_STEP",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.dt); } else if(strcasecmp("OUT_STEP",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.out_dt); } else if(strcasecmp("RESOLUTION",optstr)==0) { sscanf(cmdstr,"%*s %f",&global.resolution); } else if(strcasecmp("STARTYEAR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.startyear); } else if(strcasecmp("STARTMONTH",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.startmonth); } else if(strcasecmp("STARTDAY",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.startday); } else if(strcasecmp("STARTHOUR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.starthour); } else if(strcasecmp("ENDYEAR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.endyear); } else if(strcasecmp("ENDMONTH",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.endmonth); } else if(strcasecmp("ENDDAY",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.endday); } else if(strcasecmp("NRECS",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.nrecs); } else if(strcasecmp("SKIPYEAR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.skipyear); } else if(strcasecmp("FORCEYEAR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.forceyear[file_num]); } else if(strcasecmp("FORCEMONTH",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.forcemonth[file_num]); } else if(strcasecmp("FORCEDAY",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.forceday[file_num]); } else if(strcasecmp("FORCEHOUR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.forcehour[file_num]); } else if(strcasecmp("WIND_H",optstr)==0) { sscanf(cmdstr,"%*s %lf",&global.wind_h); } else if(strcasecmp("MEASURE_H",optstr)==0) { sscanf(cmdstr,"%*s %lf",&global.measure_h); } else if(strcasecmp("NODES",optstr)==0) { sscanf(cmdstr,"%*s %d",&options.Nnode); } else if(strcasecmp("MIN_RAIN_TEMP",optstr)==0) { sscanf(cmdstr,"%*s %lf",&global.MIN_RAIN_TEMP); } else if(strcasecmp("MAX_SNOW_TEMP",optstr)==0) { sscanf(cmdstr,"%*s %lf",&global.MAX_SNOW_TEMP); } /******************** Get Model Options ******************/ else if(strcasecmp("FULL_ENERGY",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) { options.FULL_ENERGY=TRUE; options.QUICK_FLUX=TRUE; options.GRND_FLUX=TRUE; } else options.FULL_ENERGY = FALSE; } else if(strcasecmp("FROZEN_SOIL",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) { options.FROZEN_SOIL=TRUE; options.QUICK_FLUX=FALSE; options.GRND_FLUX=TRUE; } else options.FROZEN_SOIL = FALSE; } else if( (strcasecmp("NOFLUX",optstr)==0) || (strcasecmp("NO_FLUX",optstr)==0) ) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.NOFLUX=TRUE; else options.NOFLUX = FALSE; } else if(strcasecmp("DIST_PRCP",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.DIST_PRCP=TRUE; else options.DIST_PRCP = FALSE; } else if(strcasecmp("COMPRESS",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.COMPRESS=TRUE; else options.COMPRESS = FALSE; } else if(strcasecmp("CORRPREC",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.CORRPREC=TRUE; else options.CORRPREC = FALSE; } else if(strcasecmp("PRT_SNOW_BAND",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.PRT_SNOW_BAND=TRUE; else options.PRT_SNOW_BAND = FALSE; } else if(strcasecmp("GRID_DECIMAL",optstr)==0) { sscanf(cmdstr,"%*s %d",&options.GRID_DECIMAL); } else if(strcasecmp("SNOW_BAND",optstr)==0) { sscanf(cmdstr,"%*s %d %s",&options.SNOW_BAND,names->snowband); } else if(strcasecmp("BINARY_OUTPUT",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.BINARY_OUTPUT=TRUE; else options.BINARY_OUTPUT = FALSE; } else if(strcasecmp("ALMA_OUTPUT",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.ALMA_OUTPUT=TRUE; else options.ALMA_OUTPUT = FALSE; } else if(strcasecmp("PRT_HEADER",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.PRT_HEADER=TRUE; else options.PRT_HEADER = FALSE; } else if(strcasecmp("ARC_SOIL",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.ARC_SOIL=TRUE; else options.ARC_SOIL = FALSE; } else if(strcasecmp("SNOW_STEP",optstr)==0) { sscanf(cmdstr,"%*s %d",&options.SNOW_STEP); } else if(strcasecmp("ROOT_ZONES",optstr)==0) { sscanf(cmdstr,"%*s %d",&options.ROOT_ZONES); } else if(strcasecmp("PREC_EXPT",optstr)==0) { sscanf(cmdstr,"%*s %f",&options.PREC_EXPT); } else if(strcasecmp("MIN_WIND_SPEED",optstr)==0) { sscanf(cmdstr,"%*s %f",&options.MIN_WIND_SPEED); } else if(strcasecmp("GRND_FLUX",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.GRND_FLUX=TRUE; else options.GRND_FLUX = FALSE; } else if(strcasecmp("QUICK_FLUX",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.QUICK_FLUX=TRUE; else options.QUICK_FLUX = FALSE; } else if(strcasecmp("MOISTFRACT",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.MOISTFRACT=TRUE; else options.MOISTFRACT = FALSE; } else if (strcasecmp("ARNO_PARAMS", optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) { nrerror("Please change \"ARNO_PARAMS TRUE\" to \"BASEFLOW NIJSSEN2001\" in your global parameter file."); } else { nrerror("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) { nrerror("Please change \"NIJSSEN2001_BASEFLOW TRUE\" to \"BASEFLOW NIJSSEN2001\" in your global parameter file."); } else { nrerror("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 options.BASEFLOW = ARNO; } 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(names->init_state,flgstr); } } else if(strcasecmp("BINARY_STATE_FILE",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("FALSE",flgstr)==0) options.BINARY_STATE_FILE=FALSE; else options.BINARY_STATE_FILE=TRUE; } else if(strcasecmp("STATENAME",optstr)==0) { sscanf(cmdstr,"%*s %s",names->statefile); options.SAVE_STATE = TRUE; } else if(strcasecmp("STATEYEAR",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.stateyear); } else if(strcasecmp("STATEMONTH",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.statemonth); } else if(strcasecmp("STATEDAY",optstr)==0) { sscanf(cmdstr,"%*s %d",&global.stateday); } 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 ); } } /************************************ Get Forcing Data File Information **********************************/ else if(strcasecmp("FORCING1",optstr)==0) { sscanf(cmdstr,"%*s %s",names->f_path_pfx[0]); file_num = 0; field=0; } else if(strcasecmp("FORCING2",optstr)==0) { sscanf(cmdstr,"%*s %s",names->f_path_pfx[1]); file_num = 1; field=0; } else if(strcasecmp("N_TYPES",optstr)==0) { sscanf(cmdstr,"%*s %d",¶m_set.N_TYPES[file_num]); } else if(strcasecmp("FORCE_TYPE",optstr)==0) { get_force_type(cmdstr,file_num,&field); } else if(strcasecmp("FORCE_DT",optstr)==0) { sscanf(cmdstr,"%*s %d ", ¶m_set.FORCE_DT[file_num]); } else if (strcasecmp("FORCE_ENDIAN",optstr)==0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp(flgstr, "LITTLE") == 0) param_set.FORCE_ENDIAN[file_num] = LITTLE; else if (strcasecmp(flgstr, "BIG") == 0) param_set.FORCE_ENDIAN[file_num] = BIG; else nrerror("FORCE_ENDIAN must be either BIG or LITTLE."); } else if (strcasecmp("FORCE_FORMAT",optstr)==0) { sscanf(cmdstr, "%*s %s", flgstr); if (strcasecmp(flgstr, "BINARY") == 0) param_set.FORCE_FORMAT[file_num] = BINARY; else if (strcasecmp(flgstr, "ASCII") == 0) param_set.FORCE_FORMAT[file_num] = ASCII; else nrerror("FORCE_FORMAT must be either ASCII or BINARY."); } else if(strcasecmp("ALMA_INPUT",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.ALMA_INPUT=TRUE; else options.ALMA_INPUT = FALSE; } /************************************ Get Information for Parameter Files ************************************/ else if(strcasecmp("SOIL",optstr)==0) { sscanf(cmdstr,"%*s %s",names->soil); } else if(strcasecmp("SOIL_DIR",optstr)==0) { sscanf(cmdstr,"%*s %s",names->soil_dir); } else if(strcasecmp("VEGPARAM",optstr)==0) { sscanf(cmdstr,"%*s %s",names->veg); } else if(strcasecmp("VEGLIB",optstr)==0) { sscanf(cmdstr,"%*s %s",names->veglib); } else if(strcasecmp("GLOBAL_LAI",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) options.GLOBAL_LAI=TRUE; else options.GLOBAL_LAI = FALSE; } else if(strcasecmp("RESULT_DIR",optstr)==0) { sscanf(cmdstr,"%*s %s",names->result_dir); } /************************************ Get Output File Information **********************************/ else if(strcasecmp("N_OUTFILES",optstr)==0) { ; // do nothing } else if(strcasecmp("OUTFILE",optstr)==0) { ; // do nothing } else if(strcasecmp("OUTVAR",optstr)==0) { ; // do nothing } /****************************** Get Model Debugging Options ****************************/ #if LINK_DEBUG else if(strcasecmp("PRT_FLUX",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_FLUX=TRUE; else debug.PRT_FLUX = FALSE; } else if(strcasecmp("PRT_BALANCE",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_BALANCE=TRUE; else debug.PRT_BALANCE = FALSE; } else if(strcasecmp("PRT_SOIL",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_SOIL=TRUE; else debug.PRT_SOIL = FALSE; } else if(strcasecmp("PRT_VEGE",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_VEGE=TRUE; else debug.PRT_VEGE = FALSE; } else if(strcasecmp("PRT_GLOBAL",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_GLOBAL=TRUE; else debug.PRT_GLOBAL = FALSE; } else if(strcasecmp("PRT_ATMOS",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_ATMOS=TRUE; else debug.PRT_ATMOS = FALSE; } else if(strcasecmp("PRT_SNOW",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_SNOW=TRUE; else debug.PRT_SNOW = FALSE; } else if(strcasecmp("PRT_MOIST",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_MOIST=TRUE; else debug.PRT_MOIST = FALSE; } else if(strcasecmp("PRT_TEMP",optstr)==0) { sscanf(cmdstr,"%*s %s",flgstr); if(strcasecmp("TRUE",flgstr)==0) debug.PRT_TEMP=TRUE; else debug.PRT_TEMP = FALSE; } else if(strcasecmp("DEBUG_DIR",optstr)==0) { sscanf(cmdstr,"%*s %s",debug.debug_dir); } #endif /*********************************** Unrecognized Global Parameter Flag ***********************************/ else { fprintf(stderr,"WARNING: Unrecognized option in the global parameter file:\n\t%s is unknown - check your spelling\n", optstr); } } fgets(cmdstr,MAXSTRING,gp); } fclose(gp); /****************************************** Check for undefined required parameters ******************************************/ // Validate model time step if (global.dt == MISSING) nrerror("Model time step has not been defined. Make sure that the global file defines TIME_STEP."); else if (global.dt < 1) { sprintf(ErrStr,"The specified model time step (%d) < 1 hour. Make sure that the global file defines a positive number of hours for TIME_STEP.",global.dt); nrerror(ErrStr); } // Validate the output step if (global.out_dt == 0 || global.out_dt == MISSING) { global.out_dt = global.dt; } else if (global.out_dt < global.dt || global.out_dt > 24 || (float)global.out_dt/(float)global.dt != (float)(global.out_dt/global.dt)) { nrerror("Invalid output step specified. Output step must be an integer multiple of the model time step; >= model time step and <= 24"); } // Validate SNOW_STEP and set NR and NF if (global.dt < 24 && global.dt != options.SNOW_STEP) nrerror("If the model step is smaller than daily, the snow model should run\nat the same time step as the rest of the model."); if (global.dt % options.SNOW_STEP != 0 || options.SNOW_STEP > global.dt) nrerror("SNOW_STEP should be <= TIME_STEP and divide TIME_STEP evenly "); NF = global.dt/options.SNOW_STEP; if (NF == 1) NR = 0; else NR = NF; // Validate simulation start date if (global.startyear == MISSING) nrerror("Simulation start year has not been defined. Make sure that the global file defines STARTYEAR."); else if (global.startyear < 0) { sprintf(ErrStr,"The specified simulation start year (%d) < 0. Make sure that the global file defines a positive integer for STARTYEAR.",global.startyear); nrerror(ErrStr); } if (global.startmonth == MISSING) nrerror("Simulation start month has not been defined. Make sure that the global file defines STARTMONTH."); else if (global.startmonth < 0) { sprintf(ErrStr,"The specified simulation start month (%d) < 0. Make sure that the global file defines a positive integer for STARTMONTH.",global.startmonth); nrerror(ErrStr); } if (global.startday == MISSING) nrerror("Simulation start day has not been defined. Make sure that the global file defines STARTDAY."); else if (global.startday < 0) { sprintf(ErrStr,"The specified simulation start day (%d) < 0. Make sure that the global file defines a positive integer for STARTDAY.",global.startday); nrerror(ErrStr); } if (global.starthour == MISSING) { if (global.dt == 24) global.starthour = 0; else nrerror("Simulation start hour has not been defined, yet model time step is less than 24 hours. Make sure that the global file defines STARTHOUR."); } else if (global.starthour < 0) { sprintf(ErrStr,"The specified simulation start hour (%d) < 0. Make sure that the global file defines a positive integer for STARTHOUR.",global.starthour); nrerror(ErrStr); } // Validate simulation end date and/or number of timesteps if (global.nrecs == MISSING && global.endyear == MISSING && global.endmonth == MISSING && global.endday == MISSING) nrerror("The model global file MUST define EITHER the number of records to simulate (NRECS), or the year (ENDYEAR), month (ENDMONTH), and day (ENDDAY) of the last full simulation day"); else if (global.nrecs == MISSING) { if (global.endyear == MISSING) nrerror("Simulation end year has not been defined. Make sure that the global file defines ENDYEAR."); else if (global.endyear < 0) { sprintf(ErrStr,"The specified simulation end year (%d) < 0. Make sure that the global file defines a positive integer for ENDYEAR.",global.endyear); nrerror(ErrStr); } if (global.endmonth == MISSING) nrerror("Simulation end month has not been defined. Make sure that the global file defines ENDMONTH."); else if (global.endmonth < 0) { sprintf(ErrStr,"The specified simulation end month (%d) < 0. Make sure that the global file defines a positive integer for ENDMONTH.",global.endmonth); nrerror(ErrStr); } if (global.endday == MISSING) nrerror("Simulation end day has not been defined. Make sure that the global file defines ENDDAY."); else if (global.endday < 0) { sprintf(ErrStr,"The specified simulation end day (%d) < 0. Make sure that the global file defines a positive integer for ENDDAY.",global.endday); nrerror(ErrStr); } } else if (global.nrecs < 1) { sprintf(ErrStr,"The specified duration of simulation (%d) < 1 time step. Make sure that the global file defines a positive integer for NRECS.",global.nrecs); nrerror(ErrStr); } // Validate forcing files and variables if ( strcmp ( names->f_path_pfx[0], "MISSING" ) == 0 ) nrerror("No forcing file has been defined. Make sure that the global file defines FORCING1."); for(i=0;i<2;i++) { if ( i == 0 || (i == 1 && param_set.N_TYPES[i] != MISSING) ) { if (param_set.N_TYPES[i] == MISSING) { sprintf(ErrStr,"Need to specify the number forcing variables types in forcing file %d.", i); nrerror(ErrStr); } if (param_set.FORCE_FORMAT[i] == MISSING) { sprintf(ErrStr,"Need to specify the INPUT_FORMAT (ASCII or BINARY) for forcing file %d.",i); nrerror(ErrStr); } if (param_set.FORCE_INDEX[i][param_set.N_TYPES[i]-1] == MISSING) { sprintf(ErrStr,"Did not define enough forcing variables in forcing file %d.",i); nrerror(ErrStr); } if(param_set.FORCE_DT[i] == MISSING ) { sprintf(ErrStr,"Must define time steps (FORCE_DT <dt>) in control file for focing file %d.",file_num); nrerror(ErrStr); } } } if(param_set.N_TYPES[1] != MISSING && global.forceyear[1] == MISSING) { global.forceyear[1] = global.forceyear[0]; global.forcemonth[1] = global.forcemonth[0]; global.forceday[1] = global.forceday[0]; global.forcehour[1] = global.forcehour[0]; global.forceskip[1] = 0; } // Validate result directory if ( strcmp ( names->result_dir, "MISSING" ) == 0 ) nrerror("No results directory has been defined. Make sure that the global file defines the result directory on the line that begins with \"RESULT_DIR\"."); // Validate soil parameter file information if ( strcmp ( names->soil, "MISSING" ) == 0 ) nrerror("No soil parameter file has been defined. Make sure that the global file defines the soil parameter file on the line that begins with \"SOIL\"."); if (options.ARC_SOIL && strcmp ( names->soil_dir, "MISSING" ) == 0) nrerror("\"ARC_SOIL\" was specified as TRUE, but no soil parameter directory (\"SOIL_DIR\") has been defined. Make sure that the global file defines the soil parameter directory on the line that begins with \"SOIL_DIR\"."); /******************************************************************************* Validate parameters required for normal simulations but NOT for OUTPUT_FORCE *******************************************************************************/ #if !OUTPUT_FORCE // Validate veg parameter information if ( strcmp ( names->veg, "MISSING" ) == 0 ) nrerror("No vegetation parameter file has been defined. Make sure that the global file defines the vegetation parameter file on the line that begins with \"VEGPARAM\"."); if ( strcmp ( names->veglib, "MISSING" ) == 0 ) nrerror("No vegetation library file has been defined. Make sure that the global file defines the vegetation library file on the line that begins with \"VEGLIB\"."); if(options.ROOT_ZONES<0) nrerror("ROOT_ZONES must be defined to a positive integer greater than 0, in the global control file."); // Validate the elevation band file information if(options.SNOW_BAND > 1) { if ( strcmp ( names->snowband, "MISSING" ) == 0 ) { sprintf(ErrStr, "\"SNOW_BAND\" was specified with %d elevation bands, but no elevation band file has been defined. Make sure that the global file defines the elevation band file on the line that begins with \"SNOW_BAND\" (after the number of bands).", options.SNOW_BAND); nrerror(ErrStr); } if(options.SNOW_BAND > MAX_BANDS) { sprintf(ErrStr,"Global file wants more snow bands (%d) than are defined by MAX_BANDS (%d). Edit user_def.h and recompile.",options.SNOW_BAND,MAX_BANDS); nrerror(ErrStr); } } else if (options.SNOW_BAND <= 0) { sprintf(ErrStr,"Invalid number of elevation bands specified in global file (%d). Number of bands must be >= 1.",options.SNOW_BAND); nrerror(ErrStr); } // Validate the input state file information if( options.INIT_STATE ) { if ( strcmp ( names->init_state, "MISSING" ) == 0 ) nrerror("\"INIT_STATE\" was specified, but no input state file has been defined. Make sure that the global file defines the input state file on the line that begins with \"INIT_STATE\"."); } // Validate the output state file information if( options.SAVE_STATE ) { if ( strcmp ( names->statefile, "MISSING" ) == 0) nrerror("\"SAVE_STATE\" was specified, but no output state file has been defined. Make sure that the global file defines the output state file on the line that begins with \"SAVE_STATE\"."); if ( global.stateyear == MISSING || global.statemonth == MISSING || global.stateday == MISSING ) { sprintf(ErrStr,"Incomplete specification of the date to save state for state file (%s).\nSpecified date (yyyy-mm-dd): %04d-%02d-%02d\nMake sure STATEYEAR, STATEMONTH, and STATEDAY are set correctly in your global parameter file.\n", names->statefile, global.stateyear, global.statemonth, global.stateday); nrerror(ErrStr); } // Check for month, day in range lastvalidday = lastday[global.statemonth - 1]; if ( global.statemonth == 2 ) { if ( (global.stateyear % 4) == 0 && ( (global.stateyear % 100) != 0 || (global.stateyear % 400) == 0 ) ){ lastvalidday = 29; } } if ( global.stateday > lastvalidday || global.statemonth > 12 || global.statemonth < 1 || global.stateday > 31 || global.stateday < 1 ){ sprintf(ErrStr,"Unusual specification of the date to save state for state file (%s).\nSpecified date (yyyy-mm-dd): %04d-%02d-%02d\nMake sure STATEYEAR, STATEMONTH, and STATEDAY are set correctly in your global parameter file.\n", names->statefile, global.stateyear, global.statemonth, global.stateday); nrerror(ErrStr); } } // Set the statename here to be able to compare with INIT_STATE name if( options.SAVE_STATE ) { sprintf(names->statefile,"%s_%04i%02i%02i", names->statefile, global.stateyear, global.statemonth, global.stateday); } if( options.INIT_STATE && options.SAVE_STATE && (strcmp( names->init_state, names->statefile ) == 0)) { sprintf(ErrStr,"The save state file (%s) has the same name as the initialize state file (%s). The initialize state file will be destroyed when the save state file is opened.", names->statefile, names->init_state); nrerror(ErrStr); } // Validate soil parameter/simulation mode combinations if(options.Nlayer > MAX_LAYERS) { sprintf(ErrStr,"Global file wants more soil moisture layers (%d) than are defined by MAX_LAYERS (%d). Edit user_def.h and recompile.",options.Nlayer,MAX_LAYERS); nrerror(ErrStr); } if(options.Nnode > MAX_NODES) { sprintf(ErrStr,"Global file wants more soil thermal nodes (%d) than are defined by MAX_NODES (%d). Edit user_def.h and recompile.",options.Nnode,MAX_NODES); nrerror(ErrStr); } if(options.QUICK_FLUX) { if((options.FULL_ENERGY || options.FROZEN_SOIL) && options.Nnode != 3) { sprintf(ErrStr,"To run the model in FULL_ENERGY or FROZEN_SOIL modes with QUICK_FLUX=TRUE, you must define exactly 3 soil thermal nodes. Currently Nnodes is set to %d.",options.Nnode); nrerror(ErrStr); } else if (!options.FULL_ENERGY && !options.FROZEN_SOIL && options.Nnode != 1) { sprintf(ErrStr,"To run the model with FULL_ENERGY=FALSE, FROZEN_SOIL=FALSE, and QUICK_FLUX=TRUE, you must define exactly 1 soil thermal node. Currently Nnodes is set to %d.",options.Nnode); nrerror(ErrStr); } } else { if(options.Nnode < 4) { sprintf(ErrStr,"To run the model with QUICK_FLUX=FALSE, you must define at least 4 soil thermal nodes. Currently Nnodes is set to%d.",options.Nnode); nrerror(ErrStr); } } if((options.FULL_ENERGY || options.FROZEN_SOIL) && options.Nlayer<3) { sprintf(ErrStr,"You must define at least 3 soil moisture layers to run the model in FULL_ENERGY or FROZEN_SOIL modes. Currently Nlayers is set to %d.",options.Nlayer); nrerror(ErrStr); } if((options.FULL_ENERGY || options.FROZEN_SOIL) && options.Nlayer<3) { sprintf(ErrStr,"You must define at least 3 soil moisture layers to run the model in FULL_ENERGY or FROZEN_SOIL modes. Currently Nlaeyrs is set to %d.",options.Nlayer); nrerror(ErrStr); } /********************************* Output major options to stderr *********************************/ #if VERBOSE display_current_settings(DISP_ALL,names,&global); #else display_current_settings(DISP_VERSION,names,&global); #endif #if VERBOSE fprintf(stderr,"Time Step = %i hour(s)\n",global.dt); fprintf(stderr,"Simulation start date = %02i/%02i/%04i\n", global.startday, global.startmonth, global.startyear); if ( global.nrecs > 0 ) fprintf(stderr,"Number of Records = %i\n\n",global.nrecs); else fprintf(stderr,"Simulation end date = %02i/%02i/%04i\n\n", global.endday, global.endmonth, global.endyear); fprintf(stderr,"Full Energy...................(%i)\n",options.FULL_ENERGY); fprintf(stderr,"Use Distributed Precipitation.(%i)\n",options.DIST_PRCP); if(options.DIST_PRCP) fprintf(stderr,"..Using Precipitation Exponent of %f\n",options.PREC_EXPT); if ( options.GRND_FLUX ) { fprintf(stderr,"Ground heat flux will be estimated "); if ( options.QUICK_FLUX ) fprintf(stderr,"using Liang, Wood and Lettenmaier (1999).\n"); else fprintf(stderr,"using Cherkauer and Lettenmaier (1999).\n"); } else fprintf(stderr,"Ground heat flux not computed (no energy balance).\n"); fprintf(stderr,"Use Frozen Soil Model.........(%i)\n",options.FROZEN_SOIL); if ( QUICK_FS ) fprintf(stderr,".... Using linearized UFWC curve with %i temperatures.\n", QUICK_FS_TEMPS); fprintf(stderr,"Run Snow Model Using a Time Step of %i hours\n", options.SNOW_STEP); fprintf(stderr,"Compress Output Files.........(%i)\n",options.COMPRESS); fprintf(stderr,"Correct Precipitation.........(%i)\n",options.CORRPREC); fprintf(stderr,"\n"); fprintf(stderr,"Using %i Snow Bands\n",options.SNOW_BAND); fprintf(stderr,"Using %i Root Zones\n",options.ROOT_ZONES); if ( options.SAVE_STATE ) fprintf(stderr,"Model state will be saved on = %02i/%02i/%04i\n\n", global.stateday, global.statemonth, global.stateyear); if ( options.BINARY_OUTPUT ) fprintf(stderr,"Model output is in standard BINARY format.\n"); else fprintf(stderr,"Model output is in standard ASCII format.\n"); if ( LINK_DEBUG ) fprintf(stderr,"Debugging code has been included in the executable.\n"); else fprintf(stderr,"Debugging code has not been compiled.\n"); #endif // VERBOSE #endif // !OUTPUT_FORCE return global; }