https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MappingReporter.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// Stocastic Tools Includes
11#include "MappingReporter.h"
12#include "NonlinearSystemBase.h"
13#include "libmesh/parallel_sync.h"
14#include "VectorPacker.h"
15
16#include "Sampler.h"
17
18registerMooseObject("StochasticToolsApp", MappingReporter);
19
22{
27 "A reporter which can map full solution fields to a latent space for given variables.");
28 params.addRequiredParam<UserObjectName>("mapping", "Name of the mapping object.");
29 params.addRequiredParam<std::vector<VariableName>>(
30 "variables", "The names of the variables which need to be mapped to the latent space.");
31 params.addParam<std::string>("parallel_storage",
32 "The storage space where the snapshots are stored. These snapshots "
33 "are used to build the mapping. If this parameter is not specified, "
34 "the reporter will fetch the variable from the nonlinear system.");
35 params.addParam<SamplerName>(
36 "sampler",
37 "Sampler be able to identify how the samples are distributed among "
38 "the processes. Only needed if parallel storage is defined. It is important to have the "
39 "same sampler here as the one used to prepare the snapshots in the parallel storage.");
40 return params;
41}
42
44 : StochasticReporter(parameters),
45 MappingInterface(this),
46 _parallel_storage(isParamValid("parallel_storage")
47 ? &getUserObject<ParallelSolutionStorage>("parallel_storage")
48 : nullptr),
49 _sampler(isParamValid("sampler") ? &getSampler("sampler") : nullptr),
50 _mapping_name(getParam<UserObjectName>("mapping")),
51 _variable_names(getParam<std::vector<VariableName>>("variables"))
52{
54 {
55 if (_sampler)
56 {
57 // Declaring the reporters for every variable. This is a collection of vectors which describe
58 // the coordinates of the solution fields in the latent space.
60 for (auto var_i : index_range(_variable_names))
61 {
62 _vector_real_values_parallel_storage[var_i] = &declareStochasticReporter<std::vector<Real>>(
63 _variable_names[var_i] + "_" + _mapping_name, *_sampler);
64 }
65 }
66 else
67 paramError("sampler",
68 "We need a sampler object if the parallel storage is supplied! The sampler object "
69 "shall be the same as the one used to generate the solution fields in the "
70 "parallel storage object.");
71 }
72 else
73 {
74 // Declaring the reporters for every variable. This is a collection of vectors which describe
75 // the coordinates of the solution fields in the latent space.
77 for (auto var_i : index_range(_variable_names))
78 _vector_real_values[var_i] = &declareValueByName<std::vector<Real>>(
80 }
81}
82
83void
88
89void
91{
92 // We have two execution modes. If the parallel storage is supplied we loop over the snapshots in
93 // the parallel storage, and project them to obtain their coefficients.
96 // The alternative option is to just fetch the variables and reduce them
97 else
99}
100
101void
103{
104 // If the mapping is not built yet, we shall build it using the solutions in the parallel
105 // storage. The conditional process is decided in the mapping object.
106 for (const auto & var : _variable_names)
108
109 // Since the solution fields can be distributed among the processes of each sub-application
110 // (unlike samples and reporter values which are just on the root process), we need to use the
111 // information in the sampler to check which solution is where.
112 const auto rank_config = _sampler->getRankConfig(true);
113
114 // We need to do some parallel communication in case we have snapshots on processes other than
115 // the roots of the sub-applications. This will collect the vectors that we need to send in the
116 // following format:
117 // <to which processor, (variable index, global sample index, solution field)>
118 std::unordered_map<processor_id_type,
119 std::vector<std::tuple<unsigned int, unsigned int, std::vector<Real>>>>
120 send_map;
121
122 // We need to use the rank config here to ensure we are looping on the non-root processors
123 // too
124 for (const auto sample_i : make_range(rank_config.num_local_sims))
125 {
126 std::vector<Real> data = _sampler->getNextLocalRow();
127
128 // Converting the local indexing to global sample indices
129 const unsigned int global_i = sample_i + _sampler->getLocalRowBegin();
130
131 for (const auto var_i : index_range(_variable_names))
132 {
133 // Create a temporary storage for the coordinates in the latent space
134 std::vector<Real> local_vector;
135
136 // Check if the current process has this global sample
138 {
139 // Fetch the solution vector for the given sample index and variable
140 const auto & full_vector =
142
143 // At the moment we only support simulations which have only one solution field
144 // per sample. This is typically a steady-state simulation.
145 if (full_vector.size() != 1)
146 mooseError("MappingReporter is only supported for simulations with one solution "
147 "field per run!");
148
149 // We use the mapping object to generate the coordinates in the latent space
150 _mapping->map(_variable_names[var_i], global_i, local_vector);
151
152 // If we are on the root processor of the sub-application, we simply insert the result
153 // into the reporter storage space. Othervise we will send it to the root process.
154 if (rank_config.is_first_local_rank)
155 (*_vector_real_values_parallel_storage[var_i])[sample_i] = local_vector;
156 else
157 send_map[rank_config.my_first_rank].emplace_back(
158 var_i, sample_i, std::move(local_vector));
159 }
160 }
161 }
162
163 // This functor describes what we do when we receive the samples from other processes
164 auto receive_functor =
165 [this](processor_id_type /*pid*/,
166 const std::vector<std::tuple<unsigned int, unsigned int, std::vector<Real>>> & vectors)
167 {
168 // We unpack the tuples and insert the values into the reporter
169 for (const auto & [var_i, sample_i, vector] : vectors)
170 (*_vector_real_values_parallel_storage[var_i])[sample_i] = std::move(vector);
171 };
172
173 // We send the results from the non-root processors to the root processors
174 Parallel::push_parallel_packed_range(_communicator, send_map, (void *)nullptr, receive_functor);
175}
176
177void
179{
181
182 for (unsigned int var_i = 0; var_i < _variable_names.size(); ++var_i)
183 {
184 // Getting the corresponding DoF indices for the variable.
186
187 // We need to serialize the solution on the root process first.
188 DenseVector<Real> serialized_solution;
189 nl.solution().localize(serialized_solution.get_values(),
191 : std::vector<dof_id_type>());
192 // We map the solution into the latent space and save the solutions in one go
193 if (processor_id() == 0)
194 _mapping->map(_variable_names[var_i], serialized_solution, *_vector_real_values[var_i]);
195 }
196}
registerMooseObject("StochasticToolsApp", MappingReporter)
const ReporterMode REPORTER_MODE_ROOT
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
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)
An interface class that helps getting access to Mapping objects.
static InputParameters validParams()
VariableMappingBase & getMappingByName(const UserObjectName &name) const
Get the mapping by supplying the name of the object in the warehouse.
A tool to reduce solution fields to coordinates in the latent space.
void mapVariableData()
Map the available data in variables into the latent space.
VariableMappingBase * _mapping
Link to the mapping object, we need this to be a pointer due to the fact that we can only fetch this ...
void mapParallelStorageData()
Map the available data in a parallel storage into the latent space.
std::vector< std::vector< std::vector< Real > > * > _vector_real_values_parallel_storage
static InputParameters validParams()
void initialSetup() override
std::vector< std::vector< Real > * > _vector_real_values
MappingReporter(const InputParameters &parameters)
const ParallelSolutionStorage *const _parallel_storage
If we already have solution fields stored from previous runs, we can use their ParallelStorageObject ...
virtual void execute() override
Sampler *const _sampler
We only need the sampler to check which coefficients would go to which processor in case a ParallelSo...
const UserObjectName & _mapping_name
The name of the mapping object we would like to use.
const std::vector< VariableName > & _variable_names
The variables we would like to map.
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
A Reporter which stores serialized solution fields for given variables in a distributed fashion.
bool hasGlobalSample(unsigned int global_sample_i, const VariableName &variable) const
Determine if we have the solution vector with a given global sample index for a given variable.
const std::vector< DenseVector< Real > > & getGlobalSample(unsigned int global_sample_i, const VariableName &variable) const
Get the serialized solution field which is associated with a given global sample index and variable.
T & declareValueByName(const ReporterValueName &value_name, Args &&... args)
static InputParameters validParams()
std::vector< Real > getNextLocalRow()
dof_id_type getLocalRowBegin() const
const LocalRankConfig & getRankConfig(bool batch_mode) const
static InputParameters validParams()
const std::vector< dof_id_type > & getVariableGlobalDoFs()
void setVariableGlobalDoFs(const std::string &var_name)
NumericVector< Number > & solution()
FEProblemBase & _fe_problem
virtual void map(const VariableName &vname, const DenseVector< Real > &full_order_vector, std::vector< Real > &reduced_order_vector) const =0
Map a full-order solution vector (in DenseVector format) for a given variable into a reduced-order ve...
virtual void buildMapping(const VariableName &vname)=0
Abstract function for building mapping for a given variable.
virtual void localize(std::vector< T > &v_local) const=0
const Parallel::Communicator & _communicator
processor_id_type processor_id() const