https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ThreadedElementLoopBase.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 "ParallelUniqueId.h"
13#include "MooseMesh.h"
14#include "MooseTypes.h"
15#include "MooseException.h"
16#include "libmesh/libmesh_exceptions.h"
17#include "libmesh/elem.h"
18
19// C++
20#include <cstring> // for "Jacobian" exception test
21
25template <typename RangeType>
27{
28public:
30
32
34
35 virtual void operator()(const RangeType & range, bool bypass_threading = false);
36
40 virtual void pre();
41
45 virtual void post();
46
52 virtual void onElement(const Elem * elem);
53
59 virtual void preElement(const Elem * elem);
60
66 virtual void postElement(const Elem * elem);
67
76 virtual void preBoundary(const Elem * elem,
77 unsigned int side,
78 BoundaryID bnd_id,
79 const Elem * lower_d_elem = nullptr);
80
89 virtual void onBoundary(const Elem * elem,
90 unsigned int side,
91 BoundaryID bnd_id,
92 const Elem * lower_d_elem = nullptr);
93
100 virtual void preInternalSide(const Elem * elem, unsigned int side);
101
108 virtual void postInternalSide(const Elem * elem, unsigned int side);
109
116 virtual void onInternalSide(const Elem * elem, unsigned int side);
117
124 virtual void onExternalSide(const Elem * elem, unsigned int side);
125
133 virtual void onInterface(const Elem * elem, unsigned int side, BoundaryID bnd_id);
134
141 virtual void subdomainChanged();
142
150
156
162 virtual bool keepGoing() { return true; }
163
164protected:
167
170
173
176
179
181 virtual void printGeneralExecutionInformation() const {}
182
184 virtual void printBlockExecutionInformation() const {}
185
187 virtual void printBoundaryExecutionInformation(const unsigned int /*bid*/) const {}
188
190 mutable std::set<SubdomainID> _blocks_exec_printed;
191
193 mutable std::set<BoundaryID> _boundaries_exec_printed;
194
197
204 virtual bool shouldComputeInternalSide(const Elem & elem, const Elem & neighbor) const;
205};
206
207template <typename RangeType>
211
212template <typename RangeType>
218
219template <typename RangeType>
223
224template <typename RangeType>
225void
226ThreadedElementLoopBase<RangeType>::operator()(const RangeType & range, bool bypass_threading)
227{
228 try
229 {
230 try
231 {
232 ParallelUniqueId puid;
233 _tid = bypass_threading ? 0 : puid.id;
234
235 pre();
236 printGeneralExecutionInformation();
237
238 _subdomain = Moose::INVALID_BLOCK_ID;
239 _neighbor_subdomain = Moose::INVALID_BLOCK_ID;
240 typename RangeType::const_iterator el = range.begin();
241 for (el = range.begin(); el != range.end(); ++el)
242 {
243 if (!keepGoing())
244 break;
245
246 const Elem * elem = *el;
247
248 preElement(elem);
249
250 _old_subdomain = _subdomain;
251 _subdomain = elem->subdomain_id();
252 if (_subdomain != _old_subdomain)
253 {
254 subdomainChanged();
255 printBlockExecutionInformation();
256 }
257
258 onElement(elem);
259
260 if (_mesh.interiorLowerDBlocks().count(elem->subdomain_id()) > 0 ||
261 _mesh.boundaryLowerDBlocks().count(elem->subdomain_id()) > 0)
262 {
263 postElement(elem);
264 continue;
265 }
266
267 const auto elem_boundary_ids = _mesh.getBoundaryIDs(elem);
268 for (unsigned int side = 0; side < elem->n_sides(); side++)
269 {
270 const auto & boundary_ids = elem_boundary_ids[side];
271 const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
272
273 for (const auto bnd_id : boundary_ids)
274 {
275 preBoundary(elem, side, bnd_id, lower_d_elem);
276 printBoundaryExecutionInformation(bnd_id);
277 onBoundary(elem, side, bnd_id, lower_d_elem);
278 }
279
280 const Elem * neighbor = elem->neighbor_ptr(side);
281 if (neighbor)
282 {
283 preInternalSide(elem, side);
284
285 _old_neighbor_subdomain = _neighbor_subdomain;
286 _neighbor_subdomain = neighbor->subdomain_id();
287 if (_neighbor_subdomain != _old_neighbor_subdomain)
288 neighborSubdomainChanged();
289
290 if (shouldComputeInternalSide(*elem, *neighbor))
291 onInternalSide(elem, side);
292
293 for (const auto bnd_id : boundary_ids)
294 onInterface(elem, side, bnd_id);
295
296 postInternalSide(elem, side);
297 }
298 else
299 onExternalSide(elem, side);
300 } // sides
301
302 postElement(elem);
303 } // range
304
305 post();
306 resetExecPrintedSets();
307 }
308 catch (MetaPhysicL::LogicError & e)
309 {
311 }
312 catch (std::exception & e)
313 {
314 // Continue if we find a libMesh degenerate map exception, but
315 // just re-throw for any real error
316 if (!strstr(e.what(), "Jacobian") && !strstr(e.what(), "singular") &&
317 !strstr(e.what(), "det != 0"))
318 throw; // not "throw e;" - that destroys type info!
319
320 mooseException("We caught a libMesh degeneracy exception in ThreadedElementLoopBase:\n",
321 e.what());
322 }
323 }
324 catch (MooseException & e)
325 {
326 caughtMooseException(e);
327 }
328}
329
330template <typename RangeType>
331void
335
336template <typename RangeType>
337void
341
342template <typename RangeType>
343void
345{
346}
347
348template <typename RangeType>
349void
351{
352}
353
354template <typename RangeType>
355void
357{
358}
359
360template <typename RangeType>
361void
363 unsigned int /*side*/,
364 BoundaryID /*bnd_id*/,
365 const Elem * /*lower_d_elem = nullptr*/)
366{
367}
368
369template <typename RangeType>
370void
372 unsigned int /*side*/,
373 BoundaryID /*bnd_id*/,
374 const Elem * /*lower_d_elem = nullptr*/)
375{
376}
377
378template <typename RangeType>
379void
380ThreadedElementLoopBase<RangeType>::preInternalSide(const Elem * /*elem*/, unsigned int /*side*/)
381{
382}
383
384template <typename RangeType>
385void
386ThreadedElementLoopBase<RangeType>::postInternalSide(const Elem * /*elem*/, unsigned int /*side*/)
387{
388}
389
390template <typename RangeType>
391void
392ThreadedElementLoopBase<RangeType>::onInternalSide(const Elem * /*elem*/, unsigned int /*side*/)
393{
394}
395
396template <typename RangeType>
397void
398ThreadedElementLoopBase<RangeType>::onExternalSide(const Elem * /*elem*/, unsigned int /*side*/)
399{
400}
401
402template <typename RangeType>
403void
405 unsigned int /*side*/,
406 BoundaryID /*bnd_id*/)
407{
408}
409
410template <typename RangeType>
411void
415
416template <typename RangeType>
417void
421
422template <typename RangeType>
423bool
425 const Elem & neighbor) const
426{
427 // If we're going to compute the internal side with this elem-neighbor pair, then they must both
428 // be active. Note that if elem is an active coarse element at an interface with finer elements,
429 // then its neighbor will be an equal-level inactive element, hence the following
430 // neighbor.active() check. In that case we'll catch current 'elem' when we come around and
431 // examine one of the finer elements as 'elem'
432 mooseAssert(elem.active(), "This method should never be called with an inactive element");
433 if (!neighbor.active())
434 return false;
435
436 //
437 // Define an ordering: first prefer finer by h (higher level()), then prefer finer by p (higher
438 // p_level()), then prefer smaller id()"
439 //
440
441 const auto elem_level = elem.level(), neighbor_level = neighbor.level();
442 if (elem_level != neighbor_level)
443 return elem_level > neighbor_level;
444
445 const auto elem_p_level = elem.p_level(), neighbor_p_level = neighbor.p_level();
446 if (elem_p_level != neighbor_p_level)
447 return elem_p_level > neighbor_p_level;
448
449 return elem.id() < neighbor.id();
450}
451
452template <typename RangeType>
453void
455{
456 _blocks_exec_printed.clear();
457 _boundaries_exec_printed.clear();
458}
boundary_id_type BoundaryID
unsigned int THREAD_ID
Definition MooseTypes.h:237
Provides a way for users to bail out of the current solve.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
Base class for assembly-like calculations.
virtual void onExternalSide(const Elem *elem, unsigned int side)
Called when iterating over external sides (no side neighbor)
ThreadedElementLoopBase(ThreadedElementLoopBase &x, Threads::split split)
virtual void caughtMooseException(MooseException &)
Called if a MooseException is caught anywhere during the computation.
virtual void onBoundary(const Elem *elem, unsigned int side, BoundaryID bnd_id, const Elem *lower_d_elem=nullptr)
Called when doing boundary assembling.
virtual void printBoundaryExecutionInformation(const unsigned int) const
Print information about the particular ordering of objects on each boundary.
virtual void neighborSubdomainChanged()
Called every time the neighbor subdomain changes (i.e.
virtual void printGeneralExecutionInformation() const
Print information about the loop ordering.
virtual void onInterface(const Elem *elem, unsigned int side, BoundaryID bnd_id)
Called when doing interface assembling.
virtual bool keepGoing()
Whether or not the loop should continue.
void resetExecPrintedSets() const
Resets the set of blocks and boundaries visited.
SubdomainID _old_subdomain
The subdomain for the last element.
virtual void preInternalSide(const Elem *elem, unsigned int side)
Called before evaluations on an element internal side.
virtual void operator()(const RangeType &range, bool bypass_threading=false)
virtual void postInternalSide(const Elem *elem, unsigned int side)
Called after evaluations on an element internal side.
virtual void subdomainChanged()
Called every time the current subdomain changes (i.e.
virtual void onInternalSide(const Elem *elem, unsigned int side)
Called when doing internal edge assembling.
virtual void preBoundary(const Elem *elem, unsigned int side, BoundaryID bnd_id, const Elem *lower_d_elem=nullptr)
Called before the boundary assembly.
virtual void onElement(const Elem *elem)
Assembly of the element (not including surface assembly)
virtual void postElement(const Elem *elem)
Called after the element assembly is done (including surface assembling)
virtual void preElement(const Elem *elem)
Called before the element assembly.
SubdomainID _old_neighbor_subdomain
The subdomain for the last neighbor.
SubdomainID _subdomain
The subdomain for the current element.
SubdomainID _neighbor_subdomain
The subdomain for the current neighbor.
std::set< BoundaryID > _boundaries_exec_printed
Keep track of which boundaries were visited.
virtual void printBlockExecutionInformation() const
Print information about the particular ordering of objects on each block.
virtual void post()
Called after the element range loop.
virtual void pre()
Called before the element range loop.
virtual bool shouldComputeInternalSide(const Elem &elem, const Elem &neighbor) const
Whether to compute the internal side for the provided element-neighbor pair.
std::set< SubdomainID > _blocks_exec_printed
Keep track of which blocks were visited.
MeshBase & mesh
const SubdomainID INVALID_BLOCK_ID
Definition MooseTypes.C:20
void translateMetaPhysicLError(const MetaPhysicL::LogicError &)
emit a relatively clear error message when we catch a MetaPhysicL logic error
Definition MooseError.C:155