NEML2 2.1.0
Loading...
Searching...
No Matches
OptionSet.h
1// Copyright 2024, UChicago Argonne, LLC
2// All Rights Reserved
3// Software Name: NEML2 -- the New Engineering material Model Library, version 2
4// By: Argonne National Laboratory
5// OPEN SOURCE LICENSE (MIT)
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23// THE SOFTWARE.
24
25#pragma once
26
27#include <map>
28#include <string>
29#include <memory>
30
31#include "neml2/base/Option.h"
32#include "neml2/misc/errors.h"
33#include "neml2/misc/string_utils.h"
34#include "neml2/misc/types.h"
35
36namespace neml2
37{
38// Forward decl
39class OptionSet;
40template <typename T>
41struct TensorName;
42
43bool options_compatible(const OptionSet & opts, const OptionSet & additional_opts);
44
45// Streaming operators
46std::ostream & operator<<(std::ostream & os, const OptionSet & p);
47
54{
55public:
56 OptionSet() = default;
57
59 OptionSet(OptionSet &&) noexcept;
60 OptionSet & operator=(const OptionSet &);
61 OptionSet & operator=(OptionSet &&) noexcept;
62 virtual ~OptionSet() = default;
63
65
72 void operator+=(const OptionSet & source);
73 void operator+=(OptionSet && source);
75
77 const std::string & name() const { return _metadata.name; }
79 std::string & name() { return _metadata.name; }
81 const std::string & type() const { return _metadata.type; }
83 std::string & type() { return _metadata.type; }
85 const std::string & path() const { return _metadata.path; }
87 std::string & path() { return _metadata.path; }
89 const std::string & doc() const { return _metadata.doc; }
91 std::string & doc() { return _metadata.doc; }
93 const std::string & section() const { return _metadata.section; }
95 std::string & section() { return _metadata.section; }
96
98 bool contains(const std::string &) const;
99
101 bool user_specified(const std::string & name) const;
102
104 bool defined(const std::string & name) const;
105
107 void suppress(const std::string & name);
108
110 std::size_t size() const { return _values.size(); }
111
113 void clear();
114
116 std::string to_str() const;
117
122 template <typename T>
123 T get(const std::string &) const;
124
126 const OptionBase & get(const std::string &) const;
127
138 template <typename K, typename V>
139 std::map<K, V> get_map(const std::string &, const std::string &) const;
140
162 template <typename T, FType f = FType::NONE>
163 void add(const std::string & name, const T & default_value, std::string doc);
164
187 template <typename T, FType f = FType::NONE>
188 void add(const std::string & name, std::string doc);
189
212 template <typename T, FType f = FType::NONE>
213 void add_optional(const std::string & name, std::string doc);
214
230 template <typename T>
231 void add_private(const std::string & name, const T & default_value);
232
247 template <typename T>
248 void set(const std::string & name, const T & value);
249
264 template <typename T>
265 void set_private(const std::string & name, const T & value);
266
269 void add_input(const std::string &, const VariableName &, std::string);
270 void add_input(const std::string &, std::string);
271 void add_optional_input(const std::string &, std::string);
273 void add_output(const std::string &, const VariableName &, std::string);
274 void add_output(const std::string &, std::string);
275 void add_optional_output(const std::string &, std::string);
277 template <typename T>
278 void add_parameter(const std::string &, const TensorName<T> &, std::string);
279 template <typename T>
280 void add_parameter(const std::string &, std::string);
282 template <typename T>
283 void add_buffer(const std::string &, const TensorName<T> &, std::string);
284 template <typename T>
285 void add_buffer(const std::string &, std::string);
287
289 using map_type = std::map<std::string, std::unique_ptr<OptionBase>, std::less<>>;
291 using iterator = map_type::iterator;
293 using const_iterator = map_type::const_iterator;
294
303
304protected:
308 struct Metadata
309 {
323 std::string name = "";
330 std::string type = "";
349 std::string path = "";
360 std::string doc = "";
368 std::string section = "";
370
373};
374
376// Implementation
378
379template <typename T>
380T
381OptionSet::get(const std::string & name) const
382{
383 if (!this->contains(name))
384 throw NEMLException("ERROR: no option named \"" + name + "\" found.\n\nKnown options:\n" +
385 to_str());
386
387 auto * opt_base = _values.at(name).get();
388 if (!opt_base->defined())
389 throw NEMLException("ERROR: option named \"" + name +
390 "\" is being accessed before it is defined.");
391
392 auto ptr = dynamic_cast<Option<T> *>(opt_base);
393 if (!ptr)
394 throw NEMLException("ERROR: option named \"" + name +
395 "\" is not of the requested type: " + opt_base->type());
396 return ptr->get();
397}
398
399template <typename K, typename V>
400std::map<K, V>
401OptionSet::get_map(const std::string & key_option, const std::string & value_option) const
402{
403 const auto keys = this->get<std::vector<K>>(key_option);
404 const auto values = this->get<std::vector<V>>(value_option);
405 if (keys.size() != values.size())
406 throw NEMLException("Trying to build a map from '" + key_option + "' and '" + value_option +
407 "' with " + std::to_string(keys.size()) + " keys and " +
408 std::to_string(values.size()) + " values.");
409 std::map<K, V> result;
410 for (size_t i = 0; i < keys.size(); i++)
411 {
412 if (result.find(keys[i]) != result.end())
413 throw NEMLException("Trying to build a map from '" + key_option + "' and '" + value_option +
414 "' with duplicate key: " + utils::stringify(keys[i]));
415 result[keys[i]] = values[i];
416 }
417 return result;
418}
419
420template <typename T, FType F>
421void
422OptionSet::add(const std::string & name, const T & default_value, std::string doc)
423{
424 if (this->contains(name))
425 throw NEMLException("Trying to add option '" + name +
426 "', but an option with the same name already exists.");
427 _values[name] = std::make_unique<Option<T>>(name);
428 auto ptr = dynamic_cast<Option<T> *>(_values[name].get());
429
430 // docstring and Ftype are always needed
431 ptr->doc() = std::move(doc);
432 ptr->ftype() = F;
433
434 // default value
435 ptr->set() = default_value;
436
437 // metadata
438 ptr->required() = false;
439 ptr->suppressed() = false;
440 ptr->user_specified() = false;
441 ptr->defined() = true;
442}
443
444template <typename T, FType F>
445void
446OptionSet::add(const std::string & name, std::string doc)
447{
448 if (this->contains(name))
449 throw NEMLException("Trying to add option '" + name +
450 "', but an option with the same name already exists.");
451 _values[name] = std::make_unique<Option<T>>(name);
452 auto ptr = dynamic_cast<Option<T> *>(_values[name].get());
453
454 // docstring and Ftype are always needed
455 ptr->doc() = std::move(doc);
456 ptr->ftype() = F;
457
458 // metadata
459 ptr->required() = true;
460 ptr->suppressed() = false;
461 ptr->user_specified() = false;
462 ptr->defined() = false;
463}
464
465template <typename T, FType F>
466void
467OptionSet::add_optional(const std::string & name, std::string doc)
468{
469 if (this->contains(name))
470 throw NEMLException("Trying to add option '" + name +
471 "', but an option with the same name already exists.");
472 _values[name] = std::make_unique<Option<T>>(name);
473 auto ptr = dynamic_cast<Option<T> *>(_values[name].get());
474
475 // docstring and Ftype are always needed
476 ptr->doc() = std::move(doc);
477 ptr->ftype() = F;
478
479 // metadata
480 ptr->required() = false;
481 ptr->suppressed() = false;
482 ptr->user_specified() = false;
483 ptr->defined() = false;
484}
485
486template <typename T>
487void
488OptionSet::add_private(const std::string & name, const T & default_value)
489{
490 if (this->contains(name))
491 throw NEMLException("Trying to add a private option '" + name +
492 "', but an option with the same name already exists.");
493 _values[name] = std::make_unique<Option<T>>(name);
494 auto ptr = dynamic_cast<Option<T> *>(_values[name].get());
495
496 // default value
497 ptr->set() = default_value;
498
499 // metadata
500 ptr->required() = false;
501 ptr->suppressed() = true;
502 ptr->user_specified() = false;
503 ptr->defined() = true;
504}
505
506template <typename T>
507void
508OptionSet::set(const std::string & name, const T & value)
509{
510 if (!this->contains(name))
511 throw NEMLException("Trying to set option '" + name + "', but it does not exist.");
512
513 auto ptr = dynamic_cast<Option<T> *>(_values[name].get());
514
515 if (ptr->suppressed())
516 throw NEMLException("Trying to set private option '" + name +
517 "', which is not allowed. Use set_private() instead.");
518
519 // value
520 ptr->set() = value;
521
522 // metadata
523 ptr->user_specified() = false;
524 ptr->defined() = true;
525}
526
527template <typename T>
528void
529OptionSet::set_private(const std::string & name, const T & value)
530{
531 if (!this->contains(name))
532 throw NEMLException("Trying to set private option '" + name + "', but it does not exist.");
533
534 auto ptr = dynamic_cast<Option<T> *>(_values[name].get());
535
536 if (!ptr->suppressed())
537 throw NEMLException("Trying to set private option '" + name +
538 "', but it is not marked as private.");
539
540 // value
541 ptr->set() = value;
542
543 // metadata
544 ptr->user_specified() = false;
545 ptr->defined() = true;
546}
547
548template <typename T>
549void
550OptionSet::add_parameter(const std::string & name,
551 const TensorName<T> & tensor_name,
552 std::string doc)
553{
554 add<TensorName<T>, FType::PARAMETER>(name, tensor_name, std::move(doc));
555}
556
557template <typename T>
558void
559OptionSet::add_parameter(const std::string & name, std::string doc)
560{
562}
563
564template <typename T>
565void
566OptionSet::add_buffer(const std::string & name, const TensorName<T> & tensor_name, std::string doc)
567{
568 add<TensorName<T>, FType::BUFFER>(name, tensor_name, std::move(doc));
569}
570
571template <typename T>
572void
573OptionSet::add_buffer(const std::string & name, std::string doc)
574{
576}
577
578} // namespace neml2
Definition errors.h:34
Definition OptionBase.h:44
A custom map-like data structure. The keys are strings, and the values can be nonhomogeneously typed.
Definition OptionSet.h:54
map_type::iterator iterator
Option map iterator.
Definition OptionSet.h:291
map_type _values
Data structure to map names with values.
Definition OptionSet.h:372
std::map< K, V > get_map(const std::string &, const std::string &) const
Get two options and bind them to form a map.
Definition OptionSet.h:401
void add_input(const std::string &, const VariableName &, std::string)
const std::string & name() const
A readonly reference to the option set's name.
Definition OptionSet.h:77
const_iterator begin() const
Iterator pointing to the beginning of the set of options.
OptionSet()=default
const std::string & type() const
A readonly reference to the option set's type.
Definition OptionSet.h:81
void add_parameter(const std::string &, const TensorName< T > &, std::string)
Convenient methods to add parameter.
Definition OptionSet.h:550
bool defined(const std::string &name) const
OptionSet(const OptionSet &)
std::string to_str() const
Print the contents.
T get(const std::string &) const
Definition OptionSet.h:381
map_type::const_iterator const_iterator
Constant option map iterator.
Definition OptionSet.h:293
std::map< std::string, std::unique_ptr< OptionBase >, std::less<> > map_type
The type of the map that we store internally.
Definition OptionSet.h:289
std::string & name()
A writable reference to the option set's name.
Definition OptionSet.h:79
void add_output(const std::string &, const VariableName &, std::string)
Convenient methods to add output variable.
const OptionBase & get(const std::string &) const
Get a const reference to the specified option value.
std::string & type()
A writable reference to the option set's type.
Definition OptionSet.h:83
const std::string & doc() const
A readonly reference to the option set's docstring.
Definition OptionSet.h:89
void suppress(const std::string &name)
Suppress an option.
void add_optional(const std::string &name, std::string doc)
Create an optional option with its docstring, without a default value.
Definition OptionSet.h:467
const std::string & section() const
A readonly reference to the option set's section.
Definition OptionSet.h:93
void set(const std::string &name, const T &value)
Set an option.
Definition OptionSet.h:508
void add_private(const std::string &name, const T &default_value)
Create a private option with its default value.
Definition OptionSet.h:488
const std::string & path() const
A readonly reference to the option set's path.
Definition OptionSet.h:85
void add_buffer(const std::string &, const TensorName< T > &, std::string)
Convenient methods to add buffer.
Definition OptionSet.h:566
void set_private(const std::string &name, const T &value)
Set a private option.
Definition OptionSet.h:529
std::string & doc()
A writable reference to the option set's docstring.
Definition OptionSet.h:91
bool user_specified(const std::string &name) const
struct neml2::OptionSet::Metadata _metadata
void clear()
Clear internal data structures & frees any allocated memory.
iterator end()
Iterator pointing to the end of the set of options.
const_iterator end() const
Iterator pointing to the end of the set of options.
std::string & path()
A writable reference to the option set's path.
Definition OptionSet.h:87
iterator begin()
Iterator pointing to the beginning of the set of options.
void add(const std::string &name, const T &default_value, std::string doc)
Create an option with its default value and its docstring.
Definition OptionSet.h:422
std::string & section()
A writable reference to the option set's section.
Definition OptionSet.h:95
std::size_t size() const
Definition OptionSet.h:110
bool contains(const std::string &) const
void add_optional_input(const std::string &, std::string)
void add_output(const std::string &, std::string)
void add_input(const std::string &, std::string)
void add_optional_output(const std::string &, std::string)
OptionSet(OptionSet &&) noexcept
Definition Option.h:70
std::string stringify(const T &t)
Definition string_utils.h:70
Definition DiagnosticsInterface.h:31
std::ostream & operator<<(std::ostream &, const EnumSelection &)
bool options_compatible(const OptionSet &opts, const OptionSet &additional_opts)
std::string VariableName
Definition types.h:75
@ BUFFER
Definition types.h:95
@ PARAMETER
Definition types.h:94
Definition OptionSet.h:309
std::string path
Path to the option set.
Definition OptionSet.h:349
std::string type
Type of the option set.
Definition OptionSet.h:330
std::string name
Name of the option set.
Definition OptionSet.h:323
std::string section
Which NEML2 input file section this object belongs to.
Definition OptionSet.h:368
std::string doc
Option set's doc string.
Definition OptionSet.h:360
The name of a tensor object that can be referenced in the input files.
Definition TensorName.h:47