Skip to content

Commit 828403d

Browse files
With connectivity map between master and slave mortar sides
1 parent 3a26dff commit 828403d

File tree

3 files changed

+89
-105
lines changed

3 files changed

+89
-105
lines changed

src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsAugmentedLagrangianContact.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
/*
23
* ------------------------------------------------------------------------------------------------------------
34
* SPDX-License-Identifier: LGPL-2.1-only

src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsMortarContact.cpp

Lines changed: 71 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ void SolidMechanicsMortarContact::implicitStepSetup( real64 const & time_n,
8686
MeshLevel & mesh,
8787
string_array const & )
8888
{
89+
// naive way to assign master and slave mesh levels
8990
if (meshName == "meshMaster"){
9091
this->m_meshMaster = &mesh;
9192
}
@@ -94,25 +95,14 @@ void SolidMechanicsMortarContact::implicitStepSetup( real64 const & time_n,
9495
this->m_meshSlave = &mesh;
9596
}
9697

97-
//FaceManager const & faceManager = mesh.getFaceManager();
9898
ElementRegionManager const & elemManager = mesh.getElemManager();
9999

100-
// Get the topology of all faces in the grid
101-
//ArrayOfArraysView< localIndex const > const faceToNodeMap = faceManager.nodeList().toViewConst();
102-
//arrayView2d< double const > const surfaceCentroid = faceManager.faceCenter().toViewConst();
103-
104-
// Get mortar surface region
105-
//FaceElementSubRegion const & subRegion = region.getUniqueSubRegion< FaceElementSubRegion >();
106-
//arrayView2d< localIndex const > const elemsToFaces = subRegion.faceList().toViewConst();
107-
108-
std::cout << "Processing interface: " << meshName << std::endl;
109100
elemManager.forElementSubRegions< FaceElementSubRegion >([&](const FaceElementSubRegion & subRegion )
110101
{
111-
112-
// assign surface to master or slave depending on object path
102+
// assign surface to master or slave depending on object path (again, naive)
113103
string surfacePath = subRegion.getPath();
114104
if (surfacePath.find("surfaceSlave") != std::string::npos){
115-
GEOS_ERROR_IF(m_surfaceSlave != nullptr,"Slve surface has already been assigned.");
105+
GEOS_ERROR_IF(m_surfaceSlave != nullptr,"Slave surface has already been assigned.");
116106
this->m_surfaceSlave = &subRegion;
117107
}
118108

@@ -122,83 +112,12 @@ void SolidMechanicsMortarContact::implicitStepSetup( real64 const & time_n,
122112
}
123113
});
124114

125-
126-
// loop in the subRegions (only one for now)
127-
// get map from surface in surfaceRegion to face in FaceManager
128-
//arrayView2d< localIndex const > const elemsToFaces = subRegion.faceList().toViewConst();
129-
130-
// loop over each surface in the mortar interface
131-
//forAll< parallelHostPolicy >( subRegion.size(), [=] ( localIndex const ksurf )
132-
//{
133-
// inspect the surfaces and avalilable informations:
134-
// print node indices, coordinates, centroid
135-
//localIndex const kface = elemsToFaces[ksurf][0];
136-
//localIndex const numNodesPerFace = faceToNodeMap.sizeOfArray( kface );
137-
138-
//std::cout << "SURFACE " << ksurf << std::endl;
139-
/*
140-
std::cout << "Surface centroid: ";
141-
for (int i = 0; i < 3; ++i) {
142-
std::cout << surfaceCentroid[kface][i] << " ";
143-
}
144-
std::cout << "Nodes list: ";
145-
for (int jn = 0; jn < numNodesPerFace; ++jn) {
146-
std::cout << faceToNodeMap[kface][jn] << " ";
147-
}
148-
std::cout << std::endl;
149-
*/
150-
//});
151115
} );
152116

153117

154-
155-
156-
157118
std::cout << "Processing master/slave connectivity" << std::endl;
158119

