NEML2 2.0.0
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
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/Settings.h"
32#include "neml2/base/NEML2Object.h"
33#include "neml2/base/OptionCollection.h"
34
35namespace neml2
36{
37// Forward decl
38class Settings;
39
51void load_input(const std::filesystem::path & path, const std::string & additional_input = "");
52
65void reload_input(const std::filesystem::path & path, const std::string & additional_input = "");
66
73{
74public:
76 static Factory & get();
77
79 static OptionCollection & options();
80
87 static void load_options(const OptionCollection & all_options);
88
90 static bool has_object(const std::string & section, const std::string & name);
91
108 template <class T>
109 static std::shared_ptr<T> get_object_ptr(const std::string & section,
110 const std::string & name,
111 const OptionSet & additional_options = OptionSet(),
112 bool force_create = true);
113
130 template <class T>
131 static T & get_object(const std::string & section,
132 const std::string & name,
133 const OptionSet & additional_options = OptionSet(),
134 bool force_create = true);
135
137 static void clear();
138
144 static void print(std::ostream & os = std::cout);
145
146protected:
153 void create_object(const std::string & section, const OptionSet & options);
154
155private:
160 std::map<std::string, std::map<std::string, std::vector<std::shared_ptr<NEML2Object>>>> _objects;
161};
162
163template <class T>
164inline std::shared_ptr<T>
165Factory::get_object_ptr(const std::string & section,
166 const std::string & name,
167 const OptionSet & additional_options,
168 bool force_create)
169{
170 auto & factory = Factory::get();
171
172 if (Factory::options().data().empty())
173 throw FactoryException("It appears that you are trying to get an object without loading any "
174 "options. Please load options first.");
175
176 // Easy if it already exists
177 if (!force_create)
178 if (factory._objects.count(section) && factory._objects.at(section).count(name))
179 for (const auto & neml2_obj : factory._objects[section][name])
180 {
181 // Check for option clash
182 if (!options_compatible(neml2_obj->input_options(), additional_options))
183 continue;
184
185 // Check for object type
186 auto obj = std::dynamic_pointer_cast<T>(neml2_obj);
187 if (!obj)
188 throw FactoryException(
189 "Found object named " + name + " under section " + section +
190 ". But dynamic cast failed. Did you specify the correct object type?");
191
192 return obj;
193 }
194
195 // Otherwise try to create it
196 for (auto & options : Factory::options()[section])
197 if (options.first == name)
198 {
199 auto new_options = options.second;
200 new_options += additional_options;
201 factory.create_object(section, new_options);
202 break;
203 }
204
205 if (!factory._objects.count(section) || !factory._objects.at(section).count(name))
206 throw FactoryException("Failed to get object named " + name + " under section " + section);
207
208 auto obj = std::dynamic_pointer_cast<T>(factory._objects[section][name].back());
209
210 if (!obj)
211 throw FactoryException("Internal error: Factory failed to create object " + name);
212
213 return obj;
214}
215
216template <class T>
217inline T &
218Factory::get_object(const std::string & section,
219 const std::string & name,
220 const OptionSet & additional_options,
221 bool force_create)
222{
223 return *Factory::get_object_ptr<T>(section, name, additional_options, force_create);
224}
225} // namespace neml2
Definition errors.h:73
Definition Factory.h:73
static OptionCollection & options()
Get the global options singleton.
Definition Factory.cxx:66
void create_object(const std::string &section, const OptionSet &options)
Manufacture a single NEML2Object.
Definition Factory.cxx:87
static T & get_object(const std::string &section, const std::string &name, const OptionSet &additional_options=OptionSet(), bool force_create=true)
Retrive an object reference under the given section with the given object name.
Definition Factory.h:218
static std::shared_ptr< T > get_object_ptr(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:165
static void load_options(const OptionCollection &all_options)
Provide all objects' options to the factory. The factory is ready to manufacture objects after this c...
Definition Factory.cxx:80
static 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:73
static void clear()
Delete all factories and destruct all the objects.
Definition Factory.cxx:122
static Factory & get()
Get the Factory singleton.
Definition Factory.cxx:59
static void print(std::ostream &os=std::cout)
List all the manufactured objects.
Definition Factory.cxx:109
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:52
Definition Settings.h:32
Definition DiagnosticsInterface.cxx:30
bool options_compatible(const OptionSet &opts, const OptionSet &additional_opts)
Definition OptionSet.cxx:34
std::string name(ElasticConstant p)
Definition ElasticityConverter.cxx:30
void reload_input(const std::filesystem::path &path, const std::string &additional_input)
Similar to neml2::load_input, but additionally clear the Factory before loading the options,...
Definition Factory.cxx:52
void 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:35