• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Open-Sn / opensn / 20185909776

12 Dec 2025 06:55PM UTC coverage: 74.333% (+0.3%) from 74.037%
20185909776

push

github

web-flow
Merge pull request #859 from wdhawkins/td_source_driver

Adding time-dependent solver and time-dependent sources

367 of 398 new or added lines in 23 files covered. (92.21%)

113 existing lines in 28 files now uncovered.

18610 of 25036 relevant lines covered (74.33%)

68947552.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.18
/framework/parameters/parameter_block.h
1
// SPDX-FileCopyrightText: 2024 The OpenSn Authors <https://open-sn.github.io/opensn/>
2
// SPDX-License-Identifier: MIT
3

4
#pragma once
5

6
#include "framework/data_types/varying.h"
7
#include <memory>
8
#include <stdexcept>
9
#include <vector>
10
#include <string>
11
#include <map>
12

13
namespace opensn
14
{
15

16
enum class ParameterBlockType
17
{
18
  INVALID_VALUE = 0,
19
  BOOLEAN = 1,
20
  FLOAT = 3,
21
  STRING = 4,
22
  INTEGER = 5,
23
  USER_DATA = 6,
24
  ARRAY = 98,
25
  BLOCK = 99
26
};
27

28
std::string ParameterBlockTypeName(ParameterBlockType type);
29

30
class ParameterBlock;
31

32
/**
33
 * A ParameterBlock is a conceptually simple data structure that supports a hierarchy of primitive
34
 * parameters. There really are just 4 member variables on a ParameterBlock object, they are 1) the
35
 * type (as an enum), 2) the name of the block, 3) a pointer to a value (which can only be a
36
 * primitive type), and 4) a vector of child parameters.
37
 *
38
 * If a ParameterBlock has a primitive type, i.e., BOOLEAN, FLOAT, STRING, or INTEGER, then the
39
 * value_ptr will contain a pointer to the value of a primitive type. Otherwise, for types ARRAY and
40
 * BLOCK, the ParameterBlock will not have a value_ptr and instead the vector member will contain
41
 * sub-parameters.
42
 */
43
class ParameterBlock
44
{
45
public:
46
  /// Sets the name of the block.
47
  void SetBlockName(const std::string& name);
48

49
  // Helpers
50
  template <typename T>
51
  struct IsBool
52
  {
53
    static constexpr bool value = std::is_same_v<T, bool>;
54
  };
55
  template <typename T>
56
  struct IsFloat
57
  {
58
    static constexpr bool value = std::is_floating_point_v<T>;
59
  };
60
  template <typename T>
61
  struct IsString
62
  {
63
    static constexpr bool value = std::is_same_v<T, std::string> or std::is_same_v<T, const char*>;
64
  };
65
  template <typename T>
66
  struct IsInteger
67
  {
68
    static constexpr bool value = std::is_integral_v<T> and not std::is_same_v<T, bool>;
69
  };
70
  template <typename T>
71
  struct IsUserData
72
  {
73
    static constexpr bool value = (std::is_pointer_v<T> or is_shared_ptr_v<T> or
74
                                   (std::is_class_v<T> and not std::is_same_v<T, std::string>)) and
75
                                  (not std::is_same_v<T, const char*>);
76
  };
77

78
  // Constructors
79
  /// Constructs an empty parameter block with the given name and type BLOCK.
80
  explicit ParameterBlock(const std::string& name = "");
81

82
  /// Derived type constructor
83
  template <typename T>
84
  ParameterBlock(const std::string& name, const std::vector<T>& array)
3,512✔
85
    : type_(ParameterBlockType::ARRAY), name_(name)
3,512✔
86
  {
87
    size_t k = 0;
3,512✔
88
    for (const T& value : array)
3,632✔
89
      AddParameter(std::to_string(k++), value);
240✔
90
  }
3,512✔
91

92
  /// Constructs one of the fundamental types.
93
  template <typename T>
94
  explicit ParameterBlock(const std::string& name, T value) : name_(name)
110,102✔
95
  {
96
    constexpr bool is_supported = IsBool<T>::value or IsFloat<T>::value or IsString<T>::value or
110,102✔
97
                                  IsInteger<T>::value or IsUserData<T>::value;
98

99
    static_assert(is_supported, "Value type not supported for parameter block");
100

101
    if (IsBool<T>::value)
102
      type_ = ParameterBlockType::BOOLEAN;
103
    if (IsFloat<T>::value)
104
      type_ = ParameterBlockType::FLOAT;
73,131✔
105
    if (IsString<T>::value)
106
      type_ = ParameterBlockType::STRING;
107
    if (IsInteger<T>::value)
108
      type_ = ParameterBlockType::INTEGER;
109
    if (IsUserData<T>::value)
110
      type_ = ParameterBlockType::USER_DATA;
111

112
    value_ptr_ = std::make_shared<Varying>(value);
110,102✔
113
  }
110,102✔
114

8,142✔
115
  /// Copy constructor
116
  ParameterBlock(const ParameterBlock& other);
117

118
  /// Copy assignment operator
119
  ParameterBlock& operator=(const ParameterBlock& other);
120

121
  /// Move constructor
122
  ParameterBlock(ParameterBlock&& other) noexcept = default;
123

124
  /// Move assignment operator
125
  ParameterBlock& operator=(ParameterBlock&& other) noexcept;
126

127
  // Accessors
128
  ParameterBlockType GetType() const;
129

130
  /**
131
   * Returns true if the parameter block comprises a single value of any of the types BOOLEAN,
132
   * FLOAT, STRING, INTEGER.
133
   */
134
  bool IsScalar() const;
135

136
  /// Returns a string version of the type.
137
  std::string GetTypeName() const;
138
  std::string GetName() const;
139
  const Varying& GetValue() const;
140

141
  /// Returns the number of parameters in a block. This is normally only useful for the ARRAY type.
142
  size_t GetNumParameters() const;
143

144
  /// Returns the sub-parameters of this block.
145
  const std::vector<ParameterBlock>& GetParameters() const;
146

147
  /**
148
   * Returns whether or not the block has a value. If this block has sub-parameters it should not
149
   * have a value. This is a good way to check if the block is actually a single value because some
150
   * Parameter blocks can be passed as empty.
151
   */
152
  bool HasValue() const;
153

154
  // Mutators
155

156
  /// Changes the block type to array, making it accessible via integer keys.
157
  void ChangeToArray();
158

159
  /// Sets a string to be displayed alongside exceptions that give some notion of the origin of the
160
  /// error.
161
  void SetErrorOriginScope(const std::string& scope);
162

163
  /// Gets a string that allows error messages to print the scope of an error.
164
  std::string GetErrorOriginScope() const { return error_origin_scope_; }
165

166
  // Requirements
167

168
  /**
169
   * Checks that the block is of the given type. If it is not it will throw an exception
170
   * `std::logic_error`.
171
   */
172
  void RequireBlockTypeIs(ParameterBlockType type) const;
173
  void RequireParameterBlockTypeIs(const std::string& param_name, ParameterBlockType type) const
174
  {
175
    GetParam(param_name).RequireBlockTypeIs(type);
176
  }
177

178
  /// Check that the parameter with the given name exists otherwise throws a `std::logic_error`.
179
  void RequireParameter(const std::string& param_name) const;
180

181
  // utilities
182

183
  /// Adds a parameter to the sub-parameter list.
184
  void AddParameter(ParameterBlock block);
185

186
  /// Makes a ParameterBlock and adds it to the sub-parameters list.
187
  template <typename T>
188
  void AddParameter(const std::string& name, const T& value)
37,384✔
189
  {
190
    AddParameter(ParameterBlock(name, value));
37,384✔
191
  }
37,384✔
192

193
  /// Sorts the sub-parameter list according to name. This is useful for regression testing.
194
  void SortParameters();
195

196
  /// Returns true if a parameter with the specified name is in the list of sub-parameters.
197
  /// Otherwise, false.
198
  bool Has(const std::string& param_name) const;
199

200
  /// Gets a parameter by name.
201
  ParameterBlock& GetParam(const std::string& param_name);
202

203
  /// Gets a parameter by index.
204
  ParameterBlock& GetParam(size_t index);
205

206
  /// Gets a parameter by name.
207
  const ParameterBlock& GetParam(const std::string& param_name) const;
208

209
  /// Gets a parameter by index.
210
  const ParameterBlock& GetParam(size_t index) const;
211

212
  /// Returns the value of the parameter.
213
  template <typename T>
214
  T GetValue() const
93,356✔
215
  {
216
    if (value_ptr_ == nullptr)
93,356✔
UNCOV
217
      throw std::logic_error(error_origin_scope_ + std::string(__PRETTY_FUNCTION__) +
×
UNCOV
218
                             ": Value not available for block type " +
×
UNCOV
219
                             ParameterBlockTypeName(GetType()));
×
220
    try
221
    {
222
      return GetValue().GetValue<T>();
93,356✔
223
    }
224
    catch (const std::exception& exc)
×
225
    {
226
      throw std::logic_error(error_origin_scope_ + ":" + GetName() + " " + exc.what());
×
227
    }
228
  }
229

230
  /// Fetches the parameter with the given name and returns it value.
231
  template <typename T>
232
  T GetParamValue(const std::string& param_name) const
23,094✔
233
  {
234
    try
235
    {
236
      const auto& param = GetParam(param_name);
23,094✔
237
      return param.GetValue<T>();
23,094✔
238
    }
UNCOV
239
    catch (const std::out_of_range& oor)
×
240
    {
UNCOV
241
      throw std::out_of_range(error_origin_scope_ + std::string(__PRETTY_FUNCTION__) +
×
UNCOV
242
                              ": Parameter \"" + param_name + "\" not present in block");
×
243
    }
244
  }
245

246
  /**
247
   * Fetches the parameter of type std::shared_ptr<T> with the given name and returns its value.
248
   *
249
   * Will perform checking on whether or not the pointed-to-object is null (if \p check = true)
250
   *
251
   * The optional second template argument can be used to attempt to cast the object
252
   * to the derived type and will throw an exception if the cast fails.
253
   */
254
  template <typename T, typename Derived = T>
255
  std::shared_ptr<Derived> GetSharedPtrParam(const std::string& param_name,
256
                                             const bool check = true) const
257
  {
258
    static_assert(std::is_base_of_v<T, Derived>, "T is not a base of derived");
259

260
    auto value = this->GetParamValue<std::shared_ptr<T>>(param_name);
261
    if (!value)
262
    {
263
      if (check)
264
        throw std::logic_error(error_origin_scope_ + std::string(__PRETTY_FUNCTION__) +
265
                               ": shared_ptr param is null");
266
      return nullptr;
267
    }
268
    if constexpr (!std::is_same_v<T, Derived>)
269
    {
270
      if (auto derived_value = std::dynamic_pointer_cast<Derived>(value))
271
        return derived_value;
272

273
      throw std::logic_error(error_origin_scope_ + std::string(__PRETTY_FUNCTION__) +
274
                             ": Supplied object is not derived from " + typeid(T).name());
275
    }
276
    else
277
    {
278
      return value;
279
    }
280
  }
281

282
  /**
283
   * Converts the parameters of an array-type parameter block to a vector of primitive types and
284
   * returns it.
285
   */
286
  template <typename T>
287
  std::vector<T> GetVectorValue() const
3,613✔
288
  {
289
    if (GetType() != ParameterBlockType::ARRAY)
3,613✔
UNCOV
290
      throw std::logic_error(error_origin_scope_ + std::string(__PRETTY_FUNCTION__) +
×
UNCOV
291
                             ": Invalid type requested for parameter of type " +
×
UNCOV
292
                             ParameterBlockTypeName(GetType()));
×
293

294
    std::vector<T> vec;
3,613✔
295
    if (parameters_.empty())
3,613✔
296
      return vec;
297

298
    // Check the first sub-param is of the right type
299
    const auto& front_param = parameters_.front();
300

301
    // Check that all other parameters are of the required type
302
    for (const auto& param : parameters_)
68,151✔
303
      if (param.GetType() != front_param.GetType())
65,498✔
UNCOV
304
        throw std::logic_error(error_origin_scope_ + " " + std::string(__PRETTY_FUNCTION__) +
×
UNCOV
305
                               ": Parameter \"" + name_ +
×
306
                               "\", cannot construct vector from block because "
UNCOV
307
                               "the sub_parameters do not all have the correct type. param->" +
×
UNCOV
308
                               ParameterBlockTypeName(param.GetType()) + " vs param0->" +
×
UNCOV
309
                               ParameterBlockTypeName(front_param.GetType()));
×
310

311
    const size_t num_params = parameters_.size();
2,653✔
312
    for (size_t k = 0; k < num_params; ++k)
68,151✔
313
    {
314
      const auto& param = GetParam(k);
65,498✔
315
      vec.push_back(param.GetValue<T>());
65,571✔
316
    }
317

318
    return vec;
UNCOV
319
  }
×
320

321
  /// Gets a vector of primitive types from an array-type parameter block specified as a parameter
322
  /// of the current block.
323
  template <typename T>
324
  std::vector<T> GetParamVectorValue(const std::string& param_name) const
2,476✔
325
  {
326
    const auto& param = GetParam(param_name);
2,476✔
327
    return param.GetVectorValue<T>();
2,476✔
328
  }
12,871✔
329

2,692✔
330
  // Iterator
2,692✔
331
  class Iterator
2,692✔
332
  {
749✔
UNCOV
333
  public:
×
334
    ParameterBlock& ref_block;
749✔
335
    size_t ref_id;
1,547✔
336

2,692✔
337
    Iterator(ParameterBlock& block, size_t i) : ref_block(block), ref_id(i) {}
5,546✔
338

10,412✔
339
    Iterator operator++()
340
    {
341
      Iterator i = *this;
342
      ref_id++;
343
      return i;
344
    }
345
    Iterator operator++(int)
346
    {
347
      ref_id++;
348
      return *this;
349
    }
350

351
    ParameterBlock& operator*() { return ref_block.parameters_[ref_id]; }
352
    bool operator==(const Iterator& rhs) const { return ref_id == rhs.ref_id; }
353
    bool operator!=(const Iterator& rhs) const { return ref_id != rhs.ref_id; }
354
  };
355

356
  class ConstIterator
357
  {
358
  public:
359
    const ParameterBlock& ref_block;
360
    size_t ref_id;
361

362
    ConstIterator(const ParameterBlock& block, size_t i) : ref_block(block), ref_id(i) {}
1,013✔
363

364
    ConstIterator operator++()
1,102✔
365
    {
366
      ConstIterator i = *this;
1,102✔
367
      ref_id++;
1,102✔
368
      return i;
1,102✔
369
    }
370
    ConstIterator operator++(int)
371
    {
372
      ref_id++;
373
      return *this;
374
    }
375

376
    const ParameterBlock& operator*() { return ref_block.parameters_[ref_id]; }
1,102✔
377
    bool operator==(const ConstIterator& rhs) const { return ref_id == rhs.ref_id; }
378
    bool operator!=(const ConstIterator& rhs) const { return ref_id != rhs.ref_id; }
1,023✔
379
  };
380

381
  Iterator begin() { return {*this, 0}; }
382
  Iterator end() { return {*this, parameters_.size()}; }
383

384
  ConstIterator begin() const { return {*this, 0}; }
1,013✔
385
  ConstIterator end() const { return {*this, parameters_.size()}; }
1,013✔
386

4✔
UNCOV
387
  /**
×
UNCOV
388
   * Given a reference to a string, recursively travels the parameter tree and print values into
×
UNCOV
389
   * the reference string.
×
UNCOV
390
   */
×
UNCOV
391
  void RecursiveDumpToString(std::string& outstr, const std::string& offset = "") const;
×
UNCOV
392

×
UNCOV
393
  /// Print the block tree structure into a designated string.
×
394
  void RecursiveDumpToJSON(std::string& outstr) const;
×
395

12,489,302✔
396
private:
396✔
397
  ParameterBlockType type_ = ParameterBlockType::BLOCK;
396✔
398
  std::string name_;
×
399
  std::shared_ptr<Varying> value_ptr_ = nullptr;
×
400
  std::vector<ParameterBlock> parameters_;
100✔
401
  std::string error_origin_scope_ = "Unknown Scope";
100✔
402
};
100✔
403

404
} // namespace opensn
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc