1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
16 cfMesh is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "demandDrivenData.H"
29 #include "meshSurfacePartitioner.H"
30 #include "partTriMesh.H"
31 #include "triSurfModifier.H"
32 #include "meshSurfaceEngine.H"
33 #include "helperFunctionsPar.H"
34 #include "parTriFace.H"
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 void partTriMesh::createParallelAddressing
49 const labelList& nodeLabelForPoint,
50 const labelList& nodeLabelForFace
53 const meshSurfaceEngine& mse = mPart_.surfaceEngine();
55 const pointField& pts = surf_.points();
57 //- vertices marked as SMOOTH are used by the smoother
58 const direction useType = SMOOTH;
60 //- allocate global point labels
61 if( !globalPointLabelPtr_ )
62 globalPointLabelPtr_ = new labelLongList();
63 labelLongList& globalPointLabel = *globalPointLabelPtr_;
64 globalPointLabel.setSize(pts.size());
65 globalPointLabel = -1;
67 //- allocated point-processors addressing
69 pAtProcsPtr_ = new VRWGraph();
70 VRWGraph& pProcs = *pAtProcsPtr_;
72 pProcs.setSize(pts.size());
74 //- allocate global-to-local point addressing
75 if( !globalToLocalPointAddressingPtr_ )
76 globalToLocalPointAddressingPtr_ = new Map<label>();
77 Map<label>& globalToLocal = *globalToLocalPointAddressingPtr_;
78 globalToLocal.clear();
80 //- allocate storage for points at parallel boundaries
81 if( !pAtParallelBoundariesPtr_ )
82 pAtParallelBoundariesPtr_ = new labelLongList();
83 labelLongList& pAtParallelBoundaries = *pAtParallelBoundariesPtr_;
84 pAtParallelBoundaries.clear();
86 //- create point-processors addressing
87 std::map<label, labelLongList> exchangeData;
88 std::map<label, labelLongList>::iterator iter;
90 const Map<label>& globalToLocalPointAddressing =
91 mse.globalToLocalBndPointAddressing();
92 const VRWGraph& pAtProcs = mse.bpAtProcs();
93 const DynList<label>& pNeiProcs = mse.bpNeiProcs();
95 forAll(pNeiProcs, procI)
96 exchangeData.insert(std::make_pair(pNeiProcs[procI], labelLongList()));
98 //- make sure that the same vertices are marked for smoothing on all procs
99 //- this is performed by sending the labels of vertices which are not used
100 //- for tet mesh creation and the tet mesh vertices which are not moved
101 forAllConstIter(Map<label>, globalToLocalPointAddressing, it)
103 const label pI = it();
106 nodeLabelForPoint[pI] == -1 ||
107 !pointType_[nodeLabelForPoint[pI]]
110 forAllRow(pAtProcs, pI, procI)
112 const label neiProc = pAtProcs(pI, procI);
113 if( neiProc == Pstream::myProcNo() )
116 exchangeData[neiProc].append(it.key());
121 //- exchange data with other processors
122 labelLongList receivedData;
123 help::exchangeMap(exchangeData, receivedData);
125 //- set the values according to other processors
126 forAll(receivedData, i)
128 const label pointI = globalToLocalPointAddressing[receivedData[i]];
130 if( nodeLabelForPoint[pointI] == -1 )
133 pointType_[nodeLabelForPoint[pointI]] = NONE;
136 for(iter=exchangeData.begin();iter!=exchangeData.end();++iter)
137 iter->second.clear();
139 //- start creating global-to-local addressing
140 //- find the starting point labels
141 label startPoint(0), nLocalPoints(0), nSharedPoints(0);
143 //- count the number of points at processor boundaries
144 forAllConstIter(Map<label>, globalToLocalPointAddressing, it)
146 const label pI = it();
148 if( nodeLabelForPoint[pI] == -1 )
150 if( !(pointType_[nodeLabelForPoint[pI]] & useType) )
155 label pMin(Pstream::myProcNo());
156 forAllRow(pAtProcs, pI, procI)
157 pMin = Foam::min(pMin, pAtProcs(pI, procI));
159 if( pMin == Pstream::myProcNo() )
163 labelList nPointsAtProc(Pstream::nProcs());
164 nSharedPoints -= nLocalPoints;
165 nPointsAtProc[Pstream::myProcNo()] = pts.size() - nSharedPoints;
166 Pstream::gatherList(nPointsAtProc);
167 Pstream::scatterList(nPointsAtProc);
169 for(label i=0;i<Pstream::myProcNo();++i)
170 startPoint += nPointsAtProc[i];
172 //- create global labels for points at processor boundaries
173 forAllConstIter(Map<label>, globalToLocalPointAddressing, it)
175 const label pI = it();
177 if( nodeLabelForPoint[pI] == -1 )
180 const label pLabel = nodeLabelForPoint[pI];
182 if( !(pointType_[pLabel] & useType) )
185 label pMin(Pstream::myProcNo());
186 forAllRow(pAtProcs, pI, procI)
188 const label neiProc = pAtProcs(pI, procI);
189 pProcs.append(pLabel, neiProc);
190 pMin = Foam::min(pMin, neiProc);
193 if( pMin != Pstream::myProcNo() )
196 globalPointLabel[pLabel] = startPoint++;
198 forAllRow(pAtProcs, pI, procI)
200 const label neiProc = pAtProcs(pI, procI);
202 if( neiProc == Pstream::myProcNo() )
205 //- the following information is sent to other processor
206 //- 1. global point label in the original mesh
207 //- 2. global point label in the tet mesh
208 exchangeData[neiProc].append(it.key());
209 exchangeData[neiProc].append(globalPointLabel[pLabel]);
213 //- exchange data with other processors
214 receivedData.clear();
215 help::exchangeMap(exchangeData, receivedData);
218 while( counter < receivedData.size() )
220 const label gpI = receivedData[counter++];
221 const label tgI = receivedData[counter++];
223 nodeLabelForPoint[globalToLocalPointAddressing[gpI]];
225 globalPointLabel[pLabel] = tgI;
228 //- set global labels for remaining points
229 forAll(globalPointLabel, pI)
231 if( globalPointLabel[pI] == -1 )
232 globalPointLabel[pI] = startPoint++;
235 //- create global to local mapping
236 forAll(globalPointLabel, pI)
238 if( pProcs.sizeOfRow(pI) != 0 )
240 pAtParallelBoundaries.append(pI);
241 globalToLocal.insert(globalPointLabel[pI], pI);
245 //- mark vertices at parallel boundaries
246 forAll(pointType_, pI)
247 if( (pointType_[pI] & useType) && (pProcs.sizeOfRow(pI) != 0) )
248 pointType_[pI] |= PARALLELBOUNDARY;
250 //- create neighbour processors addressing
252 neiProcsPtr_ = new DynList<label>();
253 DynList<label>& neiProcs = *neiProcsPtr_;
255 for(iter=exchangeData.begin();iter!=exchangeData.end();++iter)
256 neiProcs.append(iter->first);
259 void partTriMesh::createBufferLayers()
261 pointField& pts = triSurfModifier(surf_).pointsAccess();
263 VRWGraph& pProcs = *pAtProcsPtr_;
264 labelLongList& globalPointLabel = *globalPointLabelPtr_;
265 Map<label>& globalToLocal = *globalToLocalPointAddressingPtr_;
266 const DynList<label>& neiProcs = *this->neiProcsPtr_;
268 if( !pAtBufferLayersPtr_ )
269 pAtBufferLayersPtr_ = new labelLongList();
270 labelLongList& pAtBufferLayers = *pAtBufferLayersPtr_;
271 pAtBufferLayers.clear();
274 std::map<label, LongList<parTriFace> > exchangeTrias;
275 forAll(neiProcs, procI)
278 std::make_pair(neiProcs[procI], LongList<parTriFace>())
281 //- loop over triangles and add the ones having vertices at parallel
282 //- boundaries for sending
285 const labelledTri& pt = surf_[triI];
287 DynList<label> sendToProcs;
290 const label pLabel = pt[i];
292 if( pointType_[pLabel] & PARALLELBOUNDARY )
294 forAllRow(pProcs, pLabel, i)
296 const label neiProc = pProcs(pLabel, i);
298 if( neiProc == Pstream::myProcNo() )
301 sendToProcs.appendIfNotIn(neiProc);
306 if( sendToProcs.size() )
310 globalPointLabel[pt[0]],
311 globalPointLabel[pt[1]],
312 globalPointLabel[pt[2]],
313 triangle<point, point>(pts[pt[0]], pts[pt[1]], pts[pt[2]])
316 forAll(sendToProcs, i)
318 exchangeTrias[sendToProcs[i]].append(tri);
322 if( pProcs.sizeOfRow(pt[j]) == 0 )
323 pAtBufferLayers.append(pt[j]);
325 pProcs.appendIfNotIn(pt[j], sendToProcs[i]);
331 //- receive triangles sent to this processor
332 std::map<label, List<parTriFace> > receivedTriangles;
333 help::exchangeMap(exchangeTrias, receivedTriangles);
334 exchangeTrias.clear();
336 //- add triangles into the mesh and update the addressing
337 Map<label> newGlobalToLocal;
338 std::map<label, point> addCoordinates;
339 label nPoints = pts.size();
342 std::map<label, List<parTriFace> >::const_iterator it =
343 receivedTriangles.begin();
344 it!=receivedTriangles.end();
348 const List<parTriFace>& receivedTrias = it->second;
350 forAll(receivedTrias, i)
352 const parTriFace& tri = receivedTrias[i];
354 DynList<label, 3> triPointLabels(3);
355 for(label j=0;j<3;++j)
357 const label gpI = tri.globalLabelOfPoint(j);
359 if( globalToLocal.found(gpI) )
361 //- point already exists in the triangulation
362 const label pI = globalToLocal[gpI];
363 triPointLabels[j] = pI;
365 else if( newGlobalToLocal.found(gpI) )
367 //- point is already added into the triangulation
368 triPointLabels[j] = newGlobalToLocal[gpI];
369 pProcs.appendIfNotIn(newGlobalToLocal[gpI], it->first);
373 //- point does not exist in the triangulation
374 //- and is not yet added in
375 newGlobalToLocal.insert(gpI, nPoints);
376 triPointLabels[j] = nPoints;
381 tp = tri.trianglePoints().a();
385 tp = tri.trianglePoints().b();
389 tp = tri.trianglePoints().c();
391 addCoordinates[nPoints] = tp;
394 pointLabelInMeshSurface_.append(-1);
395 pointType_.append(NONE);
397 DynList<label> triAtProcs;
398 triAtProcs.append(it->first);
400 globalPointLabel.append(gpI);
401 triAtProcs.append(Pstream::myProcNo());
402 pProcs.appendList(triAtProcs);
420 //- store newly added points
421 pts.setSize(nPoints);
424 std::map<label, point>::const_iterator it=addCoordinates.begin();
425 it!=addCoordinates.end();
428 pts[it->first] = it->second;
430 addCoordinates.clear();
432 //- insert the global labels of the buffer points
433 //- into the globalToLocal map
434 forAllConstIter(Map<label>, newGlobalToLocal, it)
435 globalToLocal.insert(it.key(), it());
437 //- update addressing of the surface mesh
438 surf_.clearAddressing();
441 void partTriMesh::updateBufferLayers()
443 const pointField& points = surf_.points();
444 const labelLongList& bufferLayerPoints = this->bufferLayerPoints();
445 const VRWGraph& pProcs = this->pointAtProcs();
446 const labelLongList& globalPointLabel = this->globalPointLabel();
447 const Map<label>& globalToLocal = this->globalToLocalPointAddressing();
448 const DynList<label>& neiProcs = this->neiProcs();
451 std::map<label, LongList<labelledPoint> > exchangeData;
455 std::make_pair(neiProcs[i], LongList<labelledPoint>())
458 //- add points into the map
459 forAll(bufferLayerPoints, pI)
461 const label pointI = bufferLayerPoints[pI];
463 forAllRow(pProcs, pointI, i)
465 const label neiProc = pProcs(pointI, i);
467 if( neiProc == Pstream::myProcNo() )
470 exchangeData[neiProc].append
472 labelledPoint(globalPointLabel[pointI], points[pointI])
477 LongList<labelledPoint> receivedData;
478 help::exchangeMap(exchangeData, receivedData);
480 forAll(receivedData, i)
482 const labelledPoint& lp = receivedData[i];
486 globalToLocal[lp.pointLabel()],
492 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
494 } // End namespace Foam
496 // ************************************************************************* //