From 5ac8fa5e6c129ae75428aa4b2e7727647334f279 Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Mon, 11 May 2026 12:01:03 -0700 Subject: [PATCH 01/10] added checking and logging for nan input --- src/bmi_cfe.c | 32 ++++++++++++++++++++-- src/conceptual_reservoir.c | 54 ++++++++++++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index 77cc5fc9..aa549bf7 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -979,9 +980,36 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) return BMI_FAILURE; } - // compute gw storage in meters + // compute gw storage in meters if ((is_gw_storage_set == TRUE) && (is_gw_max_set == TRUE)) { - model->gw_reservoir.storage_m = model->gw_reservoir.gw_storage * model->gw_reservoir.storage_max_m; + if (!isfinite(model->gw_reservoir.gw_storage) || + !isfinite(model->gw_reservoir.storage_max_m) || + !isfinite(model->gw_reservoir.coeff_primary) || + !isfinite(model->gw_reservoir.exponent_primary) || + model->gw_reservoir.gw_storage < 0.0 || + model->gw_reservoir.storage_max_m <= 0.0) { + + Log(WARNING, + "Invalid CFE groundwater reservoir parameters from config; " + "disabling groundwater reservoir and setting DEEP_GW_TO_CHANNEL_FLUX to 0. " + "gw_storage=%lf, max_gw_storage=%lf, Cgw=%lf, expon=%lf. " + "This is likely an upstream NHF parameter-generation issue.\n", + model->gw_reservoir.gw_storage, + model->gw_reservoir.storage_max_m, + model->gw_reservoir.coeff_primary, + model->gw_reservoir.exponent_primary); + + model->gw_reservoir.gw_storage = 0.0; + model->gw_reservoir.storage_max_m = 0.0; + model->gw_reservoir.storage_m = 0.0; + model->gw_reservoir.coeff_primary = 0.0; + model->gw_reservoir.exponent_primary = 1.0; + } + else { + model->gw_reservoir.storage_m = + model->gw_reservoir.gw_storage * + model->gw_reservoir.storage_max_m; + } } if (is_num_timesteps_set == FALSE && strcmp(model->forcing_file, "BMI")) { diff --git a/src/conceptual_reservoir.c b/src/conceptual_reservoir.c index 83879e41..b7d2e522 100644 --- a/src/conceptual_reservoir.c +++ b/src/conceptual_reservoir.c @@ -1,6 +1,8 @@ #ifndef _CONCEPTUAL_RESERVOIR_C #define _CONCEPTUAL_RESERVOIR_C +#include +#include "logger.h" #include "conceptual_reservoir.h" @@ -40,20 +42,62 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser // ***************************************************************************** // ------------------ Conceptual Ground Water Reservoir ------------------------- // single outlet reservoir like the NWM V1.2 exponential conceptual gw reservoir - if (da_reservoir->is_exponential == TRUE) { + if (da_reservoir->is_exponential == TRUE) { + *primary_flux_m = 0.0; + *secondary_flux_m = 0.0; + + if (!isfinite(da_reservoir->storage_m) || + !isfinite(da_reservoir->storage_max_m) || + !isfinite(da_reservoir->coeff_primary) || + !isfinite(da_reservoir->exponent_primary) || + da_reservoir->storage_m <= 0.0 || + da_reservoir->storage_max_m <= 0.0) { + + Log(WARNING, + "Invalid CFE groundwater reservoir state or parameters; " + "setting DEEP_GW_TO_CHANNEL_FLUX to 0. " + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.\n", + da_reservoir->storage_m, + da_reservoir->storage_max_m, + da_reservoir->coeff_primary, + da_reservoir->exponent_primary); + + if (!isfinite(da_reservoir->storage_m) || + da_reservoir->storage_m < 0.0) { + da_reservoir->storage_m = 0.0; + } + + return; + } + // calculate the one flux and return. double exp_term = exp(da_reservoir->exponent_primary * da_reservoir->storage_m / da_reservoir->storage_max_m); - - *primary_flux_m = da_reservoir->coeff_primary * (exp_term - 1.0); - *secondary_flux_m = 0.0; + double calculated_flux_m = da_reservoir->coeff_primary * (exp_term - 1.0); + + if (!isfinite(calculated_flux_m) || calculated_flux_m < 0.0) { + Log(WARNING, + "Invalid CFE groundwater flux calculation; " + "setting DEEP_GW_TO_CHANNEL_FLUX to 0. " + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf, raw_flux=%lf.\n", + da_reservoir->storage_m, + da_reservoir->storage_max_m, + da_reservoir->coeff_primary, + da_reservoir->exponent_primary, + calculated_flux_m); + + return; + } + + *primary_flux_m = calculated_flux_m; // cap so flux never exceeds storage, but commented out here per OWP request (9/11/2025) //if (*primary_flux_m > da_reservoir->storage_m) { // *primary_flux_m = da_reservoir->storage_m; //} - + return; } + // ***************************************************************************** // code goes past here iff it is not a single outlet exponential deep groundwater reservoir of the NWM variety From 9113c367ff69137fb526c96c69237485451686af Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Mon, 11 May 2026 15:52:55 -0700 Subject: [PATCH 02/10] warning throtling --- src/bmi_cfe.c | 31 ++++++++++++++++++++++--------- src/conceptual_reservoir.c | 29 +++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index aa549bf7..b37c128b 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -981,6 +981,8 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) } // compute gw storage in meters + static int gw_bad_param_warned = 0; + if ((is_gw_storage_set == TRUE) && (is_gw_max_set == TRUE)) { if (!isfinite(model->gw_reservoir.gw_storage) || !isfinite(model->gw_reservoir.storage_max_m) || @@ -989,15 +991,26 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) model->gw_reservoir.gw_storage < 0.0 || model->gw_reservoir.storage_max_m <= 0.0) { - Log(WARNING, - "Invalid CFE groundwater reservoir parameters from config; " - "disabling groundwater reservoir and setting DEEP_GW_TO_CHANNEL_FLUX to 0. " - "gw_storage=%lf, max_gw_storage=%lf, Cgw=%lf, expon=%lf. " - "This is likely an upstream NHF parameter-generation issue.\n", - model->gw_reservoir.gw_storage, - model->gw_reservoir.storage_max_m, - model->gw_reservoir.coeff_primary, - model->gw_reservoir.exponent_primary); + if (gw_bad_param_warned == 0) { + Log(WARNING, + "Invalid CFE groundwater reservoir parameters from config; " + "disabling groundwater reservoir and setting DEEP_GW_TO_CHANNEL_FLUX to 0. " + "gw_storage=%lf, max_gw_storage=%lf, Cgw=%lf, expon=%lf. " + "This is likely an upstream NHF parameter-generation issue.\n", + model->gw_reservoir.gw_storage, + model->gw_reservoir.storage_max_m, + model->gw_reservoir.coeff_primary, + model->gw_reservoir.exponent_primary); + + gw_bad_param_warned = 1; + } + else if (gw_bad_param_warned == 1) { + Log(WARNING, + "Invalid CFE groundwater reservoir parameters occurred again; " + "further warnings suppressed.\n"); + + gw_bad_param_warned = 2; + } model->gw_reservoir.gw_storage = 0.0; model->gw_reservoir.storage_max_m = 0.0; diff --git a/src/conceptual_reservoir.c b/src/conceptual_reservoir.c index b7d2e522..7a61fd39 100644 --- a/src/conceptual_reservoir.c +++ b/src/conceptual_reservoir.c @@ -46,6 +46,8 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser *primary_flux_m = 0.0; *secondary_flux_m = 0.0; + static int gw_bad_state_warned = 0; + if (!isfinite(da_reservoir->storage_m) || !isfinite(da_reservoir->storage_max_m) || !isfinite(da_reservoir->coeff_primary) || @@ -53,14 +55,25 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser da_reservoir->storage_m <= 0.0 || da_reservoir->storage_max_m <= 0.0) { - Log(WARNING, - "Invalid CFE groundwater reservoir state or parameters; " - "setting DEEP_GW_TO_CHANNEL_FLUX to 0. " - "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.\n", - da_reservoir->storage_m, - da_reservoir->storage_max_m, - da_reservoir->coeff_primary, - da_reservoir->exponent_primary); + if (gw_bad_state_warned == 0) { + Log(WARNING, + "Invalid CFE groundwater reservoir state or parameters; " + "setting DEEP_GW_TO_CHANNEL_FLUX to 0. " + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.\n", + da_reservoir->storage_m, + da_reservoir->storage_max_m, + da_reservoir->coeff_primary, + da_reservoir->exponent_primary); + + gw_bad_state_warned = 1; + } + else if (gw_bad_state_warned == 1) { + Log(WARNING, + "Invalid CFE groundwater reservoir state or parameters occurred again; " + "further warnings suppressed.\n"); + + gw_bad_state_warned = 2; + } if (!isfinite(da_reservoir->storage_m) || da_reservoir->storage_m < 0.0) { From 89ddd84a833feccbc40987d1a273bac752741f17 Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Mon, 11 May 2026 16:03:09 -0700 Subject: [PATCH 03/10] handling POTENTIAL_ET = nan issue --- src/cfe.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/cfe.c b/src/cfe.c index 62eb014b..f4ae4124 100644 --- a/src/cfe.c +++ b/src/cfe.c @@ -73,6 +73,31 @@ extern void cfe( // partition rainfall using Schaake function //################################################## + static int potentialEtIssueWarned = 0; + + if (!isfinite(evap_struct->potential_et_m_per_s) || + evap_struct->potential_et_m_per_s < 0.0) { + + if (potentialEtIssueWarned == 0) { + Log(WARNING, + "Invalid CFE potential ET input; setting POTENTIAL_ET to 0. " + "water_potential_evaporation_flux=%lf, time_step_size=%lf. " + "This is likely an upstream forcing/BMI provider issue.\n", + evap_struct->potential_et_m_per_s, + time_step_size); + + potentialEtIssueWarned = 1; + } + else if (potentialEtIssueWarned == 1) { + Log(WARNING, + "Invalid CFE potential ET input occurred again; " + "further warnings suppressed.\n"); + + potentialEtIssueWarned = 2; + } + + evap_struct->potential_et_m_per_s = 0.0; + } evap_struct->potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; evap_struct->reduced_potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; From dae7f6fcf4df765865938607caaeee55a6d0f74a Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Tue, 12 May 2026 15:46:09 -0700 Subject: [PATCH 04/10] update based on feedback from Ian. removed default setting of values when they are nan --- src/bmi_cfe.c | 28 ++++++++-------- src/cfe.c | 10 +++--- src/conceptual_reservoir.c | 65 +++++++++++++++++++++----------------- 3 files changed, 55 insertions(+), 48 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index b37c128b..4cb2829f 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -983,6 +983,7 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) // compute gw storage in meters static int gw_bad_param_warned = 0; + // compute gw storage in meters if ((is_gw_storage_set == TRUE) && (is_gw_max_set == TRUE)) { if (!isfinite(model->gw_reservoir.gw_storage) || !isfinite(model->gw_reservoir.storage_max_m) || @@ -991,12 +992,14 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) model->gw_reservoir.gw_storage < 0.0 || model->gw_reservoir.storage_max_m <= 0.0) { + static int gw_bad_param_warned = 0; + if (gw_bad_param_warned == 0) { - Log(WARNING, - "Invalid CFE groundwater reservoir parameters from config; " - "disabling groundwater reservoir and setting DEEP_GW_TO_CHANNEL_FLUX to 0. " + Log(SEVERE, + "Invalid CFE groundwater reservoir parameters from config. " "gw_storage=%lf, max_gw_storage=%lf, Cgw=%lf, expon=%lf. " - "This is likely an upstream NHF parameter-generation issue.\n", + "CFE cannot initialize groundwater reservoir with non-finite or physically invalid required values. " + "Please check upstream parameter generation.\n", model->gw_reservoir.gw_storage, model->gw_reservoir.storage_max_m, model->gw_reservoir.coeff_primary, @@ -1005,24 +1008,19 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) gw_bad_param_warned = 1; } else if (gw_bad_param_warned == 1) { - Log(WARNING, + Log(SEVERE, "Invalid CFE groundwater reservoir parameters occurred again; " "further warnings suppressed.\n"); gw_bad_param_warned = 2; } - model->gw_reservoir.gw_storage = 0.0; - model->gw_reservoir.storage_max_m = 0.0; - model->gw_reservoir.storage_m = 0.0; - model->gw_reservoir.coeff_primary = 0.0; - model->gw_reservoir.exponent_primary = 1.0; - } - else { - model->gw_reservoir.storage_m = - model->gw_reservoir.gw_storage * - model->gw_reservoir.storage_max_m; + return BMI_FAILURE; } + + model->gw_reservoir.storage_m = + model->gw_reservoir.gw_storage * + model->gw_reservoir.storage_max_m; } if (is_num_timesteps_set == FALSE && strcmp(model->forcing_file, "BMI")) { diff --git a/src/cfe.c b/src/cfe.c index f4ae4124..980383bd 100644 --- a/src/cfe.c +++ b/src/cfe.c @@ -73,16 +73,17 @@ extern void cfe( // partition rainfall using Schaake function //################################################## - static int potentialEtIssueWarned = 0; + static int potentialEtIssueWarned = 0; - if (!isfinite(evap_struct->potential_et_m_per_s) || + if (!isfinite(evap_struct->potential_et_m_per_s) || evap_struct->potential_et_m_per_s < 0.0) { if (potentialEtIssueWarned == 0) { Log(WARNING, - "Invalid CFE potential ET input; setting POTENTIAL_ET to 0. " + "Invalid CFE potential ET input received; using zero PET for this timestep " + "to prevent NaN propagation. " "water_potential_evaporation_flux=%lf, time_step_size=%lf. " - "This is likely an upstream forcing/BMI provider issue.\n", + "This indicates an upstream forcing/BMI provider issue that should be corrected.\n", evap_struct->potential_et_m_per_s, time_step_size); @@ -98,6 +99,7 @@ extern void cfe( evap_struct->potential_et_m_per_s = 0.0; } + evap_struct->potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; evap_struct->reduced_potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; diff --git a/src/conceptual_reservoir.c b/src/conceptual_reservoir.c index 7a61fd39..2f325dbb 100644 --- a/src/conceptual_reservoir.c +++ b/src/conceptual_reservoir.c @@ -1,7 +1,6 @@ #ifndef _CONCEPTUAL_RESERVOIR_C #define _CONCEPTUAL_RESERVOIR_C -#include #include "logger.h" #include "conceptual_reservoir.h" @@ -56,28 +55,23 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser da_reservoir->storage_max_m <= 0.0) { if (gw_bad_state_warned == 0) { - Log(WARNING, - "Invalid CFE groundwater reservoir state or parameters; " - "setting DEEP_GW_TO_CHANNEL_FLUX to 0. " - "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.\n", - da_reservoir->storage_m, - da_reservoir->storage_max_m, - da_reservoir->coeff_primary, - da_reservoir->exponent_primary); - - gw_bad_state_warned = 1; + Log(WARNING, + "Invalid CFE groundwater reservoir state or parameters during flux calculation; " + "returning zero groundwater flux for this timestep. " + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.\n", + da_reservoir->storage_m, + da_reservoir->storage_max_m, + da_reservoir->coeff_primary, + da_reservoir->exponent_primary); + + gw_bad_state_warned = 1; } else if (gw_bad_state_warned == 1) { - Log(WARNING, - "Invalid CFE groundwater reservoir state or parameters occurred again; " - "further warnings suppressed.\n"); + Log(WARNING, + "Invalid CFE groundwater reservoir state or parameters occurred again; " + "further warnings suppressed.\n"); - gw_bad_state_warned = 2; - } - - if (!isfinite(da_reservoir->storage_m) || - da_reservoir->storage_m < 0.0) { - da_reservoir->storage_m = 0.0; + gw_bad_state_warned = 2; } return; @@ -88,15 +82,28 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser double calculated_flux_m = da_reservoir->coeff_primary * (exp_term - 1.0); if (!isfinite(calculated_flux_m) || calculated_flux_m < 0.0) { - Log(WARNING, - "Invalid CFE groundwater flux calculation; " - "setting DEEP_GW_TO_CHANNEL_FLUX to 0. " - "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf, raw_flux=%lf.\n", - da_reservoir->storage_m, - da_reservoir->storage_max_m, - da_reservoir->coeff_primary, - da_reservoir->exponent_primary, - calculated_flux_m); + static int gw_bad_flux_warned = 0; + + if (gw_bad_flux_warned == 0) { + Log(WARNING, + "Invalid CFE groundwater flux calculation; " + "returning zero groundwater flux for this timestep. " + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf, raw_flux=%lf.\n", + da_reservoir->storage_m, + da_reservoir->storage_max_m, + da_reservoir->coeff_primary, + da_reservoir->exponent_primary, + calculated_flux_m); + + gw_bad_flux_warned = 1; + } + else if (gw_bad_flux_warned == 1) { + Log(WARNING, + "Invalid CFE groundwater flux calculation occurred again; " + "further warnings suppressed.\n"); + + gw_bad_flux_warned = 2; + } return; } From 9bbfa07f1787bc86e65f5d10c733a4e7c3a830be Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Wed, 13 May 2026 07:07:52 -0700 Subject: [PATCH 05/10] update based on feedback from Ian. removed default setting of values when they are nan --- src/bmi_cfe.c | 29 +++++++++++++++-------------- src/cfe.c | 28 ---------------------------- 2 files changed, 15 insertions(+), 42 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index 4cb2829f..7a80ce31 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -2315,28 +2315,29 @@ static int Set_value (Bmi *self, const char *name, void *src) if (self->get_var_nbytes(self, name, &nbytes) == BMI_FAILURE) return BMI_FAILURE; - memcpy (dest, src, nbytes); + if (strcmp(name, "water_potential_evaporation_flux") == 0) { + double potential_et_m_per_s = *((double*)src); - if (strcmp (name, "maxsmc") == 0 || strcmp (name, "alpha_fc") == 0 || strcmp (name, "wltsmc") == 0 || strcmp (name, "maxsmc") == 0 || strcmp (name, "b") == 0 || strcmp (name, "slope") == 0 || strcmp (name, "satpsi") == 0 || strcmp (name, "Klf") == 0 || strcmp (name, "satdk") == 0){ + if (!isfinite(potential_et_m_per_s) || + potential_et_m_per_s < 0.0) { + Log(FATAL, + "Invalid water_potential_evaporation_flux passed to CFE Set_value: %lf. " + "PET forcing must be finite and non-negative. Aborting...\n", + potential_et_m_per_s); - cfe_state_struct* cfe_ptr = (cfe_state_struct *) self->data; - init_soil_reservoir(cfe_ptr); + return BMI_FAILURE; + } } - if (strcmp (name, "refkdt") == 0 || strcmp (name, "satdk") == 0){ - cfe_state_struct* cfe_ptr = (cfe_state_struct *) self->data; - cfe_ptr->infiltration_excess_params_struct.Schaake_adjusted_magic_constant_by_soil_type = cfe_ptr->NWM_soil_params.refkdt * cfe_ptr->NWM_soil_params.satdk / 0.000002; + memcpy (dest, src, nbytes); + + if (strcmp (name, "maxsmc") == 0 || strcmp (name, "alpha_fc") == 0 || strcmp (name, "wltsmc") == 0 || strcmp (name, "maxsmc") == 0 || strcmp (name, "b") == 0 || strcmp (name, "slope") == 0 || strcmp (name, "satpsi") == 0 || strcmp (name, "Klf") == 0 || strcmp (name, "satdk") == 0){ + init_soil_reservoir((cfe_state_struct*) self->data); } - if (strcmp (name, "storage_max_m") == 0) { - cfe_state_struct* cfe_ptr = (cfe_state_struct *) self->data; - cfe_ptr->gw_reservoir.storage_m = cfe_ptr->gw_reservoir.gw_storage * cfe_ptr->gw_reservoir.storage_max_m; - } - - return BMI_SUCCESS; + return Set_value_at_indices(self, name, inds, 1, src); } - static int Get_component_name (Bmi *self, char * name) { strncpy (name, "The CFE Model", BMI_MAX_COMPONENT_NAME); diff --git a/src/cfe.c b/src/cfe.c index 980383bd..cfc8c98a 100644 --- a/src/cfe.c +++ b/src/cfe.c @@ -72,34 +72,6 @@ extern void cfe( //################################################## // partition rainfall using Schaake function //################################################## - - static int potentialEtIssueWarned = 0; - - if (!isfinite(evap_struct->potential_et_m_per_s) || - evap_struct->potential_et_m_per_s < 0.0) { - - if (potentialEtIssueWarned == 0) { - Log(WARNING, - "Invalid CFE potential ET input received; using zero PET for this timestep " - "to prevent NaN propagation. " - "water_potential_evaporation_flux=%lf, time_step_size=%lf. " - "This indicates an upstream forcing/BMI provider issue that should be corrected.\n", - evap_struct->potential_et_m_per_s, - time_step_size); - - potentialEtIssueWarned = 1; - } - else if (potentialEtIssueWarned == 1) { - Log(WARNING, - "Invalid CFE potential ET input occurred again; " - "further warnings suppressed.\n"); - - potentialEtIssueWarned = 2; - } - - evap_struct->potential_et_m_per_s = 0.0; - } - evap_struct->potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; evap_struct->reduced_potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; From f29b5aaec2e7cbf99cfe7aef6a90a7abd7a25b13 Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Wed, 13 May 2026 09:51:36 -0700 Subject: [PATCH 06/10] log message rewording --- src/bmi_cfe.c | 4 ++-- src/conceptual_reservoir.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index 7a80ce31..9b18244b 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -999,7 +999,7 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) "Invalid CFE groundwater reservoir parameters from config. " "gw_storage=%lf, max_gw_storage=%lf, Cgw=%lf, expon=%lf. " "CFE cannot initialize groundwater reservoir with non-finite or physically invalid required values. " - "Please check upstream parameter generation.\n", + "Please check upstream parameter generation.", model->gw_reservoir.gw_storage, model->gw_reservoir.storage_max_m, model->gw_reservoir.coeff_primary, @@ -1010,7 +1010,7 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) else if (gw_bad_param_warned == 1) { Log(SEVERE, "Invalid CFE groundwater reservoir parameters occurred again; " - "further warnings suppressed.\n"); + "subsequent occurrences of this message will be suppressed."); gw_bad_param_warned = 2; } diff --git a/src/conceptual_reservoir.c b/src/conceptual_reservoir.c index 2f325dbb..f0b14f23 100644 --- a/src/conceptual_reservoir.c +++ b/src/conceptual_reservoir.c @@ -58,7 +58,7 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser Log(WARNING, "Invalid CFE groundwater reservoir state or parameters during flux calculation; " "returning zero groundwater flux for this timestep. " - "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.\n", + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf.", da_reservoir->storage_m, da_reservoir->storage_max_m, da_reservoir->coeff_primary, @@ -69,7 +69,7 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser else if (gw_bad_state_warned == 1) { Log(WARNING, "Invalid CFE groundwater reservoir state or parameters occurred again; " - "further warnings suppressed.\n"); + "subsequent occurrences of this message will be suppressed."); gw_bad_state_warned = 2; } @@ -88,7 +88,7 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser Log(WARNING, "Invalid CFE groundwater flux calculation; " "returning zero groundwater flux for this timestep. " - "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf, raw_flux=%lf.\n", + "storage_m=%lf, storage_max_m=%lf, Cgw=%lf, expon=%lf, raw_flux=%lf.", da_reservoir->storage_m, da_reservoir->storage_max_m, da_reservoir->coeff_primary, @@ -100,7 +100,7 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser else if (gw_bad_flux_warned == 1) { Log(WARNING, "Invalid CFE groundwater flux calculation occurred again; " - "further warnings suppressed.\n"); + "subsequent occurrences of this message will be suppressed."); gw_bad_flux_warned = 2; } From 716c6d7b7ace9aa1e27b9c804ae1867c3b57561f Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Mon, 18 May 2026 11:13:34 -0700 Subject: [PATCH 07/10] added additional checking at Set_value_at_indices --- src/bmi_cfe.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index 9b18244b..dd362988 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -2269,11 +2269,27 @@ static int Set_value_at_indices (Bmi *self, const char *name, int * inds, int le if (self->get_var_itemsize(self, name, &itemsize) == BMI_FAILURE) return BMI_FAILURE; + if (strcmp(name, "water_potential_evaporation_flux") == 0) { + for (size_t i=0; i Date: Mon, 18 May 2026 19:20:43 -0700 Subject: [PATCH 08/10] removed any value update --- src/bmi_cfe.c | 49 ++++++-------------------------------- src/cfe.c | 23 ++++++++++++++++++ src/conceptual_reservoir.c | 3 --- 3 files changed, 30 insertions(+), 45 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index dd362988..8c844d6a 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -976,13 +976,12 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) return BMI_FAILURE; } if (is_gw_storage_set == FALSE) { - Log(SEVERE, "Config param 'gw_storage' not found in config file. Aborting...n"); + Log(SEVERE, "Config param 'gw_storage' not found in config file. Aborting...\n"); return BMI_FAILURE; } // compute gw storage in meters - static int gw_bad_param_warned = 0; - + // compute gw storage in meters // compute gw storage in meters if ((is_gw_storage_set == TRUE) && (is_gw_max_set == TRUE)) { if (!isfinite(model->gw_reservoir.gw_storage) || @@ -995,11 +994,10 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) static int gw_bad_param_warned = 0; if (gw_bad_param_warned == 0) { - Log(SEVERE, + Log(WARNING, "Invalid CFE groundwater reservoir parameters from config. " "gw_storage=%lf, max_gw_storage=%lf, Cgw=%lf, expon=%lf. " - "CFE cannot initialize groundwater reservoir with non-finite or physically invalid required values. " - "Please check upstream parameter generation.", + "This indicates an upstream parameter-generation issue that should be corrected.\n", model->gw_reservoir.gw_storage, model->gw_reservoir.storage_max_m, model->gw_reservoir.coeff_primary, @@ -1008,14 +1006,12 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) gw_bad_param_warned = 1; } else if (gw_bad_param_warned == 1) { - Log(SEVERE, + Log(WARNING, "Invalid CFE groundwater reservoir parameters occurred again; " - "subsequent occurrences of this message will be suppressed."); + "further warnings suppressed.\n"); gw_bad_param_warned = 2; } - - return BMI_FAILURE; } model->gw_reservoir.storage_m = @@ -2269,27 +2265,11 @@ static int Set_value_at_indices (Bmi *self, const char *name, int * inds, int le if (self->get_var_itemsize(self, name, &itemsize) == BMI_FAILURE) return BMI_FAILURE; - if (strcmp(name, "water_potential_evaporation_flux") == 0) { - for (size_t i=0; iget_var_nbytes(self, name, &nbytes) == BMI_FAILURE) return BMI_FAILURE; - if (strcmp(name, "water_potential_evaporation_flux") == 0) { - double potential_et_m_per_s = *((double*)src); - - if (!isfinite(potential_et_m_per_s) || - potential_et_m_per_s < 0.0) { - Log(FATAL, - "Invalid water_potential_evaporation_flux passed to CFE Set_value: %lf. " - "PET forcing must be finite and non-negative. Aborting...\n", - potential_et_m_per_s); - - return BMI_FAILURE; - } - } - memcpy (dest, src, nbytes); if (strcmp (name, "maxsmc") == 0 || strcmp (name, "alpha_fc") == 0 || strcmp (name, "wltsmc") == 0 || strcmp (name, "maxsmc") == 0 || strcmp (name, "b") == 0 || strcmp (name, "slope") == 0 || strcmp (name, "satpsi") == 0 || strcmp (name, "Klf") == 0 || strcmp (name, "satdk") == 0){ diff --git a/src/cfe.c b/src/cfe.c index cfc8c98a..3baa99bf 100644 --- a/src/cfe.c +++ b/src/cfe.c @@ -72,6 +72,29 @@ extern void cfe( //################################################## // partition rainfall using Schaake function //################################################## + static int potentialEtIssueWarned = 0; + + if (!isfinite(evap_struct->potential_et_m_per_s) || + evap_struct->potential_et_m_per_s < 0.0) { + + if (potentialEtIssueWarned == 0) { + Log(WARNING, + "Invalid CFE potential ET input detected. " + "water_potential_evaporation_flux=%lf, time_step_size=%lf. " + "This indicates an upstream forcing/BMI provider issue.\n", + evap_struct->potential_et_m_per_s, + time_step_size); + + potentialEtIssueWarned = 1; + } + else if (potentialEtIssueWarned == 1) { + Log(WARNING, + "Invalid CFE potential ET input occurred again; " + "further warnings suppressed.\n"); + + potentialEtIssueWarned = 2; + } + } evap_struct->potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; evap_struct->reduced_potential_et_m_per_timestep = evap_struct->potential_et_m_per_s * time_step_size; diff --git a/src/conceptual_reservoir.c b/src/conceptual_reservoir.c index f0b14f23..9cfdede7 100644 --- a/src/conceptual_reservoir.c +++ b/src/conceptual_reservoir.c @@ -42,9 +42,6 @@ extern void conceptual_reservoir_flux_calc(struct conceptual_reservoir *da_reser // ------------------ Conceptual Ground Water Reservoir ------------------------- // single outlet reservoir like the NWM V1.2 exponential conceptual gw reservoir if (da_reservoir->is_exponential == TRUE) { - *primary_flux_m = 0.0; - *secondary_flux_m = 0.0; - static int gw_bad_state_warned = 0; if (!isfinite(da_reservoir->storage_m) || From f9a6ede6f3151cc7cfa5c09ec871f37c0f2fd9f9 Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Tue, 19 May 2026 09:12:22 -0700 Subject: [PATCH 09/10] updated message --- src/bmi_cfe.c | 2 +- src/cfe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index 8c844d6a..b23d44ad 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -1008,7 +1008,7 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) else if (gw_bad_param_warned == 1) { Log(WARNING, "Invalid CFE groundwater reservoir parameters occurred again; " - "further warnings suppressed.\n"); + "subsequent occurrences of this message will be suppressed.\n"); gw_bad_param_warned = 2; } diff --git a/src/cfe.c b/src/cfe.c index 3baa99bf..d90c9e51 100644 --- a/src/cfe.c +++ b/src/cfe.c @@ -90,7 +90,7 @@ extern void cfe( else if (potentialEtIssueWarned == 1) { Log(WARNING, "Invalid CFE potential ET input occurred again; " - "further warnings suppressed.\n"); + "subsequent occurrences of this message will be suppressed.\n"); potentialEtIssueWarned = 2; } From 33682a9a386f0d45ccdc0b869dd4f0ad6cc8306b Mon Sep 17 00:00:00 2001 From: Mohammed Karim Date: Tue, 19 May 2026 10:41:43 -0700 Subject: [PATCH 10/10] reversed some unnecessary chnages --- src/bmi_cfe.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/bmi_cfe.c b/src/bmi_cfe.c index b23d44ad..c0728139 100644 --- a/src/bmi_cfe.c +++ b/src/bmi_cfe.c @@ -980,8 +980,6 @@ int read_init_config_cfe(const char* config_file, cfe_state_struct* model) return BMI_FAILURE; } - // compute gw storage in meters - // compute gw storage in meters // compute gw storage in meters if ((is_gw_storage_set == TRUE) && (is_gw_max_set == TRUE)) { if (!isfinite(model->gw_reservoir.gw_storage) || @@ -2280,6 +2278,7 @@ static int Set_value_at_indices (Bmi *self, const char *name, int * inds, int le } + static int Set_value (Bmi *self, const char *name, void *src) { // serialization @@ -2313,10 +2312,22 @@ static int Set_value (Bmi *self, const char *name, void *src) memcpy (dest, src, nbytes); if (strcmp (name, "maxsmc") == 0 || strcmp (name, "alpha_fc") == 0 || strcmp (name, "wltsmc") == 0 || strcmp (name, "maxsmc") == 0 || strcmp (name, "b") == 0 || strcmp (name, "slope") == 0 || strcmp (name, "satpsi") == 0 || strcmp (name, "Klf") == 0 || strcmp (name, "satdk") == 0){ - init_soil_reservoir((cfe_state_struct*) self->data); + + cfe_state_struct* cfe_ptr = (cfe_state_struct *) self->data; + init_soil_reservoir(cfe_ptr); } + if (strcmp (name, "refkdt") == 0 || strcmp (name, "satdk") == 0){ + cfe_state_struct* cfe_ptr = (cfe_state_struct *) self->data; + cfe_ptr->infiltration_excess_params_struct.Schaake_adjusted_magic_constant_by_soil_type = cfe_ptr->NWM_soil_params.refkdt * cfe_ptr->NWM_soil_params.satdk / 0.000002; - return Set_value_at_indices(self, name, inds, 1, src); + } + + if (strcmp (name, "storage_max_m") == 0) { + cfe_state_struct* cfe_ptr = (cfe_state_struct *) self->data; + cfe_ptr->gw_reservoir.storage_m = cfe_ptr->gw_reservoir.gw_storage * cfe_ptr->gw_reservoir.storage_max_m; + } + + return BMI_SUCCESS; } static int Get_component_name (Bmi *self, char * name)