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  using std::abs;
82 
83  const Elem * r_elem = nullptr;
84  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
85  r_elem = r.elem;
86 
87  // Handle the single isolated element case
88  if (r_elem && r_elem->n_neighbors() == 0)
89  return base_value;
90 
91  // If these techniques are of interest elsewhere, they should be moved to a
92  // FunctorAveragingUtils file and namespaced
94  {
95  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
96  {
97  unsigned int n_faces = 0;
98  for (const auto side_index : r_elem->side_index_range())
99  {
100  auto fi = _mesh.faceInfo(r_elem, side_index);
101  if (!fi)
102  fi =
103  _mesh.faceInfo(r_elem->neighbor_ptr(side_index),
104  r_elem->neighbor_ptr(side_index)->which_neighbor_am_i(r_elem));
105  Moose::FaceArg face_arg{
106  fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
107  if (face_arg.fi)
108  {
109  average += functor_in(face_arg, t);
110  n_faces++;
111  }
112  }
113  average /= n_faces;
114  }
115  else
116  // a conceptually simple option here would be to use the smoothed version of the
117  // ElemArg to compute all the other functor arguments. Maybe with the same smoothing
118  // on the gradient calls
119  mooseError("Face averaging smoothing has only been defined for the ElemArg functor "
120  "argument, not for ",
122  ". Please contact a MOOSE developer or implement it yourself.");
123  }
125  {
126  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
127  {
128  unsigned int n_neighbors = 0;
129  for (const auto neighbor : r_elem->neighbor_ptr_range())
130  if (neighbor)
131  {
132  n_neighbors++;
133  average += functor_in(Moose::ElemArg{neighbor, false}, t);
134  }
135  average /= n_neighbors;
136  }
137  else
138  mooseError("Element layered averaging smoothing has only been defined for the "
139  "ElemArg functor argument, not for ",
141  ". Please contact a MOOSE developer or implement it yourself.");
142  }
143  else
144  {
145  if constexpr (std::is_same_v<const Moose::ElemArg &, decltype(r)>)
146  {
147  // We average the local value with the average of the two values furthest away
148  // among the neighbors. For a checkerboarding but overall linear evolution, this will
149  // compute the average of the "high" and "low" profiles
150  average += base_value / 2;
151 
152  // Find the neighbor with the furthest value
153  typename Moose::ADType<T>::type extreme_value = 0;
154  typename Moose::ADType<T>::type delta = 0;
155 
156  unsigned int furthest_one = 0;
157  unsigned int num_neighbors = 0;
158  for (const auto side_index : r_elem->side_index_range())
159  {
160  auto neighbor = r_elem->neighbor_ptr(side_index);
161  if (neighbor)
162  {
163  num_neighbors++;
164  auto neighbor_value = functor_in(Moose::ElemArg{neighbor, false}, t);
165  if (abs(neighbor_value - base_value) > delta)
166  {
167  furthest_one = side_index;
168  extreme_value = neighbor_value;
169  delta = abs(neighbor_value - base_value);
170  }
171  }
172  }
173 
174  // We're on a boundary in 1D, or maybe an odd shape corner in 2D
175  if (num_neighbors == 1)
176  {
177  average += extreme_value / 2;
178  return average;
179  }
180  else
181  average += extreme_value / 4;
182 
183  // Get the value from the neighbor opposite the furthest-value neighbor
184  try
185  {
186  auto opposite_side = r_elem->opposite_side(furthest_one);
187  auto neighbor = r_elem->neighbor_ptr(opposite_side);
188  if (neighbor)
189  {
190  average += functor_in(Moose::ElemArg{neighbor, false}, t) / 4;
191  }
192  else
193  // We're probably at a boundary
194  average += extreme_value / 4;
195  }
196  // if there is no opposite side (for example a triangle)
197  catch (libMesh::LogicError & e)
198  {
199  // find the second furthest
200  delta = 0;
201  typename Moose::ADType<T>::type second_extreme_value = 0;
202 
203  for (const auto side_index : r_elem->side_index_range())
204  {
205  auto neighbor = r_elem->neighbor_ptr(side_index);
206  auto neighbor_value =
207  neighbor ? functor_in(Moose::ElemArg{neighbor, false}, t) : base_value;
208  if (abs(neighbor_value - base_value) > delta && side_index != furthest_one)
209  {
210  second_extreme_value = neighbor_value;
211  delta = abs(neighbor_value - base_value);
212  }
213  }
214  average += second_extreme_value / 4;
215  }
216  }
217  else
218  mooseError("Checkerboard removal smoothing has only been defined for the "
219  "ElemArg functor argument, not for ",
221  ". Please contact a MOOSE developer or implement it yourself.");
222  }
223  return average;
224  },
225  clearance_schedule);
226  }
227 }
228 
229 template class FunctorSmootherTempl<Real>;
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Definition: EigenADReal.h:50
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:131
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:401
registerMooseObject("MooseApp", FunctorSmoother)
const std::vector< const FaceInfo * > & faceInfo() const
Accessor for local FaceInfo objects.
Definition: MooseMesh.h:2216
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
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:3107
MooseMesh & _mesh
Definition: MaterialBase.h:338
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:329
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:357
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:271
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:1151