diff --git a/vic/plugins/crops/include/crop.h b/vic/plugins/crops/include/crop.h index 05375db0f..62a42a83f 100644 --- a/vic/plugins/crops/include/crop.h +++ b/vic/plugins/crops/include/crop.h @@ -13,6 +13,8 @@ typedef struct { } crop_con_map_struct; typedef struct { + double tsum1; + double tsum2; double *DVS_point; double *N_amount; double *P_amount; @@ -20,6 +22,8 @@ typedef struct { } crop_con_struct; typedef struct { + double *tsum1; + double *tsum2; double **DVS_point; double **N_amount; double **P_amount; diff --git a/vic/plugins/crops/src/crop_alloc_free.c b/vic/plugins/crops/src/crop_alloc_free.c index 3b82fed9f..da20d8809 100644 --- a/vic/plugins/crops/src/crop_alloc_free.c +++ b/vic/plugins/crops/src/crop_alloc_free.c @@ -51,6 +51,16 @@ crop_alloc(void) crop_con[i] = malloc(crop_con_map[i].nc_active * sizeof(*crop_con[i])); check_alloc_status(crop_con[i], "Memory allocation error"); + crop_force[i].tsum1 = + malloc(crop_con_map[i].nc_active * + sizeof(*crop_force[i].tsum1)); + check_alloc_status(crop_force[i].tsum1, "Memory allocation error"); + + crop_force[i].tsum2 = + malloc(crop_con_map[i].nc_active * + sizeof(*crop_force[i].tsum2)); + check_alloc_status(crop_force[i].tsum2, "Memory allocation error"); + crop_force[i].DVS_point = malloc(crop_con_map[i].nc_active * sizeof(*crop_force[i].DVS_point)); @@ -153,6 +163,8 @@ crop_finalize(void) free(crop_con_map[i].veg_class); free(crop_con_map[i].Cc); free(crop_con[i]); + free(crop_force[i].tsum1); + free(crop_force[i].tsum2); free(crop_force[i].DVS_point); free(crop_force[i].N_amount); free(crop_force[i].P_amount); diff --git a/vic/plugins/crops/src/crop_forcing.c b/vic/plugins/crops/src/crop_forcing.c index bd014e0b0..bd329f9ce 100644 --- a/vic/plugins/crops/src/crop_forcing.c +++ b/vic/plugins/crops/src/crop_forcing.c @@ -14,6 +14,8 @@ crop_forcing(void) double *dvar; + size_t d4count[4]; + size_t d4start[4]; size_t d5count[5]; size_t d5start[5]; @@ -25,6 +27,15 @@ crop_forcing(void) dvar = malloc(local_domain.ncells_active * sizeof(*dvar)); check_alloc_status(dvar, "Memory allocation error."); + d4start[0] = 0; + d4start[1] = 0; + d4start[2] = 0; + d4start[3] = 0; + d4count[0] = 1; + d4count[1] = 1; + d4count[2] = global_domain.n_ny; + d4count[3] = global_domain.n_nx; + d5start[0] = 0; d5start[1] = 0; d5start[2] = 0; @@ -36,6 +47,51 @@ crop_forcing(void) d5count[3] = global_domain.n_ny; d5count[4] = global_domain.n_nx; + // Get tsum forcing data + if (plugin_options.WOFOST_FORCE_TSUM) { + // Get tsum1 + if (plugin_global_param.forcerun[FORCING_TSUM_1]) { + d4start[0] = plugin_global_param.forceskip[FORCING_TSUM_1] + + plugin_global_param.forceoffset[FORCING_TSUM_1]; + for (j = 0; j < plugin_options.NCROPTYPES; j++) { + d4start[1] = j; + get_scatter_nc_field_double(&(plugin_filenames.forcing[ + FORCING_TSUM_1]), + plugin_filenames.f_varname[ + FORCING_TSUM_1], d4start, + d4count, dvar); + + for (i = 0; i < local_domain.ncells_active; i++) { + iCrop = crop_con_map[i].cidx[j]; + if (iCrop != NODATA_VEG) { + crop_force[i].tsum1[iCrop] = dvar[i]; + } + } + } + } + + // Get tsum2 + if (plugin_global_param.forcerun[FORCING_TSUM_2]) { + d4start[0] = plugin_global_param.forceskip[FORCING_TSUM_2] + + plugin_global_param.forceoffset[FORCING_TSUM_2]; + for (j = 0; j < plugin_options.NCROPTYPES; j++) { + d4start[1] = j; + get_scatter_nc_field_double(&(plugin_filenames.forcing[ + FORCING_TSUM_2]), + plugin_filenames.f_varname[ + FORCING_TSUM_2], d4start, + d4count, dvar); + + for (i = 0; i < local_domain.ncells_active; i++) { + iCrop = crop_con_map[i].cidx[j]; + if (iCrop != NODATA_VEG) { + crop_force[i].tsum2[iCrop] = dvar[i]; + } + } + } + } + } + // Get fertilizer forcing data if (plugin_options.WOFOST_FORCE_FERT) { // Get DVS_point diff --git a/vic/plugins/crops/src/crop_get_global_param.c b/vic/plugins/crops/src/crop_get_global_param.c index 7679166f1..97d32cc86 100644 --- a/vic/plugins/crops/src/crop_get_global_param.c +++ b/vic/plugins/crops/src/crop_get_global_param.c @@ -33,6 +33,10 @@ crop_get_global_param(char *cmdstr) sscanf(cmdstr, "%*s %s", flgstr); plugin_options.WOFOST_PFERT = str_to_bool(flgstr); } + else if (strcasecmp("WOFOST_POTENTIAL_TEMPERATURE", optstr) == 0) { + sscanf(cmdstr, "%*s %s", flgstr); + plugin_options.WOFOST_PTEMP = str_to_bool(flgstr); + } else if (strcasecmp("WOFOST_DIST_SEASON", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); plugin_options.WOFOST_DIST_SEASON = str_to_bool(flgstr); @@ -41,6 +45,10 @@ crop_get_global_param(char *cmdstr) sscanf(cmdstr, "%*s %s", flgstr); plugin_options.WOFOST_DIST_TSUM = str_to_bool(flgstr); } + else if (strcasecmp("WOFOST_FORCE_TSUM", optstr) == 0) { + sscanf(cmdstr, "%*s %s", flgstr); + plugin_options.WOFOST_FORCE_TSUM = str_to_bool(flgstr); + } else if (strcasecmp("WOFOST_DIST_FERTILIZER", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); plugin_options.WOFOST_DIST_FERT = str_to_bool(flgstr); @@ -57,6 +65,10 @@ crop_get_global_param(char *cmdstr) sscanf(cmdstr, "%*s %s", flgstr); plugin_options.WOFOST_CONTINUE = str_to_bool(flgstr); } + else if (strcasecmp("WOFOST_FORCE_TSUM", optstr) == 0) { + sscanf(cmdstr, "%*s %s", flgstr); + plugin_options.WOFOST_FORCE_TSUM = str_to_bool(flgstr); + } else if (strcasecmp("WOFOST_FORCE_FERTILIZER", optstr) == 0) { sscanf(cmdstr, "%*s %s", flgstr); plugin_options.WOFOST_FORCE_FERT = str_to_bool(flgstr); @@ -103,6 +115,19 @@ crop_validate_global_param(void) if (!plugin_options.FORCE_CO2) { log_err("WOFOST = TRUE but FORCE_CO2 = FALSE"); } + if (plugin_options.WOFOST_FORCE_TSUM) { + if (!plugin_options.WOFOST_DIST_TSUM) { + log_err("WOFOST_FORCE_TSUM = TRUE but WOFOST_DIST_TSUM = FALSE"); + } + if (strcasecmp(plugin_filenames.f_path_pfx[FORCING_TSUM_1], + MISSING_S) == 0) { + log_err("WOFOST_FORCE_TSUM = TRUE but tsum1 forcing file is missing"); + } + if (strcasecmp(plugin_filenames.f_path_pfx[FORCING_TSUM_2], + MISSING_S) == 0) { + log_err("WOFOST_FORCE_TSUM = TRUE but tsum2 forcing file is missing"); + } + } if (plugin_options.WOFOST_FORCE_FERT) { if (!plugin_options.WOFOST_DIST_FERT) { log_err("WOFOST_FORCE_FERT = TRUE but WOFOST_DIST_FERT = FALSE"); diff --git a/vic/plugins/crops/src/crop_init_library.c b/vic/plugins/crops/src/crop_init_library.c index 004b8418c..37c7fff73 100644 --- a/vic/plugins/crops/src/crop_init_library.c +++ b/vic/plugins/crops/src/crop_init_library.c @@ -37,6 +37,8 @@ initialize_crop_con(crop_con_struct *crop_con) size_t i; + crop_con->tsum1 = 0.; + crop_con->tsum2 = 0.; for (i = 0; i < plugin_options.NFERTTIMES; i++) { crop_con->DVS_point[i] = 0.; crop_con->N_amount[i] = 0.; @@ -58,6 +60,8 @@ initialize_crop_force(crop_force_struct *crop_force, size_t iFert; for (iCrop = 0; iCrop < ncrops; iCrop++) { + crop_force->tsum1[iCrop] = 0.; + crop_force->tsum2[iCrop] = 0.; for (iFert = 0; iFert < plugin_options.NFERTTIMES; iFert++) { crop_force->DVS_point[iCrop][iFert] = 0.; crop_force->N_amount[iCrop][iFert] = 0.; diff --git a/vic/plugins/crops/src/crop_output.c b/vic/plugins/crops/src/crop_output.c index b5643203d..7b2c5cef3 100644 --- a/vic/plugins/crops/src/crop_output.c +++ b/vic/plugins/crops/src/crop_output.c @@ -944,7 +944,7 @@ crop_put_state_data(size_t iCell) cgrid->growing; out_data[iCell][N_OUTVAR_TYPES + OUT_CROP_TMAXSTRESS][crop_class] += - cgrid->met->TmaxStress * + cgrid->met->TempStress * area_fract * cgrid->growing; out_data[iCell][N_OUTVAR_TYPES + @@ -1255,7 +1255,7 @@ crop_put_rate_data(size_t iCell) cgrid->growing; out_data[iCell][N_OUTVAR_TYPES + OUT_CROP_TMAXSTRESS][crop_class] += - cgrid->met->TmaxStress * + cgrid->met->TempStress * area_fract * cgrid->growing; out_data[iCell][N_OUTVAR_TYPES + diff --git a/vic/plugins/crops/src/crop_run.c b/vic/plugins/crops/src/crop_run.c index b09202b25..62ee38716 100644 --- a/vic/plugins/crops/src/crop_run.c +++ b/vic/plugins/crops/src/crop_run.c @@ -234,6 +234,11 @@ crop_run(size_t iCell) /* Determine if the sowing already has occurred */ IfSowing(cgrid, &cgrid->start); + if (plugin_options.WOFOST_DIST_TSUM) { + cgrid->crp->prm.TempSum1 = crop_con[iCell][iCrop].tsum1; + cgrid->crp->prm.TempSum2 = crop_con[iCell][iCrop].tsum2; + } + if (plugin_options.WOFOST_DIST_FERT) { for (iTime = 0; iTime < plugin_options.NFERTTIMES; diff --git a/vic/plugins/crops/src/crop_start.c b/vic/plugins/crops/src/crop_start.c index 531511fec..d0010c512 100644 --- a/vic/plugins/crops/src/crop_start.c +++ b/vic/plugins/crops/src/crop_start.c @@ -37,6 +37,9 @@ crop_start(void) extern domain_struct global_domain; extern plugin_filenames_struct plugin_filenames; + size_t tsum_idx[2] = { + FORCING_TSUM_1, FORCING_TSUM_2 + }; size_t fert_idx[4] = { FORCING_FERT_DVS, FORCING_FERT_N, FORCING_FERT_P, FORCING_FERT_K }; @@ -61,6 +64,33 @@ crop_start(void) plugin_options.NFERTTIMES = get_nc_dimension(&(plugin_filenames.crop), "fertilizer_times"); } + if (plugin_options.WOFOST_FORCE_TSUM) { + for (i = 0; i < 2; i++) { + // Get information from the forcing file(s) + // Open first-year forcing files and get info + snprintf(plugin_filenames.forcing[tsum_idx[i]].nc_filename, + MAXSTRING, "%s%4d.nc", + plugin_filenames.f_path_pfx[tsum_idx[i]], + global_param.startyear); + status = nc_open(plugin_filenames.forcing[tsum_idx[i]].nc_filename, + NC_NOWRITE, + &(plugin_filenames.forcing[tsum_idx[i]].nc_id)); + check_nc_status(status, "Error opening %s", + plugin_filenames.forcing[tsum_idx[i]].nc_filename); + + dim_len = get_nc_dimension(&(plugin_filenames.forcing[tsum_idx[i]]), + "crop_class"); + if (dim_len != plugin_options.NCROPTYPES) { + log_err( + "Tsum forcing crop_class length is not equal to NCROPTYPES"); + } + + // Close first-year forcing files + status = nc_close(plugin_filenames.forcing[tsum_idx[i]].nc_id); + check_nc_status(status, "Error closing %s", + plugin_filenames.forcing[tsum_idx[i]].nc_filename); + } + } if (plugin_options.WOFOST_FORCE_FERT) { for (i = 0; i < 4; i++) { // Get information from the forcing file(s) diff --git a/vic/plugins/crops/src/wofost_copy_library.c b/vic/plugins/crops/src/wofost_copy_library.c index 0a121e625..145d2c1bb 100644 --- a/vic/plugins/crops/src/wofost_copy_library.c +++ b/vic/plugins/crops/src/wofost_copy_library.c @@ -307,6 +307,7 @@ copy_wofost_parameters(Parameters *from, to->TempEffMax = from->TempEffMax; to->TSumEmergence = from->TSumEmergence; to->IdentifyAnthesis = from->IdentifyAnthesis; + to->MaxOptimumTemp = from->MaxOptimumTemp; to->OptimumDaylength = from->OptimumDaylength; to->CriticalDaylength = from->CriticalDaylength; to->SatVernRequirement = from->SatVernRequirement; @@ -493,7 +494,7 @@ copy_wofost_vic(Meteo *from, to->CosLD = from->CosLD; to->DiffRadPP = from->DiffRadPP; to->DSinBE = from->DSinBE; - to->TmaxStress = from->TmaxStress; + to->TempStress = from->TempStress; to->TminStress = from->TminStress; } diff --git a/vic/plugins/crops/src/wofost_init.c b/vic/plugins/crops/src/wofost_init.c index 4e12b9cd2..7003be6c9 100644 --- a/vic/plugins/crops/src/wofost_init.c +++ b/vic/plugins/crops/src/wofost_init.c @@ -205,14 +205,16 @@ wofost_set_data(void) for (i = 0; i < local_domain.ncells_active; i++) { iCrop = crop_con_map[i].cidx[j]; if (iCrop != NODATA_VEG) { - for (k = 0; k < options.SNOW_BAND; k++) { - iGrid = Grid[i][k]; - for (l = 0; l < (size_t)iCrop; l++) { - iGrid = iGrid->next; - } - - iGrid->crp->prm.TempSum1 = dvar[i]; - } + crop_con[i][iCrop].tsum1 = dvar[i]; + +// for (k = 0; k < options.SNOW_BAND; k++) { +// iGrid = Grid[i][k]; +// for (l = 0; l < (size_t)iCrop; l++) { +// iGrid = iGrid->next; +// } +// +// iGrid->crp->prm.TempSum1 = dvar[i]; +// } } } } @@ -227,14 +229,16 @@ wofost_set_data(void) for (i = 0; i < local_domain.ncells_active; i++) { iCrop = crop_con_map[i].cidx[j]; if (iCrop != NODATA_VEG) { - for (k = 0; k < options.SNOW_BAND; k++) { - iGrid = Grid[i][k]; - for (l = 0; l < (size_t)iCrop; l++) { - iGrid = iGrid->next; - } - - iGrid->crp->prm.TempSum2 = dvar[i]; - } + crop_con[i][iCrop].tsum2 = dvar[i]; + +// for (k = 0; k < options.SNOW_BAND; k++) { +// iGrid = Grid[i][k]; +// for (l = 0; l < (size_t)iCrop; l++) { +// iGrid = iGrid->next; +// } +// +// iGrid->crp->prm.TempSum2 = dvar[i]; +// } } } } diff --git a/vic/plugins/crops/src/wofost_init_library.c b/vic/plugins/crops/src/wofost_init_library.c index ae6518a21..3fe8dcfa9 100644 --- a/vic/plugins/crops/src/wofost_init_library.c +++ b/vic/plugins/crops/src/wofost_init_library.c @@ -202,6 +202,7 @@ initialize_wofost_parameters(Parameters *prm) prm->TempEffMax = 0.; prm->TSumEmergence = 0.; prm->IdentifyAnthesis = 0; + prm->MaxOptimumTemp = 0; prm->OptimumDaylength = 0.; prm->CriticalDaylength = 0.; prm->SatVernRequirement = 0.; @@ -382,7 +383,7 @@ initialize_wofost_vic(Meteo *met) met->CosLD = 0.; met->DiffRadPP = 0.; met->DSinBE = 0.; - met->TmaxStress = 0.; + met->TempStress = 0.; met->TminStress = 0.; } diff --git a/vic/plugins/crops/src/wofost_update_step_vars.c b/vic/plugins/crops/src/wofost_update_step_vars.c index e2be84699..7924bcd48 100644 --- a/vic/plugins/crops/src/wofost_update_step_vars.c +++ b/vic/plugins/crops/src/wofost_update_step_vars.c @@ -4,25 +4,67 @@ void wofost_update_step_vars(size_t iCell) { + extern option_struct options; extern plugin_option_struct plugin_options; extern crop_force_struct *crop_force; extern crop_con_struct **crop_con; extern crop_con_map_struct *crop_con_map; + extern SimUnit ***Grid; + SimUnit *iGrid; + size_t iCrop; size_t iFert; + size_t iBand; + size_t l; + if (plugin_options.WOFOST_FORCE_TSUM) { + for (iCrop = 0; iCrop < crop_con_map[iCell].nc_active; iCrop++) { + for (iBand = 0; iBand < options.SNOW_BAND; iBand++) { + iGrid = Grid[iCell][iBand]; + for (l = 0; l < (size_t)iCrop; l++) { + iGrid = iGrid->next; + } + + /* Determine if the sowing already has occurred */ + IfSowing(iGrid, &iGrid->start); + + if(iGrid->crp->Sowing != 1){ + continue; + } + + crop_con[iCell][iCrop].tsum1 = + crop_force[iCell].tsum1[iCrop]; + crop_con[iCell][iCrop].tsum2 = + crop_force[iCell].tsum2[iCrop]; + } + } + } if (plugin_options.WOFOST_FORCE_FERT) { for (iCrop = 0; iCrop < crop_con_map[iCell].nc_active; iCrop++) { for (iFert = 0; iFert < plugin_options.NFERTTIMES; iFert++) { - crop_con[iCell][iCrop].DVS_point[iFert] = - crop_force[iCell].DVS_point[iCrop][iFert]; - crop_con[iCell][iCrop].N_amount[iFert] = - crop_force[iCell].N_amount[iCrop][iFert]; - crop_con[iCell][iCrop].P_amount[iFert] = - crop_force[iCell].P_amount[iCrop][iFert]; - crop_con[iCell][iCrop].K_amount[iFert] = - crop_force[iCell].K_amount[iCrop][iFert]; + for (iBand = 0; iBand < options.SNOW_BAND; iBand++) { + iGrid = Grid[iCell][iBand]; + for (l = 0; l < (size_t)iCrop; l++) { + iGrid = iGrid->next; + } + + /* Determine if the sowing already has occurred */ + IfSowing(iGrid, &iGrid->start); + + if(iGrid->crp->Sowing != 1){ + continue; + } + + crop_con[iCell][iCrop].DVS_point[iFert] = + crop_force[iCell].DVS_point[iCrop][iFert]; + crop_con[iCell][iCrop].N_amount[iFert] = + crop_force[iCell].N_amount[iCrop][iFert]; + crop_con[iCell][iCrop].P_amount[iFert] = + crop_force[iCell].P_amount[iCrop][iFert]; + crop_con[iCell][iCrop].K_amount[iFert] = + crop_force[iCell].K_amount[iCrop][iFert]; + } } } } diff --git a/vic/plugins/general/include/plugin_def.h b/vic/plugins/general/include/plugin_def.h index a7ec8fa6c..f067eb7e2 100644 --- a/vic/plugins/general/include/plugin_def.h +++ b/vic/plugins/general/include/plugin_def.h @@ -185,6 +185,8 @@ enum { FORCING_ENE_GROUNDWATER, /**< energy groundwater fraction [-] */ FORCING_ENE_CONSUMPTION, /**< energy consumption fraction [-] */ // crops + FORCING_TSUM_1, /**< Temperature sum from emergence to anthesis [degree C] */ + FORCING_TSUM_2, /**< Temperature sum from athesis to maturity [degree C] */ FORCING_FERT_DVS, /**< Fertilizer application DVS point [-] */ FORCING_FERT_N, /**< Fertilizer application N amount [kg ha-1] */ FORCING_FERT_P, /**< Fertilizer application P amount [kg ha-1] */ @@ -255,12 +257,14 @@ typedef struct { bool NONRENEW_RUNOFF; /**< non-renewable water abstractions flag */ bool WOFOST_PIRR; /**< potential irrigation for wofost module flag */ bool WOFOST_PFERT; /**< potential fertilization for wofost module flag */ + bool WOFOST_PTEMP; /**< optimal (maximum) temperatures for wofost module flag */ bool WOFOST_DIST_SEASON; /**< distributed seasons for wofost module flag */ bool WOFOST_DIST_TSUM; /**< distributed tsums for wofost module flag */ bool WOFOST_DIST_FERT; /**< distributed fertilization for wofost module flag */ bool WOFOST_DIST_MIN; /**< distributed mineralization for wofost module flag */ bool WOFOST_CALC_MIN; /**< calculated mineralization for wofost module flag */ bool WOFOST_CONTINUE; /**< continue on end land-use for wofost module flag */ + bool WOFOST_FORCE_TSUM; /**< distributed tsums forcing for wofost module flag */ bool WOFOST_FORCE_FERT; /**< distributed fertilizer forcing for wofost module flag */ short unsigned int NCROPTYPES; /**< number of crop types */ short unsigned int NFERTTIMES; /**< number of fertilizer occations */ diff --git a/vic/plugins/general/src/plugin_broadcast.c b/vic/plugins/general/src/plugin_broadcast.c index 8cbd34bd0..6821c5e74 100644 --- a/vic/plugins/general/src/plugin_broadcast.c +++ b/vic/plugins/general/src/plugin_broadcast.c @@ -199,7 +199,7 @@ plugin_create_MPI_option_struct_type(MPI_Datatype *mpi_type) MPI_Datatype *mpi_types; // nitems has to equal the number of elements in global_param_struct - nitems = 36; + nitems = 38; blocklengths = malloc(nitems * sizeof(*blocklengths)); check_alloc_status(blocklengths, "Memory allocation error."); offsets = malloc(nitems * sizeof(*offsets)); @@ -293,6 +293,9 @@ plugin_create_MPI_option_struct_type(MPI_Datatype *mpi_type) // bool WOFOST_PFERT; offsets[i] = offsetof(plugin_option_struct, WOFOST_PFERT); mpi_types[i++] = MPI_C_BOOL; + // bool WOFOST_PTEMP; + offsets[i] = offsetof(plugin_option_struct, WOFOST_PTEMP); + mpi_types[i++] = MPI_C_BOOL; // bool WOFOST_DIST_SEASON; offsets[i] = offsetof(plugin_option_struct, WOFOST_DIST_SEASON); mpi_types[i++] = MPI_C_BOOL; @@ -311,6 +314,9 @@ plugin_create_MPI_option_struct_type(MPI_Datatype *mpi_type) // bool WOFOST_CONTINUE; offsets[i] = offsetof(plugin_option_struct, WOFOST_CONTINUE); mpi_types[i++] = MPI_C_BOOL; + // bool WOFOST_FORCE_TSUM; + offsets[i] = offsetof(plugin_option_struct, WOFOST_FORCE_TSUM); + mpi_types[i++] = MPI_C_BOOL; // bool WOFOST_FORCE_FERT; offsets[i] = offsetof(plugin_option_struct, WOFOST_FORCE_FERT); mpi_types[i++] = MPI_C_BOOL; diff --git a/vic/plugins/general/src/plugin_init_library.c b/vic/plugins/general/src/plugin_init_library.c index 11639bfcc..a3c568267 100644 --- a/vic/plugins/general/src/plugin_init_library.c +++ b/vic/plugins/general/src/plugin_init_library.c @@ -63,12 +63,14 @@ plugin_initialize_options(plugin_option_struct *plugin_options) plugin_options->NONRENEW_RUNOFF = false; plugin_options->WOFOST_PIRR = false; plugin_options->WOFOST_PFERT = false; + plugin_options->WOFOST_PTEMP = false; plugin_options->WOFOST_DIST_SEASON = false; plugin_options->WOFOST_DIST_TSUM = false; plugin_options->WOFOST_DIST_FERT = false; plugin_options->WOFOST_DIST_MIN = false; plugin_options->WOFOST_CALC_MIN = false; plugin_options->WOFOST_CONTINUE = false; + plugin_options->WOFOST_FORCE_TSUM = false; plugin_options->WOFOST_FORCE_FERT = false; plugin_options->NCROPTYPES = 0; plugin_options->NFERTTIMES = 0; diff --git a/vic/plugins/general/src/plugin_print.c b/vic/plugins/general/src/plugin_print.c index dea95e6ee..ed0ec1092 100644 --- a/vic/plugins/general/src/plugin_print.c +++ b/vic/plugins/general/src/plugin_print.c @@ -113,12 +113,16 @@ plugin_print_options(plugin_option_struct *op) op->WOFOST_CALC_MIN ? "true" : "false"); fprintf(LOG_DEST, "\tWOFOST_CONTINUE : %s\n", op->WOFOST_CONTINUE ? "true" : "false"); + fprintf(LOG_DEST, "\tWOFOST_FOREC_TSUM : %s\n", + op->WOFOST_FORCE_TSUM ? "true" : "false"); fprintf(LOG_DEST, "\tWOFOST_FOREC_FERT : %s\n", op->WOFOST_FORCE_FERT ? "true" : "false"); fprintf(LOG_DEST, "\tWOFOST_PIRR : %s\n", op->WOFOST_PIRR ? "true" : "false"); fprintf(LOG_DEST, "\tWOFOST_PFERT : %s\n", op->WOFOST_PFERT ? "true" : "false"); + fprintf(LOG_DEST, "\tWOFOST_PTEMP : %s\n", + op->WOFOST_PTEMP ? "true" : "false"); fprintf(LOG_DEST, "\tFORCE_CO2 : %s\n", op->FORCE_CO2 ? "true" : "false"); diff --git a/vic/plugins/general/src/plugin_set_force_type.c b/vic/plugins/general/src/plugin_set_force_type.c index 5ece8723a..fd37ac7b3 100644 --- a/vic/plugins/general/src/plugin_set_force_type.c +++ b/vic/plugins/general/src/plugin_set_force_type.c @@ -116,6 +116,12 @@ plugin_set_force_type(char *cmdstr) else if (strcasecmp("CO2", nctype) == 0) { type = FORCING_CO2; } + else if (strcasecmp("TSUM1", nctype) == 0) { + type = FORCING_TSUM_1; + } + else if (strcasecmp("TSUM2", nctype) == 0) { + type = FORCING_TSUM_2; + } else if (strcasecmp("FERT_DVS", nctype) == 0) { type = FORCING_FERT_DVS; } diff --git a/vic/plugins/wofost/include/wofost.h b/vic/plugins/wofost/include/wofost.h index 7f73ee0e3..56776d0e2 100644 --- a/vic/plugins/wofost/include/wofost.h +++ b/vic/plugins/wofost/include/wofost.h @@ -77,6 +77,7 @@ typedef struct PARAMETERS { /** Phenology **/ int IdentifyAnthesis; + float MaxOptimumTemp; float OptimumDaylength; float CriticalDaylength; float SatVernRequirement; @@ -434,7 +435,7 @@ typedef struct METEO { float CosLD; float DiffRadPP; float DSinBE; - float TmaxStress; + float TempStress; float TminStress; } Meteo; diff --git a/vic/plugins/wofost/src/Assim.c b/vic/plugins/wofost/src/Assim.c index 6963581cc..f9a36bf98 100644 --- a/vic/plugins/wofost/src/Assim.c +++ b/vic/plugins/wofost/src/Assim.c @@ -106,9 +106,15 @@ DailyTotalAssimilation(SimUnit *Grid) /* Correction for the atmospheric CO2 concentration */ EFF = EFF * Factor; - Grid->met->TmaxStress = Afgen(Grid->crp->prm.FactorAssimRateTemp, + Grid->met->TempStress = Afgen(Grid->crp->prm.FactorAssimRateTemp, &Grid->met->DayTemp); - AssimMax = Grid->met->TmaxStress * + if (plugin_options.WOFOST_PTEMP) { + // Only adjust TempStress if temperature is above optimal (not below) + if(Grid->met->DayTemp > Grid->crp->prm.MaxOptimumTemp){ + Grid->met->TempStress = 1; + } + } + AssimMax = Grid->met->TempStress * Afgen(Grid->crp->prm.MaxAssimRate, &(Grid->crp->st.Development)) * Afgen(Grid->crp->prm.CO2AMAXTB, &Grid->met->CO2); diff --git a/vic/plugins/wofost/src/Cropdata.c b/vic/plugins/wofost/src/Cropdata.c index 6b96e67b9..8c1c37b9a 100644 --- a/vic/plugins/wofost/src/Cropdata.c +++ b/vic/plugins/wofost/src/Cropdata.c @@ -145,6 +145,18 @@ GetCropData(Plant *CROP, CROP->prm.N_MaxLeaves = Table[19]; CROP->prm.P_MaxLeaves = Table[20]; CROP->prm.K_MaxLeaves = Table[21]; + + head = CROP->prm.FactorAssimRateTemp; + XValue = 0; + YValue = 0; + while (head) { + if(head->y >= YValue){ + XValue = head->x; + YValue = head->y; + } + head = head->next; + } + CROP->prm.MaxOptimumTemp = XValue; CROP->Emergence = 0; CROP->TSumEmergence = 0.;