Commit 3c050d06 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

initfile set to AMDiS format

parent bb9b82d4
...@@ -7,6 +7,7 @@ dune_library_add_sources(amdis SOURCES ...@@ -7,6 +7,7 @@ dune_library_add_sources(amdis SOURCES
AdaptStationary.cpp AdaptStationary.cpp
AMDiS.cpp AMDiS.cpp
Initfile.cpp Initfile.cpp
InitfileParser.cpp
ProblemInstatBase.cpp ProblemInstatBase.cpp
# ProblemInstat.cpp # ProblemInstat.cpp
ProblemStat.cpp ProblemStat.cpp
...@@ -31,6 +32,7 @@ install(FILES ...@@ -31,6 +32,7 @@ install(FILES
GridFunctionOperator.hpp GridFunctionOperator.hpp
GridFunctions.hpp GridFunctions.hpp
Initfile.hpp Initfile.hpp
InitfileParser.hpp
LinearAlgebra.hpp LinearAlgebra.hpp
LocalAssembler.hpp LocalAssembler.hpp
LocalAssemblerBase.hpp LocalAssemblerBase.hpp
......
#define AMDIS_NO_EXTERN_INITFILE #include <dune/amdis/Initfile.hpp>
#include "Initfile.hpp"
#undef AMDIS_NO_EXTERN_INITFILE
#include <string> #include <dune/amdis/InitfileParser.hpp>
#ifdef _MSC_VER
#include <io.h> // _access
#else
#include <unistd.h>
#endif
#include <dune/common/parametertreeparser.hh>
// a parser for arithmetic expressions // a parser for arithmetic expressions
// #include <muParser.h> // #include <muParser.h>
#include <dune/amdis/Output.hpp>
namespace AMDiS namespace AMDiS
{ {
/// check for file existence
inline bool file_exists(std::string const& filename)
{
#ifdef _MSC_VER
return _access(filename.c_str(), 0) == 0;
#else
return access(filename.c_str(), F_OK) == 0;
#endif
}
// namespace detail // namespace detail
// { // {
// double mu_parser_eval(std::string const& valStr) // double mu_parser_eval(std::string const& valStr)
...@@ -42,54 +20,41 @@ namespace AMDiS ...@@ -42,54 +20,41 @@ namespace AMDiS
// } // }
// } // }
/// initialize singleton object an global parameters void Initfile::init(std::string in)
void Initfile::init(std::string in) {
{ singlett().read(in);
singlett().read(in); singlett().getInternalParameters();
singlett().getInternalParameters(); }
}
/// Fill an initfile from a file with filename fn
void Initfile::read(std::string fn, bool /*force*/)
{
test_exit(file_exists(fn),
"init-file '", fn, "' cannot be opened for reading");
Dune::ParameterTreeParser::readINITree(fn, pt);
}
/// read standard values for output and information of parameter-values void Initfile::read(std::string fn, bool /*force*/)
void Initfile::getInternalParameters() {
{ InitfileParser::readInitfile(fn, pt_);
int val = 0; }
get("level of information", val);
msgInfo = val;
val = 1;
get("parameter information", val);
paramInfo = val;
val = 0; void Initfile::getInternalParameters()
get("break on missing tag", val); {
breakOnMissingTag = val; int val = 0;
get("level of information", val);
msgInfo = val;
if (msgInfo == 0) val = 1;
paramInfo = 0; get("parameter information", val);
} paramInfo = val;
val = 0;
get("break on missing tag", val);
breakOnMissingTag = val;
/// print all parameters to std::cout if (msgInfo == 0)
void Initfile::printParameters() paramInfo = 0;
{ }
// TODO: implement printing of all parameters
}
// explicit template instatiation
template void Initfile::get(std::string, int&);
template void Initfile::get(std::string, double&);
template void Initfile::get(std::string, std::string&);
void Initfile::printParameters()
{
// TODO: implement printing of all parameters
}
} // end namespace AMDiS } // end namespace AMDiS
#pragma once #pragma once
#include <array>
#include <string> #include <string>
#include <iostream>
#include <type_traits>
#include <list>
#include <vector>
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/tokenizer.hpp>
#include <dune/common/fvector.hh>
#include <dune/common/parametertree.hh> #include <dune/common/parametertree.hh>
// #include <boost/property_tree/ptree.hpp>
#include <dune/common/std/optional.hh> #include <dune/common/std/optional.hh>
#include <dune/amdis/Output.hpp>
#include <dune/amdis/common/Math.hpp>
namespace AMDiS namespace AMDiS
{ {
// /// output-stream for std::list class Initfile
// template <class T, class Alloc>
// std::ostream& operator<<(std::ostream& out, std::list<T,Alloc> const& l)
// {
// auto it = l.begin();
// out << "[";
// if (l.size() > 0)
// out << *it;
// for (; it != l.end(); ++it)
// out << ", " << *it;
// out << "]";
// return out;
// }
// /// output-stream for std::vector
// template <class T, class Alloc>
// std::ostream& operator<<(std::ostream& out, std::vector<T,Alloc> const& l)
// {
// auto it = l.begin();
// out << "[";
// if (l.size() > 0)
// out << *it;
// for (; it != l.end(); ++it)
// out << ", " << *it;
// out << "]";
// return out;
// }
inline void replaceAll(std::string& str, std::string const& from, std::string const& to)
{
if (from.empty())
return;
std::size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
// _____________________________________________________________________________
/** Basis data container as a map of tag on a value as strings. The container
* throws an exception, if the tag was not found.
*/
struct Initfile
{ {
using Self = Initfile; public:
/// initialize singleton object and global parameters
/** initialize init-file from file with filename in, read data and save it
* to singleton-map
* @param in: filename string
*/
static void init(std::string in); static void init(std::string in);
/// \brief Get parameter-values from parameter-tree
/**
* Looks for the `key` in the parameter-tree and returns
* the stored and parsed value if found and parsable.
*
* Does not thrown an exception if something goes wrong!
**/
template <class T> template <class T>
static Dune::Std::optional<T> get(std::string key) static Dune::Std::optional<T> get(std::string key)
{ {
replaceAll(key, "->", ".");
try { try {
return singlett().pt.get<T>(key); return pt().get<T>(key);
} }
catch (...) { catch (...) {
return Dune::Std::nullopt; return Dune::Std::nullopt;
} }
} }
/// \brief Get parameter-values from parameter-tree with default value
/** \brief Static get routine for getting parameter-values from init-file /**
* initialized in init()-method. * initialized in init()-method.
* Cast the value to the desired type. * Cast the value to the desired type.
* *
* \param tag: The tag to look for * \param key: The tag to look for
* \param value: The result. * \param value: The default value and result.
*/ **/
template <class T> template <class T>
static void get(std::string key, T& value) static void get(std::string key, T& value)
{ {
replaceAll(key, "->", "."); value = pt().get(key, value);
value = singlett().pt.get(key, value);
}
/// update map tag->value_old to tag->value in singleton
template <class T>
static void set(std::string tag, T& value, int debugInfo= -1)
{
if (debugInfo == -1)
debugInfo = singlett().getMsgInfo();
replaceAll(tag, "->", ".");
// auto tagPath = path(tag, '>');
// singlett().pt.put(tagPath, value);
// update msg parameters msgInfo, msgWait, paramInfo
singlett().getInternalParameters();
// if (debugInfo == 2)
// std::cout << "Parameter '" << tag << "'"
// << " set to: " << value << std::endl;
}
/// add map tag->value to data in singleton
template <class T>
static void add(std::string tag, T& value, int debugInfo = -1)
{
set(tag, value, debugInfo);
} }
/// Returns specified info level /// Returns specified info level
...@@ -139,47 +53,32 @@ namespace AMDiS ...@@ -139,47 +53,32 @@ namespace AMDiS
return singlett().msgInfo; return singlett().msgInfo;
} }
/// print all data in singleton to std::cout /// print all data in singleton to std::cout
static void printParameters(); static void printParameters();
static void clearData() {}
/// clear data in singleton
static void clearData()
{
// singlett().clear();
}
/// save singlett-data to file with filename fn
static void save(std::string /*fn*/)
{
// using boost::property_tree::json_parser;
// json_parser::write_jason(fn, singlett().pt);
}
protected: protected:
Initfile() = default; Initfile() = default;
/// return the singleton that contains the data /// Return the singleton that contains the data
static Initfile& singlett() static Initfile& singlett()
{ {
static Initfile initfile; static Initfile initfile;
return initfile; return initfile;
} }
/** Fill the initfile from an input stream. /// Return the parameter-tree
* @param in: the stream to fill the data from. static Dune::ParameterTree& pt()
* Current dataformat: tag:value {
* Comment char: percent '%' return singlett().pt_;
* Include files: #include "filename" or #include <filename> }
*/
void read(std::string fn, bool force = false);
/// Write data-map to initfile with filename fn /// Fill an parametr-tree from a file with filename fn
void read(std::string fn, bool force = false);
void write(std::string fn); void write(std::string fn);
/// read parameters for msgInfo, msgWait, paramInfo /// read standard values for output and information of parameter-values
void getInternalParameters(); void getInternalParameters();
int msgInfo = 0; int msgInfo = 0;
...@@ -187,15 +86,9 @@ namespace AMDiS ...@@ -187,15 +86,9 @@ namespace AMDiS
int breakOnMissingTag = 0; int breakOnMissingTag = 0;
/// ParameterTree to read/store parameter values /// ParameterTree to read/store parameter values
Dune::ParameterTree pt; Dune::ParameterTree pt_;
}; };
using Parameters = Initfile; using Parameters = Initfile;
#ifndef AMDIS_NO_EXTERN_INITFILE
extern template void Initfile::get(std::string, int&);
extern template void Initfile::get(std::string, double&);
extern template void Initfile::get(std::string, std::string&);
#endif
} // end namespace AMDiS } // end namespace AMDiS
#include <dune/amdis/InitfileParser.hpp>
#include <dune/amdis/Output.hpp>
#include <dune/amdis/utility/Filesystem.hpp>
#include <dune/amdis/utility/String.hpp>
namespace AMDiS {
void InitfileParser::readInitfile(std::string fn, Dune::ParameterTree& pt, bool overwrite)
{
test_exit(filesystem::exists(fn),
"init-file '", fn, "' cannot be opened for reading");
// read file if its not parsed already
auto ins = includeList().insert(fn);
if (ins.second) {
std::ifstream in(fn.c_str());
readInitfile(in, pt, overwrite);
}
}
void InitfileParser::readInitfile(std::istream& in, Dune::ParameterTree& pt, bool overwrite)
{
std::string swap;
std::getline(in, swap);
while (in.good() || swap.size() > 0) {
std::string whitespaces = " \t\r\f\n";
std::string delimiter = "\r\n";
std::string sw(swap);
std::size_t pos0 = sw.find_first_not_of(whitespaces);
if (pos0 != std::string::npos
&& sw[pos0] != '%'
&& sw[pos0] != '#'
&& sw[pos0] != 0)
{
// parse line and extract map: tag->value
std::size_t pos = sw.find(':');
if (pos == std::string::npos)
throw std::runtime_error("cannot find the delimiter ':' in line '" + sw + "'");
std::string name = sw.substr(0, pos);
std::string value = sw.substr(pos + 1, sw.length() - (pos + 1));
// remove everything after the %
pos = value.find('%');
if (pos != std::string::npos)
value = value.substr(0, pos);
// add parameter to map after variable replacement
std::string paramName = replaceVariable(pt, trim(name));
std::string paramValue = replaceVariable(pt, trim(value));
paramValue = replaceExpression(pt, paramValue);
// add parameter to parametertree
if (overwrite || ! pt.hasKey(paramName))
pt[paramName] = paramValue;
}
else if (pos0 != std::string::npos &&
sw[pos0] == '#' &&
std::size_t(sw.find("#include")) == pos0)
{
// include file by '#include "filename"' or '#include <filename>'
std::size_t pos = sw.find_first_not_of(whitespaces, pos0 + std::string("#include").size() + 1);
std::size_t epos = 0;
std::string fn = "";
switch (char c = swap[pos++]) {
case '<':
c= '>';
case '\"':
delimiter += c;
epos = sw.find_first_of(delimiter, pos);
fn = sw.substr(pos, epos - pos);
if (sw[epos]!=c)
throw std::runtime_error("filename in #include not terminated by " + std::to_string(c));
break;
default:
throw std::runtime_error("no filename given for #include");
}
readInitfile(fn, pt, overwrite);
}
swap.clear();
std::getline(in, swap);
}
}
std::string InitfileParser::replaceVariable(Dune::ParameterTree const& pt, std::string input)
{
std::string whitespaces = " \t\r\f";
std::string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
std::string inputSwap = input;
std::size_t posVar = inputSwap.find_first_of('$');
while (posVar != std::string::npos) {
std::size_t posVarBegin, posVarEnd;
if (inputSwap[posVar+1] == '{') { // ${var_name}
posVarEnd = inputSwap.find_first_of('}',posVar + 2);
posVarBegin = posVar + 1;
} else if (inputSwap[posVar+1] != '(' && inputSwap[posVar+1] != '[') { // $var_name
posVarEnd = inputSwap.find_first_not_of(allowedChars, posVar + 1);
posVarBegin = posVar;
} else {
posVar = inputSwap.find_first_of('$',posVar+1);
continue;
}
std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);
// if varname is found in parameter list then replace variable by value
// otherwise throw tagNotFound exception
if (!pt.hasKey(varName))
throw std::runtime_error("required tag '" + varName + "' for variable substitution not found");
std::string varParam = pt[varName];
std::string replaceName = inputSwap.substr(posVar , posVarEnd - posVar + (posVarBegin - posVar));
inputSwap.replace(inputSwap.find(replaceName), replaceName.length(), varParam);
posVar = inputSwap.find_first_of('$',posVarBegin);
}
return inputSwap;
}
std::string InitfileParser::replaceExpression(Dune::ParameterTree const& pt, std::string input)
{
#if 0
std::string whitespaces = " \t\r\f";
std::string inputSwap = input;
std::size_t posVar = inputSwap.find("$(");
while (posVar != std::string::npos) {
size_t posVarBegin, posVarEnd;
posVarEnd = inputSwap.find_first_of(')',posVar + 2);
posVarBegin = posVar + 1;
std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);
double value = 0.0;
detail::convert(varName, value); // string -> double (using muparser)
detail::convert(value, varName); // double -> string
std::string replaceName = inputSwap.substr(posVar , posVarEnd - posVar + (posVarBegin - posVar));
inputSwap.replace(inputSwap.find(replaceName), replaceName.length(), varName);
posVar = inputSwap.find("$(",posVarBegin);
}
return inputSwap;
#else
// currently no evaluation implemented.
return input;
#endif
}
} // end namespace AMDiS
#pragma once
#include <fstream>
#include <set>
#include <string>
#include <dune/common/parametertree.hh>
namespace AMDiS
{
/// Parser for AMDiS initfile format
/**
* An AMDiS initfile is a list of pairs `(paramter, value)`
* stored in a structured textfile of the format
* \verbatim
* parameter: value % a comment
*
* #include <filename> % include files
* var_${parameter}: value2 % variable replacement in keys
* parameter2: ${parameter} % variable replacement in values
*
* parameter3: 1 + sin(4.0) % expressions in the values
* parameter4: $(1 + 2) % expression replacement
* \endverbatim
**/
class InitfileParser
{
public:
/// Read initfile from input stream into parameter-tree
static void readInitfile(std::istream& in, Dune::ParameterTree& pt, bool overwrite);
/// Read initfile from input stream into parameter-tree
static void readInitfile(std::string fn, Dune::ParameterTree& pt, bool overwrite = true);
private:
/// Provide a list of already read files. This is necessary to not double include the same file.
static std::set<std::string>& includeList()
{
static std::set<std::string> includeFiles;
return includeFiles;