Now config file handles most parameters (but not external potential)

This commit is contained in:
Yohai Meiron 2020-03-17 12:24:53 -04:00
parent bb9a343763
commit 9296db0609
6 changed files with 188 additions and 165 deletions

126
config.cpp Normal file
View file

@ -0,0 +1,126 @@
#include "config.h"
#include <stdexcept>
#include <cstdio>
#include <fstream>
using Dictionary = std::unordered_map<std::string,std::string>;
std::string Config::strip(const std::string str)
{
std::string str_new = str;
auto pos = str_new.find_first_not_of(" \t");
if (pos != std::string::npos) str_new = str_new.substr(pos, str_new.size());
pos = str_new.find_last_not_of(" \t");
if (pos != std::string::npos) str_new = str_new.substr(0, pos+1);
return str_new;
}
Dictionary Config::read_config_file(const std::string file_name)
{
std::unordered_map<std::string,std::string> dictionary;
std::ifstream file(file_name);
if (!file.good()) throw std::runtime_error("File not found.");
std::string str;
int line_number = 0;
while (std::getline(file, str)) {
line_number++;
auto pos = str.find('#');
if (pos != std::string::npos) str = str.substr(0, pos);
str = strip(str);
if (str.size() == 0) continue;
pos = str.find_first_of("=");
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<> std::string Config::string_cast(const std::string str)
{
return str;
}
template<> double Config::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 Config::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 Config::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<typename T>
T Config::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<T>((*item).second);
}
// For optional parameters
template<typename T>
T Config::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<T>((*item).second);
}
void Config::error_checking()
{
if ((live_smbh_count < 0) || (live_smbh_count > 2))
throw std::runtime_error("The number of live black holes (live_smbh_count) can be 0, 1, or 2");
if (binary_smbh_pn && (live_smbh_count!=2))
throw std::runtime_error("Post-Newtonian gravity (binary_smbh_pn=true) requires live_smbh_count=2");
if (live_smbh_custom_eps == eps) live_smbh_custom_eps = -1;
if (live_smbh_output && (live_smbh_count == 0))
throw std::runtime_error("Black hole output (live_smbh_output=true) requires at least one live black hole (live_smbh_count)");
if (live_smbh_neighbor_output && (live_smbh_count == 0))
throw std::runtime_error("Black hole neighbour output (live_smbh_neighbor_output=true) requires at least one live black hole (live_smbh_count)");
if (binary_smbh_influence_sphere_output && (live_smbh_count != 2))
throw std::runtime_error("Binary black hole influence sphere output (binary_smbh_influence_sphere_output=true) requires exactly two live black holes (live_smbh_count=2)");
}
Config::Config(std::string file_name)
{
auto dictionary = read_config_file(file_name);
// TODO check if dt_disk and dt_contr are powers of two
eps = get_parameter<double>(dictionary, "eps");
t_end = get_parameter<double>(dictionary, "t_end");
dt_disk = get_parameter<double>(dictionary, "dt_disk");
dt_contr = get_parameter<double>(dictionary, "dt_contr");
dt_bh = get_parameter<double>(dictionary, "dt_bh", dt_contr);
eta = get_parameter<double>(dictionary, "eta");
input_file_name = get_parameter<std::string>(dictionary, "input_file_name", "data.con");
dt_min_warning = get_parameter<bool>(dictionary, "dt_min_warning", false);
live_smbh_count = get_parameter<int>(dictionary, "live_smbh_count", 0);
live_smbh_custom_eps = get_parameter<double>(dictionary, "live_smbh_custom_eps", -1);
live_smbh_output = get_parameter<bool>(dictionary, "live_smbh_output", false);
live_smbh_neighbor_output = get_parameter<bool>(dictionary, "live_smbh_neighbor_output", false);
live_smbh_neighbor_number = get_parameter<int>(dictionary, "live_smbh_neighbor_number", 10);
binary_smbh_pn = get_parameter<bool>(dictionary, "binary_smbh_pn", false);
binary_smbh_influence_sphere_output = get_parameter<bool>(dictionary, "binary_smbh_influence_sphere_output", false);
binary_smbh_influence_radius_factor = get_parameter<double>(dictionary, "binary_smbh_influence_radius_factor", 10.);
error_checking();
}