18#include "libmesh/mesh_tools.h"
19#include "libmesh/point.h"
28 params.
addParam<
unsigned int>(
"num_layers",
"The number of layers.");
29 params.
addParam<std::vector<Real>>(
"bounds",
30 "The 'bounding' positions of the layers i.e.: '0, "
31 "1.2, 3.7, 4.2' will mean 3 layers between those "
34 "bound_uniform_splits > 0",
35 "The number of times the bins specified in 'bounds' "
36 "should be split uniformly.");
37 params.
addParam<std::vector<unsigned int>>(
38 "bound_splits",
"Number of uniform splits of all layers in 'bounds' (default to all ones)");
40 MooseEnum sample_options(
"direct interpolate average",
"direct");
43 "How to sample the layers. 'direct' means get the value of the layer "
44 "the point falls in directly (or average if that layer has no value). "
45 " 'interpolate' does a linear interpolation between the two closest "
46 "layers. 'average' averages the two closest layers.");
48 params.
addParam<
unsigned int>(
"average_radius",
50 "When using 'average' sampling this is how "
51 "the number of values both above and below "
52 "the layer that will be averaged.");
57 "When true the value in each layer is the sum of the values up to and including that layer");
59 "positive_cumulative_direction",
61 "When 'cumulative' is true, whether the direction for summing the cumulative value "
62 "is the positive direction or negative direction");
64 params.
addParam<std::vector<SubdomainName>>(
65 "block",
"The list of block ids (SubdomainID) that this object will be applied");
67 params.
addParam<std::vector<SubdomainName>>(
"layer_bounding_block",
68 "List of block ids (SubdomainID) that are used to "
69 "determine the upper and lower geometric bounds for "
70 "all layers. If this is not specified, the ids "
71 "specified in 'block' are used for this purpose.");
73 params.
addParam<Real>(
"direction_min",
74 "Minimum coordinate along 'direction' that bounds the layers");
75 params.
addParam<Real>(
"direction_max",
76 "Maximum coordinate along 'direction' that bounds the layers");
78 "direction num_layers bounds direction_min direction_max bound_uniform_splits bound_splits",
79 "Layers extent and definition");
80 params.
addParamNamesToGroup(
"sample_type average_radius cumulative positive_cumulative_direction",
81 "Value sampling / aggregating");
87 parameters.getObjectName() +
"_layered_base",
90 _layered_base_name(parameters.getObjectName()),
91 _layered_base_params(parameters),
92 _direction_enum(parameters.get<
MooseEnum>(
"direction")),
93 _direction(_direction_enum),
94 _sample_type(parameters.get<
MooseEnum>(
"sample_type")),
95 _average_radius(parameters.get<unsigned
int>(
"average_radius")),
96 _using_displaced_mesh(_layered_base_params.get<bool>(
"use_displaced_mesh")),
97 _layer_values(declareRestartableData<
std::vector<Real>>(
"layer_values")),
98 _layer_has_value(declareRestartableData<
std::vector<
int>>(
"layer_has_value")),
99 _cumulative(parameters.get<bool>(
"cumulative")),
100 _positive_cumulative_direction(parameters.get<bool>(
"positive_cumulative_direction")),
101 _layered_base_subproblem(*parameters.getCheckedPointerParam<
SubProblem *>(
"_subproblem")),
102 _layer_bounding_blocks(),
103 _has_direction_max_min(false)
107 mooseError(
"'bounds' and 'num_layers' cannot both be set");
111 "The 'positive_cumulative_direction' parameter is unused when 'cumulative' is false");
125 mooseError(
"At least two boundaries must be provided in 'bounds' to form layers!");
132 mooseError(
"Parameters 'bound_splits' and 'bound_uniform_splits' cannot be both supplied");
138 for (
unsigned int s = 0; s < splits; ++s)
140 std::vector<Real> new_bnds;
157 mooseError(
"'bound_splits' size must be equal to the size of 'bounds' minus one");
159 std::vector<Real> new_layers;
160 new_layers.reserve(std::accumulate(nsubs.begin(), nsubs.end(), (
unsigned int)0));
162 for (
const auto i : index_range(nsubs))
165 for (
const auto j : make_range(nsubs[i]))
168 new_layers.push_back(new_layers.back() + dz);
180 mooseError(
"One of 'bounds' or 'num_layers' must be specified");
183 mooseError(
"'sample_type = interpolate' not supported with 'bounds'");
191 mooseWarning(
"'direction_min' is unused when providing 'bounds'");
194 mooseWarning(
"'direction_max' is unused when providing 'bounds'");
197 if (has_layer_bounding_block && (has_direction_min || has_direction_max))
198 mooseError(
"Only one of 'layer_bounding_block' and the pair 'direction_max' and "
199 "'direction_min' can be provided");
202 if (has_direction_min != has_direction_max)
203 mooseError(
"If providing the layer max/min directions, both 'direction_max' and "
204 "'direction_min' must be specified.");
206 if (has_layer_bounding_block)
214 if (has_direction_min && has_direction_max)
221 mooseError(
"'direction_max' must be larger than 'direction_min'");
240 int higher_layer = -1;
241 int lower_layer = -1;
252 for (
int i = layer - 1; i >= 0; i--)
261 if (higher_layer == -1 && lower_layer == -1)
268 if (higher_layer == -1)
271 if (
unsigned(higher_layer) == layer)
274 if (lower_layer == -1)
281 if (higher_layer == -1)
286 Real lower_value = 0;
287 if (lower_layer != -1)
289 lower_coor += (lower_layer + 1) * layer_length;
298 (higher_value - lower_value) * (p(
_direction) - lower_coor) / layer_length;
303 unsigned int num_values = 0;
305 if (higher_layer != -1)
309 int current_layer = higher_layer + i;
322 if (lower_layer != -1)
326 int current_layer = lower_layer - i;
328 if (current_layer < 0)
339 return total / num_values;
395 const auto & lb =
dynamic_cast<const LayeredBase &
>(y);
397 if (lb.layerHasValue(i))
423 std::vector<Real>::const_iterator one_higher =
428 return static_cast<unsigned int>(
437 return static_cast<unsigned int>(std::distance(
_layer_bounds.begin(), one_higher - 1));
483 for (
auto & elem_ptr : *
mesh.getActiveLocalElementRange())
485 auto subdomain_id = elem_ptr->subdomain_id();
491 for (
auto & node : elem_ptr->node_ref_range())
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
void ErrorVector unsigned int
This base class computes volume integrals of a variable storing partial sums for the specified number...
virtual void threadJoin(const UserObject &y)
LayeredBase(const InputParameters ¶meters)
SubProblem & _layered_base_subproblem
Subproblem for the child object.
bool _has_direction_max_min
whether the max/min coordinate in the direction is known from user input
unsigned int _num_layers
Number of layers to split the mesh into.
virtual Real getLayerValue(unsigned int layer) const
Get the value for a given layer.
std::string _layered_base_name
Name of this object.
bool _interval_based
Whether or not this object is based on equally spaced intervals or "bounds".
bool _using_displaced_mesh
true if this object operates on the displaced mesh, otherwise false
virtual unsigned int getLayer(const Point &p) const
Helper function to return the layer the point lies in.
void setLayerValue(unsigned int layer, Real value)
Set the value for a particular layer.
std::vector< SubdomainID > _layer_bounding_blocks
List of SubdomainIDs, if given.
std::vector< int > & _layer_has_value
Whether or not each layer has had any value summed into it.
void computeLayerCenters()
Compute the center points for each layer.
std::vector< Real > _layer_centers
center coordinates of each layer
unsigned int _sample_type
How to sample the values.
bool _cumulative
Whether the values are cumulative over the layers.
const bool _positive_cumulative_direction
Whether the cumulative values should be summed in the positive or negative direction.
virtual Real integralValue(const Point &p) const
Given a Point return the integral value associated with the layer that point falls in.
static InputParameters validParams()
const InputParameters & _layered_base_params
Params for this object.
unsigned int _direction
The component direction the layers are going in. We cache this for speed (so we're not always going t...
unsigned int _average_radius
How many layers both above and below the found layer will be used in the average.
std::vector< Real > _layer_bounds
The boundaries of the layers.
virtual void initialize()
std::vector< Real > & _layer_values
Value of the integral for each layer.
void getBounds()
Compute bounds, restricted to blocks if given.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
std::vector< SubdomainID > getSubdomainIDs(const std::vector< SubdomainName > &subdomain_names) const
Get the associated subdomainIDs for the subdomain names that are passed in.
A class for creating restricted objects.
Generic class for solving transient nonlinear problems.
virtual MooseMesh & mesh()=0
void max(const T &r, T &o, Request &req) const
Base class for user-specific data.
const Parallel::Communicator & comm() const