Program Listing for File input.hpp
↰ Return to documentation for file (input.hpp
)
// ***********************************************************************************
// Idefix MHD astrophysical code
// Copyright(C) 2020-2022 Geoffroy R. J. Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
// and other code contributors
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************
#ifndef INPUT_HPP_
#define INPUT_HPP_
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include "idefix.hpp"
using IdefixParamContainer = std::vector<std::string>;
using IdefixBlockContainer = std::map<std::string,IdefixParamContainer>;
using IdefixInputContainer = std::map<std::string,IdefixBlockContainer>;
class Input {
public:
// Constructor from a file
Input (int, char ** );
void ShowConfig();
// Accessor to input parameters
// the parameters are always: BlockName, EntryName, ParameterNumber (starting from 0)
// These specialised functions are deprecated. Use the template Get<T> function.
std::string GetString(std::string, std::string, int);
real GetReal(std::string, std::string, int);
int GetInt(std::string, std::string, int);
int CheckEntry(std::string, std::string);
template<typename T>
T Get(std::string, std::string, int);
template<typename T>
T GetOrSet(std::string, std::string, int, T);
bool CheckBlock(std::string);
bool CheckForAbort(); // have we been asked for an abort?
void CheckForStopFile(); // have we been asked for an abort from
// a stop file?
Input();
void PrintLogo();
bool restartRequested{false}; //< Should we restart?
int restartFileNumber; //< if yes, from which file?
static bool abortRequested; //< Did we receive an abort signal (USR2) from the system?
int maxCycles{-1}; //< whether we should perform a maximum number of cycles
bool forceNoWrite{false}; //< explicitely disable all writes to disk
private:
std::string inputFileName;
IdefixInputContainer inputParameters;
void ParseCommandLine(int , char **argv);
static void signalHandler(int);
std::vector<std::string> getDirectoryFiles();
std::string getFileExtension(const std::string file_name);
Kokkos::Timer timer;
double lastStopFileCheck;
};
// Template functions
template<typename T>
T Input::Get(std::string blockName, std::string paramName, int num) {
if(CheckEntry(blockName, paramName) <= num) {
std::stringstream msg;
msg << "Mandatory parameter [" << blockName << "]:" << paramName << "(" << num
<< "). Cannot be found in the input file" << std::endl;
IDEFIX_ERROR(msg);
}
// Fetch it
std::string paramString = inputParameters[blockName][paramName][num];
T value;
try {
if constexpr(std::is_same<T, int>::value) {
double dv = std::stod(paramString, NULL);
value = static_cast<int>(std::round(dv));
if (std::abs((dv - value)/dv) > 1e-14) {
IDEFIX_WARNING("Detected a truncation error while reading an integer");
}
} else if constexpr(std::is_same<T, double>::value) {
value = std::stod(paramString, NULL);
} else if constexpr(std::is_same<T, float>::value) {
value = std::stof(paramString, NULL);
} else if constexpr(std::is_same<T, int64_t>::value) {
value = static_cast<int64_t>(std::round(std::stod(paramString, NULL)));
} else if constexpr(std::is_same<T, std::string>::value) {
value = paramString;
} else if constexpr(std::is_same<T, bool>::value) {
// convert string to lower case
std::for_each(paramString.begin(), paramString.end(), [](char & c){
c = ::tolower(c);
});
if(paramString.compare("yes") == 0) {
value = true;
} else if(paramString.compare("true") == 0) {
value = true;
} else if(paramString.compare("debout") == 0) {
value = true;
} else if(paramString.compare("no") == 0) {
value = false;
} else if(paramString.compare("false") == 0) {
value = false;
} else if(paramString.compare("couche") == 0) {
value = false;
} else {
std::stringstream msg;
msg << "Boolean parameter [" << blockName << "]:" << paramName << "(" << num
<< ") cannot be interpreted as boolean in the input file." << std::endl
<< std::endl << "I read \"" << paramString << "\"" << std::endl
<< "Use \"yes\" or \"true\" for boolean true ;"
<< " use \"no\" or \"false\" for boolean false.";
IDEFIX_ERROR(msg);
}
} else {
IDEFIX_ERROR("Unknown type has been requested from the input file");
}
} catch(const std::exception& e) {
std::stringstream errmsg;
errmsg << e.what() << std::endl
<< "Input::Get: Error while reading [" << blockName << "]:" << paramName << "(" << num
<< ")." << std::endl
<< "\"" << paramString << "\" cannot be interpreted as required." << std::endl;
IDEFIX_ERROR(errmsg);
}
return(value);
}
template<typename T>
T Input::GetOrSet(std::string blockName, std::string paramName, int num, T def) {
int entrySize = CheckEntry(blockName, paramName);
if(entrySize <= num ) {
// the requested entry has not been set, add it (if we can), otherwise throw an error
if(entrySize < 0 && num>0) {
std::stringstream msg;
msg << "Entry [" << blockName << "]:" << paramName << "is not defined." << std::endl
<< "Only the first (index 0) parameter can be set by default." << std::endl;
IDEFIX_ERROR(msg);
}
if(entrySize+1 < num) {
std::stringstream msg;
msg << "Entry [" << blockName << "]:" << paramName << "has " << entrySize << " parameters."
<< std::endl << ". Only the " << entrySize << "th (index " << entrySize-1
<< ") parameter can be set by default." << std::endl;
IDEFIX_ERROR(msg);
}
std::stringstream strm;
strm << std::boolalpha << def;
inputParameters[blockName][paramName].push_back(strm.str());
}
return(Get<T>(blockName, paramName, num));
}
#endif // INPUT_HPP_