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:382
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.
void mooseWarning(Args &&... args) const
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.
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:271
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