diff --git a/src/libs/pestpp_common/EnsembleMethodUtils.cpp b/src/libs/pestpp_common/EnsembleMethodUtils.cpp index 938aff7b..aac66d72 100644 --- a/src/libs/pestpp_common/EnsembleMethodUtils.cpp +++ b/src/libs/pestpp_common/EnsembleMethodUtils.cpp @@ -2492,7 +2492,18 @@ double L2PhiHandler::calc_std(map *phi_map) double L2PhiHandler::get_representative_phi(phiType pt) { - if (pest_scenario->get_pestpp_options().get_ies_n_iter_mean() < 0) { + //if (pest_scenario->get_pestpp_options().get_ies_n_iter_mean() < 0) + bool use_min = false; + for (auto& fac : pest_scenario->get_pestpp_options().get_ies_n_iter_mean()) + { + if (fac < 0) + { + use_min = true; + break; + } + } + if (use_min) + { return get_min(pt); } @@ -4286,7 +4297,7 @@ void EnsembleMethod::throw_em_error(string message) } -bool EnsembleMethod::should_terminate() +bool EnsembleMethod::should_terminate(int current_n_iter_mean) { //todo: use ies accept fac here? double phiredstp = pest_scenario.get_control_info().phiredstp; @@ -4306,10 +4317,10 @@ bool EnsembleMethod::should_terminate() message(1, "phiredstp: ", phiredstp); message(1, "nphistp: ", nphistp); message(1, "nphinored (also used for consecutive bad lambda cycles): ", nphinored); - int n_mean_iter = pest_scenario.get_pestpp_options().get_ies_n_iter_mean(); + //int n_mean_iter = pest_scenario.get_pestpp_options().get_ies_n_iter_mean(); vector::iterator begin_idx = best_mean_phis.begin(); - if ((n_mean_iter > 0) && (best_mean_phis.size() > n_mean_iter)) - begin_idx = best_mean_phis.end() - (n_mean_iter+1); //bc of prior phi and then adding the mean shift to the list + if ((current_n_iter_mean > 0) && (best_mean_phis.size() > current_n_iter_mean)) + begin_idx = best_mean_phis.end() - (current_n_iter_mean+1); //bc of prior phi and then adding the mean shift to the list if (best_mean_phis.size() > 0) { @@ -4330,7 +4341,7 @@ bool EnsembleMethod::should_terminate() for (auto& phi : best_mean_phis) { ratio = (phi - best_phi_yet) / phi; - if ((i>=(iter - n_mean_iter)) && (ratio <= phiredstp)) + if ((i>=(iter - current_n_iter_mean)) && (ratio <= phiredstp)) count++; i++; } @@ -4897,11 +4908,21 @@ void EnsembleMethod::initialize(int cycle, bool run, bool use_existing) consec_bad_lambda_cycles = 0; reinflate_to_minphi_real = false; - if (pest_scenario.get_pestpp_options().get_ies_n_iter_mean() < 0) + bool use_min = false; + for (auto& fac : pest_scenario.get_pestpp_options().get_ies_n_iter_mean()) + { + if (fac < 0) + { + use_min = true; + fac *= -1; + } + } + + if (use_min) { - message(2,"n_iter_mean < 0, using min-phi real for re-inflation, resetting n_iter_reinflate to positive"); + message(2,"n_iter_reinflate < 0, using min-phi real for re-inflation, resetting n_iter_reinflate to positive"); reinflate_to_minphi_real = true; - pest_scenario.get_pestpp_options_ptr()->set_ies_n_iter_mean(-1 * pest_scenario.get_pestpp_options().get_ies_n_iter_mean()); + //pest_scenario.get_pestpp_options_ptr()->set_ies_n_iter_mean(-1 * pest_scenario.get_pestpp_options().get_ies_n_iter_mean()); } lam_mults = pest_scenario.get_pestpp_options().get_ies_lam_mults(); if (lam_mults.size() == 0) diff --git a/src/libs/pestpp_common/EnsembleMethodUtils.h b/src/libs/pestpp_common/EnsembleMethodUtils.h index 64c47a8c..fcb1575f 100644 --- a/src/libs/pestpp_common/EnsembleMethodUtils.h +++ b/src/libs/pestpp_common/EnsembleMethodUtils.h @@ -358,7 +358,7 @@ class EnsembleMethod RunManagerAbstract* _run_mgr_ptr, string _alg_tag="EnsembleMethod"); virtual void throw_em_error(string message); - bool should_terminate(); + bool should_terminate(int current_n_iter_mean=0); void sanity_checks(); //template //void message(int level, const string& _message, vector _extras, bool echo = true); diff --git a/src/libs/pestpp_common/EnsembleSmoother.cpp b/src/libs/pestpp_common/EnsembleSmoother.cpp index c19ceb75..3fc04c0a 100644 --- a/src/libs/pestpp_common/EnsembleSmoother.cpp +++ b/src/libs/pestpp_common/EnsembleSmoother.cpp @@ -36,7 +36,11 @@ void IterEnsembleSmoother::iterate_2_solution() ofstream &frec = file_manager.rec_ofstream(); bool accept; - int n_iter_mean = pest_scenario.get_pestpp_options().get_ies_n_iter_mean(); + vector n_iter_mean = pest_scenario.get_pestpp_options().get_ies_n_iter_mean(); + + int iters_since_reinflate = 0; + int n_iter_mean_idx = 0; + int current_n_iter_mean = n_iter_mean[n_iter_mean_idx]; int solution_iter = 0; for (int i = 0; i < pest_scenario.get_control_info().noptmax; i++) { @@ -72,15 +76,23 @@ void IterEnsembleSmoother::iterate_2_solution() else consec_bad_lambda_cycles++; - if ((n_iter_mean> 0) && (solution_iter % n_iter_mean == 0)) + //if ((n_iter_mean > 0) && (solution_iter % n_iter_mean == 0)) + if ((current_n_iter_mean > 0) && (iters_since_reinflate >= current_n_iter_mean)) { iter++; reset_par_ensemble_to_prior_mean(); + iters_since_reinflate = 0; + if (n_iter_mean.size() > n_iter_mean_idx) + { + n_iter_mean_idx++; + current_n_iter_mean = n_iter_mean[n_iter_mean_idx]; + } } - if (should_terminate()) + if (should_terminate(current_n_iter_mean)) { - if (iter > pest_scenario.get_pestpp_options().get_ies_n_iter_mean()) { + //if (iter > pest_scenario.get_pestpp_options().get_ies_n_iter_mean()) { + if (iter > current_n_iter_mean) { break; } else{ diff --git a/src/libs/pestpp_common/pest_data_structs.cpp b/src/libs/pestpp_common/pest_data_structs.cpp index a148b576..56878d5e 100644 --- a/src/libs/pestpp_common/pest_data_structs.cpp +++ b/src/libs/pestpp_common/pest_data_structs.cpp @@ -1185,7 +1185,13 @@ bool PestppOptions::assign_ies_value_by_key(const string& key, const string& val { passed_args.insert("IES_N_ITER_MEAN"); passed_args.insert("IES_N_ITER_REINFLATE"); - convert_ip(value,ies_n_iter_mean); + ies_n_iter_mean.clear(); + vector tok; + tokenize(value, tok, ","); + for (const auto& fac : tok) + { + ies_n_iter_mean.push_back(convert_cp(fac)); + } return true; } else if (key == "IES_UPDATE_BY_REALS") @@ -1837,7 +1843,10 @@ void PestppOptions::summary(ostream& os) const os << "ies_localizer_forgive_extra: " << ies_localizer_forgive_missing << endl; os << "ies_phi_factors_file: " << ies_phi_fractions_file << endl; os << "ies_phi_factors_by_real: " << ies_phi_factors_by_real << endl; - os << "ies_n_iter_reinflate: " << ies_n_iter_mean << endl; + os << "ies_n_iter_reinflate: " << endl; + for (auto v : ies_n_iter_mean) + os << v << ","; + os << endl; os << "ies_updatebyreals: " << ies_updatebyreals << endl; @@ -2024,7 +2033,7 @@ void PestppOptions::set_defaults() set_ies_localizer_forgive_missing(false); set_ies_phi_fractions_files(""); set_ies_phi_factors_by_real(false); - set_ies_n_iter_mean(0); + set_ies_n_iter_mean(vector{0}); set_ies_updatebyreals(false); set_save_dense(false); diff --git a/src/libs/pestpp_common/pest_data_structs.h b/src/libs/pestpp_common/pest_data_structs.h index 2d6b7b3b..858086a9 100644 --- a/src/libs/pestpp_common/pest_data_structs.h +++ b/src/libs/pestpp_common/pest_data_structs.h @@ -550,8 +550,8 @@ class PestppOptions { void set_ies_multimodal_alpha(double _flag) { ies_multimodal_alpha = _flag; } void set_ensemble_output_precision(int prec) { ensemble_output_precision = prec;} int get_ensemble_output_precision() const {return ensemble_output_precision;} - void set_ies_n_iter_mean(int _n_iter_mean) {ies_n_iter_mean = _n_iter_mean;} - int get_ies_n_iter_mean() const {return ies_n_iter_mean;} + void set_ies_n_iter_mean(vector _n_iter_mean) {ies_n_iter_mean = _n_iter_mean;} + vector get_ies_n_iter_mean() const {return ies_n_iter_mean;} string get_gsa_method() const { return gsa_method; } @@ -828,7 +828,7 @@ class PestppOptions { bool ies_localizer_forgive_missing; string ies_phi_fractions_file; bool ies_phi_factors_by_real; - int ies_n_iter_mean; + vector ies_n_iter_mean; bool ies_updatebyreals;