159-
std::unique_ptr<TreeNodeMortar> treeMaster = std::make_unique<TreeNodeMortar>();
160-
std::unique_ptr<TreeNodeMortar> treeSlave = std::make_unique<TreeNodeMortar>();
161-
162-
// list of surfaces of master root
163-
array1d<localIndex> surfRootMaster(m_surfaceMaster->size()) ;
164-
array1d<localIndex> surfRootSlave(m_surfaceSlave->size()) ;
165-
166-
for (localIndex i=0; i < m_surfaceMaster->size(); ++i)
167-
{
168-
surfRootMaster(i) = i;
169-
}
170-
171-
for (localIndex i=0; i < m_surfaceSlave->size(); ++i)
172-
{
173-
surfRootSlave(i) = i;
174-
}
175-
176-
// create binary trees recursively
177-
std::cout << "Populating master tree" << std::endl;
178-
treeMaster->createNode(*m_meshMaster,*m_surfaceMaster,surfRootMaster);
179-
std::cout << "Populating slave tree" << std::endl;
180-
treeSlave->createNode(*m_meshSlave,*m_surfaceSlave,surfRootSlave);
181-
182-
// prepare connectivitiy map slave -> master
183-
localIndex nSurfSlave = m_surfaceSlave->size();
184-
m_connectivityMap.resize(nSurfSlave);
185-
186-
// populate connectivity map
187-
contactSearch(treeSlave,treeMaster);
188-
189-
for (localIndex i=0; i<nSurfSlave; ++i)
190-
{
191-
localIndex N = m_connectivityMap.sizeOfArray(i);
192-
std::cout << "SLAVE ELEMENT: " << i << std::endl;
193-
std::cout << "N = " << N << " MASTER ELEMENT:";
194-
for (localIndex j=0; j<N; ++j)
195-
{
196-
std::cout << " " << m_connectivityMap[i][j];
197-
}
198-
std::cout << std::endl;
199-
std::cout << "__________________________________________" << std::endl;
200-
}
201-
120+
this->getConnectivityMap();
202121

203122
//////////////////////////////////////////////////////////////////////////////////
204123
GEOS_ERROR("Mortar solver is not implemented yet. ");
@@ -273,13 +192,60 @@ void SolidMechanicsMortarContact::updateState( DomainPartition & domain )
273192
GEOS_UNUSED_VAR( domain );
274193
}
275194

