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
14
15

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

#include <boost/property_tree/ptree.hpp>

16
17
#include <dune/common/fvector.hh>

18
19
#include <dune/amdis/Output.hpp>
#include <dune/amdis/Math.hpp>
20
21
22
23
24

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

    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);
      }
    };

47
48
49
50
51
52
53
54
//     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(...) {
55
//             error_exit("Could not parse '", valStr, "' to '", typeid(T).name(), "'\n");
56
57
58
//         }
//       }
//     };
59

60
61
62
63
64
65
66
67
//     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);
//       }
//     };
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//     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)
        {
84
85
          test_exit(i < dim, "Vector data exceeds field-vector dimension!");

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

//     convert string to vector
94
    template <class V, std::size_t dim>
95
96
97
98
99
100
101
102
103
104
    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);
105
        std::size_t i = 0;
106
107
        for (auto token : tokens)
        {
108
109
          test_exit(i < dim, "Vector data exceeds array dimension!");

110
111
112
113
114
115
          value_type v;
          Convert<value_type>::eval(token, v);
          values[i++] = v;
        }
      }
    };
116
117
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

    // 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
145
146
147
    out << "[";
    if (l.size() > 0)
      out << *it;
148
149
150
151
152
153
154
155
156
157
158
159
    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
160
161
162
    out << "[";
    if (l.size() > 0)
      out << *it;
163
164
165
166
167
168
169
170
171
172
    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;
173
    std::size_t start_pos = 0;
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    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>
198
    static boost::optional<T> get(std::string tag)
199
200
201
202
203
    {
      using path = boost::property_tree::ptree::path_type;
      replaceAll(tag, "->", ">");
      auto tagPath = path(tag, '>');

204
      return singlett().pt.get_optional<T>(tagPath);
205
206
207
    }


208
209
210
211
212
213
214
    /** \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.
    */
215
    template <class T>
216
    static void get(std::string tag, T& value)
217
    {
218
219
220
      auto v = get<std::string>(tag);
      if (v)
        detail::Convert<T>::eval(v.value(), value);
221
222
223
224
225
226
227
228
    }


    /// 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)
229
        debugInfo = singlett().getMsgInfo();
230
231
232
233

      using path = boost::property_tree::ptree::path_type;
      replaceAll(tag, "->", ">");
      auto tagPath = path(tag, '>');
234
      singlett().pt.put(tagPath, value);
235
236

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


    /// 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()
    {
254
      return singlett().msgInfo;
255
256
257
258
259
260
261
262
263
264
    }


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


    /// clear data in singleton
    static void clearData()
    {
265
      // singlett().clear();
266
267
268
269
270
271
    }


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

  protected:
    Initfile() = default;

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

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

    /// boost:property_tree to read/store parameter values
    boost::property_tree::ptree pt;
  };

  using Parameters = Initfile;

#ifndef AMDIS_NO_EXTERN_INITFILE
311
312
313
  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&);
314
315
316
#endif

} // end namespace AMDiS