https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
31template <typename T>
33{
34public:
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
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
66 using typename Moose::FunctorBase<T>::DotType;
68
69protected:
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 using PointFn = std::function<T(const Moose::PointArg &, const Moose::StateArg &)>;
77
78 ValueType evaluate(const Moose::ElemArg & elem_arg, const Moose::StateArg & time) const override;
79 ValueType evaluate(const Moose::FaceArg & face, const Moose::StateArg & time) const override;
80 ValueType evaluate(const Moose::ElemQpArg & elem_qp, const Moose::StateArg & time) const override;
81 ValueType evaluate(const Moose::ElemSideQpArg & elem_side_qp,
82 const Moose::StateArg & time) const override;
83 ValueType evaluate(const Moose::ElemPointArg & elem_point,
84 const Moose::StateArg & time) const override;
85 ValueType evaluate(const Moose::NodeArg & node_arg, const Moose::StateArg & time) const override;
86 ValueType evaluate(const Moose::PointArg & point_arg,
87 const Moose::StateArg & time) const override;
88
91 const Moose::StateArg &) const override;
93 const Moose::StateArg &) const override;
94
95private:
102 template <typename C>
104 const std::unordered_map<SubdomainID, C> & functors) const;
105
109 std::string subdomainNameAndID(SubdomainID sub_id) const;
110
113 std::unordered_map<SubdomainID, ElemFn> _elem_functor;
114
117 std::unordered_map<SubdomainID, FaceFn> _face_functor;
118
120 std::unordered_map<SubdomainID, ElemQpFn> _elem_qp_functor;
121
123 std::unordered_map<SubdomainID, ElemSideQpFn> _elem_side_qp_functor;
124
126 std::unordered_map<SubdomainID, ElemPointFn> _elem_point_functor;
127
129 std::unordered_map<SubdomainID, NodeFn> _node_functor;
130
132 std::unordered_map<SubdomainID, PointFn> _point_functor;
133
136};
137
138template <typename T>
139template <typename PolymorphicLambda>
141 const std::string & name,
142 PolymorphicLambda my_lammy,
143 const std::set<ExecFlagType> & clearance_schedule,
144 const MooseMesh & mesh,
145 const std::set<SubdomainID> & block_ids)
146 : Moose::FunctorBase<T>(name, clearance_schedule), _mesh(mesh)
147{
148 setFunctor(mesh, block_ids, my_lammy);
149}
150
151template <typename T>
152template <typename PolymorphicLambda>
153void
155 const std::set<SubdomainID> & block_ids,
156 PolymorphicLambda my_lammy)
157{
158 mooseAssert(&mesh == &_mesh,
159 "We should always be setting this functor with the same mesh. We may relax this "
160 "assertion later");
161
162 auto add_lammy = [this, my_lammy](const SubdomainID block_id)
163 {
164 auto pr = _elem_functor.emplace(block_id, my_lammy);
165 if (!pr.second)
166 mooseError("No insertion for the functor material property '",
167 this->functorName(),
168 "' for block id ",
169 block_id,
170 ". Another material must already declare this property on that block.");
171 _face_functor.emplace(block_id, my_lammy);
172 _elem_qp_functor.emplace(block_id, my_lammy);
173 _elem_side_qp_functor.emplace(block_id, my_lammy);
174 _elem_point_functor.emplace(block_id, my_lammy);
175 _node_functor.emplace(block_id, my_lammy);
176 _point_functor.emplace(block_id, my_lammy);
177 };
178
179 for (const auto block_id : block_ids)
180 add_lammy(block_id);
181
182 // Handle special case of ANY_BLOCK_ID and empty block restriction that also cover
183 // INVALID_BLOCK_ID
184 if (block_ids.count(Moose::ANY_BLOCK_ID) || block_ids.empty() ||
185 block_ids == mesh.meshSubdomains())
186 add_lammy(Moose::INVALID_BLOCK_ID);
187}
188
189template <typename T>
190bool
192 const Elem *,
193 const Moose::StateArg &) const
194{
195 if (!fi.neighborPtr())
196 return true;
197
198 const bool defined_on_elem = _elem_functor.count(fi.elem().subdomain_id());
199 const bool defined_on_neighbor = _elem_functor.count(fi.neighbor().subdomain_id());
200 const bool extrapolated = (defined_on_elem + defined_on_neighbor) == 1;
201
202 mooseAssert(defined_on_elem || defined_on_neighbor,
203 "This shouldn't be called if we aren't defined on either side.");
204 return extrapolated;
205}
206
207template <typename T>
208bool
210{
211 // If any of the maps has a functor for that block, it has the block
212 const bool has_blocks = _elem_functor.count(id);
213 mooseAssert(has_blocks == _face_functor.count(id),
214 "All functor sets should agree on whether we have this sub id");
215 mooseAssert(has_blocks == _elem_qp_functor.count(id),
216 "All functor sets should agree on whether we have this sub id");
217 mooseAssert(has_blocks == _elem_side_qp_functor.count(id),
218 "All functor sets should agree on whether we have this sub id");
219 return has_blocks;
220}
221
222template <typename T>
223std::string
225{
226 const auto & name = _mesh.getSubdomainName(sub_id);
227 if (name.empty())
228 return Moose::stringify(sub_id);
229 return "'" + name + "' (" + Moose::stringify(sub_id) + ")";
230}
231
232template <typename T>
233template <typename C>
234void
236 const SubdomainID sub_id, const std::unordered_map<SubdomainID, C> & functors) const
237{
238 std::vector<std::string> block_names_and_ids;
239 block_names_and_ids.reserve(functors.size());
240 for (const auto & [available_sub_id, functor] : functors)
241 {
242 libmesh_ignore(functor);
243 block_names_and_ids.push_back(subdomainNameAndID(available_sub_id));
244 }
245 mooseError("The provided subdomain ",
246 subdomainNameAndID(sub_id),
247 " doesn't exist in the map for lambda functor '",
248 this->functorName(),
249 "'! This is likely because you did not provide a functor material "
250 "definition on that subdomain.\nSubdomains in the map: ",
251 Moose::stringify(block_names_and_ids));
252}
253
254template <typename T>
257 const Moose::StateArg & time) const
258{
259 const Elem * const elem = elem_arg.elem;
260 mooseAssert(elem && elem != libMesh::remote_elem,
261 "The element must be non-null and non-remote in functor material properties");
262 auto it = _elem_functor.find(elem->subdomain_id());
263 if (it == _elem_functor.end())
264 subdomainErrorMessage(elem->subdomain_id(), _elem_functor);
265
266 return it->second(elem_arg, time);
267}
268
269template <typename T>
272 const Moose::StateArg & time) const
273{
274 using namespace Moose::FV;
275
276 if (face.face_side)
277 {
278 const auto sub_id = face.face_side->subdomain_id();
279 auto it = _face_functor.find(sub_id);
280 if (it == _face_functor.end())
281 subdomainErrorMessage(sub_id, _face_functor);
282
283 return it->second(face, time);
284 }
285
286 mooseAssert(this->isInternalFace(*face.fi),
287 "If we did not have a face side, then we must be an internal face");
288 return interpolate(*this, face, time);
289}
290
291template <typename T>
294 const Moose::StateArg & time) const
295{
296 const auto sub_id = elem_qp.elem->subdomain_id();
297 auto it = _elem_qp_functor.find(sub_id);
298 if (it == _elem_qp_functor.end())
299 subdomainErrorMessage(sub_id, _elem_qp_functor);
300
301 return it->second(elem_qp, time);
302}
303
304template <typename T>
307 const Moose::StateArg & time) const
308{
309 const auto sub_id = elem_side_qp.elem->subdomain_id();
310 auto it = _elem_side_qp_functor.find(sub_id);
311 if (it == _elem_side_qp_functor.end())
312 subdomainErrorMessage(sub_id, _elem_side_qp_functor);
313
314 return it->second(elem_side_qp, time);
315}
316
317template <typename T>
320 const Moose::StateArg & time) const
321{
322 const Elem * const elem = elem_point_arg.elem;
323 mooseAssert(elem && elem != libMesh::remote_elem,
324 "The element must be non-null and non-remote in functor material properties");
325 auto it = _elem_point_functor.find(elem->subdomain_id());
326 if (it == _elem_point_functor.end())
327 subdomainErrorMessage(elem->subdomain_id(), _elem_point_functor);
328
329 return it->second(elem_point_arg, time);
330}
331
332template <typename T>
335 const Moose::StateArg & time) const
336{
337 mooseAssert(node_arg.node, "The node must be non-null in functor material properties");
338 if (node_arg.subdomain_ids->size() != 1)
339 mooseError("We do not currently support multi-subdomain evaluation of nodal arguments");
340 const auto sub_id = *(node_arg.subdomain_ids->begin());
341 auto it = _node_functor.find(sub_id);
342 if (it == _node_functor.end())
343 subdomainErrorMessage(sub_id, _node_functor);
344
345 return it->second(node_arg, time);
346}
347
348template <typename T>
351 const Moose::StateArg & time) const
352{
353 // A point has no subdomain, so this is only available for functors defined on all blocks
354 auto it = _point_functor.find(Moose::INVALID_BLOCK_ID);
355 if (it == _point_functor.end())
356 subdomainErrorMessage(Moose::INVALID_BLOCK_ID, _point_functor);
357
358 return it->second(point_arg, time);
359}
360
361template <typename T>
364 const Moose::StateArg & time) const
365{
366 return Moose::FV::greenGaussGradient(elem_arg, time, *this, true, _mesh);
367}
368
369template <typename T>
372 const Moose::StateArg & time) const
373{
374 return Moose::FV::greenGaussGradient(face_arg, time, *this, true, _mesh);
375}
subdomain_id_type SubdomainID
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition FaceInfo.h:38
const Elem & elem() const
Definition FaceInfo.h:85
const Elem * neighborPtr() const
Definition FaceInfo.h:88
const Elem & neighbor() const
Definition FaceInfo.h:220
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
Base class template for functor objects.
typename FunctorReturnType< T, FunctorEvaluationKind::Gradient >::type GradientType
This rigmarole makes it so that a user can create functors that return containers (std::vector,...
A material property that is evaluated on-the-fly via calls to various overloads of operator()
virtual ~PiecewiseByBlockLambdaFunctor()=default
std::function< T(const Moose::ElemSideQpArg &, const Moose::StateArg &)> ElemSideQpFn
ValueType evaluate(const Moose::ElemArg &elem_arg, const Moose::StateArg &time) const override
Evaluate the functor with a given element.
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.
GradientType evaluateGradient(const Moose::ElemArg &elem_arg, const Moose::StateArg &) const override
Evaluate the functor gradient with a given element.
std::unordered_map< SubdomainID, FaceFn > _face_functor
Functors that return the property value on the requested side of the face (e.g.
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_...
std::unordered_map< SubdomainID, ElemSideQpFn > _elem_side_qp_functor
Functors that will evaluate elements at side quadrature points.
std::unordered_map< SubdomainID, PointFn > _point_functor
Functors that return evaluations at an arbitrary physical point without mesh information.
std::unordered_map< SubdomainID, NodeFn > _node_functor
Functors that return nodal values.
std::string subdomainNameAndID(SubdomainID sub_id) const
Format a subdomain ID with its name, when available.
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.
std::function< T(const Moose::FaceArg &, const Moose::StateArg &)> FaceFn
PiecewiseByBlockLambdaFunctor(const std::string &name, PolymorphicLambda my_lammy, const std::set< ExecFlagType > &clearance_schedule, const MooseMesh &mesh, const std::set< SubdomainID > &block_ids)
bool supportsElemSideQpArg() const override final
Whether this functor supports evaluation with ElemSideQpArg.
const MooseMesh & _mesh
The mesh that this functor operates on.
std::function< T(const Moose::NodeArg &, const Moose::StateArg &)> NodeFn
bool hasBlocks(SubdomainID id) const override
Returns whether the functor is defined on this block.
std::function< T(const Moose::ElemArg &, const Moose::StateArg &)> ElemFn
std::unordered_map< SubdomainID, ElemFn > _elem_functor
Functors that return element average values (or cell centroid values or whatever the implementer want...
bool supportsFaceArg() const override final
Whether this functor supports evaluation with FaceArg.
std::function< T(const Moose::ElemQpArg &, const Moose::StateArg &)> ElemQpFn
std::unordered_map< SubdomainID, ElemQpFn > _elem_qp_functor
Functors that will evaluate elements at quadrature points.
std::function< T(const Moose::ElemPointArg &, const Moose::StateArg &)> ElemPointFn
std::function< T(const Moose::PointArg &, const Moose::StateArg &)> PointFn
std::unordered_map< SubdomainID, ElemPointFn > _elem_point_functor
Functors that return evaluations at an arbitrary physical point in an element.
subdomain_id_type subdomain_id() const
MeshBase & mesh
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.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const SubdomainID ANY_BLOCK_ID
Definition MooseTypes.C:19
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
const SubdomainID INVALID_BLOCK_ID
Definition MooseTypes.C:20
const RemoteElem * remote_elem
A structure that is used to evaluate Moose functors logically at an element/cell center.
const libMesh::Elem * elem
A structure that is used to evaluate Moose functors at an arbitrary physical point contained within a...
const libMesh::Elem * elem
Argument for requesting functor evaluation at a quadrature point location in an element.
const libMesh::Elem * elem
The element.
Argument for requesting functor evaluation at quadrature point locations on an element side.
const libMesh::Elem * elem
The element.
A structure defining a "face" evaluation calling argument for Moose functors.
const libMesh::Elem * face_side
A member that can be used to indicate whether there is a sidedness to this face.
const FaceInfo * fi
a face information object which defines our location in space
const libMesh::Node * node
The node which defines our location in space.
const std::set< SubdomainID > * subdomain_ids
Indicates what subdomains this argument should be associated with.
A structure that is used to evaluate Moose functors at an arbitrary physical point,...
State argument for evaluating functors.