11 #include "libmesh/replicated_mesh.h" 12 #include "libmesh/mesh_generation.h" 14 #include "libmesh/parallel_algebra.h" 15 #include "libmesh/parallel_sync.h" 28 "Names of variables we want to " 29 "extract from solution vectors.");
31 "The errors allowed in the snapshot reconstruction.");
33 "Names of tags for the reduced operators.");
34 params.
addParam<std::vector<std::string>>(
35 "filenames",
"Files where the eigenvalues are printed for each variable (if given).");
39 "List of keywords describing if the tags" 40 " correspond to independent operators or not. (op/op_dir/src/src_dir)");
46 _var_names(declareModelData<
std::vector<
std::string>>(
47 "_var_names", getParam<
std::vector<
std::string>>(
"var_names"))),
48 _error_res(getParam<
std::vector<
Real>>(
"error_res")),
49 _tag_names(declareModelData<
std::vector<
std::string>>(
50 "_tag_names", getParam<
std::vector<
std::string>>(
"tag_names"))),
51 _tag_types(declareModelData<
std::vector<
std::string>>(
52 "_tag_types", getParam<
std::vector<
std::string>>(
"tag_types"))),
53 _base(declareModelData<
std::vector<
std::vector<DenseVector<
Real>>>>(
"_base")),
54 _red_operators(declareModelData<
std::vector<DenseMatrix<
Real>>>(
"_red_operators")),
55 _base_completed(false),
56 _empty_operators(true)
60 "The number of elements is not equal to the number" 61 " of elements in 'var_names'!");
65 "The number of elements is not equal to the number" 66 " of elements in 'tag_names'!");
68 std::vector<std::string> available_names{
"op",
"src",
"op_dir",
"src_dir"};
71 auto it = std::find(available_names.begin(), available_names.end(), tag_type);
72 if (it == available_names.end())
76 "' is not valid, available names are:",
77 " op, op_dir, src, src_dir");
127 for (
unsigned int tag_i = 0; tag_i <
_red_operators.size(); ++tag_i)
136 const std::shared_ptr<DenseVector<Real>> & snapshot)
138 _snapshots[var_i].addNewEntry(glob_i, snapshot);
150 for (
unsigned int var_i = 0; var_i <
_snapshots.size(); ++var_i)
163 MeshTools::Generation::build_square(
164 mesh, no_snaps, no_snaps, -0.5, no_snaps - 0.5, -0.5, no_snaps - 0.5);
168 mesh.add_elem_integer(
"filled");
173 for (Elem * elem :
mesh.active_element_ptr_range())
175 const auto centroid = elem->vertex_average();
176 if (centroid(0) > centroid(1))
177 mesh.delete_elem(elem);
181 mesh.prepare_for_use();
189 std::unordered_map<unsigned int, std::vector<std::shared_ptr<DenseVector<Real>>>> local_vectors;
190 for (
unsigned int loc_vec_i = 0; loc_vec_i <
_snapshots[0].getNumberOfLocalEntries(); ++loc_vec_i)
192 const unsigned int glob_vec_i =
_snapshots[0].getGlobalIndex(loc_vec_i);
193 auto & entry = local_vectors[glob_vec_i];
195 for (
unsigned int v_ind = 0; v_ind <
_snapshots.size(); ++v_ind)
196 entry.push_back(
_snapshots[v_ind].getLocalEntry(loc_vec_i));
210 std::unordered_map<processor_id_type, std::set<unsigned int>> send_vectors;
213 std::vector<std::tuple<unsigned int, unsigned int, std::shared_ptr<DenseVector<Real>>>>>
218 for (Elem * elem :
mesh.active_element_ptr_range())
223 const auto centroid = elem->vertex_average();
224 const unsigned int i = centroid(0);
225 const unsigned int j = centroid(1);
236 if (send_vectors[elem->processor_id()].count(i))
241 send_vectors[elem->processor_id()].insert(i);
242 for (
unsigned int v_ind = 0; v_ind <
_snapshots.size(); ++v_ind)
243 send_map[elem->processor_id()].emplace_back(
244 i, v_ind,
_snapshots[v_ind].getGlobalEntry(i));
249 if (send_vectors[elem->processor_id()].count(
j))
254 send_vectors[elem->processor_id()].insert(
j);
255 for (
unsigned int v_ind = 0; v_ind <
_snapshots.size(); ++v_ind)
256 send_map[elem->processor_id()].emplace_back(
262 elem->set_extra_integer(0, 0);
266 std::unordered_map<unsigned int, std::vector<std::shared_ptr<DenseVector<Real>>>>
271 [
this, &
mesh, &received_vectors, &local_vectors](
274 std::tuple<unsigned int, unsigned int, std::shared_ptr<DenseVector<Real>>>> & vectors)
277 Parallel::push_parallel_packed_range(
_communicator, send_map, (
void *)
nullptr, functor);
283 std::vector<std::tuple<
unsigned int,
unsigned int, std::shared_ptr<DenseVector<Real>>>>());
291 for (
unsigned int row_i = 1; row_i < corr_mx.m(); ++row_i)
292 for (
unsigned int col_i = 0; col_i < row_i; ++col_i)
293 corr_mx(row_i, col_i) = corr_mx(col_i, row_i);
298 ReplicatedMesh & mesh,
299 std::unordered_map<
unsigned int, std::vector<std::shared_ptr<DenseVector<Real>>>> &
301 std::unordered_map<
unsigned int, std::vector<std::shared_ptr<DenseVector<Real>>>> &
304 const std::vector<std::tuple<
unsigned int,
unsigned int, std::shared_ptr<DenseVector<Real>>>> &
307 for (
auto & tuple : vectors)
309 const auto glob_vec_i = std::get<0>(tuple);
310 const auto var_i = std::get<1>(tuple);
311 const auto & vector = std::get<2>(tuple);
314 std::vector<std::shared_ptr<DenseVector<Real>>> & entry = received_vectors[glob_vec_i];
321 entry[var_i] = vector;
326 for (Elem * elem :
mesh.active_local_element_ptr_range())
329 if (elem->get_extra_integer(0))
334 const unsigned int i = elem->vertex_average()(0);
335 const unsigned int j = elem->vertex_average()(1);
336 std::vector<std::shared_ptr<DenseVector<Real>>> * i_vec =
nullptr;
337 std::vector<std::shared_ptr<DenseVector<Real>>> * j_vec =
nullptr;
339 const auto find_i_local = local_vectors.find(i);
340 if (find_i_local != local_vectors.end())
341 i_vec = &find_i_local->second;
344 const auto find_i_received = received_vectors.find(i);
345 if (find_i_received != received_vectors.end())
347 i_vec = &find_i_received->second;
353 const auto find_j_local = local_vectors.find(
j);
354 if (find_j_local != local_vectors.end())
355 j_vec = &find_j_local->second;
358 const auto find_j_received = received_vectors.find(
j);
359 if (find_j_received != received_vectors.end())
361 j_vec = &find_j_received->second;
368 for (
unsigned int v_ind = 0; v_ind < _snapshots.size(); ++v_ind)
369 _corr_mx[v_ind](i,
j) = (*i_vec)[v_ind]->dot(*(*j_vec)[v_ind]);
372 elem->set_extra_integer(0, 1);
379 for (
unsigned int v_ind = 0; v_ind <
_corr_mx.size(); ++v_ind)
381 unsigned int no_snaps =
_corr_mx[v_ind].n();
385 DenseVector<Real> eigenvalues(no_snaps);
389 DenseVector<Real> eigenvalues_imag(no_snaps);
392 _corr_mx[v_ind].evd_left(eigenvalues, eigenvalues_imag, eigenvectors);
396 std::vector<unsigned int>
idx(eigenvalues.size());
397 std::iota(
idx.begin(),
idx.end(), 0);
398 std::vector<Real> &
v = eigenvalues.get_values();
402 idx.begin(),
idx.end(), [&
v](
unsigned int i,
unsigned int j) {
return v[i] >
v[
j]; });
406 std::stable_sort(
v.begin(),
v.end(), std::greater<Real>());
414 for (
unsigned int j = 0;
j < cutoff; ++
j)
430 Real sum = std::accumulate(inp_vec.begin(), inp_vec.end(), 0.0);
433 for (
unsigned int i = 0; i < inp_vec.size(); ++i)
435 part_sum += inp_vec[i];
436 if (part_sum / sum > 1 - error)
439 return (inp_vec.size());
446 for (
unsigned int var_i = 0; var_i <
_eigenvectors.size(); ++var_i)
449 unsigned int no_snaps =
_snapshots[var_i].getNumberOfLocalEntries();
451 _base[var_i].resize(no_bases);
455 for (
unsigned int base_i = 0; base_i < no_bases; ++base_i)
457 _base[var_i][base_i].resize(
_snapshots[var_i].getLocalEntry(0)->size());
459 for (
unsigned int loc_i = 0; loc_i < no_snaps; ++loc_i)
461 unsigned int glob_i =
_snapshots[var_i].getGlobalIndex(loc_i);
462 const DenseVector<Real> & snapshot = *
_snapshots[var_i].getLocalEntry(loc_i);
464 for (
unsigned int i = 0; i <
_base[var_i][base_i].size(); ++i)
490 for (
unsigned int tag_i = 0; tag_i <
_red_operators.size(); ++tag_i)
502 std::vector<DenseVector<Real>> & residual)
507 unsigned int counter = 0;
508 for (
unsigned int var_i = 0; var_i <
_var_names.size(); ++var_i)
510 for (
unsigned int base_j = 0; base_j <
_base[var_i].size(); ++base_j)
523 return _snapshots[var_i].getNumberOfGlobalEntries();
529 unsigned int sum = 0;
531 for (
unsigned int i = 0; i <
_base.size(); ++i)
532 sum +=
_base[i].size();
537 const DenseVector<Real> &
540 return _base[var_i][base_i];
543 const DenseVector<Real> &
546 unsigned int counter = 0;
548 for (
unsigned int var_i = 0; var_i <
_var_names.size(); ++var_i)
549 for (
unsigned int base_i = 0; base_i <
_base[var_i].size(); ++base_i)
551 if (glob_i == counter)
552 return _base[var_i][base_i];
557 mooseError(
"The basis vector with global index ", glob_i,
"is not available!");
564 unsigned int counter = 0;
566 for (
unsigned int var_i = 0; var_i <
_var_names.size(); ++var_i)
567 for (
unsigned int base_i = 0; base_i <
_base[var_i].size(); ++base_i)
569 if (glob_i == counter)
575 mooseError(
"Variable with global base index ", glob_i,
"is not available!");
584 std::vector<std::string> filenames = getParam<std::vector<std::string>>(
"filenames");
588 "The number of file names is not equal to the number of variable names!");
590 for (
unsigned int var_i = 0; var_i <
_var_names.size(); ++var_i)
593 fb.open(filenames[var_i], std::ios::out);
594 std::ostream
os(&fb);
595 os <<
"evs" << std::endl;
virtual void execute() override
void addToReducedOperator(unsigned int base_i, unsigned int tag_i, std::vector< DenseVector< Real >> &residual)
Adding the contribution of a residual to the reduced operators.
std::vector< std::vector< DenseVector< Real > > > & _base
The reduced basis for the variables.
virtual void initialSetup() override
PODReducedBasisTrainer(const InputParameters ¶meters)
std::vector< DenseMatrix< Real > > _eigenvectors
The eigenvectors of the correalation matrix for each variable.
void printEigenvalues()
Prints the eigenvalues of the correlation matrix for each variable.
void initReducedOperators()
Initializing the reduced operators.
const Parallel::Communicator & _communicator
std::basic_ostream< charT, traits > * os
void receiveObjects(ReplicatedMesh &mesh, std::unordered_map< unsigned int, std::vector< std::shared_ptr< DenseVector< Real >>>> &received_vectors, std::unordered_map< unsigned int, std::vector< std::shared_ptr< DenseVector< Real >>>> &local_vectors, processor_id_type, const std::vector< std::tuple< unsigned int, unsigned int, std::shared_ptr< DenseVector< Real >>>> &vectors)
Function that manipulates the received objects and computes the correlation matrices on the fly...
static InputParameters validParams()
void addSnapshot(unsigned int var_i, unsigned int glob_i, const std::shared_ptr< DenseVector< Real >> &snapshot)
Adding a snapshot for a variable.
virtual void finalize() override
std::vector< DistributedSnapshots > _snapshots
Distributed container for snapshots per variable.
static InputParameters validParams()
bool isParamValid(const std::string &name) const
uint8_t processor_id_type
bool _empty_operators
Flag describing if the reduced operators are empty or not.
std::vector< std::string > & _tag_types
list of bools describing which tag is indepedent of the solution.
std::vector< DenseVector< Real > > _eigenvalues
The eigenvalues of the correalation matrix for each variable.
void paramError(const std::string ¶m, Args... args) const
unsigned int getVariableIndex(unsigned int glob_i) const
Getting appropriate variable index for a global base index.
std::vector< DenseMatrix< Real > > _corr_mx
The correlation matrices for the variables.
std::vector< DenseMatrix< Real > > & _red_operators
The reduced operators that should be transferred to the surrogate.
unsigned int getSnapsSize(unsigned int var_i) const
Getting the snapshot size across all of the processors for a given variable with index var_i...
unsigned int determineNumberOfModes(Real error, const std::vector< Real > &inp_vec) const
Computes the number of bases necessary for a given error indicator.
bool _base_completed
Switch that tells if the object has already computed the necessary basis vectors. ...
registerMooseObject("StochasticToolsApp", PODReducedBasisTrainer)
StochasticTools::DistributedData< std::shared_ptr< DenseVector< Real > > > DistributedSnapshots
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
void computeEigenDecomposition()
Computes the eigen-decomposition of the stored correlation matrices.
void mooseError(Args &&... args) const
std::vector< std::string > & _tag_names
Names of the tags that should be used to fetch residuals from the MultiApp.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< std::string > & _var_names
Vector containing the names of the variables we want to use for constructing the surrogates.
std::vector< Real > _error_res
Energy limits that define how many basis functions will be kept for each variable.
This is the base trainer class whose main functionality is the API for declaring model data...
processor_id_type processor_id() const
static const std::string k
unsigned int getSumBaseSize() const
Getting the overall base size, which is the sum of the individual bases.
void computeCorrelationMatrix()
Computes the correlation matrices using the snapshots.
const DenseVector< Real > & getBasisVector(unsigned int var_i, unsigned int base_i) const
Getting a basis vector for a given variable.
void computeBasisVectors()
Generates the basis vectors using the snapshots together with the eigen-decomposition of the correlat...