https://mooseframework.inl.gov
BoundaryRestrictable.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 // MOOSE includes
11 #include "BoundaryRestrictable.h"
12 #include "Material.h"
13 #include "MooseMesh.h"
14 #include "MooseObject.h"
15 
18 {
19 
20  // Create instance of InputParameters
22 
23  // Create user-facing 'boundary' input for restricting inheriting object to boundaries
24  params.addParam<std::vector<BoundaryName>>(
25  "boundary", "The list of boundaries (ids or names) from the mesh where this object applies");
26 
27  // A parameter for disabling error message for objects restrictable by boundary and block,
28  // if the parameter is valid it was already set so don't do anything
29  if (!params.isParamValid("_dual_restrictable"))
30  params.addPrivateParam<bool>("_dual_restrictable", false);
31 
32  return params;
33 }
34 
35 // Standard constructor
37  : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
38  ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
39  : NULL),
40  _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
41  : NULL),
42  _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
43  _block_ids(_empty_block_ids),
44  _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
45  _bnd_material_data(
46 #ifdef MOOSE_KOKKOS_ENABLED
47  moose_object->isKokkosObject()
48  ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
49  :
50 #endif
51  _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
52  _bnd_nodal(nodal),
53  _moose_object(*moose_object)
54 {
56 }
57 
58 // Dual restricted constructor
60  const std::set<SubdomainID> & block_ids,
61  bool nodal)
62  : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
63  ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
64  : NULL),
65  _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
66  : NULL),
67  _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
68  _block_ids(block_ids),
69  _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
70  _bnd_material_data(
71 #ifdef MOOSE_KOKKOS_ENABLED
72  moose_object->isKokkosObject()
73  ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
74  :
75 #endif
76  _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
77  _bnd_nodal(nodal),
78  _moose_object(*moose_object)
79 {
81 }
82 
83 void
85 {
86  // The name and id of the object
87  const std::string & name = _moose_object.name();
88 
89  // If the mesh pointer is not defined, but FEProblemBase is, get it from there
90  if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
92 
93  // Check that the mesh pointer was defined, it is required for this class to operate
94  if (_bnd_mesh == NULL)
95  mooseError("The input parameters must contain a pointer to FEProblemBase via '_fe_problem' or "
96  "a pointer to the MooseMesh via '_mesh'");
97 
98  // If the user supplies boundary IDs
99  if (_moose_object.isParamValid("boundary"))
100  {
101  // Extract the blocks from the input
102  _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
103 
104  // Get the IDs from the supplied names
106 
107  // Store the IDs, handling ANY_BOUNDARY_ID if supplied
108  if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
109  _boundary_names.end())
111  else
112  _bnd_ids.insert(_vec_ids.begin(), _vec_ids.end());
113  }
114 
115  // Produce error if the object is not allowed to be both block and boundary restricted
116  if (!_bnd_dual_restrictable && !_bnd_ids.empty() && !_block_ids.empty())
117  if (!_block_ids.empty() && _block_ids.find(Moose::ANY_BLOCK_ID) == _block_ids.end())
118  _moose_object.paramError("boundary",
119  "Attempted to restrict the object '",
120  name,
121  "' to a boundary, but the object is already restricted by block(s)");
122 
123  // Store ANY_BOUNDARY_ID if empty
124  if (_bnd_ids.empty())
125  {
127  _boundary_names = {"ANY_BOUNDARY_ID"};
128  }
129 
130  // If this object is block restricted, check that defined blocks exist on the mesh
131  if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
132  {
133  const std::set<BoundaryID> * valid_ids;
134  const char * message_ptr = nullptr;
135 
136  if (_bnd_nodal)
137  {
138  valid_ids = &_bnd_mesh->meshNodesetIds();
139  message_ptr = "node sets";
140  }
141  else
142  {
143  valid_ids = &_bnd_mesh->meshSidesetIds();
144  message_ptr = "side sets";
145  }
146 
147  std::vector<BoundaryID> diff;
148 
149  std::set_difference(_bnd_ids.begin(),
150  _bnd_ids.end(),
151  valid_ids->begin(),
152  valid_ids->end(),
153  std::back_inserter(diff));
154 
155  if (!diff.empty())
156  {
157  std::ostringstream msg;
158  auto sep = " ";
159  msg << "the following " << message_ptr << " (ids) do not exist on the mesh:";
160  for (const auto & id : diff)
161  {
162  if (_boundary_names.size() > 0)
163  {
164  auto & name = _boundary_names.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) -
165  _vec_ids.begin());
166  if (std::to_string(id) != name)
167  msg << sep << name << " (" << id << ")";
168  else
169  msg << sep << id;
170  }
171  else
172  msg << sep << id;
173  sep = ", ";
174  }
175 
176  const auto & other_ids =
178  std::vector<BoundaryID> other_boundary_ids;
179  std::set_intersection(diff.begin(),
180  diff.end(),
181  other_ids.begin(),
182  other_ids.end(),
183  std::back_inserter(other_boundary_ids));
184  if (!other_boundary_ids.empty())
185  {
186  msg << "\n\nThe following boundary ";
187  if (other_boundary_ids.size() == 1)
188  msg << "id exists";
189  else
190  msg << "ids exist";
191  if (other_boundary_ids.size() == 1)
192  msg << " as " << (_bnd_nodal ? "a side set" : "a node set")
193  << " but is being requested as " << (_bnd_nodal ? "a node set" : "a side set") << ":";
194  else
195  msg << " as " << (_bnd_nodal ? "side sets" : "node sets")
196  << " but are being requested as " << (_bnd_nodal ? "node sets" : "side sets") << ":";
197 
198  sep = " ";
199  for (const auto id : other_boundary_ids)
200  {
201  msg << sep << id;
202  sep = ", ";
203  }
204 
205  if (!_bnd_nodal)
206  msg << "\n\nTry setting Mesh/construct_side_list_from_node_list=true if you want side "
207  "sets constructed from node sets.";
208  }
209 
210  _moose_object.paramError("boundary", msg.str());
211  }
212  }
213 
214 #ifdef MOOSE_KOKKOS_ENABLED
218 #endif
219 }
220 
222 
223 const std::set<BoundaryID> &
225 {
226  return _bnd_ids;
227 }
228 
229 const std::vector<BoundaryName> &
231 {
232  return _boundary_names;
233 }
234 
235 unsigned int
237 {
238  return (unsigned int)_bnd_ids.size();
239 }
240 
241 bool
243 {
245 }
246 
247 bool
248 BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
249 {
250  return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
251 }
252 
253 bool
254 BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
255 {
256  // Create a vector and utilize the getBoundaryIDs function, which
257  // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
258  return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
259 }
260 
261 bool
262 BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
263 {
264  return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
265 }
266 
267 bool
269 {
270  if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
271  return true;
272  else
273  return _bnd_ids.find(id) != _bnd_ids.end();
274 }
275 
276 bool
277 BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
278 {
279  std::set<BoundaryID> ids_set(ids.begin(), ids.end());
280  return hasBoundary(ids_set, type);
281 }
282 
283 bool
284 BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
285 {
286  // An empty input is assumed to be ANY_BOUNDARY_ID
287  if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
288  return true;
289 
290  // All supplied IDs must match those of the object
291  else if (type == ALL)
292  {
293  if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
294  return true;
295  else
296  return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
297  }
298  // Any of the supplied IDs must match those of the object
299  else
300  {
301  // Loop through the supplied ids
302  for (const auto & id : ids)
303  {
304  // Test the current supplied id
305  bool test = hasBoundary(id);
306 
307  // If the id exists in the stored ids, then return true, otherwise
308  if (test)
309  return true;
310  }
311  return false;
312  }
313 }
314 
315 bool
316 BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
317 {
318  // An empty input is assumed to be ANY_BOUNDARY_ID
319  if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
320  return true;
321 
322  if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
323  return std::includes(ids.begin(),
324  ids.end(),
325  _bnd_mesh->meshBoundaryIds().begin(),
326  _bnd_mesh->meshBoundaryIds().end());
327  else
328  return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
329 }
330 
331 bool
332 BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
333 {
334  std::set<BoundaryID> ids_set(ids.begin(), ids.end());
335  return isBoundarySubset(ids_set);
336 }
337 
338 const std::set<BoundaryID> &
340 {
341  return _bnd_mesh->getBoundaryIDs();
342 }
343 
344 bool
346 {
347  // Reference to MaterialWarehouse for testing and retrieving boundary ids
349 
350  // Complete set of BoundaryIDs that this object is defined
351  const std::set<BoundaryID> & ids =
353 
354  // Loop over each BoundaryID for this object
355  for (const auto & id : ids)
356  {
357  // Storage of material properties that have been DECLARED on this BoundaryID
358  std::set<std::string> declared_props;
359 
360  // If boundary materials exist, populated the set of properties that were declared
361  if (warehouse.hasActiveBoundaryObjects(id))
362  {
363  const std::vector<std::shared_ptr<MaterialBase>> & mats =
364  warehouse.getActiveBoundaryObjects(id);
365  for (const auto & mat : mats)
366  {
367  const std::set<std::string> & mat_props = mat->getSuppliedItems();
368  declared_props.insert(mat_props.begin(), mat_props.end());
369  }
370  }
371 
372  // If the supplied property is not in the list of properties on the current id, return false
373  if (declared_props.find(prop_name) == declared_props.end())
374  return false;
375  }
376 
377  // If you get here the supplied property is defined on all boundaries
378  return true;
379 }
std::string name(const ElemQuality q)
const std::set< BoundaryID > & meshNodesetIds() const
Returns a read-only reference to the set of nodesets currently present in the Mesh.
Definition: MooseMesh.C:3289
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
virtual ~BoundaryRestrictable()
Empty class destructor.
bool isBoundarySubset(const std::set< BoundaryID > &ids) const
Test if the class boundary ids are a subset of the supplied objects.
void initializeBoundaryRestrictable()
An initialization routine needed for dual constructors.
virtual bool boundaryRestricted() const
Returns true if this object has been restricted to a boundary.
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:467
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseBase.h:416
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
const std::set< BoundaryID > & meshSidesetIds() const
Returns a read-only reference to the set of sidesets currently present in the Mesh.
Definition: MooseMesh.C:3283
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
bool isKokkosObject() const
Get whether this object is a Kokkos functor The parameter MooseBase::kokkos_object_param is set by th...
Definition: MooseObject.h:63
MooseMesh * _bnd_mesh
Point to mesh.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
MaterialBase objects are special in that they have additional objects created automatically (see FEPr...
const MaterialWarehouse & getMaterialWarehouse() const
const bool _bnd_dual_restrictable
Flag for allowing dual restriction with BlockRestrictable.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
InputParameters emptyInputParameters()
const std::set< BoundaryID > & meshBoundaryIds() const
Returns a read-only reference to the set of boundary IDs currently present in the Mesh...
Definition: MooseMesh.C:3277
bool hasBoundaryMaterialPropertyHelper(const std::string &prop_name) const
A helper method to avoid circular #include problems.
bool hasActiveBoundaryObjects(THREAD_ID tid=0) const
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
static bool restricted(const std::set< BoundaryID > &ids)
Helper for determining if the object is boundary restricted.
void addKokkosMeshInitializationHook(std::function< void()> function)
Add a function hook that needs to be called after Kokkos mesh initialization.
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
boundary_id_type BoundaryID
std::set< BoundaryID > _bnd_ids
Set of the boundary ids.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:93
const std::set< BoundaryID > & meshBoundaryIDs() const
Returns the set of all boundary ids for the entire mesh.
unsigned int numBoundaryIDs() const
Return the number of boundaries for this object.
TEST_TYPE
A flag changing the behavior of hasBoundary.
bool _bnd_nodal
Whether or not this object is restricted to nodesets.
static InputParameters validParams()
const std::map< BoundaryID, std::vector< std::shared_ptr< T > > > & getActiveBoundaryObjects(THREAD_ID tid=0) const
std::vector< BoundaryID > _vec_ids
Vector of the boundary ids.
bool hasBoundary(const BoundaryName &name) const
Test if the supplied boundary name is valid for this object.
const MooseObject & _moose_object
The moose object that this is an interface for.
const SubdomainID ANY_BLOCK_ID
Definition: MooseTypes.C:19
std::vector< BoundaryName > _boundary_names
Vector the the boundary names.
virtual MooseMesh & mesh() override
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...
const std::set< SubdomainID > & _block_ids
Reference to the block_ids, defaults to an empty set if not provided.
FEProblemBase * _bnd_feproblem
Pointer to FEProblemBase.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
std::vector< BoundaryID > getBoundaryIDs(const Elem *const elem, const unsigned short int side) const
Returns a vector of boundary IDs for the requested element on the requested side. ...
BoundaryRestrictable(const MooseObject *moose_object, bool nodal)
Class constructor Populates the _bnd_ids for the given boundary names supplied with the &#39;boundary&#39; in...
const std::vector< BoundaryName > & boundaryNames() const
Return the boundary names for this object.
virtual const std::set< BoundaryID > & boundaryIDs() const
Return the boundary IDs for this object.
void initializeKokkosBoundaryRestrictable()
const BoundaryID ANY_BOUNDARY_ID
Definition: MooseTypes.C:21
unsigned int THREAD_ID
Definition: MooseTypes.h:237
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.