https://mooseframework.inl.gov
PiecewiseByBlockLambdaFunctor.h
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 #pragma once
11 
12 #include "MooseMesh.h"
13 #include "MooseTypes.h"
14 #include "MooseError.h"
15 #include "MooseFunctor.h"
16 #include "Moose.h"
17 #include "Limiter.h"
18 #include "MathFVUtils.h"
19 #include "GreenGaussGradient.h"
20 
21 #include "libmesh/elem.h"
22 #include "libmesh/remote_elem.h"
23 #include "libmesh/tensor_tools.h"
24 
25 #include <unordered_map>
26 #include <functional>
27 
31 template <typename T>
33 {
34 public:
35  template <typename PolymorphicLambda>
36  PiecewiseByBlockLambdaFunctor(const std::string & name,
37  PolymorphicLambda my_lammy,
38  const std::set<ExecFlagType> & clearance_schedule,
39  const MooseMesh & mesh,
40  const std::set<SubdomainID> & block_ids);
41 
48  template <typename PolymorphicLambda>
49  void setFunctor(const MooseMesh & mesh,
50  const std::set<SubdomainID> & block_ids,
51  PolymorphicLambda my_lammy);
52 
53  virtual ~PiecewiseByBlockLambdaFunctor() = default;
54 
55  bool isExtrapolatedBoundaryFace(const FaceInfo & fi,
56  const Elem * elem,
57  const Moose::StateArg & time) const override;
58 
59  bool hasBlocks(SubdomainID id) const override;
60 
61  bool supportsFaceArg() const override final { return true; }
62  bool supportsElemSideQpArg() const override final { return true; }
63 
65  using typename Moose::FunctorBase<T>::ValueType;
66  using typename Moose::FunctorBase<T>::DotType;
68 
69 protected:
70  using ElemFn = std::function<T(const Moose::ElemArg &, const Moose::StateArg &)>;
71  using FaceFn = std::function<T(const Moose::FaceArg &, const Moose::StateArg &)>;
72  using ElemQpFn = std::function<T(const Moose::ElemQpArg &, const Moose::StateArg &)>;
73  using ElemSideQpFn = std::function<T(const Moose::ElemSideQpArg &, const Moose::StateArg &)>;
74  using ElemPointFn = std::function<T(const Moose::ElemPointArg &, const Moose::StateArg &)>;
75  using NodeFn = std::function<T(const Moose::NodeArg &, const Moose::StateArg &)>;
76 
77  ValueType evaluate(const Moose::ElemArg & elem_arg, const Moose::StateArg & time) const override;
78  ValueType evaluate(const Moose::FaceArg & face, const Moose::StateArg & time) const override;
79  ValueType evaluate(const Moose::ElemQpArg & elem_qp, const Moose::StateArg & time) const override;
80  ValueType evaluate(const Moose::ElemSideQpArg & elem_side_qp,
81  const Moose::StateArg & time) const override;
82  ValueType evaluate(const Moose::ElemPointArg & elem_point,
83  const Moose::StateArg & time) const override;
84  ValueType evaluate(const Moose::NodeArg & node_arg, const Moose::StateArg & time) const override;
85 
88  const Moose::StateArg &) const override;
90  const Moose::StateArg &) const override;
91 
92 private:
99  template <typename C>
101  const std::unordered_map<SubdomainID, C> & functors) const;
102 
105  std::unordered_map<SubdomainID, ElemFn> _elem_functor;
106 
109  std::unordered_map<SubdomainID, FaceFn> _face_functor;
110 
112  std::unordered_map<SubdomainID, ElemQpFn> _elem_qp_functor;
113 
115  std::unordered_map<SubdomainID, ElemSideQpFn> _elem_side_qp_functor;
116 
118  std::unordered_map<SubdomainID, ElemPointFn> _elem_point_functor;
119 
121  std::unordered_map<SubdomainID, NodeFn> _node_functor;
122 
124  const MooseMesh & _mesh;
125 };
126 
127 template <typename T>
128 template <typename PolymorphicLambda>
130  const std::string & name,
131  PolymorphicLambda my_lammy,
132  const std::set<ExecFlagType> & clearance_schedule,
133  const MooseMesh & mesh,
134  const std::set<SubdomainID> & block_ids)
135  : Moose::FunctorBase<T>(name, clearance_schedule), _mesh(mesh)
136 {
137  setFunctor(mesh, block_ids, my_lammy);
138 }
139 
140 template <typename T>
141 template <typename PolymorphicLambda>
142 void
144  const std::set<SubdomainID> & block_ids,
145  PolymorphicLambda my_lammy)
146 {
147  mooseAssert(&mesh == &_mesh,
148  "We should always be setting this functor with the same mesh. We may relax this "
149  "assertion later");
150 
151  auto add_lammy = [this, my_lammy](const SubdomainID block_id)
152  {
153  auto pr = _elem_functor.emplace(block_id, my_lammy);
154  if (!pr.second)
155  mooseError("No insertion for the functor material property '",
156  this->functorName(),
157  "' for block id ",
158  block_id,
159  ". Another material must already declare this property on that block.");
160  _face_functor.emplace(block_id, my_lammy);
161  _elem_qp_functor.emplace(block_id, my_lammy);
162  _elem_side_qp_functor.emplace(block_id, my_lammy);
163  _elem_point_functor.emplace(block_id, my_lammy);
164  _node_functor.emplace(block_id, my_lammy);
165  };
166 
167  for (const auto block_id : block_ids)
168  add_lammy(block_id);
169 
170  // Handle special case of ANY_BLOCK_ID and empty block restriction that also cover
171  // INVALID_BLOCK_ID
172  if (block_ids.count(Moose::ANY_BLOCK_ID) || block_ids.empty() ||
173  block_ids == mesh.meshSubdomains())
174  add_lammy(Moose::INVALID_BLOCK_ID);
175 }
176 
177 template <typename T>
178 bool
180  const Elem *,
181  const Moose::StateArg &) const
182 {
183  if (!fi.neighborPtr())
184  return true;
185 
186  const bool defined_on_elem = _elem_functor.count(fi.elem().subdomain_id());
187  const bool defined_on_neighbor = _elem_functor.count(fi.neighbor().subdomain_id());
188  const bool extrapolated = (defined_on_elem + defined_on_neighbor) == 1;
189 
190  mooseAssert(defined_on_elem || defined_on_neighbor,
191  "This shouldn't be called if we aren't defined on either side.");
192  return extrapolated;
193 }
194 
195 template <typename T>
196 bool
198 {
199  // If any of the maps has a functor for that block, it has the block
200  const bool has_blocks = _elem_functor.count(id);
201  mooseAssert(has_blocks == _face_functor.count(id),
202  "All functor sets should agree on whether we have this sub id");
203  mooseAssert(has_blocks == _elem_qp_functor.count(id),
204  "All functor sets should agree on whether we have this sub id");
205  mooseAssert(has_blocks == _elem_side_qp_functor.count(id),
206  "All functor sets should agree on whether we have this sub id");
207  return has_blocks;
208 }
209 
210 template <typename T>
211 template <typename C>
212 void
214  const SubdomainID sub_id, const std::unordered_map<SubdomainID, C> & functors) const
215 {
216  std::vector<SubdomainID> block_ids;
217  block_ids.reserve(functors.size());
218  for (const auto & [available_sub_id, functor] : functors)
219  {
220  libmesh_ignore(functor);
221  block_ids.push_back(available_sub_id);
222  }
223  mooseError("The provided subdomain ID ",
224  std::to_string(sub_id),
225  " doesn't exist in the map for lambda functor '",
226  this->functorName(),
227  "'! This is likely because you did not provide a functor material "
228  "definition on that subdomain.\nSubdomain IDs in the map: ",
229  Moose::stringify(block_ids));
230 }
231 
232 template <typename T>
235  const Moose::StateArg & time) const
236 {
237  const Elem * const elem = elem_arg.elem;
238  mooseAssert(elem && elem != libMesh::remote_elem,
239  "The element must be non-null and non-remote in functor material properties");
240  auto it = _elem_functor.find(elem->subdomain_id());
241  if (it == _elem_functor.end())
242  subdomainErrorMessage(elem->subdomain_id(), _elem_functor);
243 
244  return it->second(elem_arg, time);
245 }
246 
247 template <typename T>
250  const Moose::StateArg & time) const
251 {
252  using namespace Moose::FV;
253 
254  if (face.face_side)
255  {
256  const auto sub_id = face.face_side->subdomain_id();
257  auto it = _face_functor.find(sub_id);
258  if (it == _face_functor.end())
259  subdomainErrorMessage(sub_id, _face_functor);
260 
261  return it->second(face, time);
262  }
263 
264  mooseAssert(this->isInternalFace(*face.fi),
265  "If we did not have a face side, then we must be an internal face");
266  return interpolate(*this, face, time);
267 }
268 
269 template <typename T>
272  const Moose::StateArg & time) const
273 {
274  const auto sub_id = elem_qp.elem->subdomain_id();
275  auto it = _elem_qp_functor.find(sub_id);
276  if (it == _elem_qp_functor.end())
277  subdomainErrorMessage(sub_id, _elem_qp_functor);
278 
279  return it->second(elem_qp, time);
280 }
281 
282 template <typename T>
285  const Moose::StateArg & time) const
286 {
287  const auto sub_id = elem_side_qp.elem->subdomain_id();
288  auto it = _elem_side_qp_functor.find(sub_id);
289  if (it == _elem_side_qp_functor.end())
290  subdomainErrorMessage(sub_id, _elem_side_qp_functor);
291 
292  return it->second(elem_side_qp, time);
293 }
294 
295 template <typename T>
298  const Moose::StateArg & time) const
299 {
300  const Elem * const elem = elem_point_arg.elem;
301  mooseAssert(elem && elem != libMesh::remote_elem,
302  "The element must be non-null and non-remote in functor material properties");
303  auto it = _elem_point_functor.find(elem->subdomain_id());
304  if (it == _elem_point_functor.end())
305  subdomainErrorMessage(elem->subdomain_id(), _elem_point_functor);
306 
307  return it->second(elem_point_arg, time);
308 }
309 
310 template <typename T>
313  const Moose::StateArg & time) const
314 {
315  mooseAssert(node_arg.node, "The node must be non-null in functor material properties");
316  if (node_arg.subdomain_ids->size() != 1)
317  mooseError("We do not currently support multi-subdomain evaluation of nodal arguments");
318  const auto sub_id = *(node_arg.subdomain_ids->begin());
319  auto it = _node_functor.find(sub_id);
320  if (it == _node_functor.end())
321  subdomainErrorMessage(sub_id, _node_functor);
322 
323  return it->second(node_arg, time);
324 }
325 
326 template <typename T>
329  const Moose::StateArg & time) const
330 {
331  return Moose::FV::greenGaussGradient(elem_arg, time, *this, true, _mesh);
332 }
333 
334 template <typename T>
337  const Moose::StateArg & time) const
338 {
339  return Moose::FV::greenGaussGradient(face_arg, time, *this, true, _mesh);
340 }
std::string name(const ElemQuality q)
ValueType evaluate(const Moose::ElemArg &elem_arg, const Moose::StateArg &time) const override
Evaluate the functor with a given element.
A material property that is evaluated on-the-fly via calls to various overloads of operator() ...
std::function< T(const Moose::NodeArg &, const Moose::StateArg &)> NodeFn
bool supportsFaceArg() const override final
Whether this functor supports evaluation with FaceArg.
Base class template for functor objects.
Definition: MooseFunctor.h:137
std::unordered_map< SubdomainID, ElemFn > _elem_functor
Functors that return element average values (or cell centroid values or whatever the implementer want...
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
std::unordered_map< SubdomainID, ElemPointFn > _elem_point_functor
Functors that return evaluations at an arbitrary physical point in an element.
const libMesh::Elem * face_side
A member that can be used to indicate whether there is a sidedness to this face.
std::function< T(const Moose::ElemPointArg &, const Moose::StateArg &)> ElemPointFn
const Elem & elem() const
Definition: FaceInfo.h:81
libMesh::VectorValue< T > greenGaussGradient(const ElemArg &elem_arg, const StateArg &state_arg, const FunctorBase< T > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh, const bool force_green_gauss=false)
Compute a cell gradient using the method of Green-Gauss.
std::unordered_map< SubdomainID, ElemSideQpFn > _elem_side_qp_functor
Functors that will evaluate elements at side quadrature points.
void subdomainErrorMessage(SubdomainID sub_id, const std::unordered_map< SubdomainID, C > &functors) const
Provide a useful error message about lack of functor material property on the provided subdomain sub_...
MeshBase & mesh
GradientType evaluateGradient(const Moose::ElemArg &elem_arg, const Moose::StateArg &) const override
Evaluate the functor gradient with a given element.
A structure that is used to evaluate Moose functors at an arbitrary physical point contained within a...
const libMesh::Node * node
The node which defines our location in space.
typename FunctorReturnType< T, FunctorEvaluationKind::Gradient >::type GradientType
This rigmarole makes it so that a user can create functors that return containers (std::vector...
Definition: MooseFunctor.h:149
virtual ~PiecewiseByBlockLambdaFunctor()=default
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition: FaceInfo.h:36
void libmesh_ignore(const Args &...)
std::unordered_map< SubdomainID, ElemQpFn > _elem_qp_functor
Functors that will evaluate elements at quadrature points.
const std::set< SubdomainID > * subdomain_ids
Indicates what subdomains this argument should be associated with.
std::unordered_map< SubdomainID, NodeFn > _node_functor
Functors that return nodal values.
const Elem * neighborPtr() const
Definition: FaceInfo.h:84
std::unordered_map< SubdomainID, FaceFn > _face_functor
Functors that return the property value on the requested side of the face (e.g.
A structure defining a "face" evaluation calling argument for Moose functors.
PiecewiseByBlockLambdaFunctor(const std::string &name, PolymorphicLambda my_lammy, const std::set< ExecFlagType > &clearance_schedule, const MooseMesh &mesh, const std::set< SubdomainID > &block_ids)
void setFunctor(const MooseMesh &mesh, const std::set< SubdomainID > &block_ids, PolymorphicLambda my_lammy)
Set the functor that will be used in calls to evaluate overloads.
const FaceInfo * fi
a face information object which defines our location in space
const MooseMesh & _mesh
The mesh that this functor operates on.
std::function< T(const Moose::ElemArg &, const Moose::StateArg &)> ElemFn
const libMesh::Elem * elem
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:88
const Elem & neighbor() const
Definition: FaceInfo.h:216
const libMesh::Elem * elem
A structure that is used to evaluate Moose functors logically at an element/cell center.
Argument for requesting functor evaluation at a quadrature point location in an element.
const libMesh::Elem * elem
The element.
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
std::function< T(const Moose::ElemSideQpArg &, const Moose::StateArg &)> ElemSideQpFn
bool supportsElemSideQpArg() const override final
Whether this functor supports evaluation with ElemSideQpArg.
std::function< T(const Moose::FaceArg &, const Moose::StateArg &)> FaceFn
const SubdomainID ANY_BLOCK_ID
Definition: MooseTypes.C:19
subdomain_id_type subdomain_id() const
std::function< T(const Moose::ElemQpArg &, const Moose::StateArg &)> ElemQpFn
bool hasBlocks(SubdomainID id) const override
Returns whether the functor is defined on this block.
State argument for evaluating functors.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
bool isExtrapolatedBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
Returns whether this (sided) face is an extrapolated boundary face for this functor.
const libMesh::Elem * elem
The element.
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
Provides interpolation of face values for non-advection-specific purposes (although it can/will still...
Definition: MathFVUtils.h:282
Argument for requesting functor evaluation at quadrature point locations on an element side...
const RemoteElem * remote_elem