https://mooseframework.inl.gov
Loading...
Searching...
No Matches
InverseMapping.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "InverseMapping.h"
11#include "SubProblem.h"
12#include "Assembly.h"
13#include "NonlinearSystemBase.h"
14
15#include "libmesh/sparse_matrix.h"
16
17registerMooseObject("StochasticToolsApp", InverseMapping);
18
21{
23
24 params.addClassDescription("Evaluates surrogate models and maps the results back to a full "
25 "solution field for given variables.");
26 params.addParam<std::vector<UserObjectName>>(
27 "surrogate", std::vector<UserObjectName>(), "The names of the surrogates for each variable.");
28 params.addRequiredParam<UserObjectName>(
29 "mapping", "The name of the mapping object which provides the inverse mapping function.");
30 params.addRequiredParam<std::vector<VariableName>>(
31 "variable_to_fill",
32 "The names of the variables that this object is supposed to populate with the "
33 "reconstructed results.");
34 params.addRequiredParam<std::vector<VariableName>>(
35 "variable_to_reconstruct",
36 "The names of the variables in the nonlinear system which we would like to approximate. This "
37 "is important for DoF information.");
38 params.addRequiredParam<std::vector<Real>>(
39 "parameters",
40 "The input parameters for the surrogate. If no surrogate is supplied these are assumed to be "
41 "the coordinates in the latent space.");
42 params.declareControllable("parameters");
43
44 return params;
45}
46
48 : GeneralUserObject(parameters),
49 MappingInterface(this),
51 _var_names_to_fill(getParam<std::vector<VariableName>>("variable_to_fill")),
52 _var_names_to_reconstruct(getParam<std::vector<VariableName>>("variable_to_reconstruct")),
53 _surrogate_model_names(getParam<std::vector<UserObjectName>>("surrogate")),
54 _input_parameters(getParam<std::vector<Real>>("parameters"))
55{
57 paramError("variable_to_fill",
58 "The number of variables to fill should be the same as the number of entries in "
59 "`variable_to_reconstruct`");
60 if (_surrogate_model_names.size())
61 {
62 if (_var_names_to_fill.size() != _surrogate_model_names.size())
63 paramError("surrogate",
64 "The number of surrogates should match the number of variables which need to be "
65 "reconstructed!");
66 }
67}
68
69void
71{
72 _mapping = &getMapping("mapping");
73
74 _surrogate_models.clear();
75 for (const auto & name : _surrogate_model_names)
77
78 _variable_to_fill.clear();
80
81 const auto & mapping_variable_names = _mapping->getVariableNames();
82
83 // We query the links to the MooseVariables mentioned in the input parameters
84 for (const auto & var_i : index_range(_var_names_to_reconstruct))
85 {
86 if (std::find(mapping_variable_names.begin(),
87 mapping_variable_names.end(),
88 _var_names_to_reconstruct[var_i]) == mapping_variable_names.end())
89 paramError("variable_to_reconstruct",
90 "Couldn't find mapping for " + _var_names_to_reconstruct[var_i] +
91 "! Double check the training process and make sure that the mapping includes "
92 "the given variable!");
93
97
98 auto & fe_type_reconstruct = _variable_to_reconstruct.back()->feType();
99 auto & fe_type_fill = _variable_to_fill.back()->feType();
100
101 if (fe_type_reconstruct != fe_type_fill)
102 paramError("variable_to_fill",
103 "The FEtype should match the ones defined for `variable_to_reconstruct`");
104
105 if (fe_type_reconstruct.family == SCALAR)
106 paramError("variable_to_fill", "InverseMapping does not support SCALAR variables!");
107 }
108}
109
110void
112{
113 for (auto var_i : index_range(_var_names_to_reconstruct))
114 {
115 MooseVariableFieldBase & var_to_fill = *_variable_to_fill[var_i];
116 MooseVariableFieldBase & var_to_reconstruct = *_variable_to_reconstruct[var_i];
117
118 // We create a temporary solution vector that will store the reconstructed solution.
119 std::unique_ptr<NumericVector<Number>> temporary_vector =
120 var_to_reconstruct.sys().solution().zero_clone();
121
122 std::vector<Real> reduced_coefficients;
123 if (_surrogate_models.size())
124 _surrogate_models[var_i]->evaluate(_input_parameters, reduced_coefficients);
125 else
126 reduced_coefficients = _input_parameters;
127
128 // The sanity check on the size of reduced_coefficients is happening in the inverse mapping
129 // function
130 DenseVector<Real> reconstructed_solution;
132 _var_names_to_reconstruct[var_i], reduced_coefficients, reconstructed_solution);
133
134 // We set the global DoF indices of the requested variable. The underlying assumption here is
135 // that we are reconstructing the solution in an application which has the same ordering in the
136 // extracted `dofs` vector as the one which was used to serialize the solution vectors in
137 // `SerializedSolutionTransfer`.
138 var_to_reconstruct.sys().setVariableGlobalDoFs(_var_names_to_reconstruct[var_i]);
139
140 // Get the DoF indices
141 const auto & dofs = var_to_reconstruct.sys().getVariableGlobalDoFs();
142
143 // Get the dof map to be able to determine the local dofs easily
144 const auto & dof_map = var_to_reconstruct.sys().system().get_dof_map();
145 dof_id_type local_dof_begin = dof_map.first_dof();
146 dof_id_type local_dof_end = dof_map.end_dof();
147
148 // Populate the temporary vector with the reconstructed solution
149 for (const auto & dof_i : index_range(dofs))
150 if (dofs[dof_i] >= local_dof_begin && dofs[dof_i] < local_dof_end)
151 temporary_vector->set(dofs[dof_i], reconstructed_solution(dof_i));
152
153 // Get the system and variable numbers for the dof objects
154 unsigned int to_sys_num = _variable_to_fill[var_i]->sys().system().number();
155 unsigned int to_var_num = var_to_fill.sys().system().variable_number(_var_names_to_fill[var_i]);
156
157 unsigned int from_sys_num = var_to_reconstruct.sys().system().number();
158 unsigned int from_var_num =
159 var_to_reconstruct.sys().system().variable_number(_var_names_to_reconstruct[var_i]);
160
161 // Get a link to the mesh for the loops over dof objects
162 const MeshBase & to_mesh = _fe_problem.mesh().getMesh();
163
164 // First, we cover nodal degrees of freedom.
165 for (const auto & node : to_mesh.local_node_ptr_range())
166 {
167 const auto n_dofs = node->n_dofs(to_sys_num, to_var_num);
168 // We have nothing to do if we don't have dofs at this node
169 if (n_dofs < 1)
170 continue;
171
172 // For special cases we might have multiple dofs for the same node (hierarchic types)
173 for (auto dof_i : make_range(n_dofs))
174 {
175 // Get the dof ids for the from/to variables
176 const auto & to_dof_id = node->dof_number(to_sys_num, to_var_num, dof_i);
177 const auto & from_dof_id = node->dof_number(from_sys_num, from_var_num, dof_i);
178
179 // Fill the dof of the variable using the dof of the temporary variable
180 var_to_fill.sys().solution().set(to_dof_id, (*temporary_vector)(from_dof_id));
181 }
182 }
183
184 // Then we move on to element-based degrees of freedom. Considering that we don't
185 // support scalar variables at the moment, this should take care of every remaining
186 // local entry. Of course, we'll only need this part if the variable is not nodal.
187 if (!_variable_to_reconstruct[var_i]->isNodal())
188 for (auto & elem : as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
189 {
190 // Check how many dofs we have on the current element, if none we have nothing to do
191 const auto n_dofs = elem->n_dofs(to_sys_num, to_var_num);
192 if (n_dofs < 1)
193 continue;
194
195 // Loop over the dofs and populate the variable
196 for (auto dof_i : make_range(n_dofs))
197 {
198 // Get the dof for the from/to variables
199 const auto & to_dof_id = elem->dof_number(to_sys_num, to_var_num, dof_i);
200 const auto & from_dof_id = elem->dof_number(from_sys_num, from_var_num, dof_i);
201
202 var_to_fill.sys().solution().set(to_dof_id, (*temporary_vector)(from_dof_id));
203 }
204 }
205
206 // Close the solution to make sure we can output the variable
207 var_to_fill.sys().solution().close();
208 }
209}
registerMooseObject("StochasticToolsApp", InverseMapping)
T evaluate(Real, const Point &)
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
virtual MooseMesh & mesh() override
static InputParameters validParams()
void declareControllable(const std::string &name, std::set< ExecFlagType > execute_flags={})
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
A user object which takes a surrogate (or just user supplied values) to determine coordinates in a la...
const std::vector< VariableName > & _var_names_to_reconstruct
The names of the variables in the nonlinear system whose reconstruction we are working on.
void initialSetup() override
std::vector< SurrogateModel * > _surrogate_models
Links to the surrogate models which provide functions to determine the coordinates in the latent spac...
static InputParameters validParams()
std::vector< MooseVariableFieldBase * > _variable_to_reconstruct
Links to the MooseVariables from the nonlinear system whose dof numbering we need to populate the var...
InverseMapping(const InputParameters &params)
std::vector< MooseVariableFieldBase * > _variable_to_fill
Links to the MooseVariables of the requested variables.
VariableMappingBase * _mapping
Link to the mapping object which provides the inverse mapping function.
void execute() override
const std::vector< VariableName > & _var_names_to_fill
The names of the variables which serve as a container for the reconstructed solution.
const std::vector< UserObjectName > & _surrogate_model_names
The names of the surrogate models for each variable.
const std::vector< Real > & _input_parameters
Input parameters for the surrogate models.
An interface class that helps getting access to Mapping objects.
VariableMappingBase & getMapping(const std::string &name) const
Get the mapping using the parameters of the moose object.
const std::string & name() const
void paramError(const std::string &param, Args... args) const
MeshBase & getMesh()
SystemBase & sys()
Interface for objects that need to use samplers.
T & getSurrogateModelByName(const UserObjectName &name) const
Get a sampler with a given name.
const std::vector< dof_id_type > & getVariableGlobalDoFs()
void setVariableGlobalDoFs(const std::string &var_name)
NumericVector< Number > & solution()
virtual libMesh::System & system()=0
FEProblemBase & _fe_problem
const THREAD_ID _tid
virtual const std::vector< VariableName > & getVariableNames()
Get the available variable names in this mapping.
virtual void inverse_map(const VariableName &vname, const std::vector< Real > &reduced_order_vector, DenseVector< Real > &full_order_vector) const =0
Map a reduced-order vector (from the latent space) back to a full-order solution vector (in DenseVect...
virtual void set(const numeric_index_type i, const T value)=0
virtual void close()=0
virtual std::unique_ptr< NumericVector< T > > zero_clone() const=0
unsigned int variable_number(std::string_view var) const
const DofMap & get_dof_map() const
unsigned int number() const