Program Listing for File input.cpp¶
↰ Return to documentation for file (src/input/input.cpp)
#include "input.hpp"
#include <string>
#include "json.hpp"
#include "parameter.hpp"
// Simplify namespace
using json = nlohmann::ordered_json;
namespace lili::input {
std::string InputTypeToString(InputType input_type) {
switch (input_type) {
case InputType::None:
return "None";
case InputType::Initial:
return "Initial";
case InputType::Restart:
return "Restart";
case InputType::TestParticle:
return "TestParticle";
default:
return "None";
}
}
void InputParticles::Print() {
lili::lout << "Name : " << name << std::endl;
lili::lout << " n : " << n << std::endl;
lili::lout << " q : " << q << std::endl;
lili::lout << " m : " << m << std::endl;
lili::lout << " n_track : " << n_track << std::endl;
lili::lout << " dl_track : " << dl_track << std::endl;
lili::lout << " dtrack_save : " << dtrack_save << std::endl;
lili::lout << " Pos. dist. : ";
switch (pos_dist) {
case PPosDist::Stationary:
lili::lout << "Stationary" << std::endl;
break;
case PPosDist::Uniform:
lili::lout << "Uniform" << std::endl;
break;
default:
lili::lout << "Unknown" << std::endl;
break;
}
lili::lout << " param : ";
for (auto& p : pos_dist_param) {
lili::lout << p << " ";
}
lili::lout << std::endl;
lili::lout << " Vel. dist. : ";
switch (vel_dist) {
case PVelDist::Maxwellian:
lili::lout << "Maxwellian" << std::endl;
break;
default:
lili::lout << "Unknown" << std::endl;
break;
}
lili::lout << " param : ";
for (auto& p : vel_dist_param) {
lili::lout << p << " ";
}
lili::lout << std::endl;
lili::lout << " offset : ";
for (auto& p : vel_offset) {
lili::lout << p << " ";
}
lili::lout << std::endl;
}
Input::Input() {
input_file_ = "";
problem_name_ = "LILI";
input_type_ = InputType::None;
}
Input::Input(const char* in_file) {
input_file_ = in_file;
problem_name_ = "LILI";
input_type_ = InputType::None;
}
Input::Input(const Input& input) {
input_file_ = input.input_file_;
problem_name_ = input.problem_name_;
restart_file_ = input.restart_file_;
input_type_ = input.input_type_;
mesh_ = input.mesh_;
particles_ = input.particles_;
loop_ = input.loop_;
}
void swap(Input& first, Input& second) {
using std::swap;
swap(first.input_file_, second.input_file_);
swap(first.problem_name_, second.problem_name_);
swap(first.restart_file_, second.restart_file_);
swap(first.input_type_, second.input_type_);
swap(first.mesh_, second.mesh_);
swap(first.particles_, second.particles_);
swap(first.loop_, second.loop_);
}
void Input::Parse() {
// Open input file
std::ifstream ifs(input_file_.c_str());
if (!ifs.is_open()) {
std::cerr << "Cannot open input file: " << input_file_ << std::endl;
lili::output::LiliExit(2);
}
// Parse the JSON file ignoring comment
json j;
try {
j = json::parse(ifs,
/* callback */ nullptr,
/* allow exceptions */ true,
/* ignore comments */ true);
} catch (json::parse_error& e) {
std::cerr << "Parse error: " << e.what() << std::endl;
lili::output::LiliExit(2);
}
// Close input file
ifs.close();
// Check the type of input file
if (!j.contains("input_type")) {
std::cerr << "No input type in " << input_file_ << std::endl;
lili::output::LiliExit(2);
} else {
std::string input_type_str = j.at("input_type").get<std::string>();
if (strcmp(input_type_str.c_str(), "initial") == 0) {
input_type_ = InputType::Initial;
} else if (strcmp(input_type_str.c_str(), "restart") == 0) {
input_type_ = InputType::Restart;
} else if (strcmp(input_type_str.c_str(), "test_particle") == 0) {
input_type_ = InputType::TestParticle;
} else {
std::cerr << "Unrecognized input type in " << input_type_str << std::endl;
std::cerr << "Available input type: [initial | restart]" << std::endl;
lili::output::LiliExit(2);
}
}
// Parse problem name
if (!j.contains("problem_name")) {
std::cerr << "No problem name in " << input_file_ << std::endl;
std::cerr << "Using default problem name: LILI" << std::endl;
} else {
problem_name_ = j.at("problem_name").get<std::string>();
}
// Parse restart file
if (input_type_ == InputType::Restart ||
input_type_ == InputType::TestParticle) {
if (!j.contains("restart_file")) {
std::cerr << "No restart file in " << input_file_ << std::endl;
lili::output::LiliExit(2);
} else {
restart_file_ = j.at("restart_file").get<std::string>();
}
}
// Parse mesh
if (j.contains("mesh")) {
auto j_mesh = j.at("mesh");
// Parse mesh dimension
mesh_.dim = j_mesh.at("dimension").get<int>();
if (mesh_.dim < 1 || mesh_.dim > 3) {
std::cerr << "Invalid mesh dimension in " << input_file_ << std::endl;
lili::output::LiliExit(2);
}
// Parse mesh size
mesh_.nx = j_mesh.at("x").at("n").get<int>();
mesh_.lx = j_mesh.at("x").at("l").get<double>();
if (j_mesh.at("x").contains("ng")) {
mesh_.ngx = j_mesh.at("x").at("ng").get<int>();
} else {
mesh_.ngx = __LILIM_DEFAULT_NGHOST;
}
if (mesh_.dim > 1) {
mesh_.ny = j_mesh.at("y").at("n").get<int>();
mesh_.ly = j_mesh.at("y").at("l").get<double>();
if (j_mesh.at("y").contains("ng")) {
mesh_.ngy = j_mesh.at("y").at("ng").get<int>();
} else {
mesh_.ngy = __LILIM_DEFAULT_NGHOST;
}
} else {
mesh_.ny = 1;
mesh_.ly = 1.0;
mesh_.ngy = 0;
}
if (mesh_.dim > 2) {
mesh_.nz = j_mesh.at("z").at("n").get<int>();
mesh_.lz = j_mesh.at("z").at("l").get<double>();
if (j_mesh.at("z").contains("ng")) {
mesh_.ngz = j_mesh.at("z").at("ng").get<int>();
} else {
mesh_.ngz = __LILIM_DEFAULT_NGHOST;
}
} else {
mesh_.nz = 1;
mesh_.lz = 1.0;
mesh_.ngz = 0;
}
// Calculate the starting point of the mesh
mesh_.x0 = 0.;
mesh_.y0 = 0.;
mesh_.z0 = 0.;
}
// Parse particles
if (j.contains("particles")) {
// Iterate over all species
for (auto& [key, val] : j.at("particles").items()) {
InputParticles species;
species.name = key;
// Parse particle variables
species.n = val.at("n").get<int>();
species.q = val.at("q").get<double>();
species.m = val.at("m").get<double>();
// Parse tracking variables
if (val.contains("track")) {
auto& vtrack = val.at("track");
species.n_track = vtrack.value("n_track", 0);
species.dl_track = vtrack.value("dl_track", 1);
species.dtrack_save = vtrack.value("dtrack_save", 1);
} else {
species.n_track = 0;
species.dl_track = 1;
species.dtrack_save = 1;
}
// Parse particle position distribution
if (val.contains("position_distribution")) {
auto& pdist = val.at("position_distribution");
std::string pdist_str = pdist.value("type", "stationary");
if (strcmp(pdist_str.c_str(), "stationary") == 0) {
species.pos_dist = PPosDist::Stationary;
} else if (strcmp(pdist_str.c_str(), "uniform") == 0) {
species.pos_dist = PPosDist::Uniform;
// Set position distribution parameters
if (pdist.contains("param")) {
// Read the value as a vector
species.pos_dist_param =
pdist.at("param").get<std::vector<double>>();
} else {
// Set default param to the mesh positions
species.pos_dist_param.push_back(0.);
species.pos_dist_param.push_back(mesh_.lx);
species.pos_dist_param.push_back(0.);
species.pos_dist_param.push_back(mesh_.ly);
species.pos_dist_param.push_back(0.);
species.pos_dist_param.push_back(mesh_.lz);
}
} else {
std::cerr << "Unrecognized position distribution: " << pdist_str
<< std::endl;
std::cerr << "Available position distribution: [stationary | uniform]"
<< std::endl;
lili::output::LiliExit(2);
}
}
// Parse particle velocity distribution
if (val.contains("velocity_distribution")) {
auto& vdist = val.at("velocity_distribution");
std::string vdist_str = vdist.value("type", "uniform");
if (strcmp(vdist_str.c_str(), "maxwellian") == 0) {
species.vel_dist = PVelDist::Maxwellian;
} else {
std::cerr << "Unrecognized velocity distribution: " << vdist_str
<< std::endl;
std::cerr << "Available velocity distribution: [ maxwellian ]"
<< std::endl;
lili::output::LiliExit(2);
}
// Set velocity distribution parameters
if (vdist.contains("param")) {
// Read the value as a vector
species.vel_dist_param = vdist.at("param").get<std::vector<double>>();
} else {
std::cerr << "No velocity distribution parameters for " << key
<< std::endl;
lili::output::LiliExit(2);
}
// Set velocity offset
if (vdist.contains("offset")) {
// Read the value as a vector
species.vel_offset = vdist.at("offset").get<std::vector<double>>();
}
}
// Add species to the list
particles_.push_back(species);
}
}
// Parse loop variables
if (j.contains("loop")) {
// Parse time step
loop_.dt = j.at("loop").value("dt", 1.0);
// Parse number of time steps
loop_.n_loop = j.at("loop").value("n_loop", 1);
// Parse the task list
if (j.at("loop").contains("tasks")) {
auto& j_tasks = j.at("loop").at("tasks");
// Iterate over all tasks and print them
for (auto& [key, val] : j_tasks.items()) {
InputLoopTask task;
task.name = key;
task.type = val.value("type", "none");
// Add task to the list
loop_.tasks.push_back(task);
}
}
}
}
Input ParseArguments(int argc, char** argv, lili::output::LiliCout& lout) {
// Variable declaration
int i_arg = 0;
bool has_input = false;
Input input;
// Parse command line arguments
for (i_arg = 1; i_arg < argc; ++i_arg) {
if (argv[i_arg][0] == '-') {
switch (argv[i_arg][1]) {
case '-':
// Long option
if (strcmp(argv[i_arg], "--help") == 0) {
// Print help
lili::output::PrintHelp(lout);
lili::output::LiliExit(0);
} else if (strcmp(argv[i_arg], "--version") == 0) {
// Print version
lili::output::PrintVersion(lout);
lili::output::LiliExit(0);
} else if (strcmp(argv[i_arg], "--input") == 0) {
if (has_input) {
// Throw error for multiple input file
std::cerr << "There are multiple input file" << std::endl;
lili::output::LiliExit(1);
}
// Parse input file
input.input_file() = argv[++i_arg];
input.Parse();
has_input = true;
} else if (strcmp(argv[i_arg], "--") == 0) {
// End of options
++i_arg;
} else {
// Throw error for unrecognized option
std::cerr << "Unrecognized option: " << argv[i_arg] << std::endl;
lili::output::LiliExit(1);
}
break;
case 'i':
if (has_input) {
// Throw error for multiple input file
std::cerr << "There are multiple input file" << std::endl;
lili::output::LiliExit(1);
}
// Parse input file
input.input_file() = argv[++i_arg];
input.Parse();
has_input = true;
break;
case 'h':
// Print help
lili::output::PrintHelp(lout);
lili::output::LiliExit(0);
break;
case 'v':
// Print version
lili::output::PrintVersion(lout);
lili::output::LiliExit(0);
break;
default:
// Throw error for unrecognized option
std::cerr << "Unrecognized option: " << argv[i_arg] << std::endl;
lili::output::LiliExit(1);
}
} else if (!has_input) {
// Parse input file
input.input_file() = argv[i_arg];
input.Parse();
has_input = true;
} else {
// Throw error for multiple input file
std::cerr << "There are multiple input file" << std::endl;
lili::output::LiliExit(1);
}
}
// Check if there is input file
if (!has_input) {
// Throw error for no input file
std::cerr << "No input file" << std::endl;
// Print help
lili::output::PrintHelp();
lili::output::LiliExit(1);
}
return input;
}
} // namespace lili::input