Initfile.hpp 7.94 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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

    // 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();
    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;
169
    std::size_t start_pos = 0;
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
    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>
194
    static boost::optional<T> get(std::string tag)
195
196
197
198
199
    {
      using path = boost::property_tree::ptree::path_type;
      replaceAll(tag, "->", ">");
      auto tagPath = path(tag, '>');

200
      return singlett().pt.get_optional<T>(tagPath);
201
202
203
    }


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


    /// 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)
225
        debugInfo = singlett().getMsgInfo();
226
227
228
229

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

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


    /// 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()
    {
250
      return singlett().msgInfo;
251
252
253
254
255
256
257
258
259
260
    }


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


    /// clear data in singleton
    static void clearData()
    {
261
      // singlett().clear();
262
263
264
265
266
267
268
    }


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

  protected:
    Initfile() = default;

275
276
    /// return the singleton that contains the data
    static Initfile& singlett()
277
    {
278
279
      static Initfile initfile;
      return initfile;
280
281
282
283
284
285
286
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;

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

  using Parameters = Initfile;

#ifndef AMDIS_NO_EXTERN_INITFILE
307
308
309
  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&);
310
311
312
#endif

} // end namespace AMDiS