NEML2 2.0.0
Loading...
Searching...
No Matches
Factory.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 <filesystem>
28#include <iostream>
29
30#include "neml2/misc/errors.h"
31#include "neml2/base/InputFile.h"
32
33namespace neml2
34{
35// Forward decl
36class Settings;
37class Factory;
38class NEML2Object;
39class Solver;
40class Data;
41class Model;
42class Driver;
43class WorkScheduler;
44
56std::unique_ptr<Factory> load_input(const std::filesystem::path & path,
57 const std::string & additional_input = "");
58
65{
66public:
68
70 InputFile & input_file() { return _input_file; }
71
73 const InputFile & input_file() const { return _input_file; }
74
76 const std::shared_ptr<Settings> & settings() const { return _input_file.settings(); }
77
79 bool has_object(const std::string & section, const std::string & name);
80
97 template <class T>
98 std::shared_ptr<T> get_object(const std::string & section,
99 const std::string & name,
100 const OptionSet & additional_options = OptionSet(),
101 bool force_create = true);
102
104 template <class T = Solver>
105 std::shared_ptr<T> get_solver(const std::string & name);
107 template <class T = Data>
108 std::shared_ptr<T> get_data(const std::string & name);
110 template <class T = Model>
111 std::shared_ptr<T> get_model(const std::string & name);
113 template <class T = Driver>
114 std::shared_ptr<T> get_driver(const std::string & name);
116 template <class T = WorkScheduler>
117 std::shared_ptr<T> get_scheduler(const std::string & name);
118
120 void clear();
121
127 void print(std::ostream & os = std::cout);
128
129protected:
136 void create_object(const std::string & section, const OptionSet & options);
137
138private:
140 bool options_compatible(const std::shared_ptr<NEML2Object> & obj, const OptionSet & opts) const;
141
143 InputFile _input_file;
144
149 std::map<std::string, std::map<std::string, std::vector<std::shared_ptr<NEML2Object>>>> _objects;
150};
151
152template <class T>
153std::shared_ptr<T>
154Factory::get_object(const std::string & section,
155 const std::string & name,
156 const OptionSet & additional_options,
157 bool force_create)
158{
159 if (input_file().data().empty())
160 throw FactoryException("The input file is empty.");
161
162 // Easy if it already exists
163 if (!force_create)
164 if (_objects.count(section) && _objects.at(section).count(name))
165 for (const auto & neml2_obj : _objects[section][name])
166 {
167 // Check for option clash
168 if (!options_compatible(neml2_obj, additional_options))
169 continue;
170
171 // Check for object type
172 auto obj = std::dynamic_pointer_cast<T>(neml2_obj);
173 if (!obj)
174 throw FactoryException(
175 "Found object named " + name + " under section " + section +
176 ". But dynamic cast failed. Did you specify the correct object type?");
177
178 return obj;
179 }
180
181 // Otherwise try to create it
182 for (const auto & options : _input_file[section])
183 if (options.first == name)
184 {
185 auto new_options = options.second;
186 new_options.set<Factory *>("_factory") = this;
187 new_options.set<std::shared_ptr<Settings>>("_settings") = settings();
188 new_options += additional_options;
189 create_object(section, new_options);
190 break;
191 }
192
193 if (!_objects.count(section) || !_objects.at(section).count(name))
194 throw FactoryException("Failed to get object named " + name + " under section " + section +
195 ". Check to make sure the object is defined in the input file.");
196
197 auto obj = std::dynamic_pointer_cast<T>(_objects[section][name].back());
198
199 if (!obj)
200 throw FactoryException("Internal error: Factory failed to create object " + name);
201
202 return obj;
203}
204
205template <class T>
206std::shared_ptr<T>
207Factory::get_solver(const std::string & name)
208{
209 return get_object<T>("Solvers", name);
210}
211
212template <class T>
213std::shared_ptr<T>
214Factory::get_data(const std::string & name)
215{
216 return get_object<T>("Data", name);
217}
218
219template <class T>
220std::shared_ptr<T>
221Factory::get_model(const std::string & name)
222{
223 return get_object<T>("Models", name);
224}
225
226template <class T>
227std::shared_ptr<T>
228Factory::get_driver(const std::string & name)
229{
230 return get_object<T>("Drivers", name);
231}
232
233template <class T>
234std::shared_ptr<T>
235Factory::get_scheduler(const std::string & name)
236{
237 return get_object<T>("Schedulers", name);
238}
239} // namespace neml2
Definition errors.h:73
Definition Factory.h:65
std::shared_ptr< T > get_object(const std::string &section, const std::string &name, const OptionSet &additional_options=OptionSet(), bool force_create=true)
Retrive an object pointer under the given section with the given object name.
Definition Factory.h:154
std::shared_ptr< T > get_driver(const std::string &name)
Get a driver by its name.
Definition Factory.h:228
std::shared_ptr< T > get_data(const std::string &name)
Get a data by its name.
Definition Factory.h:214
void create_object(const std::string &section, const OptionSet &options)
Manufacture a single NEML2Object.
Definition Factory.cxx:60
const std::shared_ptr< Settings > & settings() const
Global settings.
Definition Factory.h:76
Factory(InputFile)
Definition Factory.cxx:47
std::shared_ptr< T > get_model(const std::string &name)
Get a model by its name.
Definition Factory.h:221
std::shared_ptr< T > get_scheduler(const std::string &name)
Get a scheduler by its name.
Definition Factory.h:235
bool has_object(const std::string &section, const std::string &name)
Check if an object with the given name exists under the given section.
Definition Factory.cxx:54
InputFile & input_file()
Get the input file.
Definition Factory.h:70
const InputFile & input_file() const
Get the input file.
Definition Factory.h:73
void clear()
Delete all factories and destruct all the objects.
Definition Factory.cxx:101
std::shared_ptr< T > get_solver(const std::string &name)
Get a solver by its name.
Definition Factory.h:207
void print(std::ostream &os=std::cout)
List all the manufactured objects.
Definition Factory.cxx:88
A data structure that holds options of multiple objects.
Definition InputFile.h:37
const std::shared_ptr< Settings > & settings() const
Get global settings.
Definition InputFile.h:42
A custom map-like data structure. The keys are strings, and the values can be nonhomogeneously typed.
Definition OptionSet.h:51
Definition DiagnosticsInterface.cxx:30
std::string name(ElasticConstant p)
Definition ElasticityConverter.cxx:30
std::unique_ptr< Factory > load_input(const std::filesystem::path &path, const std::string &additional_input)
A convenient function to parse all options from an input file.
Definition Factory.cxx:34