https://mooseframework.inl.gov
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 
18 template <typename T>
21 {
23  params.addClassDescription("Creates smoother functor(s) using various averaging techniques");
24  params.addParam<std::vector<MooseFunctorName>>("functors_in",
25  "The name(s) of the functors to smooth");
26  params.addParam<std::vector<MooseFunctorName>>("functors_out",
27  "The name(s) of the smooth output functors");
28  MooseEnum smoothing_techniques("face_average layered_elem_average remove_checkerboard");
29  params.addParam<MooseEnum>(
30  "smoothing_technique", smoothing_techniques, "How to smooth the functor");
31 
32  return params;
33 }
34 
35 template <typename T>
37  : FunctorMaterial(parameters),
38  _functors_in(getParam<std::vector<MooseFunctorName>>("functors_in")),
39  _functors_out(getParam<std::vector<MooseFunctorName>>("functors_out")),
40  _smoothing_technique(getParam<MooseEnum>("smoothing_technique"))
41 {
42  if (_tid == 0)
43  {
44  // We need one layer of ghosting at least to get neighbor values
45  auto & factory = _app.getFactory();
46  auto rm_params = factory.getValidParams("ElementSideNeighborLayers");
47  rm_params.template set<std::string>("for_whom") = name();
48  rm_params.template set<MooseMesh *>("mesh") = &const_cast<MooseMesh &>(_mesh);
49  rm_params.template set<Moose::RelationshipManagerType>("rm_type") =
52  rm_params.template set<unsigned short>("layers") = 1;
53  rm_params.template set<bool>("use_point_neighbors") = false;
54  rm_params.template set<bool>("use_displaced_mesh") =
55  parameters.template get<bool>("use_displaced_mesh");
56  mooseAssert(rm_params.areAllRequiredParamsValid(),
57  "All relationship manager parameters should be valid.");
58  auto rm_obj = factory.template create<RelationshipManager>(
59  "ElementSideNeighborLayers", name() + "_functor_smoothing", rm_params);
60 
61  // Delete the resources created on behalf of the RM if it ends up not being added to the
62  // App.
63  if (!_app.addRelationshipManager(rm_obj))
64  factory.releaseSharedObjects(*rm_obj);
65  }
66 
67  const std::set<ExecFlagType> clearance_schedule(_execute_enum.begin(), _execute_enum.end());
68 
69  for (const auto i : index_range(_functors_in))
70  {
71  // This potentially upcasts functors from non-AD to AD
72  const auto & functor_in = getFunctor<typename Moose::ADType<T>::type>(_functors_in[i]);
73 
74  // We always add the AD type
75  addFunctorProperty<typename Moose::ADType<T>::type>(
76  _functors_out[i],
77  [this, &functor_in](const auto & r, const auto & t) -> typename Moose::ADType<T>::type
78  {
79  typename Moose::ADType<T>::type base_value = functor_in(r, t);
80  typename Moose::ADType<T>::type average = 0;
81 
82  const Elem * r_elem = nullptr;
83  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
84  r_elem = r.elem;
85 
86  // Handle the single isolated element case
87  if (r_elem && r_elem->n_neighbors() == 0)
88  return base_value;
89 
90  // If these techniques are of interest elsewhere, they should be moved to a
91  // FunctorAveragingUtils file and namespaced
93  {
94  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
95  {
96  unsigned int n_faces = 0;
97  for (const auto side_index : r_elem->side_index_range())
98  {
99  auto fi = _mesh.faceInfo(r_elem, side_index);
100  if (!fi)
101  fi =
102  _mesh.faceInfo(r_elem->neighbor_ptr(side_index),
103  r_elem->neighbor_ptr(side_index)->which_neighbor_am_i(r_elem));
104  Moose::FaceArg face_arg{
105  fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
106  if (face_arg.fi)
107  {
108  average += functor_in(face_arg, t);
109  n_faces++;
110  }
111  }
112  average /= n_faces;
113  }
114  else
115  // a conceptually simple option here would be to use the smoothed version of the
116  // ElemArg to compute all the other functor arguments. Maybe with the same smoothing
117  // on the gradient calls
118  mooseError("Face averaging smoothing has only been defined for the ElemArg functor "
119  "argument, not for ",
121  ". Please contact a MOOSE developer or implement it yourself.");
122  }
124  {
125  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
126  {
127  unsigned int n_neighbors = 0;
128  for (const auto neighbor : r_elem->neighbor_ptr_range())
129  if (neighbor)
130  {
131  n_neighbors++;
132  average += functor_in(Moose::ElemArg{neighbor, false}, t);
133  }
134  average /= n_neighbors;
135  }
136  else
137  mooseError("Element layered averaging smoothing has only been defined for the "
138  "ElemArg functor argument, not for ",
140  ". Please contact a MOOSE developer or implement it yourself.");
141  }
142  else
143  {
144  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
145  {
146  // We average the local value with the average of the two values furthest away
147  // among the neighbors. For a checkerboarding but overall linear evolution, this will
148  // compute the average of the "high" and "low" profiles
149  average += base_value / 2;
150 
151  // Find the neighbor with the furthest value
152  typename Moose::ADType<T>::type extreme_value = 0;
153  typename Moose::ADType<T>::type delta = 0;
154 
155  unsigned int furthest_one = 0;
156  unsigned int num_neighbors = 0;
157  for (const auto side_index : r_elem->side_index_range())
158  {
159  auto neighbor = r_elem->neighbor_ptr(side_index);
160  if (neighbor)
161  {
162  num_neighbors++;
163  auto neighbor_value = functor_in(Moose::ElemArg{neighbor, false}, t);
164  if (std::abs(neighbor_value - base_value) > delta)
165  {
166  furthest_one = side_index;
167  extreme_value = neighbor_value;
168  delta = std::abs(neighbor_value - base_value);
169  }
170  }
171  }
172 
173  // We're on a boundary in 1D, or maybe an odd shape corner in 2D
174  if (num_neighbors == 1)
175  {
176  average += extreme_value / 2;
177  return average;
178  }
179  else
180  average += extreme_value / 4;
181 
182  // Get the value from the neighbor opposite the furthest-value neighbor
183  try
184  {
185  auto opposite_side = r_elem->opposite_side(furthest_one);
186  auto neighbor = r_elem->neighbor_ptr(opposite_side);
187  if (neighbor)
188  {
189  average += functor_in(Moose::ElemArg{neighbor, false}, t) / 4;
190  }
191  else
192  // We're probably at a boundary
193  average += extreme_value / 4;
194  }
195  // if there is no opposite side (for example a triangle)
196  catch (libMesh::LogicError & e)
197  {
198  // find the second furthest
199  delta = 0;
200  typename Moose::ADType<T>::type second_extreme_value = 0;
201 
202  for (const auto side_index : r_elem->side_index_range())
203  {
204  auto neighbor = r_elem->neighbor_ptr(side_index);
205  auto neighbor_value =
206  neighbor ? functor_in(Moose::ElemArg{neighbor, false}, t) : base_value;
207  if (std::abs(neighbor_value - base_value) > delta && side_index != furthest_one)
208  {
209  second_extreme_value = neighbor_value;
210  delta = std::abs(neighbor_value - base_value);
211  }
212  }
213  average += second_extreme_value / 4;
214  }
215  }
216  else
217  mooseError("Checkerboard removal smoothing has only been defined for the "
218  "ElemArg functor argument, not for ",
220  ". Please contact a MOOSE developer or implement it yourself.");
221  }
222  return average;
223  },
224  clearance_schedule);
225  }
226 }
227 
228 template class FunctorSmootherTempl<Real>;
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Definition: EigenADReal.h:42
This functor material smooths a functor material property.
const MooseEnum _smoothing_technique
Smoothing technique to use.
static InputParameters validParams()
MooseEnumIterator begin() const
Returns a begin/end iterator to all of the set values in the enum.
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:127
static InputParameters validParams()
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:68
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
MooseEnumIterator end() const
const std::vector< MooseFunctorName > _functors_in
Incoming functor(s) names.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition: MooseApp.h:394
registerMooseObject("MooseApp", FunctorSmoother)
const std::vector< const FaceInfo * > & faceInfo() const
Accessor for local FaceInfo objects.
Definition: MooseMesh.h:2173
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:99
FunctorMaterials compute functor material properties.
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition: MooseApp.C:3024
MooseMesh & _mesh
Definition: MaterialBase.h:326
const std::vector< MooseFunctorName > _functors_out
Smoothed functor(s) names.
A structure defining a "face" evaluation calling argument for Moose functors.
THREAD_ID _tid
Definition: MaterialBase.h:317
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
A structure that is used to evaluate Moose functors logically at an element/cell center.
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:353
const ExecFlagEnum & _execute_enum
Execute settings for this object.
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
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...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
auto index_range(const T &sizable)
FunctorSmootherTempl(const InputParameters &parameters)
std::string prettyCppType(const std::string &cpp_type)
Definition: MooseUtils.C:1246