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 "meshSurfaceOptimizer.H"
30 #include "meshSurfaceEngineModifier.H"
32 #include "meshSurfaceMapper.H"
33 #include "surfaceOptimizer.H"
34 #include "refLabelledPoint.H"
35 #include "helperFunctions.H"
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 void meshSurfaceOptimizer::nodeDisplacementLaplacianParallel
48 const labelLongList& nodesToSmooth,
49 const bool transformIntoPlane
52 if( returnReduce(nodesToSmooth.size(), sumOp<label>()) == 0 )
55 //- create storage for data
56 std::map<label, labelledPoint> localData;
58 //- exchange data with other processors
59 std::map<label, LongList<refLabelledPoint> > exchangeData;
61 const pointField& points = surfaceEngine_.points();
62 const labelList& bPoints = surfaceEngine_.boundaryPoints();
63 const VRWGraph& pPoints = surfaceEngine_.pointPoints();
64 const vectorField& pNormals = surfaceEngine_.pointNormals();
65 const labelList& globalPointLabel =
66 surfaceEngine_.globalBoundaryPointLabel();
67 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
68 const Map<label>& globalToLocal =
69 surfaceEngine_.globalToLocalBndPointAddressing();
72 forAll(nodesToSmooth, pI)
74 const label bpI = nodesToSmooth[pI];
76 if( vertexType_[bpI] & LOCKED )
79 if( magSqr(pNormals[bpI]) < VSMALL )
82 const plane pl(points[bPoints[bpI]], pNormals[bpI]);
84 //- project points onto the plane
85 localData.insert(std::make_pair(bpI, labelledPoint(0, vector::zero)));
86 labelledPoint& lpd = localData[bpI];
88 forAllRow(pPoints, bpI, ppI)
90 const label nei = pPoints(bpI, ppI);
92 if( bpAtProcs.sizeOfRow(nei) != 0 )
94 label pMin(Pstream::nProcs());
95 forAllRow(bpAtProcs, nei, procI)
97 const label procJ = bpAtProcs(nei, procI);
98 if( (procJ < pMin) && bpAtProcs.contains(bpI, procJ) )
102 if( pMin != Pstream::myProcNo() )
106 const point& p = points[bPoints[nei]];
108 lpd.coordinates() += transformIntoPlane?pl.nearestPoint(p):p;
111 forAllRow(bpAtProcs, bpI, procI)
113 const label neiProc = bpAtProcs(bpI, procI);
114 if( neiProc == Pstream::myProcNo() )
117 if( exchangeData.find(neiProc) == exchangeData.end() )
121 std::make_pair(neiProc, LongList<refLabelledPoint>())
125 //- add data to the list which will be sent to other processor
126 LongList<refLabelledPoint>& dts = exchangeData[neiProc];
127 dts.append(refLabelledPoint(globalPointLabel[bpI], lpd));
131 //- exchange data with other processors
132 LongList<refLabelledPoint> receivedData;
133 help::exchangeMap(exchangeData, receivedData);
135 forAll(receivedData, i)
137 const refLabelledPoint& lp = receivedData[i];
138 const label bpI = globalToLocal[lp.objectLabel()];
140 labelledPoint& lpd = localData[bpI];
142 lpd.pointLabel() += lp.lPoint().pointLabel();
143 lpd.coordinates() += lp.lPoint().coordinates();
146 forAll(nodesToSmooth, pI)
148 const label bpI = nodesToSmooth[pI];
150 if( localData.find(bpI) == localData.end() )
153 //- create new point position
154 const labelledPoint& lp = localData[bpI];
155 const point newP = lp.coordinates() / lp.pointLabel();
157 meshSurfaceEngineModifier surfaceModifier(surfaceEngine_);
158 surfaceModifier.moveBoundaryVertexNoUpdate
166 void meshSurfaceOptimizer::nodeDisplacementLaplacianFCParallel
168 const labelLongList& nodesToSmooth,
169 const bool transformIntoPlane
172 if( returnReduce(nodesToSmooth.size(), sumOp<label>()) == 0 )
175 //- create storage for data
176 std::map<label, labelledPoint> localData;
178 //- exchange data with other processors
179 std::map<label, LongList<refLabelledPoint> > exchangeData;
181 const pointField& points = surfaceEngine_.points();
182 const labelList& bPoints = surfaceEngine_.boundaryPoints();
183 const VRWGraph& pFaces = surfaceEngine_.pointFaces();
184 const vectorField& faceCentres = surfaceEngine_.faceCentres();
185 const vectorField& pNormals = surfaceEngine_.pointNormals();
187 const labelList& globalPointLabel =
188 surfaceEngine_.globalBoundaryPointLabel();
189 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
190 const Map<label>& globalToLocal =
191 surfaceEngine_.globalToLocalBndPointAddressing();
193 //- perform smoothing
194 forAll(nodesToSmooth, pI)
196 const label bpI = nodesToSmooth[pI];
198 if( vertexType_[bpI] & LOCKED )
201 if( magSqr(pNormals[bpI]) < VSMALL )
204 const plane pl(points[bPoints[bpI]], pNormals[bpI]);
206 //- project points onto the plane
207 localData.insert(std::make_pair(bpI, labelledPoint(0, vector::zero)));
208 labelledPoint& lpd = localData[bpI];
210 forAllRow(pFaces, bpI, pfI)
212 const point& p = faceCentres[pFaces(bpI, pfI)];
214 lpd.coordinates() += transformIntoPlane?pl.nearestPoint(p):p;
217 forAllRow(bpAtProcs, bpI, procI)
219 const label neiProc = bpAtProcs(bpI, procI);
220 if( neiProc == Pstream::myProcNo() )
223 if( exchangeData.find(neiProc) == exchangeData.end() )
227 std::make_pair(neiProc, LongList<refLabelledPoint>())
231 //- add data to the list which will be sent to other processor
232 LongList<refLabelledPoint>& dts = exchangeData[neiProc];
233 dts.append(refLabelledPoint(globalPointLabel[bpI], lpd));
237 //- exchange data with other processors
238 LongList<refLabelledPoint> receivedData;
239 help::exchangeMap(exchangeData, receivedData);
241 forAll(receivedData, i)
243 const refLabelledPoint& lp = receivedData[i];
244 const label bpI = globalToLocal[lp.objectLabel()];
246 labelledPoint& lpd = localData[bpI];
248 lpd.pointLabel() += lp.lPoint().pointLabel();
249 lpd.coordinates() += lp.lPoint().coordinates();
252 pointField newPositions(nodesToSmooth.size());
255 # pragma omp parallel for schedule(dynamic, 20)
257 forAll(nodesToSmooth, pI)
259 const label bpI = nodesToSmooth[pI];
261 if( localData.find(bpI) == localData.end() )
263 newPositions[pI] = points[bPoints[bpI]];
267 //- create new point position
268 const labelledPoint& lp = localData[bpI];
269 const point newP = lp.coordinates() / lp.pointLabel();
271 newPositions[pI] = newP;
274 meshSurfaceEngineModifier surfaceModifier(surfaceEngine_);
276 # pragma omp parallel for schedule(dynamic, 20)
278 forAll(newPositions, pI)
280 surfaceModifier.moveBoundaryVertexNoUpdate
288 void meshSurfaceOptimizer::edgeNodeDisplacementParallel
290 const labelLongList& nodesToSmooth
293 std::map<label, DynList<labelledPoint, 2> > mPts;
295 //- insert labels into the map
296 const labelList& globalPointLabel =
297 surfaceEngine_.globalBoundaryPointLabel();
299 forAll(nodesToSmooth, nI)
305 globalPointLabel[nodesToSmooth[nI]],
306 DynList<labelledPoint, 2>()
311 //- add local edge points
312 const pointField& points = surfaceEngine_.points();
313 const labelList& bPoints = surfaceEngine_.boundaryPoints();
314 const edgeList& edges = surfaceEngine_.edges();
315 const VRWGraph& bpEdges = surfaceEngine_.boundaryPointEdges();
316 const labelList& bp = surfaceEngine_.bp();
318 forAll(nodesToSmooth, nI)
320 const label bpI = nodesToSmooth[nI];
322 if( vertexType_[bpI] & LOCKED)
325 DynList<labelledPoint, 2>& neiPoints = mPts[globalPointLabel[bpI]];
327 forAllRow(bpEdges, bpI, epI)
329 const edge& e = edges[bpEdges(bpI, epI)];
330 const label pI = bp[e.otherVertex(bPoints[bpI])];
331 if( vertexType_[pI] & (EDGE+CORNER) )
335 labelledPoint(globalPointLabel[pI], points[bPoints[pI]])
341 //- start preparing data which can be exchanged with other processors
342 const DynList<label>& neiProcs = surfaceEngine_.bpNeiProcs();
343 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
345 std::map<label, LongList<refLabelledPoint> > mProcs;
346 forAll(neiProcs, procI)
348 const label neiProc = neiProcs[procI];
350 if( neiProc == Pstream::myProcNo() )
353 mProcs.insert(std::make_pair(neiProc, LongList<refLabelledPoint>()));
356 forAll(nodesToSmooth, nI)
358 const label bpI = nodesToSmooth[nI];
360 const DynList<labelledPoint, 2>& neiPoints =
361 mPts[globalPointLabel[bpI]];
363 forAllRow(bpAtProcs, bpI, procI)
365 const label neiProc = bpAtProcs(bpI, procI);
367 if( neiProc == Pstream::myProcNo() )
370 forAll(neiPoints, npI)
372 LongList<refLabelledPoint>& neiProcPts = mProcs[neiProc];
375 refLabelledPoint(globalPointLabel[bpI], neiPoints[npI])
381 //- exchange data with other processors
382 LongList<refLabelledPoint> receivedData;
383 help::exchangeMap(mProcs, receivedData);
385 forAll(receivedData, prI)
387 const refLabelledPoint& lp = receivedData[prI];
388 DynList<labelledPoint, 2>& lPts = mPts[lp.objectLabel()];
389 lPts.appendIfNotIn(receivedData[prI].lPoint());
392 //- Finally, the data is ready to start smoothing
393 meshSurfaceEngineModifier sm(surfaceEngine_);
395 pointField newPositions(nodesToSmooth.size());
397 # pragma omp parallel for schedule(dynamic, 20)
399 forAll(nodesToSmooth, pI)
401 const label bpI = nodesToSmooth[pI];
403 const DynList<labelledPoint, 2>& nPts = mPts[globalPointLabel[bpI]];
404 point newP(vector::zero);
406 newP += nPts[ppI].coordinates();
408 if( nPts.size() == 2 )
411 newPositions[pI] = newP;
415 newPositions[pI] = points[bPoints[bpI]];
420 # pragma omp parallel for schedule(dynamic, 20)
422 forAll(newPositions, pI)
423 sm.moveBoundaryVertexNoUpdate(nodesToSmooth[pI], newPositions[pI]);
426 void meshSurfaceOptimizer::exchangeData
428 const labelLongList& nodesToSmooth,
429 std::map<label, DynList<parTriFace> >& m
433 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
434 const DynList<label>& neiProcs = surfaceEngine_.bpNeiProcs();
436 std::map<label, LongList<parTriFace> > shareData;
437 forAll(neiProcs, procI)
439 const label neiProc = neiProcs[procI];
441 if( neiProc == Pstream::myProcNo() )
444 shareData.insert(std::make_pair(neiProc, LongList<parTriFace>()));
447 //- create data which will be sent to other processors
448 const pointField& points = surfaceEngine_.points();
449 const labelList& globalPointLabel =
450 surfaceEngine_.globalBoundaryPointLabel();
451 const labelList& bPoints = surfaceEngine_.boundaryPoints();
452 const LongList<triFace>& triangles = this->triangles();
453 const VRWGraph& pTriangles = pointTriangles();
456 std::map<label, DynList<parTriFace> >::iterator pIter;
457 forAll(nodesToSmooth, nI)
459 const label bpI = nodesToSmooth[nI];
461 pIter = m.find(globalPointLabel[bpI]);
462 if( pIter == m.end() )
466 std::make_pair(globalPointLabel[bpI], DynList<parTriFace>())
469 pIter = m.find(globalPointLabel[bpI]);
472 forAll(pTriangles[bpI], ptI)
474 const triFace& tri = triangles[pTriangles[bpI][ptI]];
478 globalPointLabel[tri[0]],
479 globalPointLabel[tri[1]],
480 globalPointLabel[tri[2]],
481 triangle<point, point>
483 points[bPoints[tri[0]]],
484 points[bPoints[tri[1]]],
485 points[bPoints[tri[2]]]
489 pIter->second.append(ptf);
492 forAllRow(bpAtProcs, bpI, procI)
494 const label neiProc = bpAtProcs(bpI, procI);
495 if( neiProc == Pstream::myProcNo() )
498 LongList<parTriFace>& shData = shareData[neiProc];
500 const DynList<parTriFace>& localData = pIter->second;
503 shData.append(localData[i]);
507 //- send data to other processors
508 LongList<parTriFace> receivedData;
509 help::exchangeMap(shareData, receivedData);
511 forAll(receivedData, tI)
513 const label gpI = receivedData[tI].globalLabelOfPoint(0);
516 if( pIter == m.end() )
520 "void meshSurfaceOptimizer::exchangeData("
521 "const labelLongList& nodesToSmooth,"
522 "map<label, DynList<parTriFace> >& m"
524 ) << "Unknown point " << gpI << abort(FatalError);
527 pIter->second.append(receivedData[tI]);
532 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
534 } // End namespace Foam
536 // ************************************************************************* //