www.mooseframework.org
DiracKernelInfo.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
13 // LibMesh
14 #include "libmesh/point_locator_base.h"
15 #include "libmesh/elem.h"
16 #include "libmesh/enum_point_locator_type.h"
17 #include "libmesh/point.h"
18 
20  : _point_locator(), _point_equal_distance_sq(libMesh::TOLERANCE * libMesh::TOLERANCE)
21 {
22 }
23 
25 
26 void
27 DiracKernelInfo::addPoint(const Elem * elem, Point p)
28 {
29  _elements.insert(elem);
30 
31  std::pair<std::vector<Point>, std::vector<unsigned int>> & multi_point_list = _points[elem];
32 
33  const unsigned int npoint = multi_point_list.first.size();
34  mooseAssert(npoint == multi_point_list.second.size(),
35  "Different sizes for location and multiplicity data");
36 
37  for (unsigned int i = 0; i < npoint; ++i)
38  if (pointsFuzzyEqual(multi_point_list.first[i], p))
39  {
40  // a point at the same (within a tolerance) location as p exists, increase its multiplicity
41  multi_point_list.second[i]++;
42  return;
43  }
44 
45  // no prior point found at this location, add it with a multiplicity of one
46  multi_point_list.first.push_back(p);
47  multi_point_list.second.push_back(1);
48 }
49 
50 void
52 {
53  _elements.clear();
54  _points.clear();
55 }
56 
57 bool
58 DiracKernelInfo::hasPoint(const Elem * elem, Point p)
59 {
60  std::vector<Point> & point_list = _points[elem].first;
61 
62  for (const auto & pt : point_list)
63  if (pointsFuzzyEqual(pt, p))
64  return true;
65 
66  // If we haven't found it, we don't have it.
67  return false;
68 }
69 
70 void
72 {
73  // Note: we could update the PointLocator *every* time we call this
74  // function, but that may introduce an unacceptable overhead in
75  // problems which don't need a PointLocator at all. This issue will
76  // most likely become a moot point when we eventually add a shared
77  // "CachingPointLocator" to MOOSE.
78  // _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
79 
80  // Construct the PointLocator object if *any* processors have Dirac
81  // points. Note: building a PointLocator object is a parallel_only()
82  // function, so this is an all-or-nothing thing.
83  unsigned pl_needs_rebuild = _elements.size();
84  mesh.comm().max(pl_needs_rebuild);
85 
86  if (pl_needs_rebuild)
87  {
88  // PointLocatorBase::build() is a parallel_only function! So we
89  // can't skip building it just becuase our local _elements is
90  // empty, it might be non-empty on some other processor!
91  _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
92 
93  // We may be querying for points which are not in the semilocal
94  // part of a distributed mesh.
95  _point_locator->enable_out_of_mesh_mode();
96  }
97  else
98  {
99  // There are no elements with Dirac points, but we have been
100  // requested to update the PointLocator so we have to assume the
101  // old one is invalid. Therefore we reset it to NULL... however
102  // adding this line causes the code to hang because it triggers
103  // the PointLocator to be rebuilt in a non-parallel-only segment
104  // of the code later... so it's commented out for now even though
105  // it's probably the right behavior.
106  // _point_locator.reset(NULL);
107  }
108 }
109 
110 const Elem *
111 DiracKernelInfo::findPoint(Point p, const MooseMesh & mesh)
112 {
113  // If the PointLocator has never been created, do so now. NOTE - WE
114  // CAN'T DO THIS if findPoint() is only called on some processors,
115  // PointLocatorBase::build() is a 'parallel_only' method!
116  if (_point_locator.get() == NULL)
117  {
118  _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
119  _point_locator->enable_out_of_mesh_mode();
120  }
121 
122  // Check that the PointLocator is ready to start locating points.
123  // So far I do not have any tests that trip this...
124  if (_point_locator->initialized() == false)
125  mooseError("Error, PointLocator is not initialized!");
126 
127  // Note: The PointLocator object returns NULL when the Point is not
128  // found within the Mesh. This is not considered to be an error as
129  // far as the DiracKernels are concerned: sometimes the Mesh moves
130  // out from the Dirac point entirely and in that case the Point just
131  // gets "deactivated".
132  const Elem * elem = (*_point_locator)(p);
133 
134  // The processors may not agree on which Elem the point is in. This
135  // can happen if a Dirac point lies on the processor boundary, and
136  // two or more neighboring processors think the point is in the Elem
137  // on *their* side.
138  dof_id_type elem_id = elem ? elem->id() : DofObject::invalid_id;
139 
140  // We are going to let the element with the smallest ID "win", all other
141  // procs will return NULL.
142  dof_id_type min_elem_id = elem_id;
143  mesh.comm().min(min_elem_id);
144 
145  return min_elem_id == elem_id ? elem : NULL;
146 }
147 
148 bool
149 DiracKernelInfo::pointsFuzzyEqual(const Point & a, const Point & b)
150 {
151  const Real dist_sq = (a - b).norm_sq();
152  return dist_sq < _point_equal_distance_sq;
153 }
std::set< const Elem * > _elements
The list of elements that need distributions.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:207
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...
const Elem * findPoint(Point p, const MooseMesh &mesh)
Used by client DiracKernel classes to determine the Elem in which the Point p resides.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:74
void addPoint(const Elem *elem, Point p)
Adds a point source.
void clearPoints()
Remove all of the current points and elements.
bool hasPoint(const Elem *elem, Point p)
Return true if we have Point &#39;p&#39; in Element &#39;elem&#39;.
std::unique_ptr< PointLocatorBase > _point_locator
The DiracKernelInfo object manages a PointLocator object which is used by all DiracKernels to find Po...
const Real _point_equal_distance_sq
threshold distance squared below which two points are considered identical
void updatePointLocator(const MooseMesh &mesh)
Called during FEProblemBase::meshChanged() to update the PointLocator object used by the DiracKernels...
virtual ~DiracKernelInfo()
bool pointsFuzzyEqual(const Point &, const Point &)
Check if two points are equal with respect to a tolerance.