https://mooseframework.inl.gov
PODReducedBasisSurrogate.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 
11 
12 registerMooseObject("StochasticToolsApp", PODReducedBasisSurrogate);
13 
16 {
18  params.addClassDescription("Evaluates POD-RB surrogate model with reduced operators "
19  "computed from PODReducedBasisTrainer.");
20  params.addParam<std::vector<std::string>>("change_rank",
21  std::vector<std::string>(0),
22  "Names of variables whose rank should be changed.");
23  params.addParam<std::vector<unsigned int>>(
24  "new_ranks",
25  std::vector<unsigned int>(0),
26  "The new ranks that each variable in 'change_rank' shall have.");
27  params.addParam<Real>("penalty", 1e5, "The penalty parameter for Dirichlet BCs.");
28  return params;
29 }
30 
32  : SurrogateModel(parameters),
33  _change_rank(getParam<std::vector<std::string>>("change_rank")),
34  _new_ranks(getParam<std::vector<unsigned int>>("new_ranks")),
35  _var_names(getModelData<std::vector<std::string>>("_var_names")),
36  _tag_types(getModelData<std::vector<std::string>>("_tag_types")),
37  _base(getModelData<std::vector<std::vector<DenseVector<Real>>>>("_base")),
38  _red_operators(getModelData<std::vector<DenseMatrix<Real>>>("_red_operators")),
39  _penalty(getParam<Real>("penalty")),
40  _initialized(false)
41 {
42  if (_change_rank.size() != _new_ranks.size())
43  paramError("new_ranks",
44  "The size of 'new_ranks' is not equal to the ",
45  "size of 'change_rank' ",
46  _new_ranks.size(),
47  " != ",
48  _change_rank.size());
49 
50  for (unsigned int var_i = 0; var_i < _new_ranks.size(); ++var_i)
51  if (_new_ranks[var_i] == 0)
52  paramError("new_ranks", "The values should be greater than 0!");
53 }
54 
55 void
56 PODReducedBasisSurrogate::evaluateSolution(const std::vector<Real> & params)
57 {
58  if (!_initialized)
59  {
60  // The containers are initialized (if needed).
63  _initialized = true;
64  }
65 
66  // Assembling and solving the reduced equation system.
67  solveReducedSystem(params);
68 
69  // Reconstructing the approximate solutions for every variable.
71 }
72 
73 void
74 PODReducedBasisSurrogate::evaluateSolution(const std::vector<Real> & params,
75  DenseVector<Real> & inp_vector,
76  std::string var_name)
77 {
78  if (!_initialized)
79  {
80  // The containers are initialized (if needed).
82  _initialized = true;
83  }
84 
85  // Assembling and solving the reduced equation system.
86  solveReducedSystem(params);
87 
88  // Reconstructing the approximate solutions for every variable.
89  reconstructApproximateSolution(inp_vector, var_name);
90 }
91 
92 void
94 {
95  // Storing important indices for the assembly loops.
96  _final_ranks.resize(_var_names.size());
97  _comulative_ranks.resize(_var_names.size());
98  unsigned int sum_ranks = 0;
99 
100  // Checking if the user wants to overwrite the original ranks for the
101  // variables.
102  for (unsigned int var_i = 0; var_i < _var_names.size(); ++var_i)
103  {
104  _final_ranks[var_i] = _base[var_i].size();
105  for (unsigned int var_j = 0; var_j < _change_rank.size(); ++var_j)
106  {
107  if (_change_rank[var_j] == _var_names[var_i])
108  {
109  if (_new_ranks[var_j] > _base[var_i].size())
110  {
111  mooseWarning("The specified new rank (",
112  _new_ranks[var_j],
113  ") for variable '",
114  _var_names[var_i],
115  "' is higher than the original rank (",
116  _base[var_i].size(),
117  ")! Switched to original rank.");
118  break;
119  }
120 
121  _final_ranks[var_i] = _new_ranks[var_j];
122  }
123  }
124  sum_ranks += _final_ranks[var_i];
125  _comulative_ranks[var_i] = sum_ranks;
126  }
127 
128  // Resizing containers to match the newly prescribed ranks.
129  _sys_mx = DenseMatrix<Real>(sum_ranks, sum_ranks);
130  _rhs = DenseVector<Real>(sum_ranks);
131  _coeffs = DenseVector<Real>(sum_ranks);
132 }
133 
134 void
136 {
137  _approx_solution.resize(_var_names.size());
138  for (unsigned int var_i = 0; var_i < _var_names.size(); var_i++)
139  _approx_solution[var_i] = DenseVector<Real>(_base[var_i][0].size());
140 }
141 
142 void
143 PODReducedBasisSurrogate::solveReducedSystem(const std::vector<Real> & params)
144 {
145  // Cleaning the containers of the system matrix and right hand side.
146  _sys_mx.zero();
147  _rhs.zero();
148 
149  // The assumption here is that the reduced operators in the trainer were
150  // assembled in the order of the parameters. Also, if the number of
151  // parameters is fewer than the number of operators, the operator will
152  // just be added without scaling.
153  for (unsigned int i = 0; i < _red_operators.size(); ++i)
154  {
155  unsigned int row_start = 0;
156 
157  // Checking if the reduced operator corresponds to a Dirichlet BC, if
158  // yes introduce the penalty factor.
159  Real factor = 1.0;
160  if (_tag_types[i] == "op_dir" || _tag_types[i] == "src_dir")
161  factor = _penalty;
162 
163  // If the user decreased the rank of the reduced bases manually, some parts
164  // of the initial reduced operators have to be omited.
165  for (unsigned int var_i = 0; var_i < _var_names.size(); ++var_i)
166  {
167  for (unsigned int row_i = row_start; row_i < _comulative_ranks[var_i]; row_i++)
168  {
169  if (_tag_types[i] == "op" || _tag_types[i] == "op_dir")
170  {
171 
172  unsigned int col_start = 0;
173 
174  for (unsigned int var_j = 0; var_j < _var_names.size(); ++var_j)
175  {
176  for (unsigned int col_i = col_start; col_i < _comulative_ranks[var_j]; col_i++)
177  {
178  if (i < params.size())
179  _sys_mx(row_i, col_i) += params[i] * factor * _red_operators[i](row_i, col_i);
180  else
181  _sys_mx(row_i, col_i) += factor * _red_operators[i](row_i, col_i);
182  }
183 
184  col_start = _comulative_ranks[var_j];
185  }
186  }
187  else
188  {
189  if (i < params.size())
190  _rhs(row_i) -= params[i] * factor * _red_operators[i](row_i, 0);
191  else
192  _rhs(row_i) -= factor * _red_operators[i](row_i, 0);
193  }
194  row_start = _comulative_ranks[var_i];
195  }
196  }
197  }
198 
199  // Solving the reduced system.
201 }
202 
203 void
205 {
206  unsigned int counter = 0;
207  for (unsigned int var_i = 0; var_i < _var_names.size(); var_i++)
208  {
209  _approx_solution[var_i].zero();
210 
211  // This also takes into account the potential truncation of the bases by
212  // the user.
213  for (unsigned int base_i = 0; base_i < _final_ranks[var_i]; ++base_i)
214  {
215  for (unsigned int dof_i = 0; dof_i < _base[var_i][base_i].size(); ++dof_i)
216  _approx_solution[var_i](dof_i) += _coeffs(counter) * _base[var_i][base_i](dof_i);
217  counter++;
218  }
219  }
220 }
221 
222 void
224  std::string var_name)
225 {
226  auto it = std::find(_var_names.begin(), _var_names.end(), var_name);
227  if (it == _var_names.end())
228  mooseError("Variable '", var_name, "' does not exist in the POD-RB surrogate!");
229 
230  unsigned int var_i = std::distance(_var_names.begin(), it);
231 
232  if (inp_vector.size() != _base[var_i][0].size())
233  mooseError("The size of the input vector (",
234  inp_vector.size(),
235  ") for variable '",
236  var_name,
237  "' does not match the size of the stored base vector (",
238  _base[var_i][0].size(),
239  ") in POD-RB surrogate!");
240 
241  inp_vector.zero();
242 
243  unsigned int base_begin = 0;
244  if (var_i != 0)
245  base_begin = _comulative_ranks[var_i - 1];
246 
247  for (unsigned int base_i = 0; base_i < _final_ranks[var_i]; ++base_i)
248  {
249  for (unsigned int dof_i = 0; dof_i < inp_vector.size(); ++dof_i)
250  inp_vector(dof_i) += _coeffs(base_i + base_begin) * _base[var_i][base_i](dof_i);
251  }
252 }
253 
254 Real
255 PODReducedBasisSurrogate::getNodalQoI(std::string var_name, unsigned int qoi_type) const
256 {
257  Real val = 0.0;
258 
259  auto it = std::find(_var_names.begin(), _var_names.end(), var_name);
260  if (it == _var_names.end())
261  mooseError("Variable '", var_name, "' not found!");
262 
263  switch (qoi_type)
264  {
265  case 0:
266  val = _approx_solution[it - _var_names.begin()].max();
267  break;
268 
269  case 1:
270  val = _approx_solution[it - _var_names.begin()].min();
271  break;
272 
273  case 2:
274  val = _approx_solution[it - _var_names.begin()].l1_norm();
275  break;
276 
277  case 3:
278  val = _approx_solution[it - _var_names.begin()].l2_norm();
279  break;
280 
281  case 4:
282  val = _approx_solution[it - _var_names.begin()].linfty_norm();
283  break;
284  }
285 
286  return (val);
287 }
PODReducedBasisSurrogate(const InputParameters &parameters)
std::vector< DenseVector< Real > > _approx_solution
Reconstructed solution for each variable.
void reconstructApproximateSolution()
Reconstruct the approximate solution vector using the stored coefficients.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual void zero() override final
Real getNodalQoI(std::string var_name, unsigned int qoi_type) const
Get the nodal QoI of the reconstructed solution for a given variable.
DenseVector< Real > _rhs
The reduced right hand side.
const Real _penalty
Penalty parameter for Dirichlet BCs.
void mooseWarning(Args &&... args) const
std::vector< unsigned int > _final_ranks
The final rank that should be used for every variable.
const std::vector< std::string > & _tag_types
Strings describing which operator is indepedent of the solution and which corresponds to a reduced Di...
static InputParameters validParams()
const std::vector< std::vector< DenseVector< Real > > > & _base
The basis vectors for all the variables.
registerMooseObject("StochasticToolsApp", PODReducedBasisSurrogate)
const std::vector< DenseMatrix< Real > > & _red_operators
The reduced operators in the same order as given in tag_types.
void paramError(const std::string &param, Args... args) const
DenseMatrix< Real > _sys_mx
The reduced system matrix.
void evaluateSolution(const std::vector< Real > &params)
Get the reduced solution for a given parameter sample.
const std::vector< std::string > & _var_names
Vector containing the names of the variables we want to reconstruct.
void lu_solve(const DenseVector< Real > &b, DenseVector< Real > &x)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void initializeApproximateSolution()
Initialize approximate solution vector.
DenseVector< Real > _coeffs
Coefficients of the reduced order model.
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
bool _initialized
Switch that is set to see if the ROM matrices and vectors are initialized.
void initializeReducedSystem()
Initialize reduced matrices, vectors and additional containers.
void solveReducedSystem(const std::vector< Real > &params)
Assemble and solve the reduced equation system.
std::vector< std::string > _change_rank
A vector containing the number of basis functions each variable should use.
void ErrorVector unsigned int
std::vector< unsigned int > _new_ranks
The new rank the variable should have.
static InputParameters validParams()
std::vector< unsigned int > _comulative_ranks
Comulative ranks of the system. Used for indexing only.