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 "meshOctree.H"
30 #include "triSurfacePartitioner.H"
31 #include "meshSurfaceMapper.H"
32 #include "meshSurfaceEngine.H"
33 #include "meshSurfaceEngineModifier.H"
34 #include "meshSurfacePartitioner.H"
35 #include "labelledScalar.H"
37 #include "helperFunctions.H"
43 //#define DEBUGMapping
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 void meshSurfaceMapper::findMappingDistance
54 const labelLongList& nodesToMap,
55 scalarList& mappingDistance
58 const vectorField& faceCentres = surfaceEngine_.faceCentres();
59 const VRWGraph& pFaces = surfaceEngine_.pointFaces();
60 const labelList& bPoints = surfaceEngine_.boundaryPoints();
61 const pointFieldPMG& points = surfaceEngine_.points();
63 //- generate search distance for corner nodes
64 mappingDistance.setSize(nodesToMap.size());
66 # pragma omp parallel for schedule(dynamic, 50)
70 const label bpI = nodesToMap[i];
72 mappingDistance[i] = 0.0;
74 const point& p = points[bPoints[bpI]];
75 forAllRow(pFaces, bpI, pfI)
77 const scalar d = magSqr(faceCentres[pFaces(bpI, pfI)] - p);
78 mappingDistance[i] = Foam::max(mappingDistance[i], d);
82 mappingDistance[i] *= 4.0;
85 if( Pstream::parRun() )
87 //- make sure that corner nodesd at parallel boundaries
88 //- have the same range in which they accept the corners
89 const VRWGraph& bpAtProcs = surfaceEngine_.bpAtProcs();
90 const labelList& globalPointLabel =
91 surfaceEngine_.globalBoundaryPointLabel();
93 //- create the map for exchanging data
94 std::map<label, DynList<labelledScalar> > exchangeData;
95 const DynList<label>& neiProcs = surfaceEngine_.bpNeiProcs();
99 std::make_pair(neiProcs[i], DynList<labelledScalar>())
102 Map<label> globalToLocal;
104 forAll(nodesToMap, nI)
106 const label bpI = nodesToMap[nI];
108 if( bpAtProcs.sizeOfRow(bpI) != 0 )
109 globalToLocal.insert(globalPointLabel[bpI], nI);
111 forAllRow(bpAtProcs, bpI, i)
113 const label neiProc = bpAtProcs(bpI, i);
114 if( neiProc == Pstream::myProcNo() )
117 exchangeData[neiProc].append
119 labelledScalar(globalPointLabel[bpI], mappingDistance[nI])
124 //- exchange data between processors
125 LongList<labelledScalar> receivedData;
126 help::exchangeMap(exchangeData, receivedData);
128 //- select the maximum mapping distance for processor points
129 forAll(receivedData, i)
131 const labelledScalar& ls = receivedData[i];
133 const label nI = globalToLocal[ls.scalarLabel()];
135 //- choose the maximum value for the mapping distance
136 mappingDistance[nI] = Foam::max(mappingDistance[nI], ls.value());
141 scalar meshSurfaceMapper::faceMetricInPatch
147 const face& bf = surfaceEngine_.boundaryFaces()[bfI];
149 const pointFieldPMG& points = surfaceEngine_.points();
151 const point centre = bf.centre(points);
152 const vector area = bf.normal(points);
158 meshOctree_.findNearestSurfacePointInRegion
167 DynList<point> projPoints(bf.size());
170 meshOctree_.findNearestSurfacePointInRegion
180 vector projArea(vector::zero);
187 projPoints[bf.fcIndex(pI)],
192 return magSqr(centre - projCentre) + mag(mag(projArea) - mag(area));
195 void meshSurfaceMapper::mapCorners(const labelLongList& nodesToMap)
197 const triSurfacePartitioner& sPartitioner = surfacePartitioner();
198 const labelList& surfCorners = sPartitioner.corners();
199 const List<DynList<label> >& cornerPatches = sPartitioner.cornerPatches();
201 const meshSurfacePartitioner& mPart = meshPartitioner();
202 const labelHashSet& corners = mPart.corners();
203 const VRWGraph& pPatches = mPart.pointPatches();
205 const pointFieldPMG& points = surfaceEngine_.points();
206 const labelList& bPoints = surfaceEngine_.boundaryPoints();
208 const triSurf& surf = meshOctree_.surface();
209 const pointField& sPoints = surf.points();
211 //std::map<label, scalar> mappingDistance;
212 scalarList mappingDistance;
213 findMappingDistance(nodesToMap, mappingDistance);
215 //- for every corner in the mesh surface find the nearest corner in the
217 meshSurfaceEngineModifier sMod(surfaceEngine_);
220 # pragma omp parallel for schedule(dynamic, 50)
222 forAll(nodesToMap, cornerI)
224 const label bpI = nodesToMap[cornerI];
225 if( !corners.found(bpI) )
228 "meshSurfaceMapper::mapCorners(const labelLongList&)"
229 ) << "Trying to map a point that is not a corner"
230 << abort(FatalError);
232 const point& p = points[bPoints[bpI]];
233 const scalar maxDist = mappingDistance[cornerI];
235 //- find the nearest position to the given point patches
236 const DynList<label> patches = pPatches[bpI];
238 point mapPointApprox(p);
244 point newP(vector::zero);
245 forAll(patches, patchI)
249 meshOctree_.findNearestSurfacePointInRegion
261 newP /= patches.size();
263 if( magSqr(newP - mapPointApprox) < 1e-8 * maxDist )
266 mapPointApprox = newP;
268 distSqApprox = magSqr(mapPointApprox - p);
270 //- find the nearest triSurface corner for the given corner
271 scalar distSq(mappingDistance[cornerI]);
273 forAll(surfCorners, scI)
275 const label cornerID = surfCorners[scI];
276 const point& sp = sPoints[cornerID];
278 if( Foam::magSqr(sp - p) < distSq )
281 const DynList<label>& cPatches = cornerPatches[scI];
284 if( !cPatches.contains(patches[i]) )
294 distSq = Foam::magSqr(sp - p);
299 if( distSq > 1.2 * distSqApprox )
301 mapPoint = mapPointApprox;
304 //- move the point to the nearest corner
305 sMod.moveBoundaryVertexNoUpdate(bpI, mapPoint);
308 sMod.updateGeometry(nodesToMap);
311 void meshSurfaceMapper::mapEdgeNodes(const labelLongList& nodesToMap)
313 const pointFieldPMG& points = surfaceEngine_.points();
314 const labelList& bPoints = surfaceEngine_.boundaryPoints();
316 const meshSurfacePartitioner& mPart = meshPartitioner();
317 const VRWGraph& pPatches = mPart.pointPatches();
319 //const triSurf& surf = meshOctree_.surface();
320 //const pointField& sPoints = surf.points();
322 //- find mapping distance for selected vertices
323 scalarList mappingDistance;
324 findMappingDistance(nodesToMap, mappingDistance);
326 const VRWGraph* bpAtProcsPtr(NULL);
327 if( Pstream::parRun() )
328 bpAtProcsPtr = &surfaceEngine_.bpAtProcs();
330 LongList<parMapperHelper> parallelBndNodes;
332 meshSurfaceEngineModifier sMod(surfaceEngine_);
334 //- map point to the nearest vertex on the surface mesh
336 # pragma omp parallel for schedule(dynamic, 50)
338 forAll(nodesToMap, i)
340 const label bpI = nodesToMap[i];
341 const point& p = points[bPoints[bpI]];
343 //- find patches at this edge point
344 const DynList<label> patches = pPatches[bpI];
346 const scalar maxDist = mappingDistance[i];
348 //- find approximate position of the vertex on the edge
349 point mapPointApprox(p);
354 point newP(vector::zero);
356 forAll(patches, patchI)
360 meshOctree_.findNearestSurfacePointInRegion
372 newP /= patches.size();
374 if( magSqr(newP - mapPointApprox) < 1e-8 * maxDist )
377 mapPointApprox = newP;
379 distSqApprox = magSqr(mapPointApprox - p);
381 //- find the nearest vertex on the triSurface feature edge
382 point mapPoint(mapPointApprox);
383 scalar distSq(distSqApprox);
385 meshOctree_.findNearestEdgePoint(mapPoint, distSq, nse, p, patches);
387 //- use the vertex with the smallest mapping distance
388 if( distSq > 1.2 * distSqApprox )
390 mapPoint = mapPointApprox;
391 distSq = distSqApprox;
394 //- check if the mapping distance is within the given tolerances
395 if( distSq > maxDist )
397 //- this indicates possible problems
398 //- reduce the mapping distance
399 const scalar f = Foam::sqrt(maxDist / distSq);
400 distSq = mappingDistance[i];
401 mapPoint = f * (mapPoint - p) + p;
404 //- move the point to the nearest edge vertex
405 sMod.moveBoundaryVertexNoUpdate(bpI, mapPoint);
407 if( bpAtProcsPtr && bpAtProcsPtr->sizeOfRow(bpI) )
410 # pragma omp critical
413 parallelBndNodes.append
427 sMod.updateGeometry(nodesToMap);
429 mapToSmallestDistance(parallelBndNodes);
432 void meshSurfaceMapper::mapCornersAndEdges()
434 const meshSurfacePartitioner& mPart = meshPartitioner();
435 const labelHashSet& cornerPoints = mPart.corners();
436 labelLongList selectedPoints;
437 forAllConstIter(labelHashSet, cornerPoints, it)
438 selectedPoints.append(it.key());
440 mapCorners(selectedPoints);
442 selectedPoints.clear();
443 const labelHashSet& edgePoints = mPart.edgePoints();
444 forAllConstIter(labelHashSet, edgePoints, it)
445 selectedPoints.append(it.key());
447 mapEdgeNodes(selectedPoints);
450 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
452 } // End namespace Foam
454 // ************************************************************************* //