https://mooseframework.inl.gov
MeshDivisionFunctorReductionVectorPostprocessor.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 #include "MeshDivision.h"
12 #include "MooseMesh.h"
13 #include "MooseMeshUtils.h"
14 #include "FEProblemBase.h"
15 
16 #include "libmesh/mesh_base.h"
17 
19 
22 {
24  MooseEnum reduction("integral average min max");
25  params.addRequiredParam<MooseEnum>("reduction", reduction, "Reduction operation to apply");
26  params.addRequiredParam<std::vector<MooseFunctorName>>("functors",
27  "Functors to apply the reduction on");
28  params.addRequiredParam<MeshDivisionName>(
29  "mesh_division",
30  "Mesh division object which dictates the elements to perform the reduction with");
31  params.addClassDescription("Perform reductions on functors based on a per-mesh-division basis");
32  return params;
33 }
34 
36  const InputParameters & parameters)
38  _reduction(getParam<MooseEnum>("reduction")),
39  _nfunctors(getParam<std::vector<MooseFunctorName>>("functors").size()),
40  _mesh_division(_fe_problem.getMeshDivision(getParam<MeshDivisionName>("mesh_division"), _tid))
41 {
42  // Gather the functors
43  const auto & functor_names = getParam<std::vector<MooseFunctorName>>("functors");
44  for (const auto & functor_name : functor_names)
45  _functors.push_back(&getFunctor<Real>(functor_name));
46 
47  // Set up reduction vectors
48  const auto ndiv = _mesh_division.getNumDivisions();
49  _volumes.resize(ndiv);
50  for (const auto & functor_name : functor_names)
51  {
52  auto & p = declareVector(functor_name);
53  p.resize(ndiv);
54  _functor_reductions.push_back(&p);
55  }
56 }
57 
58 void
60 {
61  for (auto & reduction : _functor_reductions)
62  {
63  if (_reduction == ReductionEnum::INTEGRAL || _reduction == ReductionEnum::AVERAGE)
64  std::fill(reduction->begin(), reduction->end(), 0);
65  else if (_reduction == ReductionEnum::MIN)
66  std::fill(reduction->begin(), reduction->end(), std::numeric_limits<Real>::max());
67  else if (_reduction == ReductionEnum::MAX)
68  std::fill(reduction->begin(), reduction->end(), std::numeric_limits<Real>::min());
69  else
70  mooseAssert(false, "Unknown reduction type");
71  }
72  std::fill(_volumes.begin(), _volumes.end(), 0);
73 }
74 
75 void
77 {
78  const auto state_arg = determineState();
79  if (hasBlocks(_current_elem->subdomain_id()))
80  {
81  const auto index = _mesh_division.divisionIndex(*_current_elem);
83  {
84  mooseWarning("Spatial value sampled outside of the mesh_division specified in element: " +
85  Moose::stringify(_current_elem->id()) + " of centroid " +
86  Moose::stringify(_current_elem->true_centroid()));
87  return;
88  }
89  for (const auto i : make_range(_nfunctors))
90  if (_functors[i]->hasBlocks(_current_elem->subdomain_id()))
91  for (const auto qp : make_range(_qrule->n_points()))
92  {
93  const Moose::ElemQpArg elem_qp = {_current_elem, qp, _qrule, _q_point[qp]};
94  const auto functor_value = (*_functors[i])(elem_qp, state_arg);
95  if (_reduction == ReductionEnum::INTEGRAL || _reduction == ReductionEnum::AVERAGE)
96  (*_functor_reductions[i])[index] += _JxW[qp] * _coord[qp] * functor_value;
97  else if (_reduction == ReductionEnum::MIN)
98  {
99  if ((*_functor_reductions[i])[index] > functor_value)
100  (*_functor_reductions[i])[index] = functor_value;
101  }
102  else if (_reduction == ReductionEnum::MAX)
103  if ((*_functor_reductions[i])[index] < functor_value)
104  (*_functor_reductions[i])[index] = functor_value;
105 
106  if (i == 0 && _reduction == ReductionEnum::AVERAGE)
107  _volumes[index] += _JxW[qp] * _coord[qp];
108  }
109  }
110 }
111 
112 void
114 {
115  for (auto & reduction : _functor_reductions)
116  if (_reduction == ReductionEnum::INTEGRAL || _reduction == ReductionEnum::AVERAGE)
117  gatherSum(*reduction);
118  else if (_reduction == ReductionEnum::MIN)
119  gatherMin(*reduction);
120  else if (_reduction == ReductionEnum::MAX)
121  gatherMax(*reduction);
122 
123  if (_reduction == ReductionEnum::AVERAGE)
124  {
126  for (const auto i_f : make_range(_nfunctors))
127  for (const auto i : index_range(*_functor_reductions[i_f]))
129  (*_functor_reductions[i_f])[i] /= _volumes[i];
130  else
131  (*_functor_reductions[i_f])[i] = 0;
132  }
133 }
134 
135 void
137 {
138  const auto & sibling = static_cast<const MeshDivisionFunctorReductionVectorPostprocessor &>(s);
139 
140  for (const auto i_f : make_range(_nfunctors))
141  for (const auto i : index_range(*_functor_reductions[i_f]))
142  {
143  if (_reduction == ReductionEnum::INTEGRAL || _reduction == ReductionEnum::AVERAGE)
144  (*_functor_reductions[i_f])[i] += (*sibling._functor_reductions[i_f])[i];
145  else if (_reduction == ReductionEnum::MIN)
146  {
147  if ((*_functor_reductions[i_f])[i] > (*sibling._functor_reductions[i_f])[i])
148  (*_functor_reductions[i_f])[i] = (*sibling._functor_reductions[i_f])[i];
149  }
150  else if (_reduction == ReductionEnum::MAX)
151  if ((*_functor_reductions[i_f])[i] < (*sibling._functor_reductions[i_f])[i])
152  (*_functor_reductions[i_f])[i] = (*sibling._functor_reductions[i_f])[i];
153 
154  // Average-reduction requires the reduction of the volume
155  if (i_f == 0 && _reduction == ReductionEnum::AVERAGE)
156  _volumes[i] += sibling._volumes[i];
157  }
158 }
159 
160 Real
162 {
163  if (_nfunctors > 1)
164  mooseError("The spatialValue user object interface was not conceived for objects that compute "
165  "multiple values for a given spatial point. Please specify only one functor");
166  const auto index = _mesh_division.divisionIndex(p);
168  mooseError("Spatial value sampled outside of the mesh_division specified at", p);
169  return (*_functor_reductions[0])[index];
170 }
171 
172 bool
174 {
175  return BlockRestrictable::hasBlocks(sub);
176 }
virtual unsigned int divisionIndex(const Point &pt) const =0
Return the index of the division to which the point belongs.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
Definition: MooseUtils.h:380
const MooseArray< Point > & _q_point
const MooseArray< Real > & _coord
Moose::StateArg determineState() const
Create a functor state argument that corresponds to the implicit state of this object.
void gatherMax(T &value)
Gather the parallel max of the variable passed in.
Definition: UserObject.h:138
static InputParameters validParams()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::vector< const Moose::Functor< Real > * > _functors
Functors that are evaluated to create the reduction.
void gatherMin(T &value)
Gather the parallel min of the variable passed in.
Definition: UserObject.h:150
registerMooseObject("MooseApp", MeshDivisionFunctorReductionVectorPostprocessor)
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
auto max(const L &left, const R &right)
const MeshDivision & _mesh_division
Mesh division providing the division.
This MeshDivisionFunctorReductionVectorPostprocessor serves to integrate functors based on the index ...
virtual void initialize() override
Called before execute() is ever called so that data can be cleared.
void gatherSum(T &value)
Gather the parallel sum of the variable passed in.
Definition: UserObject.h:126
std::vector< Real > _volumes
Vectors holding the mesh division volumes.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
virtual bool hasBlocks(SubdomainID sub) const override
Returns whether the functor is defined on this block.
Argument for requesting functor evaluation at a quadrature point location in an element.
VectorPostprocessorValue & declareVector(const std::string &vector_name)
Register a new vector to fill up.
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
const MooseEnum _reduction
Reduction operation to be performed.
unsigned int INVALID_DIVISION_INDEX
Invalid subdomain id to return when outside the mesh division.
Definition: MeshDivision.h:28
unsigned int getNumDivisions() const
Return the number of divisions.
Definition: MeshDivision.h:56
virtual void threadJoin(const UserObject &uo) override
Must override.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const QBase *const & _qrule
const Elem *const & _current_elem
The current element pointer (available during execute())
const MooseArray< Real > & _JxW
const unsigned int _nfunctors
Number of functors to be integrated.
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
Definition: MooseBase.h:295
IntRange< T > make_range(T beg, T end)
virtual Real spatialValue(const Point &p) const override
Optional interface function for "evaluating" a UserObject at a spatial position.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:267
Base class for creating a user object with the SpatialUserObject and Moose::Functor APIs...
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
bool hasBlocks(const SubdomainName &name) const
Test if the supplied block name is valid for this object.
auto min(const L &left, const R &right)
std::vector< VectorPostprocessorValue * > _functor_reductions
Vectors holding functor reductions (integrals, averages, extrema..) over each mesh division...
auto index_range(const T &sizable)
Base class for user-specific data.
Definition: UserObject.h:40