OOFEM 3.0
Loading...
Searching...
No Matches
contactsearchsweepandprune.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
36#include "floatarrayf.h"
37
38namespace oofem {
39
40ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune(
43 Domain *d
45{
46 isInitialized = false;
47}
48
49void
50ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: initialize()
51{
52 unsigned int n_slaves = contactPairs.size();
53 unsigned int n_masters = this->masterContactSurface->giveNumberOfContactElements();
54 unsigned int n = n_slaves + n_masters;
55 //
56 aabbs.resize(n_slaves + n_masters);
58 //
59 for (int axis=0; axis<3; axis++) {
60 this->boundss[axis] = {};
61 }
62 for (unsigned int i = 0; i < n; ++i) {
63 bool isSlave = i >= n_masters;
64 const auto& aabb = aabbs[i];
65 for (unsigned int axis = 0; axis < 3; ++axis) {
66 auto& bounds = this->boundss[axis];
67 bounds.push_back({
68 aabb.min[axis],
69 i,
70 isSlave,
71 true
72 });
73 bounds.push_back({
74 aabb.max[axis],
75 i,
76 isSlave,
77 false
78 });
79 }
80 }
81 for (int axis = 0; axis < 3; ++axis) {
82 auto& bounds = this->boundss[axis];
83 auto& potentialPairsPerAxis = this->potentialPairsPerAxes[axis];
84 potentialPairsPerAxis.clear();
85 std::sort(bounds.begin(), bounds.end(), [](const Bound& a, const Bound& b) {
86 return a.value < b.value;
87 });
88 unsigned int nBounds = bounds.size();
89 for (size_t i = 0; i < nBounds - 1; ++i) {
90 const auto& bi = bounds[i];
91 if (!bi.isMin) continue;
92 for (size_t j = i + 1; j < nBounds; ++j) {
93 const auto& bj = bounds[j];
94 //
95 if (bi.id == bj.id) break;
96 //
97 if (!bj.isMin) continue;
98 if (bi.isSlave == bj.isSlave) continue;
99 //
100 unsigned int i_master;
101 unsigned int i_slave;
102 if (bi.isSlave) {
103 i_slave = bi.id;
104 i_master = bj.id;
105 } else {
106 i_slave = bj.id;
107 i_master = bi.id;
108 }
109 IJ ij = {i_master, i_slave};
110 //
111 potentialPairsPerAxis.insert(ij);
112 }
113 }
114 }
115 //
116 const auto& potentialPairsPerAxis0 = this->potentialPairsPerAxes[0];
117 const auto& potentialPairsPerAxis1 = this->potentialPairsPerAxes[1];
118 const auto& potentialPairsPerAxis2 = this->potentialPairsPerAxes[2];
119 for (const auto& ij : potentialPairsPerAxis0) {
120 if (
121 contains(potentialPairsPerAxis1, ij)
122 &&
123 contains(potentialPairsPerAxis2, ij)
124 ) {
125 this->addPotentialPair(ij);
126 }
127 }
128 this->isInitialized = true;
129}
130
131void
132ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: updateAABBs()
133{
134 unsigned int index = 0;
135 //
136 unsigned int n_masters = this->masterContactSurface->giveNumberOfContactElements();
137 for (unsigned int i = 1; i <= n_masters; ++i) {
138 const auto& master = this->masterContactSurface->giveContactElement_InSet(i);
139 auto aabb = master->computeAABB();
140 aabbs[index] = aabb;
141 index++;
142 }
143 //
144 for (const auto& slave : contactPairs) {
145 auto aabb = slave->computeSlaveAABB();
146 aabbs[index] = aabb;
147 index++;
148 }
149
150}
151
152void
153ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: updateBoundss()
154{
155 updateAABBs();
156 //
157 for (int axis = 0; axis < 2; ++axis) {
158 auto& bounds =
159 (axis == 0) ? std::get<0>(this->boundss)
160 :
161 (axis == 1) ? std::get<1>(this->boundss)
162 :
163 std::get<2>(this->boundss)
164 ;
165 for (auto& b : bounds) {
166 const auto& aabb = aabbs[b.id];
167 b.value = b.isMin ? aabb.min[axis] : aabb.max[axis];
168 }
169 }
170}
171
172void
173ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: insertionSort()
174{
175 for (int axis = 0; axis < 3; ++axis) {
176 auto& bounds = this->boundss[axis];
177 for (size_t i = 1; i < bounds.size(); ++i) {
178 for (size_t j = i; j >= 1; --j) {
179 Bound& b1 = bounds[j - 1];
180 Bound& b2 = bounds[j];
181 if (b1.value <= b2.value) break;
182 std::swap(bounds[j], bounds[j - 1]);
183 this->solveInversion(axis, b2, b1);
184 }
185 }
186 }
187}
188
189void
190ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: addPotentialPair(IJ ij)
191{
192 this->potentialPairs.insert(ij);
193}
194
195void
196ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: deletePotentialPair(IJ ij)
197{
198 this->potentialPairs.erase(ij);
199}
200
201void
202ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: solveInversion(
203 int axis,
204 const Bound& b1,
205 const Bound& b2
206)
207{
208 if (b1.isSlave == b2.isSlave) return;
209 if (b1.isMin == b2.isMin) return;
210 int axis2, axis3;
211 if (axis == 0) {
212 axis2 = 1;
213 axis3 = 2;
214 } else if (axis == 1) {
215 axis2 = 0;
216 axis3 = 2;
217 } else {
218 axis2 = 0;
219 axis3 = 1;
220 }
221 auto& potentialPairsPerAxis1 = this->potentialPairsPerAxes[axis];
222 auto& potentialPairsPerAxis2 = this->potentialPairsPerAxes[axis2];
223 auto& potentialPairsPerAxis3 = this->potentialPairsPerAxes[axis3];
224 unsigned int i_master;
225 unsigned int i_slave;
226 if (b1.isSlave) {
227 i_slave = b1.id;
228 i_master = b2.id;
229 } else {
230 i_slave = b2.id;
231 i_master = b1.id;
232 }
233 IJ ij = {i_master, i_slave};
234 if (b1.isMin) {
235 potentialPairsPerAxis1.insert(ij);
236 if (
237 contains(potentialPairsPerAxis2, ij)
238 &&
239 contains(potentialPairsPerAxis3, ij)
240 ) {
241 this->addPotentialPair(ij);
242 }
243 } else {
244 potentialPairsPerAxis1.erase(ij);
245 this->deletePotentialPair(ij);
246 }
247}
248
249void
250ContactSearchAlgorithm_Surface2FESurface_3d_SweepAndPrune :: updateContactPairs(TimeStep *tStep)
251{
252 if (!this->isInitialized) {
253 this->initialize();
254 }
255 this->updateBoundss();
256 this->insertionSort();
257 //
258 std::map<unsigned int, std::vector<unsigned int>> slave2masters;
259 for (IJ ij : potentialPairs) {
260 auto [i_master, i_slave] = ij;
261 if (slave2masters.find(i_slave) == slave2masters.end()) {
262 slave2masters[i_slave] = {};
263 }
264 slave2masters[i_slave].push_back(i_master);
265 }
266 //
267 unsigned int n_masters = this->masterContactSurface->giveNumberOfContactElements();
268 //
269 /*
270 * Copy and adjustment from ContactSearchAlgorithm_Surface2FESurface_3d :: updateContactPairs
271 * TODO code deduplication
272 */
273 FloatArrayF<3> normalVector, tangentVector1, tangentVector2;
274 for (auto [i_slave_plus_n_masters, i_masters] : slave2masters) {
275 unsigned int i_slave = i_slave_plus_n_masters - n_masters;
276 auto& cp = contactPairs[i_slave];
277 auto slavePoint = dynamic_cast<FEContactPoint_Slave*> (cp->giveSlaveContactPoint());
278 int closestContactElementId = -1;
279 FloatArray contactPointLocalCoordinates;
280 double gap = 0;
281 for ( unsigned int i_master_0 : i_masters ) {
282 unsigned int i_master = i_master_0 + 1;
283 auto contactElement = this->masterContactSurface->giveContactElement_InSet(i_master);
284 auto [inElement,localCoords, newGap,normal, t1, t2] = this->masterContactSurface->findContactPointInElement_3d(slavePoint, contactElement, tStep);
285 if (inElement) {
286 if ( closestContactElementId == -1. || newGap < gap ) {
287 gap = newGap;
288 normalVector = normal;
289 tangentVector1 = t1;
290 tangentVector2 = t2;
291 contactPointLocalCoordinates = localCoords;
292 closestContactElementId = contactElement->giveNumber();
293 }
294 }
295 }
296 if (closestContactElementId) {
297 auto master_point = std::make_unique<FEContactPoint_Master>(this->masterContactSurface, closestContactElementId, 2, contactPointLocalCoordinates);
298 cp->setMasterContactPoint(std::move(master_point));
299 cp->setNormalGap(gap);
300 cp->setNormalVector(normalVector);
301 cp->setTangentVector1(tangentVector1);
302 cp->setTangentVector2(tangentVector2);
303 }
304 }
305}
306
307} // end namespace oofem
bool contains(CONTTYPE &cont, const T &t)
Definition CSG.h:1107
void solveInversion(int axis, const Bound &b1, const Bound &b2)
Handles a bound inversion event detected during sorting on a given axis.
void addPotentialPair(IJ)
Adds a candidate pair to the set of potential contact pairs.
void insertionSort()
Performs incremental sorting of bounds using insertion sort.
void deletePotentialPair(IJ)
Removes a candidate pair from the set of potential contact pairs.
void initialize()
Initializes internal data structures for sweep-and-prune.
void updateBoundss()
Updates per-axis bound (endpoint) arrays from current AABBs.
void updateAABBs()
Recomputes AABBs used by the search algorithm.
ContactSearchAlgorithm_Surface2FESurface_3d(FEContactSurface *scs, FEContactSurface *mcs, Domain *d)
std::vector< std::unique_ptr< ContactPair > > contactPairs
Abstract representation of a finite element contact surface.

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011