NEML2 1.4.0
Loading...
Searching...
No Matches
HITParser.cxx
1// Copyright 2023, 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#include "neml2/base/HITParser.h"
26#include "neml2/base/Factory.h"
27#include "neml2/base/CrossRef.h"
28#include "neml2/base/Sequence.h"
29#include "neml2/tensors/LabeledAxis.h"
30#include "neml2/tensors/tensors.h"
31#include "neml2/tensors/macros.h"
32#include <memory>
33
34namespace neml2
35{
36OptionCollection
37HITParser::parse(const std::filesystem::path & filename, const std::string & additional_input) const
38{
39 // Open and read the file
40 std::ifstream file(filename);
41 neml_assert(file.is_open(), "Unable to open file ", filename);
42
43 // Read the file into a string
44 std::stringstream buffer;
45 buffer << file.rdbuf();
46 std::string input = buffer.str();
47
48 // Let HIT lex the string
49 std::unique_ptr<hit::Node> root(hit::parse(filename, input));
50 neml_assert(root.get(), "HIT failed to lex the input file: ", filename);
51
52 // Explode the tree
53 hit::explode(root.get());
54
55 // Handle additional input (they could be coming from cli args)
56 std::unique_ptr<hit::Node> cli_root(hit::parse("cliargs", additional_input));
57 hit::explode(cli_root.get());
58 hit::merge(cli_root.get(), root.get());
59
60 // Preevaluate the input
61 hit::BraceExpander expander;
62 hit::EnvEvaler env;
63 hit::RawEvaler raw;
64 expander.registerEvaler("env", env);
65 expander.registerEvaler("raw", raw);
66 root->walk(&expander);
67
68 // Loop over each known section and extract options for each object
70 for (const auto & section : Factory::pipeline)
71 {
72 auto section_node = root->find(section);
73 if (section_node)
74 {
75 auto objects = section_node->children(hit::NodeType::Section);
76 for (auto object : objects)
77 {
78 auto options = extract_object_options(object, section_node);
79 all_options[section][options.name()] = options;
80 }
81 }
82 }
83
84 return all_options;
85}
86
88HITParser::extract_object_options(hit::Node * object, hit::Node * section) const
89{
90 // There is a special field reserved for object type
91 std::string type = object->param<std::string>("type");
92 // Extract the options
93 auto options = Registry::expected_options(type);
94 extract_options(object, options);
95
96 // Also fill in the metadata
97 options.name() = object->path();
98 options.type() = type;
99 options.path() = section->fullpath();
100
101 return options;
102}
103
104void
105HITParser::extract_options(hit::Node * object, OptionSet & options) const
106{
107 for (auto node : object->children(hit::NodeType::Field))
108 if (node->path() != "type")
109 extract_option(node, options);
110}
111
112void
113HITParser::extract_option(hit::Node * n, OptionSet & options) const
114{
115#define extract_option_base(ptype, method) \
116 else if (option->type() == \
117 utils::demangle( \
118 typeid(ptype).name())) dynamic_cast<OptionSet::Option<ptype> *>(option.get()) \
119 ->set() = method(n->strVal())
120
121#define extract_option_t(ptype) \
122 extract_option_base(ptype, utils::parse<ptype>); \
123 extract_option_base(std::vector<ptype>, utils::parse_vector<ptype>); \
124 extract_option_base(std::vector<std::vector<ptype>>, utils::parse_vector_vector<ptype>); \
125 extract_option_base(Sequence<ptype>, utils::parse<Sequence<ptype>>)
126
127#define extract_option_t_cr(ptype) extract_option_t(CrossRef<ptype>)
128
129 if (n->type() == hit::NodeType::Field)
130 {
131 bool found = false;
132 for (auto & [name, option] : options)
133 if (name == n->path())
134 {
135 neml_assert(!option->suppressed(),
136 "Option named '",
137 option->name(),
138 "' is suppressed, and its value cannot be modified.");
139
140 found = true;
141
142 if (false)
143 ;
144 extract_option_t(TorchShape);
145 extract_option_t(bool);
146 extract_option_t(int);
147 extract_option_t(unsigned int);
148 extract_option_t(TorchSize);
149 extract_option_t(Real);
150 extract_option_t(std::string);
151 extract_option_t(VariableName);
152 extract_option_t(CrossRef<torch::Tensor>);
153 FOR_ALL_BATCHTENSORBASE(extract_option_t_cr);
154 // LCOV_EXCL_START
155 else neml_assert(false, "Unsupported option type for option ", n->fullpath());
156 // LCOV_EXCL_STOP
157
158 break;
159 }
160 neml_assert(found, "Unused option ", n->fullpath());
161 }
162}
163} // namespace neml2
The wrapper (decorator) for cross-referencing unresolved values at parse time.
Definition CrossRef.h:52
static std::vector< std::string > pipeline
The sequence which we use to manufacture objects.
Definition Factory.h:42
virtual OptionCollection parse(const std::filesystem::path &filename, const std::string &additional_input="") const override
Deserialize a file.
Definition HITParser.cxx:37
virtual OptionSet extract_object_options(hit::Node *object, hit::Node *section) const
Extract options for a specific object.
Definition HITParser.cxx:88
A data structure that holds options of multiple objects.
Definition OptionCollection.h:38
A custom map-like data structure. The keys are strings, and the values can be nonhomogeneously typed.
Definition OptionSet.h:59
static std::map< std::string, OptionSet > expected_options()
Return the expected options of all registered classs.
Definition Registry.cxx:38
Definition CrossRef.cxx:32
int64_t TorchSize
Definition types.h:33
std::vector< TorchSize > TorchShape
Definition types.h:34
double Real
Definition types.h:31
LabeledAxisAccessor VariableName
Definition Variable.h:35
void neml_assert(bool assertion, Args &&... args)
Definition error.h:73