From bb9a34376316cbc2f66f662253b74cf94176f3c3 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Mon, 16 Mar 2020 23:21:22 -0400 Subject: [PATCH] Improved parameter parsing from config file --- io.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++------- phigrape.conf | 3 +- phigrape.cpp | 31 ++++++++++------ phigrape.h | 21 +++++++++++ 4 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 phigrape.h diff --git a/io.cpp b/io.cpp index b0a5641..29967ec 100644 --- a/io.cpp +++ b/io.cpp @@ -1,9 +1,12 @@ -#include +#include "phigrape.h" #include +#include +#include #include -#include #include +using Dictionary = std::unordered_map; + std::string strip(const std::string str) { std::string str_new = str; @@ -14,15 +17,11 @@ std::string strip(const std::string str) return str_new; } -int main() +Dictionary read_config_file(const std::string file_name) { std::unordered_map dictionary; - std::string file_name = "phigrape.conf"; std::ifstream file(file_name); - if (!file.good()) { - std::cout << "Not found!" << std::endl; - exit(1); - } + if (!file.good()) throw std::runtime_error("File not found."); std::string str; int line_number = 0; while (std::getline(file, str)) { @@ -32,19 +31,93 @@ int main() str = strip(str); if (str.size() == 0) continue; pos = str.find_first_of("="); - if (pos == std::string::npos) { - std::cerr << "Error: expected a key-value pair in line " << line_number << " of file " << file_name << std::endl; - exit(1); - } + if (pos == std::string::npos) throw std::runtime_error("Error: expected a key-value pair in line " + std::to_string(line_number) + " of file " + file_name); std::string key = strip(str.substr(0, pos)); pos = str.find_first_not_of(" \t", pos+1); std::string val = strip(str.substr(pos, str.size())); dictionary[key] = val; } + return dictionary; +} + +template T string_cast(const std::string str); + +template<> std::string string_cast(const std::string str) +{ + return str; +} + +template<> double string_cast(const std::string str) +{ + size_t idx; + auto value = std::stod(str, &idx); + if (idx == str.size()) return value; + else throw std::runtime_error("Cannot convert \"" + str + "\" into a double"); +} + +template<> int string_cast(const std::string str) +{ + size_t idx; + auto value = std::stoi(str, &idx); + if (idx == str.size()) return value; + else throw std::runtime_error("Cannot convert \"" + str + "\" into an int"); +} + +template<> bool string_cast(const std::string str) +{ + if ((str=="true") || (str=="True") || (str=="yes") || (str=="Yes") || (str=="1")) return true; + else if ((str=="false") || (str=="False") || (str=="no") || (str=="No") || (str=="0")) return false; + throw std::runtime_error("Cannot convert \"" + str + "\" into a bool"); +} + + +// For mandatory parameters +template +T get_parameter(Dictionary dictionary, std::string name) +{ + auto item = dictionary.find(name); + if (item==dictionary.end()) throw std::runtime_error("Mandatory parameter " + name + " must be defined"); + else return string_cast((*item).second); +} + +// For optional parameters +template +T get_parameter(Dictionary dictionary, std::string name, T default_value) +{ + auto item = dictionary.find(name); + if (item==dictionary.end()) return default_value; + else return string_cast((*item).second); +} + +int main() +{ + auto dictionary = read_config_file("phigrape.conf"); for (auto key_value : dictionary) { auto key = key_value.first; auto value = key_value.second; printf("dictionary[\"%s\"] = \"%s\"\n", key.c_str(), value.c_str()); } + + + Parameters parameters; + + // TODO check if dt_disk and dt_contr are powers of two + parameters.dt_bh = get_parameter(dictionary, "eps"); + parameters.t_end = get_parameter(dictionary, "t_end"); + parameters.dt_disk = get_parameter(dictionary, "dt_disk"); + parameters.dt_contr = get_parameter(dictionary, "dt_contr"); + parameters.dt_bh = get_parameter(dictionary, "dt_bh", parameters.dt_contr); + parameters.eta = get_parameter(dictionary, "eta"); + parameters.input_file_name = get_parameter(dictionary, "dt_bh", "data.con"); + parameters.dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); + parameters.live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); + parameters.live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); + parameters.live_smbh_output = get_parameter(dictionary, "live_smbh_output", false); + parameters.live_smbh_neighbor_output = get_parameter(dictionary, "live_smbh_neighbor_output", false); + parameters.live_smbh_neighbor_number = get_parameter(dictionary, "live_smbh_neighbor_number", 10); + parameters.binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); + parameters.binary_smbh_influence_sphere_output = get_parameter(dictionary, "binary_smbh_influence_sphere_output", false); + parameters.binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); + } diff --git a/phigrape.conf b/phigrape.conf index 34ef7ce..dd01e95 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -2,7 +2,6 @@ # GENERAL PARAMETERS # ###################### - # Plummer softening parameter (can be even 0) eps = 1E-4 @@ -27,7 +26,7 @@ inp_data = data.con ##### NOT IMPLEMENTED ####################### output_format = HDF5 -dt_min_warning = true +dt_min_warning = false ############################################# ################################### diff --git a/phigrape.cpp b/phigrape.cpp index f3d8d1e..962d9b3 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -53,18 +53,27 @@ Coded by : Peter Berczik Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ +#include "phigrape.h" +Parameters parameters; -struct Parameters { - int live_smbh_count = 2; // ADD_BH1 or ADD_BH2 - double live_smbh_custom_eps = 0; // ADD_N_BH - bool live_smbh_output = true; // BH_OUT - bool live_smbh_neighbor_output = true; // BH_OUT_NB // NOTE needs `live_smbh_neighbor_number` - bool binary_smbh_influence_sphere_output = true; // BBH_INF // NOTE needs `binary_smbh_influence_radius_factor` - double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF - int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not - bool binary_smbh_pn = true; // ADD_PN_BH - bool dt_min_warning = true; // DT_MIN_WARNING -} parameters; +// struct Parameters { +// double eps = 1E-4; +// double t_end = 1; +// double dt_disk = 0.125; +// double dt_contr = 0.125; +// double dt_bh = 0.125; +// double eta = 0.01; +// std::string input_file_name = "data.con"; +// bool dt_min_warning = true; // DT_MIN_WARNING +// int live_smbh_count = 2; // ADD_BH1 or ADD_BH2 +// double live_smbh_custom_eps = 0; // ADD_N_BH +// bool live_smbh_output = true; // BH_OUT +// bool live_smbh_neighbor_output = true; // BH_OUT_NB // NOTE needs `live_smbh_neighbor_number` +// int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not +// bool binary_smbh_pn = true; // ADD_PN_BH +// bool binary_smbh_influence_sphere_output = true; // BBH_INF // NOTE needs `binary_smbh_influence_radius_factor` +// double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF +// } parameters; //#define NORM // Physical normalization diff --git a/phigrape.h b/phigrape.h new file mode 100644 index 0000000..2c68183 --- /dev/null +++ b/phigrape.h @@ -0,0 +1,21 @@ +#pragma once +#include + +struct Parameters { + double eps; + double t_end; + double dt_disk; + double dt_contr; + double dt_bh; + double eta; + std::string input_file_name; + bool dt_min_warning; + int live_smbh_count; + double live_smbh_custom_eps; + bool live_smbh_output; + bool live_smbh_neighbor_output; + int live_smbh_neighbor_number; + bool binary_smbh_pn; + bool binary_smbh_influence_sphere_output; + double binary_smbh_influence_radius_factor; +};