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 "polyMeshGenModifier.H"
30 #include "partTetMesh.H"
31 #include "polyMeshGenAddressing.H"
32 #include "helperFunctionsPar.H"
33 #include "parPartTet.H"
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 void partTetMesh::createParallelAddressing
48 const labelLongList& nodeLabelForPoint,
49 const labelLongList& nodeLabelForFace,
50 const labelLongList& nodeLabelForCell
53 //- vertices marked as SMOOTH and BOUNDARY are used by the smoother
54 const direction useType = SMOOTH + BOUNDARY;
56 //- allocate global point labels
57 if( !globalPointLabelPtr_ )
58 globalPointLabelPtr_ = new labelLongList();
59 labelLongList& globalTetPointLabel = *globalPointLabelPtr_;
60 globalTetPointLabel.setSize(points_.size());
61 globalTetPointLabel = -1;
63 //- allocated point-processors addressing
65 pAtProcsPtr_ = new VRWGraph();
66 VRWGraph& pProcs = *pAtProcsPtr_;
68 pProcs.setSize(points_.size());
70 //- allocate global-to-local point addressing
71 if( !globalToLocalPointAddressingPtr_ )
72 globalToLocalPointAddressingPtr_ = new Map<label>();
73 Map<label>& globalToLocal = *globalToLocalPointAddressingPtr_;
74 globalToLocal.clear();
76 //- allocate storage for points at parallel boundaries
77 if( !pAtParallelBoundariesPtr_ )
78 pAtParallelBoundariesPtr_ = new labelLongList();
79 labelLongList& pAtParallelBoundaries = *pAtParallelBoundariesPtr_;
80 pAtParallelBoundaries.clear();
82 //- create point-processors addressing
83 std::map<label, labelLongList> exchangeData;
84 std::map<label, labelLongList>::iterator iter;
86 const polyMeshGenAddressing& addressing = origMesh_.addressingData();
87 const Map<label>& globalToLocalPointAddressing =
88 addressing.globalToLocalPointAddressing();
89 const VRWGraph& pAtProcs = addressing.pointAtProcs();
90 const DynList<label>& pNeiProcs = addressing.pointNeiProcs();
92 forAll(pNeiProcs, procI)
93 exchangeData.insert(std::make_pair(pNeiProcs[procI], labelLongList()));
95 //- make sure that the same vertices are marked for smoothing on all procs
96 //- this is performed by sending the labels of vertices which are not used
97 //- for tet mesh creation and the tet mesh vertices which are not moved
98 forAllConstIter(Map<label>, globalToLocalPointAddressing, it)
100 const label pI = it();
103 nodeLabelForPoint[pI] == -1 ||
104 !smoothVertex_[nodeLabelForPoint[pI]]
107 forAllRow(pAtProcs, pI, procI)
109 const label neiProc = pAtProcs(pI, procI);
110 if( neiProc == Pstream::myProcNo() )
113 exchangeData[neiProc].append(it.key());
118 //- exchange data with other processors
119 labelLongList receivedData;
120 help::exchangeMap(exchangeData, receivedData);
122 //- set the values according to other processors
123 forAll(receivedData, i)
125 const label pointI = globalToLocalPointAddressing[receivedData[i]];
127 if( nodeLabelForPoint[pointI] == -1 )
130 smoothVertex_[nodeLabelForPoint[pointI]] = NONE;
133 for(iter=exchangeData.begin();iter!=exchangeData.end();++iter)
134 iter->second.clear();
136 //- start creating global-to-local addressing
137 //- find the starting point labels
138 label startPoint(0), nLocalPoints(0), nSharedPoints(0);
140 //- count the number of points at processor boundaries
141 forAllConstIter(Map<label>, globalToLocalPointAddressing, it)
143 const label pI = it();
145 if( nodeLabelForPoint[pI] == -1 )
147 if( !(smoothVertex_[nodeLabelForPoint[pI]] & useType) )
152 label pMin(Pstream::myProcNo());
153 forAllRow(pAtProcs, pI, procI)
154 pMin = Foam::min(pMin, pAtProcs(pI, procI));
156 if( pMin == Pstream::myProcNo() )
160 labelList nPointsAtProc(Pstream::nProcs());
161 nSharedPoints -= nLocalPoints;
162 nPointsAtProc[Pstream::myProcNo()] = points_.size() - nSharedPoints;
163 Pstream::gatherList(nPointsAtProc);
164 Pstream::scatterList(nPointsAtProc);
166 for(label i=0;i<Pstream::myProcNo();++i)
167 startPoint += nPointsAtProc[i];
169 //- create global labels for points at processor boundaries
170 forAllConstIter(Map<label>, globalToLocalPointAddressing, it)
172 const label pI = it();
174 if( nodeLabelForPoint[pI] == -1 )
177 const label pLabel = nodeLabelForPoint[pI];
179 if( !(smoothVertex_[pLabel] & useType) )
182 label pMin(Pstream::myProcNo());
183 forAllRow(pAtProcs, pI, procI)
185 const label neiProc = pAtProcs(pI, procI);
186 pProcs.append(pLabel, neiProc);
187 pMin = Foam::min(pMin, neiProc);
190 if( pMin != Pstream::myProcNo() )
193 globalTetPointLabel[pLabel] = startPoint++;
195 forAllRow(pAtProcs, pI, procI)
197 const label neiProc = pAtProcs(pI, procI);
199 if( neiProc == Pstream::myProcNo() )
202 //- the following information is sent to other processor
203 //- 1. global point label in the original mesh
204 //- 2. global point label in the tet mesh
205 exchangeData[neiProc].append(it.key());
206 exchangeData[neiProc].append(globalTetPointLabel[pLabel]);
210 //- exchange data with other processors
211 receivedData.clear();
212 help::exchangeMap(exchangeData, receivedData);
215 while( counter < receivedData.size() )
217 const label gpI = receivedData[counter++];
218 const label tgI = receivedData[counter++];
220 nodeLabelForPoint[globalToLocalPointAddressing[gpI]];
222 globalTetPointLabel[pLabel] = tgI;
225 //- set global labels for remaining points
226 forAll(globalTetPointLabel, pI)
228 if( globalTetPointLabel[pI] == -1 )
229 globalTetPointLabel[pI] = startPoint++;
232 //- create global to local mapping
233 forAll(globalTetPointLabel, pI)
235 if( pProcs.sizeOfRow(pI) != 0 )
237 pAtParallelBoundaries.append(pI);
238 globalToLocal.insert(globalTetPointLabel[pI], pI);
242 //- mark vertices at parallel boundaries
243 forAll(smoothVertex_, pI)
244 if( (smoothVertex_[pI] & useType) && (pProcs.sizeOfRow(pI) != 0) )
245 smoothVertex_[pI] |= PARALLELBOUNDARY;
247 //- create neighbour processors addressing
249 neiProcsPtr_ = new DynList<label>();
250 DynList<label>& neiProcs = *neiProcsPtr_;
252 for(iter=exchangeData.begin();iter!=exchangeData.end();++iter)
253 neiProcs.append(iter->first);
256 for(label i=0;i<Pstream::nProcs();++i)
258 if( i == Pstream::myProcNo() )
260 Pout << "globalTetPointLabel " << globalTetPointLabel << endl;
263 returnReduce(i, sumOp<label>());
266 returnReduce(1, sumOp<label>());
268 forAll(nodeLabelForPoint, pI)
270 const label tpI = nodeLabelForPoint[pI];
271 if( tpI != -1 && globalTetPointLabel[tpI] == -1 )
272 FatalError << "Crap1 " << tpI << abort(FatalError);
275 returnReduce(1, sumOp<label>());
277 forAll(nodeLabelForFace, fI)
279 const label tpI = nodeLabelForFace[fI];
280 if( tpI != -1 && globalTetPointLabel[tpI] == -1 )
282 Pout << "Face point " << tpI << " is at procs "
283 << pProcs[tpI] << endl;
284 FatalError << "Crap2" << tpI << abort(FatalError);
288 returnReduce(1, sumOp<label>());
290 forAll(nodeLabelForCell, cI)
292 const label tpI = nodeLabelForCell[cI];
293 if( tpI != -1 && globalTetPointLabel[tpI] == -1 )
294 FatalError << "Crap3" << tpI << abort(FatalError);
297 forAll(smoothVertex_, vI)
298 if( smoothVertex_[vI] & partTetMesh::PARALLELBOUNDARY )
299 Pout << "Point " << globalTetPointLabel[vI]
300 << " is at par bnd" << endl;
302 Serr << Pstream::myProcNo() << "points " << points_ << endl;
303 Serr << Pstream::myProcNo() << "Tets " << tets_ << endl;
306 if( pProcs.sizeOfRow(pI) == 0 )
309 Serr << Pstream::myProcNo() << "Point " << globalTetPointLabel[pI]
310 << " is at procs " << pProcs[pI] << " n tets "
311 << pointTets_[pI].size() << endl;
314 returnReduce(1, sumOp<label>());
318 void partTetMesh::createBufferLayers()
320 VRWGraph& pProcs = *pAtProcsPtr_;
321 labelLongList& globalTetPointLabel = *globalPointLabelPtr_;
322 Map<label>& globalToLocal = *globalToLocalPointAddressingPtr_;
323 const DynList<label>& neiProcs = *this->neiProcsPtr_;
325 if( !pAtBufferLayersPtr_ )
326 pAtBufferLayersPtr_ = new labelLongList();
327 labelLongList& pAtBufferLayers = *pAtBufferLayersPtr_;
328 pAtBufferLayers.clear();
331 std::map<label, LongList<parPartTet> > exchangeTets;
332 forAll(neiProcs, procI)
335 std::make_pair(neiProcs[procI], LongList<parPartTet>())
338 //- go through the tets and add the ones having vertices at parallel
339 //- boundaries for sending
342 const partTet& pt = tets_[tetI];
344 DynList<label> sendToProcs;
347 const label pLabel = pt[i];
349 if( smoothVertex_[pLabel] & PARALLELBOUNDARY )
351 forAllRow(pProcs, pLabel, i)
353 const label neiProc = pProcs(pLabel, i);
355 if( neiProc == Pstream::myProcNo() )
358 sendToProcs.appendIfNotIn(neiProc);
363 if( sendToProcs.size() )
367 labelledPoint(globalTetPointLabel[pt[0]], points_[pt[0]]),
368 labelledPoint(globalTetPointLabel[pt[1]], points_[pt[1]]),
369 labelledPoint(globalTetPointLabel[pt[2]], points_[pt[2]]),
370 labelledPoint(globalTetPointLabel[pt[3]], points_[pt[3]])
373 forAll(sendToProcs, i)
375 exchangeTets[sendToProcs[i]].append(tet);
379 if( pProcs.sizeOfRow(pt[j]) == 0 )
380 pAtBufferLayers.append(pt[j]);
382 pProcs.appendIfNotIn(pt[j], sendToProcs[i]);
388 LongList<parPartTet> receivedTets;
389 help::exchangeMap(exchangeTets, receivedTets);
390 exchangeTets.clear();
392 Map<label> newGlobalToLocal;
393 forAll(receivedTets, i)
395 const parPartTet& tet = receivedTets[i];
397 DynList<label> tetPointLabels;
398 for(label j=0;j<4;++j)
400 const label gpI = tet[j].pointLabel();
402 if( globalToLocal.found(gpI) )
404 const label pI = globalToLocal[gpI];
405 pointTets_.append(pI, tets_.size());
406 tetPointLabels.append(pI);
408 else if( newGlobalToLocal.found(gpI) )
410 tetPointLabels.append(newGlobalToLocal[gpI]);
414 newGlobalToLocal.insert(gpI, points_.size());
415 tetPointLabels.append(points_.size());
416 points_.append(tet[j].coordinates());
417 nodeLabelInOrigMesh_.append(-1);
418 smoothVertex_.append(NONE);
419 DynList<label> helper;
420 helper.append(tets_.size());
421 pointTets_.appendList(helper);
423 globalTetPointLabel.append(gpI);
424 helper[0] = Pstream::myProcNo();
425 pProcs.appendList(helper);
442 //- insert the global labels of the buffer points
443 //- into the globalToLocal map
444 forAllConstIter(Map<label>, newGlobalToLocal, it)
445 globalToLocal.insert(it.key(), it());
448 for(label i=0;i<Pstream::nProcs();++i)
450 if( Pstream::myProcNo() == i )
452 forAllConstIter(Map<label>, globalToLocal, it)
455 if( it() < pProcs.size() )
456 forAllRow(pProcs, it(), j)
457 np.append(pProcs(it(), j));
459 Pout << "Tet mesh point " << it() << " has global label "
460 << it.key() << " and is located at procs "
465 returnReduce(1, sumOp<label>());
470 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
472 } // End namespace Foam
474 // ************************************************************************* //