bool Jacobian_1to1::calculate(ModelRun &init_model_run, vector<string> numeric_par_names, vector<string> obs_names, ParamTransformSeq &par_transform, const ParameterGroupInfo &group_info, const ParameterInfo &ctl_par_info, RunManagerAbstract &run_manager, const PriorInformation &prior_info, set<string> &out_of_bound_par, bool phiredswh_flag, bool calc_init_obs) { int i_run; string *par_name; double par_value; Parameters model_parameters(par_transform.ctl2model_cp(init_model_run.get_ctl_pars())); Observations observations(init_model_run.get_obs_template()); base_numeric_parameters = par_transform.ctl2numeric_cp( init_model_run.get_ctl_pars()); run_manager.reinitialize(file_manager.build_filename("rnj")); const vector<string> &model_par_name_vec = run_manager.get_par_name_vec(); const vector<string> &obs_name_vec = run_manager.get_obs_name_vec(); size_t n_par = model_par_name_vec.size(); failed_parameter_names.clear(); // compute runs for to jacobain calculation as it is influenced by derivative type( forward or central) vector<JacobianRun> del_numeric_par_vec; if (calc_init_obs) { del_numeric_par_vec.push_back(JacobianRun("", 0)); run_manager.add_run(model_parameters); } Parameters new_derivative_pars; bool success; Parameters base_derivative_parameters = par_transform.numeric2derivative_cp(base_numeric_parameters); //Loop through derivative parameters and build the parameter sets necessary for computing the jacobian for (auto &i_name : numeric_par_names) { assert(base_derivative_parameters.find(i_name) != base_derivative_parameters.end()); vector<JacobianRun> tmp_del_numeric_par_vec; double derivative_par_value = base_derivative_parameters.get_rec(i_name); success = get_derivative_parameters(i_name, derivative_par_value, par_transform, group_info, ctl_par_info, tmp_del_numeric_par_vec, phiredswh_flag); if (success && !tmp_del_numeric_par_vec.empty()) { del_numeric_par_vec.insert(del_numeric_par_vec.end(), tmp_del_numeric_par_vec.begin(), tmp_del_numeric_par_vec.end()); // update changed model parameters in model_parameters for (const auto &par : tmp_del_numeric_par_vec) { Parameters org_pars; Parameters new_pars; org_pars.insert(make_pair(par.par_name, model_parameters.get_rec(par.par_name))); new_pars.insert(make_pair(par.par_name, par.numeric_value)); par_transform.derivative2model_ip(new_pars); for (auto &ipar : new_pars) { model_parameters[ipar.first] = ipar.second; } run_manager.add_run(model_parameters); for (const auto &ipar : org_pars) { model_parameters[ipar.first] = ipar.second; } } } else { failed_parameter_names.insert(i_name); } } ofstream &fout_restart = file_manager.get_ofstream("rst"); fout_restart << "jacobian_model_runs_begin_group_id " << run_manager.get_cur_groupid() << endl; // make model runs run_manager.run(); fout_restart << "jacobian_model_runs_end_group_id " << run_manager.get_cur_groupid() << endl; // calculate jacobian base_sim_obs_names = obs_names; if(matrix.rows() != base_sim_obs_names.size() || matrix.cols() !=numeric_par_names.size()) { matrix.resize(base_sim_obs_names.size(), numeric_par_names.size()); } // initialize prior information prior_info_sen.clear(); unordered_map<string, int> par2col_map = get_par2col_map(); unordered_map<string, int>::iterator found; unordered_map<string, int>::iterator not_found = par2col_map.end(); i_run = 0; // if initial run was performed, get the newly calculated values if (calc_init_obs) { Parameters tmp_pars; Observations tmp_obs; bool success = run_manager.get_run(i_run, tmp_pars, tmp_obs); if (!success) { throw(PestError("Error: Base parameter run failed. Can not compute the Jacobian")); } par_transform.model2ctl_ip(tmp_pars); init_model_run.update_ctl(tmp_pars, tmp_obs); ++i_run; } base_numeric_parameters = par_transform.ctl2numeric_cp(init_model_run.get_ctl_pars()); // process the parameter pertubation runs int nruns = del_numeric_par_vec.size(); list<pair<ModelRun, double> > run_list; base_numeric_par_names.clear(); ModelRun tmp_model_run = init_model_run; int icol = 0; vector<string>par_name_vec; for(; i_run<nruns; ++i_run) { par_name = &del_numeric_par_vec[i_run].par_name; Parameters tmp_pars; Observations tmp_obs; bool success = run_manager.get_run(i_run, tmp_pars, tmp_obs); if (success) { par_name_vec.clear(); par_name_vec.push_back(*par_name); par_transform.model2ctl_ip(tmp_pars); tmp_model_run.update_ctl(tmp_pars, tmp_obs); Parameters numeric_pars(tmp_pars, par_name_vec); par_transform.ctl2numeric_ip(numeric_pars); par_value = numeric_pars.get_rec(*par_name); run_list.push_back(make_pair(tmp_model_run, par_value)); } if(i_run+1>=nruns || *par_name != del_numeric_par_vec[i_run+1].par_name) { if (!run_list.empty()) { base_numeric_par_names.push_back(*par_name); double base_numeric_par_value = base_numeric_parameters.get_rec(*par_name); run_list.push_front(make_pair(init_model_run, base_numeric_par_value)); calc_derivative(*par_name, icol, run_list, par_transform, group_info, ctl_par_info, prior_info); icol++; } else { failed_parameter_names.insert(*par_name); } run_list.clear(); } } matrix.conservativeResize(base_sim_obs_names.size(), base_numeric_par_names.size()); // clean up fout_restart << "jacobian_saved" << endl; run_manager.free_memory(); return true; }