Initfile.hpp 7.97 KB
Newer Older
1
2
#pragma once

3
#include <array>
4
5
6
#include <string>
#include <iostream>
#include <type_traits>
7
8
#include <list>
#include <vector>
9
10
11
12
13

#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/tokenizer.hpp>

14
#include <dune/common/fvector.hh>
15
16
17
18
#include <dune/common/parametertree.hh>
// #include <boost/property_tree/ptree.hpp>

#include <dune/common/std/optional.hh>
19

20
#include <dune/amdis/Output.hpp>
21
#include <dune/amdis/common/Math.hpp>
22
23
24
25
26

namespace AMDiS
{
  namespace detail
  {
27
//     double mu_parser_eval(std::string const& valStr);
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

    template <class T> inline T numeric_cast(double value)
    {
      return boost::numeric_cast< T >(value);
    }

    template <> inline bool numeric_cast<bool>(double value)
    {
      return value != 0.0;
    }

    /// convert string to intrinsic type
    template <class T, class Enable = void>
    struct Convert
    {
      static void eval(std::string valStr, T& value)
      {
        value = boost::lexical_cast<T>(valStr);
      }
    };

49
50
51
52
53
54
55
56
//     template <class T>
//     struct Convert<T, std::enable_if_t<std::is_arithmetic<T>::value> >
//     {
//       static void eval(std::string valStr, T& value)
//       {
//         try {
//             value = numeric_cast< T >(mu_parser_eval(valStr));
//         } catch(...) {
57
//             error_exit("Could not parse '", valStr, "' to '", typeid(T).name(), "'\n");
58
59
60
//         }
//       }
//     };
61

62
63
64
65
66
67
68
69
//     template <class T>
//     struct Convert<T, std::enable_if_t<std::is_enum<T>::value> >
//     {
//       static void eval(std::string valStr, T& value)
//       {
//         EnumParser<T>()(valStr, value);
//       }
//     };
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//     convert string to vector
    template <class V, int dim>
    struct Convert<Dune::FieldVector<V, dim>>
    {
      using T = Dune::FieldVector<V, dim>;
      static void eval(std::string valStr, T& values)
      {
        using value_type = typename T::value_type;
        using Tokenizer = boost::tokenizer<boost::char_separator<char>>;

        boost::char_separator<char> sep(",; ");
        Tokenizer tokens(valStr, sep);
        int i = 0;
        for (auto token : tokens)
        {
86
87
          test_exit(i < dim, "Vector data exceeds field-vector dimension!");

88
89
90
91
92
93
94
95
          value_type v;
          Convert<value_type>::eval(token, v);
          values[i++] = v;
        }
      }
    };

//     convert string to vector
96
    template <class V, std::size_t dim>
97
98
99
100
101
102
103
104
105
106
    struct Convert<std::array<V, dim>>
    {
      using T = std::array<V, dim>;
      static void eval(std::string valStr, T& values)
      {
        using value_type = typename T::value_type;
        using Tokenizer = boost::tokenizer<boost::char_separator<char>>;

        boost::char_separator<char> sep(",; ");
        Tokenizer tokens(valStr, sep);
107
        std::size_t i = 0;
108
109
        for (auto token : tokens)
        {
110
111
          test_exit(i < dim, "Vector data exceeds array dimension!");

112
113
114
115
116
117
          value_type v;
          Convert<value_type>::eval(token, v);
          values[i++] = v;
        }
      }
    };
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

    // convert string to vector
    template <class T, class Alloc>
    struct Convert<std::vector<T, Alloc>>
    {
      static void eval(std::string valStr, std::vector<T>& values)
      {
        using value_type = T;
        using Tokenizer = boost::tokenizer<boost::char_separator<char>>;

        boost::char_separator<char> sep(",; ");
        Tokenizer tokens(valStr, sep);
        for (auto token : tokens)
        {
          value_type v;
          Convert<value_type>::eval(token, v);
          values.push_back(v);
        }
      }
    };

  } // end namespace detail


  /// output-stream for std::list
  template <class T, class Alloc>
  std::ostream& operator<<(std::ostream& out, std::list<T,Alloc> const& l)
  {
    auto it = l.begin();
Praetorius, Simon's avatar
Praetorius, Simon committed
147
148
149
    out << "[";
    if (l.size() > 0)
      out << *it;
150
151
152
153
154
155
156
157
158
159
160
161
    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();
Praetorius, Simon's avatar
Praetorius, Simon committed
162
163
164
    out << "[";
    if (l.size() > 0)
      out << *it;
165
166
167
168
169
170
171
172
173
174
    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;
175
    std::size_t start_pos = 0;
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    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;

    /** 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);


    template <class T>
200
    static Dune::Std::optional<T> get(std::string key)
201
    {
202
203
204
205
206
207
208
      replaceAll(key, "->", ".");
      try {
        return singlett().pt.get<T>(key);
      }
      catch (...) {
        return Dune::Std::nullopt;
      }
209
210
211
    }


212
213
214
215
216
217
218
    /** \brief Static get routine for getting parameter-values from init-file
    *  initialized in init()-method.
    *  Cast the value to the desired type.
    *
    *  \param tag: The tag to look for
    *  \param value: The result.
    */
219
    template <class T>
220
    static void get(std::string tag, T& value)
221
    {
222
223
224
      auto v = get<std::string>(tag);
      if (v)
        detail::Convert<T>::eval(v.value(), value);
225
226
227
228
229
230
231
232
    }


    /// 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)
233
        debugInfo = singlett().getMsgInfo();
234

235
236
237
      replaceAll(tag, "->", ".");
      // auto tagPath = path(tag, '>');
      // singlett().pt.put(tagPath, value);
238
239

      // update msg parameters msgInfo, msgWait, paramInfo
240
      singlett().getInternalParameters();
241
242
243
//       if (debugInfo == 2)
//         std::cout << "Parameter '" << tag << "'"
//                   << " set to: " << value << std::endl;
244
245
246
247
248
249
250
251
252
253
254
255
256
    }


    /// 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
    static int getMsgInfo()
    {
257
      return singlett().msgInfo;
258
259
260
261
262
263
264
265
266
267
    }


    /// print all data in singleton to std::cout
    static void printParameters();


    /// clear data in singleton
    static void clearData()
    {
268
      // singlett().clear();
269
270
271
272
273
274
    }


    /// save singlett-data to file with filename fn
    static void save(std::string /*fn*/)
    {
275
      // using boost::property_tree::json_parser;
276
      // json_parser::write_jason(fn, singlett().pt);
277
278
279
280
281
    }

  protected:
    Initfile() = default;

282
283
    /// return the singleton that contains the data
    static Initfile& singlett()
284
    {
285
286
      static Initfile initfile;
      return initfile;
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
    }

    /** Fill the initfile from an input stream.
    * @param in: the stream to fill the data from.
    * Current dataformat: tag:value
    * Comment char: percent '%'
    * Include files: #include "filename" or #include <filename>
    */
    void read(std::string fn, bool force = false);

    /// Write data-map to initfile with filename fn
    void write(std::string fn);

    /// read parameters for msgInfo, msgWait, paramInfo
    void getInternalParameters();

    int msgInfo = 0;
    int paramInfo = 1;
    int breakOnMissingTag = 0;

307
308
    /// ParameterTree to read/store parameter values
    Dune::ParameterTree pt;
309
310
311
312
313
  };

  using Parameters = Initfile;

#ifndef AMDIS_NO_EXTERN_INITFILE
314
315
316
  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&);
317
318
319
#endif

} // end namespace AMDiS