195+
void SolidMechanicsMortarContact::getConnectivityMap()
196+
{
197+
// using smart pointers for the trees
198+
std::unique_ptr<TreeNodeMortar> treeMaster = std::make_unique<TreeNodeMortar>();
199+
std::unique_ptr<TreeNodeMortar> treeSlave = std::make_unique<TreeNodeMortar>();
200+
201+
// progressive list of surfaces to create tree roots
202+
array1d<localIndex> surfRootMaster(m_surfaceMaster->size()) ;
203+
array1d<localIndex> surfRootSlave(m_surfaceSlave->size()) ;
204+
205+
for (localIndex i=0; i < m_surfaceMaster->size(); ++i)
206+
{
207+
surfRootMaster(i) = i;
208+
}
209+
210+
for (localIndex i=0; i < m_surfaceSlave->size(); ++i)
211+
{
212+
surfRootSlave(i) = i;
213+
}
214+
215+
// create binary trees recursively
216+
std::cout << "Populating master tree" << std::endl;
217+
treeMaster->createNode(*m_meshMaster,*m_surfaceMaster,surfRootMaster);
218+
std::cout << "Populating slave tree" << std::endl;
219+
treeSlave->createNode(*m_meshSlave,*m_surfaceSlave,surfRootSlave);
220+
221+
// initialize connectivity map
222+
localIndex nSurfSlave = m_surfaceSlave->size();
223+
m_connectivityMap.resize(nSurfSlave);
224+
225+
// perform contact search and populate connectivity map
226+
contactSearch(treeSlave,treeMaster);
227+
228+
for (localIndex i=0; i<nSurfSlave; ++i)
229+
{
230+
localIndex N = m_connectivityMap.sizeOfArray(i);
231+
std::cout << "SLAVE ELEMENT: " << i << std::endl;
232+
std::cout << "MASTER ELEMENT:";
233+
for (localIndex j=0; j<N; ++j)
234+
{
235+
std::cout << " " << m_connectivityMap[i][j];
236+
}
237+
std::cout << std::endl;
238+
std::cout << "__________________________________________" << std::endl;
239+
}
240+
}
241+
276242
void SolidMechanicsMortarContact::contactSearch(std::unique_ptr<TreeNodeMortar> const & nodeSlave, std::unique_ptr<TreeNodeMortar> const & nodeMaster)
277243
{
278244
if (!checkIntersection(nodeSlave,nodeMaster)) return;
279245

280246
if ((nodeSlave->isLeaf) && (nodeMaster->isLeaf))
281247
{
282-
std::cout << "found intersection between slave " << nodeSlave->leafId << " and master " << nodeMaster->leafId << std::endl;
248+
//std::cout << "found intersection between slave " << nodeSlave->leafId << " and master " << nodeMaster->leafId << std::endl;
283249
m_connectivityMap.emplaceBack(nodeSlave->leafId,nodeMaster->leafId);
284250
return;
285251
}
@@ -325,7 +291,6 @@ void TreeNodeMortar::createNode(MeshLevel const & mesh,
325291
ArrayOfArraysView< localIndex const > const & faceToNodeMap = faceManager.nodeList().toViewConst();
326292
arrayView2d< double const > const surfCenter = faceManager.faceCenter().toViewConst();
327293
localIndex nSurf = surfList.size();
328-
std::cout << "NSurfaces = " << nSurf << std::endl;
329294
arrayView2d<double const> const coords = nodeManager.referencePosition();
330295

331296
double const pP[3][9] = POLYTOP_PRIMITIVES;
@@ -339,55 +304,58 @@ void TreeNodeMortar::createNode(MeshLevel const & mesh,
339304
for (localIndex j=0; j<nNodes; ++j)
340305
{
341306
localIndex id = faceToNodeMap[kface][j];
342-
//std::cout << coords[id][0] << " " << coords[id][1] << " " << coords[id][2] << std::endl;
307+
343308
for (localIndex k = 0; k<9; ++k)
344309
{
345310
real64 P = coords[id][0]*pP[0][k] +
346-
coords[id][1]*pP[1][k] +
347-
coords[id][2]*pP[2][k];
348-
if (P < this->polytop[2*k]) this->polytop[2*k] = P; // store minimum primitive
349-
if (P > this->polytop[2*k+1]) this->polytop[2*k+1] = P; // store maximum primitive
311+
coords[id][1]*pP[1][k] +
312+
coords[id][2]*pP[2][k];
313+
// store minimum polytop primitive
314+
if (P < this->polytop[2*k]) this->polytop[2*k] = P;
315+
// store maximum polytop primitive
316+
if (P > this->polytop[2*k+1]) this->polytop[2*k+1] = P;
350317
}
351318
}
352319
}
353320

354-
// get maximum polytop direction
321+
// get direction of polytop maximum size
355322
localIndex dir = 0;
356323
real64 diff = -1;
357324
for (localIndex k = 0; k<9; ++k)
358325
{
326+
// add a small tolerance to avoid degenerate boxes
359327
real64 d = polytop[2*k+1] - polytop[2*k] + 1e-3;
360-
// expand the polytop
328+
329+
// expand the polytop for safety
361330
polytop[2*k] -= BOUNDING_BOX_EXPANSION*d;
362331
polytop[2*k+1] += BOUNDING_BOX_EXPANSION*d;
332+
363333
if (d > diff)
364334
{
365335
dir = k;
366336
diff = d;
367337
}
368-
std::cout << this->polytop[2*k] << " " << this->polytop[2*k+1] << std::endl;
369338
}
370339

371340
if (surfList.size() == 1) // leaf node
372341
{
373342
this -> isLeaf = true;
374343
this -> leafId = surfList[0];
375-
std::cout << "LEAF FOUND - surface: " << leafId << std::endl;
376344
return;
377345
}
378346

379-
380347
// split the surface list into left and right child
381348
std::vector<real64> surfacePrimitive(nSurf);
382349
for (localIndex i=0; i<nSurf; ++i)
383350
{
384-
localIndex kface = elemsToFaces[surfList[i]][0];
385-
surfacePrimitive[i] = surfCenter[kface][0]*pP[0][dir] +
351+
// compute the polytopal primitives of the surface centroids
352+
localIndex kface = elemsToFaces[surfList[i]][0];
353+
surfacePrimitive[i] = surfCenter[kface][0]*pP[0][dir] +
386354
surfCenter[kface][1]*pP[1][dir] +
387355
surfCenter[kface][2]*pP[2][dir];
388356
}
389357

390-
// get median of surface centroid primitives
358+
// get median m of surface centroid primitives
391359
std::vector<real64> surfSort = surfacePrimitive;
392360
std::sort(surfSort.begin(), surfSort.end());
393361
real64 m = (nSurf % 2 == 1) ? surfSort[nSurf / 2] : (surfSort[nSurf / 2 - 1] + surfSort[nSurf / 2]) / 2.0;
@@ -401,6 +369,7 @@ void TreeNodeMortar::createNode(MeshLevel const & mesh,
401369
(surfacePrimitive[i] <= m) ? surfLeft.emplace_back(surfList[i]) : surfRight.emplace_back(surfList[i]);
402370
}
403371

372+
/*
404373
for (localIndex i = 0; i < surfLeft.size(); ++i)
405374
{
406375
std::cout << "Left child" << std::endl;
@@ -412,10 +381,10 @@ void TreeNodeMortar::createNode(MeshLevel const & mesh,
412381
std::cout << "Right child" << std::endl;
413382
std::cout << surfRight[i] << std::endl;
414383
}
415-
416384
std::cout << "_____________________________________________" << std::endl;
385+
*/
417386

418-
// create child recursively
387+
// create left and right child recursively
419388
this->left = std::make_unique<TreeNodeMortar>();
420389
this->left->createNode(mesh,surf,surfLeft);
421390
this->right = std::make_unique<TreeNodeMortar>();

src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsMortarContact.hpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,29 +105,43 @@ class SolidMechanicsMortarContact : public ContactSolverBase
105105
void updateState( DomainPartition & domain ) override final;
106106

107107
private:
108+
109+
// store pointers to relevant mesh objects of master and slave side
108110
MeshLevel const* m_meshSlave = nullptr;
109111
MeshLevel const* m_meshMaster = nullptr;
110112
FaceElementSubRegion const* m_surfaceMaster = nullptr;
111113
FaceElementSubRegion const* m_surfaceSlave = nullptr;
112114

113-
ArrayOfArrays< localIndex > m_connectivityMap; // map id of slave elements to id of connected master elements
115+
// map id of slave elements to id of connected master elements
116+
ArrayOfArrays< localIndex > m_connectivityMap;
114117

118+
// tandem traversal contact search
115119
void contactSearch(std::unique_ptr<TreeNodeMortar> const & nodeMaster,
116120
std::unique_ptr<TreeNodeMortar> const & nodeSlave);
117121

122+
// check intersection between two bounding boxes using polytops primitives
118123
bool checkIntersection(std::unique_ptr<TreeNodeMortar> const & nodeMaster,
119124
std::unique_ptr<TreeNodeMortar> const & nodeSlave);
120125

126+
void getConnectivityMap();
127+
121128
};
122129

130+
// binary tree for efficient contact search
123131
class TreeNodeMortar
124132
{
125133
public:
126134
std::unique_ptr<TreeNodeMortar> left = nullptr;
127135
std::unique_ptr<TreeNodeMortar> right = nullptr;
128136
bool isLeaf = false;
129-
double polytop[18] = POLYTOP; // array with primitives of polytopal bounding box
130-
localIndex leafId; // id of face corresponding to leaf nodes
137+
138+
// primitives of polytopal bounding box
139+
double polytop[18] = POLYTOP;
140+
141+
// id of face corresponding to leaf nodes
142+
localIndex leafId;
143+
144+
// populate a tree node (use recursion)
131145
void createNode(MeshLevel const & mesh,
132146
FaceElementSubRegion const & surf,
133147
array1d<localIndex> & surfList);

0 commit comments

Comments
 (0)