1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 // Local Includes
19 #include "libmesh/libmesh_config.h"
20
21 #ifdef LIBMESH_ENABLE_PERIODIC
22
23 #include "libmesh/periodic_boundaries.h"
24
25 #include "libmesh/boundary_info.h"
26 #include "libmesh/elem.h"
27 #include "libmesh/mesh_base.h"
28 #include "libmesh/periodic_boundary.h"
29 #include "libmesh/point_locator_base.h"
30 #include "libmesh/remote_elem.h"
31
32 namespace libMesh
33 {
34
~PeriodicBoundaries()35 PeriodicBoundaries::~PeriodicBoundaries()
36 {
37 for (auto & pr : *this)
38 delete pr.second;
39 }
40
41
42
boundary(boundary_id_type id)43 PeriodicBoundaryBase * PeriodicBoundaries::boundary(boundary_id_type id)
44 {
45 iterator i = this->find(id);
46 if (i == this->end())
47 return nullptr;
48 return i->second;
49 }
50
51
52
boundary(boundary_id_type id)53 const PeriodicBoundaryBase * PeriodicBoundaries::boundary(boundary_id_type id) const
54 {
55 const_iterator i = this->find(id);
56 if (i == this->end())
57 return nullptr;
58 return i->second;
59 }
60
61
62
63
neighbor(boundary_id_type boundary_id,const PointLocatorBase & point_locator,const Elem * e,unsigned int side,unsigned int * neigh_side)64 const Elem * PeriodicBoundaries::neighbor(boundary_id_type boundary_id,
65 const PointLocatorBase & point_locator,
66 const Elem * e,
67 unsigned int side,
68 unsigned int * neigh_side) const
69 {
70 std::unique_ptr<const Elem> neigh_side_proxy;
71
72 // Find a point on that side (and only that side)
73 Point p = e->build_side_ptr(side)->centroid();
74
75 const PeriodicBoundaryBase * b = this->boundary(boundary_id);
76 libmesh_assert (b);
77 p = b->get_corresponding_pos(p);
78
79 std::set<const Elem *> candidate_elements;
80 point_locator.operator()(p, candidate_elements);
81
82 // We might have found multiple elements, e.g. if two distinct periodic
83 // boundaries are overlapping (see systems_of_equations_ex9, for example).
84 // As a result, we need to search for the element that has boundary_id.
85 const MeshBase & mesh = point_locator.get_mesh();
86 for(const Elem * elem_it : candidate_elements)
87 {
88 std::vector<unsigned int> neigh_sides =
89 mesh.get_boundary_info().sides_with_boundary_id(elem_it, b->pairedboundary);
90
91 for (auto ns : neigh_sides)
92 {
93 if (neigh_side)
94 {
95 elem_it->build_side_ptr(neigh_side_proxy, ns);
96 if (neigh_side_proxy->contains_point(p))
97 {
98 *neigh_side = ns;
99 return elem_it;
100 }
101 }
102 else
103 // checking contains_point is too expensive if we don't
104 // definitely need it to find neigh_side
105 return elem_it;
106 }
107 }
108
109 // If we should have found a periodic neighbor but didn't then
110 // either we're on a ghosted element with a remote periodic neighbor
111 // or we're on a mesh with an inconsistent periodic boundary.
112 libmesh_assert_msg(!mesh.is_serial() &&
113 (e->processor_id() != mesh.processor_id()),
114 "Periodic boundary neighbor not found");
115 if (neigh_side)
116 *neigh_side = libMesh::invalid_uint;
117 return remote_elem;
118 }
119
120 } // namespace libMesh
121
122
123
124
125
126 #endif // LIBMESH_ENABLE_PERIODIC
127