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