https://mooseframework.inl.gov
DiracKernelInfo.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 "DiracKernelInfo.h"
11 #include "MooseMesh.h"
12 #include "MooseEnum.h"
13 #include "DiracKernelBase.h"
14 #include "MooseBase.h"
15 
16 // LibMesh
17 #include "libmesh/point_locator_base.h"
18 #include "libmesh/elem.h"
19 #include "libmesh/enum_point_locator_type.h"
20 #include "libmesh/point.h"
21 
22 using namespace libMesh;
23 
25  : _point_locator(), _point_equal_distance_sq(libMesh::TOLERANCE * libMesh::TOLERANCE)
26 {
27 }
28 
30 
31 void
32 DiracKernelInfo::addPoint(const Elem * elem, const Point & p, const Real & value)
33 {
34  _elements.insert(elem);
35 
36  std::pair<std::vector<Point>, std::vector<Real>> & multi_point_list = _points[elem];
37 
38  const unsigned int npoint = multi_point_list.first.size();
39  mooseAssert(npoint == multi_point_list.second.size(),
40  "Different sizes for location and point value data");
41 
42  for (unsigned int i = 0; i < npoint; ++i)
43  if (pointsFuzzyEqual(multi_point_list.first[i], p))
44  {
45  // A point at the same (within a tolerance) location as p exists, accumulate its value.
46  multi_point_list.second[i] += value;
47  return;
48  }
49 
50  // No prior point found at this location, add it with its initial value.
51  multi_point_list.first.push_back(p);
52  multi_point_list.second.push_back(value);
53 }
54 
55 void
57 {
58  _elements.clear();
59  _points.clear();
60 }
61 
62 bool
63 DiracKernelInfo::hasPoint(const Elem * elem, const Point & p)
64 {
65  std::vector<Point> & point_list = _points[elem].first;
66 
67  for (const auto & pt : point_list)
68  if (pointsFuzzyEqual(pt, p))
69  return true;
70 
71  // If we haven't found it, we don't have it.
72  return false;
73 }
74 
75 void
77 {
78  // Note: we could update the PointLocator *every* time we call this
79  // function, but that may introduce an unacceptable overhead in
80  // problems which don't need a PointLocator at all. This issue will
81  // most likely become a moot point when we eventually add a shared
82  // "CachingPointLocator" to MOOSE.
83  // _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
84 
85  // Construct the PointLocator object if *any* processors have Dirac
86  // points. Note: building a PointLocator object is a parallel_only()
87  // function, so this is an all-or-nothing thing.
88  unsigned pl_needs_rebuild = _elements.size();
89  mesh.comm().max(pl_needs_rebuild);
90 
91  if (pl_needs_rebuild)
92  {
93  // PointLocatorBase::build() is a parallel_only function! So we
94  // can't skip building it just becuase our local _elements is
95  // empty, it might be non-empty on some other processor!
96  _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
97 
98  // We may be querying for points which are not in the semilocal
99  // part of a distributed mesh.
100  _point_locator->enable_out_of_mesh_mode();
101  }
102  else
103  {
104  // There are no elements with Dirac points, but we have been
105  // requested to update the PointLocator so we have to assume the
106  // old one is invalid. Therefore we reset it to NULL... however
107  // adding this line causes the code to hang because it triggers
108  // the PointLocator to be rebuilt in a non-parallel-only segment
109  // of the code later... so it's commented out for now even though
110  // it's probably the right behavior.
111  // _point_locator.reset(NULL);
112  }
113 }
114 
115 const Elem *
117  const MooseMesh & mesh,
118  const std::set<SubdomainID> & blocks,
119  const PointNotFoundBehavior point_not_found_behavior,
120  const MooseBase & consumer)
121 {
122  // If the PointLocator has never been created, do so now. NOTE - WE
123  // CAN'T DO THIS if findPoint() is only called on some processors,
124  // PointLocatorBase::build() is a 'parallel_only' method!
125  if (_point_locator.get() == NULL)
126  {
127  _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
128  _point_locator->enable_out_of_mesh_mode();
129  }
130 
131  // Check that the PointLocator is ready to start locating points.
132  // So far I do not have any tests that trip this...
133  if (_point_locator->initialized() == false)
134  consumer.mooseError("PointLocator is not initialized!");
135 
136  // Note: The PointLocator object returns NULL when the Point is not
137  // found within the Mesh. This is not considered to be an error as
138  // far as the DiracKernels are concerned: sometimes the Mesh moves
139  // out from the Dirac point entirely and in that case the Point just
140  // gets "deactivated".
141  const Elem * elem = (*_point_locator)(p, &blocks);
142 
143  // The processors may not agree on which Elem the point is in. This
144  // can happen if a Dirac point lies on the processor boundary, and
145  // two or more neighboring processors think the point is in the Elem
146  // on *their* side.
147  dof_id_type elem_id = elem ? elem->id() : DofObject::invalid_id;
148 
149  // We are going to let the element with the smallest ID "win", all other
150  // procs will return NULL.
151  dof_id_type min_elem_id = elem_id;
152  mesh.comm().min(min_elem_id);
153 
154  if (min_elem_id == DofObject::invalid_id)
155  {
156  std::stringstream msg;
157  msg << "Point " << p << " not found in block(s) " << Moose::stringify(blocks, ", ") << ".\n";
158  switch (point_not_found_behavior)
159  {
160  case PointNotFoundBehavior::ERROR:
161  consumer.mooseError(msg.str());
162  break;
163  case PointNotFoundBehavior::WARNING:
164  mooseDoOnce(consumer.mooseWarning(msg.str() + "This message will not be repeated."));
165  break;
166  case PointNotFoundBehavior::IGNORE:
167  break;
168  default:
169  consumer.mooseError("Internal enum error.");
170  }
171  }
172 
173  // But we notably need the processor which owns elem_id to return it!
174  if (min_elem_id != DofObject::invalid_id)
175  if (const auto min_elem = mesh.queryElemPtr(min_elem_id);
176  min_elem && min_elem->processor_id() == mesh.processor_id())
177  return min_elem;
178  return nullptr;
179 }
180 
181 bool
183 {
184  const Real dist_sq = (a - b).norm_sq();
185  return dist_sq < _point_equal_distance_sq;
186 }
bool hasPoint(const Elem *elem, const Point &p)
Return true if we have Point &#39;p&#39; in Element &#39;elem&#39;.
void addPoint(const Elem *elem, const Point &p, const Real &value=1)
Adds a point source.
Base class for everything in MOOSE with a name and a type.
Definition: MooseBase.h:49
std::set< const Elem * > _elements
The list of elements that need distributions.
char ** blocks
auto norm_sq(const T &a)
static constexpr Real TOLERANCE
MeshBase & mesh
const Parallel::Communicator & comm() const
MultiPointMap _points
The list of physical xyz Points that need to be evaluated in each element.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
std::unique_ptr< libMesh::PointLocatorBase > _point_locator
The DiracKernelInfo object manages a PointLocator object which is used by all DiracKernels to find Po...
dof_id_type id() const
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void min(const T &r, T &o, Request &req) const
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:93
void clearPoints()
Remove all of the current points and elements.
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Elem * findPoint(const Point &p, const MooseMesh &mesh, const std::set< SubdomainID > &blocks, const PointNotFoundBehavior point_not_found_behavior, const MooseBase &consumer)
Used by client DiracKernel classes to determine the Elem in which the Point p resides.
void max(const T &r, T &o, Request &req) const
const Real _point_equal_distance_sq
threshold distance squared below which two points are considered identical
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
Definition: MooseBase.h:309
TREE_LOCAL_ELEMENTS
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:281
processor_id_type processor_id() const
void updatePointLocator(const MooseMesh &mesh)
Called during FEProblemBase::meshChanged() to update the PointLocator object used by the DiracKernels...
uint8_t dof_id_type
virtual ~DiracKernelInfo()
bool pointsFuzzyEqual(const Point &, const Point &)
Check if two points are equal with respect to a tolerance.