https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FunctorSmoother.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
10#include "FunctorSmoother.h"
11#include "MooseUtils.h"
12#include "RelationshipManager.h"
13
14#include "metaphysicl/raw_type.h"
15
17
18template <typename T>
21{
23 params.addClassDescription("Creates smoother functor(s) using various averaging techniques");
24 params.addRequiredParam<std::vector<MooseFunctorName>>("functors_in",
25 "The name(s) of the functors to smooth");
26 params.addRequiredParam<std::vector<MooseFunctorName>>(
27 "functors_out", "The name(s) of the smooth output functors");
28 MooseEnum smoothing_techniques(
29 "face_average node_average layered_elem_average remove_checkerboard");
31 "smoothing_technique", smoothing_techniques, "How to smooth the functor");
32
33 return params;
34}
35
36template <typename T>
38 : FunctorMaterial(parameters),
39 _functors_in(getParam<std::vector<MooseFunctorName>>("functors_in")),
40 _functors_out(getParam<std::vector<MooseFunctorName>>("functors_out")),
41 _smoothing_technique(getParam<MooseEnum>("smoothing_technique"))
42{
43 if (_tid == 0)
44 {
45 // We need one layer of ghosting at least to get neighbor values
46 auto & factory = _app.getFactory();
47 auto rm_params = factory.getValidParams("ElementSideNeighborLayers");
48 rm_params.template set<std::string>("for_whom") = name();
49 rm_params.template set<MooseMesh *>("mesh") = &const_cast<MooseMesh &>(_mesh);
50 rm_params.template set<Moose::RelationshipManagerType>("rm_type") =
53 rm_params.template set<unsigned short>("layers") = 1;
54 rm_params.template set<bool>("use_point_neighbors") = false;
55 rm_params.template set<bool>("use_displaced_mesh") =
56 parameters.template get<bool>("use_displaced_mesh");
57 mooseAssert(rm_params.areAllRequiredParamsValid(),
58 "All relationship manager parameters should be valid.");
59 auto rm_obj = factory.template create<RelationshipManager>(
60 "ElementSideNeighborLayers", name() + "_functor_smoothing", rm_params);
61
62 // Delete the resources created on behalf of the RM if it ends up not being added to the
63 // App.
64 if (!_app.addRelationshipManager(rm_obj))
65 factory.releaseSharedObjects(*rm_obj);
66 }
67
68 // Request the node to elem map so we don't build it in a threaded region
69 if (isNodal())
71
72 const std::set<ExecFlagType> clearance_schedule(_execute_enum.begin(), _execute_enum.end());
73
74 for (const auto i : index_range(_functors_in))
75 {
76 // This potentially upcasts functors from non-AD to AD
77 const auto & functor_in = getFunctor<typename Moose::ADType<T>::type>(_functors_in[i]);
78
79 // Check the block restriction of the incoming functor
80 for (const auto bid : blockIDs())
81 if (!functor_in.hasBlocks(bid))
82 paramError("block",
83 "Input functor '" + functor_in.functorName() +
84 "' is not defined in subdomain: " + Moose::stringify(bid));
85
86 // We always add the AD type
87 addFunctorProperty<typename Moose::ADType<T>::type>(
89 [this, &functor_in](const auto & r, const auto & t) -> typename Moose::ADType<T>::type
90 {
91 typename Moose::ADType<T>::type base_value = functor_in(r, t);
92 typename Moose::ADType<T>::type average = 0;
93 using std::abs;
94
95 const Elem * r_elem = nullptr;
96 if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
97 r_elem = r.elem;
98
99 // Handle the single isolated element case
100 if (r_elem && r_elem->n_neighbors() == 0)
101 return base_value;
102
103 // If these techniques are of interest elsewhere, they should be moved to a
104 // FunctorAveragingUtils file and namespaced
106 {
107 if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
108 {
109 unsigned int n_faces = 0;
110 for (const auto side_index : r_elem->side_index_range())
111 {
112 auto fi = _mesh.faceInfo(r_elem, side_index);
113 if (!fi)
114 fi =
115 _mesh.faceInfo(r_elem->neighbor_ptr(side_index),
116 r_elem->neighbor_ptr(side_index)->which_neighbor_am_i(r_elem));
117 Moose::FaceArg face_arg{
118 fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
119 if (face_arg.fi)
120 {
121 average += functor_in(face_arg, t);
122 n_faces++;
123 }
124 }
125 average /= n_faces;
126 }
127 else
128 // a conceptually simple option here would be to use the smoothed version of the
129 // ElemArg to compute all the other functor arguments. Maybe with the same
130 // smoothing on the gradient calls
131 mooseError("Face averaging smoothing has only been defined for the ElemArg functor "
132 "argument, not for ",
134 ". Please contact a MOOSE developer or implement it yourself.");
135 }
137 {
138 if constexpr (std::is_same_v<const Moose::NodeArg &, decltype(r)>)
139 {
140 const Node * r_node = r.node;
141
142 unsigned int n_nodes = 0;
143 const auto & node_to_elem_map = _mesh.nodeToElemMap();
144 for (const auto & shared_elem_id : libmesh_map_find(node_to_elem_map, r_node->id()))
145 {
146 const auto & shared_elem = _mesh.elemPtr(shared_elem_id);
147 const auto node_index = shared_elem->get_node_index(r_node);
148 // Limit the stencil to edge-connected nodes to limit ghosting needs
149 for (const auto edge_index : shared_elem->edges_adjacent_to_node(node_index))
150 {
151 for (const auto n : shared_elem->nodes_on_edge(edge_index))
152 {
153 // we don't consider the previous nodal value
154 // maybe we should, use will determine that
155 if (n == node_index)
156 continue;
157 const Moose::NodeArg node_arg = {
158 shared_elem->node_ptr(n), &Moose::NodeArg::undefined_subdomain_connection};
159 average += functor_in(node_arg, t);
160 n_nodes++;
161 }
162 }
163 }
164 average /= n_nodes;
165 }
166 else
167 mooseError("Node averaging smoothing has only been defined for the "
168 "NodeArg functor argument at this time, not for ",
170 ". Please contact a MOOSE developer or implement it yourself.");
171 }
173 {
174 if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
175 {
176 unsigned int n_neighbors = 0;
177 for (const auto neighbor : r_elem->neighbor_ptr_range())
178 if (neighbor)
179 {
180 n_neighbors++;
181 average += functor_in(Moose::ElemArg{neighbor, false}, t);
182 }
183 average /= n_neighbors;
184 }
185 else
186 mooseError("Element layered averaging smoothing has only been defined for the "
187 "ElemArg functor argument, not for ",
189 ". Please contact a MOOSE developer or implement it yourself.");
190 }
191 else // Checkerboard removing
192 {
193 if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
194 {
195 // We average the local value with the average of the two values furthest away
196 // among the neighbors. For a checkerboarding but overall linear evolution, this
197 // will compute the average of the "high" and "low" profiles
198 average += base_value / 2;
199
200 // Find the neighbor with the furthest value
201 typename Moose::ADType<T>::type extreme_value = 0;
202 typename Moose::ADType<T>::type delta = 0;
203
204 unsigned int furthest_one = 0;
205 unsigned int num_neighbors = 0;
206 for (const auto side_index : r_elem->side_index_range())
207 {
208 auto neighbor = r_elem->neighbor_ptr(side_index);
209 if (neighbor)
210 {
211 num_neighbors++;
212 auto neighbor_value = functor_in(Moose::ElemArg{neighbor, false}, t);
213 if (abs(neighbor_value - base_value) > delta)
214 {
215 furthest_one = side_index;
216 extreme_value = neighbor_value;
217 delta = abs(neighbor_value - base_value);
218 }
219 }
220 }
221
222 // We're on a boundary in 1D, or maybe an odd shape corner in 2D
223 if (num_neighbors == 1)
224 {
225 average += extreme_value / 2;
226 return average;
227 }
228 else
229 average += extreme_value / 4;
230
231 // Get the value from the neighbor opposite the furthest-value neighbor
232 try
233 {
234 auto opposite_side = r_elem->opposite_side(furthest_one);
235 auto neighbor = r_elem->neighbor_ptr(opposite_side);
236 if (neighbor)
237 {
238 average += functor_in(Moose::ElemArg{neighbor, false}, t) / 4;
239 }
240 else
241 // We're probably at a boundary
242 average += extreme_value / 4;
243 }
244 // if there is no opposite side (for example a triangle)
245 catch (libMesh::LogicError & e)
246 {
247 // find the second furthest
248 delta = 0;
249 typename Moose::ADType<T>::type second_extreme_value = 0;
250
251 for (const auto side_index : r_elem->side_index_range())
252 {
253 auto neighbor = r_elem->neighbor_ptr(side_index);
254 auto neighbor_value =
255 neighbor ? functor_in(Moose::ElemArg{neighbor, false}, t) : base_value;
256 if (abs(neighbor_value - base_value) > delta && side_index != furthest_one)
257 {
258 second_extreme_value = neighbor_value;
259 delta = abs(neighbor_value - base_value);
260 }
261 }
262 average += second_extreme_value / 4;
263 }
264 }
265 else
266 mooseError("Checkerboard removal smoothing has only been defined for the "
267 "ElemArg functor argument, not for ",
269 ". Please contact a MOOSE developer or implement it yourself.");
270 }
271 return average;
272 },
273 clearance_schedule);
274 }
275}
276
277template class FunctorSmootherTempl<Real>;
registerMooseObject("MooseApp", FunctorSmoother)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
virtual const std::set< SubdomainID > & blockIDs() const
Return the block subdomain ids for this object Note, if this is not block restricted,...
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition Factory.C:68
FunctorMaterials compute functor material properties.
static InputParameters validParams()
This functor material smooths a functor material property.
const std::vector< MooseFunctorName > _functors_in
Incoming functor(s) names.
const std::vector< MooseFunctorName > _functors_out
Smoothed functor(s) names.
static InputParameters validParams()
FunctorSmootherTempl(const InputParameters &parameters)
const MooseEnum _smoothing_technique
Smoothing technique to use.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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...
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.
THREAD_ID _tid
MooseMesh & _mesh
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition MooseApp.C:2996
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition MooseApp.h:407
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
virtual Elem * elemPtr(const dof_id_type i)
Definition MooseMesh.C:3222
const std::unordered_map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
If not already created, creates a map from every node to all elements to which they are connected.
Definition MooseMesh.C:1239
const std::vector< const FaceInfo * > & faceInfo() const
Accessor for local FaceInfo objects.
Definition MooseMesh.h:2347
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
MooseEnumIterator end() const
MooseEnumIterator begin() const
Returns a begin/end iterator to all of the set values in the enum.
bool isNodal() const
const ExecFlagEnum & _execute_enum
Execute settings for this object.
std::string prettyCppType(const std::string &cpp_type)
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64
A structure that is used to evaluate Moose functors logically at an element/cell center.
A structure defining a "face" evaluation calling argument for Moose functors.
static const std::set< SubdomainID > undefined_subdomain_connection
A static member that can be used when the connection of a node to subdomains is unknown.
const dof_id_type n_nodes