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 "meshSurfaceEngineModifier.H"
29 #include "polyMeshGenModifier.H"
30 #include "demandDrivenData.H"
32 #include "labelledPoint.H"
33 #include "helperFunctionsPar.H"
35 // #define DEBUGSearch
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 meshSurfaceEngineModifier::meshSurfaceEngineModifier
46 meshSurfaceEngine& surfaceEngine
49 surfaceEngine_(surfaceEngine)
52 meshSurfaceEngineModifier::meshSurfaceEngineModifier
54 const meshSurfaceEngine& surfaceEngine
57 surfaceEngine_(const_cast<meshSurfaceEngine&>(surfaceEngine))
60 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
62 meshSurfaceEngineModifier::~meshSurfaceEngineModifier()
65 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
67 void meshSurfaceEngineModifier::moveBoundaryVertexNoUpdate
73 surfaceEngine_.mesh_.points()[surfaceEngine_.boundaryPoints()[bpI]] = newP;
76 void meshSurfaceEngineModifier::moveBoundaryVertex
82 const labelList& bPoints = surfaceEngine_.boundaryPoints();
83 pointFieldPMG& points = surfaceEngine_.mesh_.points();
84 points[bPoints[bpI]] = newP;
86 if( surfaceEngine_.faceCentresPtr_ )
88 vectorField& faceCentres = *surfaceEngine_.faceCentresPtr_;
89 const VRWGraph& pFaces = surfaceEngine_.pointFaces();
90 const faceList::subList& bFaces = surfaceEngine_.boundaryFaces();
92 forAllRow(pFaces, bpI, pfI)
94 const label bfI = pFaces(bpI, pfI);
96 faceCentres[bfI] = bFaces[bfI].centre(points);
100 if( surfaceEngine_.faceNormalsPtr_ )
102 vectorField& faceNormals = *surfaceEngine_.faceNormalsPtr_;
103 const VRWGraph& pFaces = surfaceEngine_.pointFaces();
104 const faceList::subList& bFaces = surfaceEngine_.boundaryFaces();
106 forAllRow(pFaces, bpI, pfI)
108 const label bfI = pFaces(bpI, pfI);
110 faceNormals[bfI] = bFaces[bfI].normal(points);
114 if( surfaceEngine_.pointNormalsPtr_ )
116 const vectorField& faceNormals = *surfaceEngine_.faceNormalsPtr_;
117 const VRWGraph& pFaces = surfaceEngine_.pointFaces();
118 const VRWGraph& pPoints = surfaceEngine_.pointPoints();
120 vectorField& pn = *surfaceEngine_.pointNormalsPtr_;
121 vector n(vector::zero);
122 forAllRow(pFaces, bpI, pfI)
123 n += faceNormals[pFaces(bpI, pfI)];
125 const scalar l = mag(n);
137 //- change normal of vertices connected to bpI
138 forAllRow(pPoints, bpI, ppI)
140 const label bpJ = pPoints(bpI, ppI);
142 forAllRow(pFaces, bpJ, pfI)
143 n += faceNormals[pFaces(bpJ, pfI)];
145 const scalar d = mag(n);
160 void meshSurfaceEngineModifier::syncVerticesAtParallelBoundaries()
162 if( !Pstream::parRun() )
165 const Map<label>& globalToLocal =
166 surfaceEngine_.globalToLocalBndPointAddressing();
167 labelLongList syncNodes;
168 forAllConstIter(Map<label>, globalToLocal, it)
169 syncNodes.append(it());
171 syncVerticesAtParallelBoundaries(syncNodes);
174 void meshSurfaceEngineModifier::syncVerticesAtParallelBoundaries
176 const labelLongList& syncNodes
179 if( !Pstream::parRun() )
182 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
183 const labelList& globalLabel =
184 surfaceEngine_.globalBoundaryPointLabel();
185 const Map<label>& globalToLocal =
186 surfaceEngine_.globalToLocalBndPointAddressing();
187 const DynList<label>& neiProcs = surfaceEngine_.bpNeiProcs();
188 const labelList& bPoints = surfaceEngine_.boundaryPoints();
189 const pointFieldPMG& points = surfaceEngine_.mesh().points();
191 std::map<label, LongList<labelledPoint> > exchangeData;
195 std::make_pair(neiProcs[i], LongList<labelledPoint>())
198 //- construct the map
199 forAll(syncNodes, snI)
201 const label bpI = syncNodes[snI];
203 if( bpAtProcs.sizeOfRow(bpI) == 0 )
206 point p = points[bPoints[bpI]] / bpAtProcs.sizeOfRow(bpI);
207 moveBoundaryVertexNoUpdate(bpI, p);
209 forAllRow(bpAtProcs, bpI, i)
211 const label neiProc = bpAtProcs(bpI, i);
212 if( neiProc == Pstream::myProcNo() )
215 exchangeData[neiProc].append(labelledPoint(globalLabel[bpI], p));
219 //- exchange the data with other processors
220 LongList<labelledPoint> receivedData;
221 help::exchangeMap(exchangeData, receivedData);
223 //- adjust the coordinates
224 forAll(receivedData, i)
226 const labelledPoint& lp = receivedData[i];
227 const label bpI = globalToLocal[lp.pointLabel()];
228 const point newP = points[bPoints[bpI]] + lp.coordinates();
229 moveBoundaryVertexNoUpdate(bpI, newP);
233 void meshSurfaceEngineModifier::updateGeometry
235 const labelLongList& updateBndNodes
238 const pointFieldPMG& points = surfaceEngine_.points();
239 const faceList::subList& bFaces = surfaceEngine_.boundaryFaces();
240 const VRWGraph& pFaces = surfaceEngine_.pointFaces();
241 const labelList& bp = surfaceEngine_.bp();
243 boolList updateFaces(bFaces.size(), false);
245 # pragma omp parallel for if( updateBndNodes.size() > 1000 )
247 forAll(updateBndNodes, i)
249 const label bpI = updateBndNodes[i];
250 forAllRow(pFaces, bpI, j)
251 updateFaces[pFaces(bpI, j)] = true;
254 if( surfaceEngine_.faceCentresPtr_ )
256 vectorField& faceCentres = *surfaceEngine_.faceCentresPtr_;
259 # pragma omp parallel for if( updateFaces.size() > 1000 ) \
260 schedule(dynamic, 100)
262 forAll(updateFaces, bfI)
264 if( updateFaces[bfI] )
265 faceCentres[bfI] = bFaces[bfI].centre(points);
269 if( surfaceEngine_.faceNormalsPtr_ )
271 vectorField& faceNormals = *surfaceEngine_.faceNormalsPtr_;
274 # pragma omp parallel for if( updateFaces.size() > 1000 ) \
275 schedule(dynamic, 100)
277 forAll(updateFaces, bfI)
279 if( updateFaces[bfI] )
280 faceNormals[bfI] = bFaces[bfI].normal(points);
284 if( surfaceEngine_.pointNormalsPtr_ )
286 const vectorField& faceNormals = surfaceEngine_.faceNormals();
288 boolList updateBndPoint(pFaces.size(), false);
290 # pragma omp parallel for schedule(dynamic, 50)
292 forAll(updateBndNodes, i)
294 const label bpI = updateBndNodes[i];
296 forAllRow(pFaces, bpI, pfI)
298 const face& bf = bFaces[pFaces(bpI, pfI)];
301 updateBndPoint[bp[bf[pI]]] = true;
305 vectorField& pn = *surfaceEngine_.pointNormalsPtr_;
307 # pragma omp parallel for schedule(dynamic, 100)
309 forAll(updateBndPoint, bpI)
311 if( !updateBndPoint[bpI] )
314 vector n(vector::zero);
315 forAllRow(pFaces, bpI, pfI)
316 n += faceNormals[pFaces(bpI, pfI)];
318 const scalar l = mag(n);
331 if( Pstream::parRun() )
333 //- update point normals at inter-processor boundaries
334 const Map<label>& globalToLocal =
335 surfaceEngine_.globalToLocalBndPointAddressing();
336 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
337 const DynList<label>& neiProcs = surfaceEngine_.bpNeiProcs();
339 //- make sure that the points ar updated on all processors
340 std::map<label, labelLongList> exchangeNodeLabels;
342 exchangeNodeLabels[neiProcs[i]].clear();
344 forAllConstIter(Map<label>, globalToLocal, it)
346 const label bpI = it();
348 if( updateBndPoint[bpI] )
350 forAllRow(bpAtProcs, bpI, i)
352 const label neiProc = bpAtProcs(bpI, i);
354 if( neiProc == Pstream::myProcNo() )
357 exchangeNodeLabels[neiProc].append(it.key());
362 labelLongList receivedNodes;
363 help::exchangeMap(exchangeNodeLabels, receivedNodes);
365 forAll(receivedNodes, i)
366 updateBndPoint[globalToLocal[receivedNodes[i]]] = true;
369 //- start updating point normals
370 std::map<label, LongList<labelledPoint> > exchangeData;
372 exchangeData[neiProcs[i]].clear();
374 //- prepare data for sending
375 forAllConstIter(Map<label>, globalToLocal, iter)
377 const label bpI = iter();
379 if( !updateBndPoint[bpI] )
385 forAllRow(pFaces, bpI, pfI)
386 n += faceNormals[pFaces(bpI, pfI)];
388 forAllRow(bpAtProcs, bpI, procI)
390 const label neiProc = bpAtProcs(bpI, procI);
391 if( neiProc == Pstream::myProcNo() )
394 exchangeData[neiProc].append(labelledPoint(iter.key(), n));
398 //- exchange data with other procs
399 LongList<labelledPoint> receivedData;
400 help::exchangeMap(exchangeData, receivedData);
402 forAll(receivedData, i)
404 const label bpI = globalToLocal[receivedData[i].pointLabel()];
405 pn[bpI] += receivedData[i].coordinates();
408 //- normalize vectors
409 forAllConstIter(Map<label>, globalToLocal, it)
411 const label bpI = it();
413 if( !updateBndPoint[bpI] )
416 vector normal = pn[bpI];
417 const scalar d = mag(normal);
424 normal = vector::zero;
433 void meshSurfaceEngineModifier::updateGeometry()
435 labelLongList updateBndNodes(surfaceEngine_.boundaryPoints().size());
438 # pragma omp parallel for if( updateBndNodes.size() > 10000 )
440 forAll(updateBndNodes, bpI)
441 updateBndNodes[bpI] = bpI;
443 updateGeometry(updateBndNodes);
446 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
448 } // End namespace Foam
450 // ************************************************************************* //