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 "partTetMesh.H"
30 #include "polyMeshGenModifier.H"
31 #include "VRWGraphList.H"
32 #include "polyMeshGenAddressing.H"
33 #include "helperFunctions.H"
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 partTetMesh::partTetMesh(polyMeshGen& mesh, const labelLongList& lockedPoints)
55 nodeLabelInOrigMesh_(),
58 internalPointsOrderPtr_(NULL),
59 boundaryPointsOrderPtr_(NULL),
60 globalPointLabelPtr_(NULL),
62 globalToLocalPointAddressingPtr_(NULL),
64 pAtParallelBoundariesPtr_(NULL),
65 pAtBufferLayersPtr_(NULL)
67 List<direction> useCell(mesh.cells().size(), direction(1));
69 boolList lockedPoint(mesh.points().size(), false);
70 forAll(lockedPoints, i)
71 lockedPoint[lockedPoints[i]] = true;
73 createPointsAndTets(useCell, lockedPoint);
76 partTetMesh::partTetMesh
79 const labelLongList& lockedPoints,
80 const direction nLayers
86 nodeLabelInOrigMesh_(),
89 internalPointsOrderPtr_(NULL),
90 boundaryPointsOrderPtr_(NULL),
91 globalPointLabelPtr_(NULL),
93 globalToLocalPointAddressingPtr_(NULL),
95 pAtParallelBoundariesPtr_(NULL),
96 pAtBufferLayersPtr_(NULL)
98 const faceListPMG& faces = mesh.faces();
99 const cellListPMG& cells = mesh.cells();
100 const labelList& owner = mesh.owner();
101 const PtrList<boundaryPatch>& boundaries = mesh.boundaries();
102 const VRWGraph& pointCells = mesh.addressingData().pointCells();
104 List<direction> useCell(cells.size(), direction(0));
106 //- select cells containing at least one vertex of the bad faces
107 forAll(boundaries, patchI)
109 const label start = boundaries[patchI].patchStart();
110 const label size = boundaries[patchI].patchSize();
112 for(label fI=0;fI<size;++fI)
114 useCell[owner[start+fI]] = 1;
118 //- add additional layer of cells
119 for(direction layerI=1;layerI<(nLayers+1);++layerI)
122 if( useCell[cI] == layerI )
124 const cell& c = cells[cI];
128 const face& f = faces[c[fI]];
132 forAllRow(pointCells, f[pI], pcI)
134 const label cLabel = pointCells(f[pI], pcI);
135 if( !useCell[cLabel] )
136 useCell[cLabel] = layerI + 1;
142 if( Pstream::parRun() )
144 const labelLongList& globalPointLabel =
145 mesh.addressingData().globalPointLabel();
146 const VRWGraph& pProcs = mesh.addressingData().pointAtProcs();
147 const Map<label>& globalToLocal =
148 mesh.addressingData().globalToLocalPointAddressing();
150 std::map<label, LongList<label> > eData;
151 forAllConstIter(Map<label>, globalToLocal, iter)
153 const label pointI = iter();
155 forAllRow(pProcs, pointI, procI)
157 const label neiProc = pProcs(pointI, procI);
158 if( neiProc == Pstream::myProcNo() )
161 if( eData.find(neiProc) == eData.end() )
165 std::make_pair(neiProc, LongList<label>())
169 forAllRow(pointCells, pointI, pcI)
170 if( useCell[pointCells(pointI, pcI)] == layerI )
172 eData[neiProc].append(globalPointLabel[pointI]);
178 //- exchange data with other processors
179 labelLongList receivedData;
180 help::exchangeMap(eData, receivedData);
182 forAll(receivedData, i)
184 const label pointI = globalToLocal[receivedData[i]];
186 forAllRow(pointCells, pointI, pcI)
188 const label cLabel = pointCells(pointI, pcI);
189 if( !useCell[cLabel] )
190 useCell[cLabel] = layerI + 1;
196 boolList lockedPoint(mesh.points().size(), false);
197 forAll(lockedPoints, i)
198 lockedPoint[lockedPoints[i]] = true;
200 createPointsAndTets(useCell, lockedPoint);
203 partTetMesh::partTetMesh
206 const labelLongList& lockedPoints,
207 labelHashSet& badFaces,
208 const direction additionalLayers
214 nodeLabelInOrigMesh_(),
217 internalPointsOrderPtr_(NULL),
218 boundaryPointsOrderPtr_(NULL),
219 globalPointLabelPtr_(NULL),
221 globalToLocalPointAddressingPtr_(NULL),
223 pAtParallelBoundariesPtr_(NULL),
224 pAtBufferLayersPtr_(NULL)
226 const faceListPMG& faces = mesh.faces();
227 const cellListPMG& cells = mesh.cells();
228 const VRWGraph& pointCells = mesh.addressingData().pointCells();
230 List<direction> useCell(cells.size(), direction(0));
232 //- select cells containing at least one vertex of the bad faces
234 if( badFaces.found(faceI) )
236 const face& f = faces[faceI];
240 forAllRow(pointCells, f[pI], pcI)
241 useCell[pointCells(f[pI], pcI)] = 1;
245 //- add additional layer of cells
246 for(direction layerI=1;layerI<(additionalLayers+1);++layerI)
249 if( useCell[cI] == layerI )
251 const cell& c = cells[cI];
255 const face& f = faces[c[fI]];
259 forAllRow(pointCells, f[pI], pcI)
261 const label cLabel = pointCells(f[pI], pcI);
262 if( !useCell[cLabel] )
263 useCell[cLabel] = layerI + 1;
269 if( Pstream::parRun() )
271 const labelLongList& globalPointLabel =
272 mesh.addressingData().globalPointLabel();
273 const VRWGraph& pProcs = mesh.addressingData().pointAtProcs();
274 const Map<label>& globalToLocal =
275 mesh.addressingData().globalToLocalPointAddressing();
277 std::map<label, LongList<label> > eData;
278 forAllConstIter(Map<label>, globalToLocal, iter)
280 const label pointI = iter();
282 forAllRow(pProcs, pointI, procI)
284 const label neiProc = pProcs(pointI, procI);
285 if( neiProc == Pstream::myProcNo() )
288 if( eData.find(neiProc) == eData.end() )
292 std::make_pair(neiProc, LongList<label>())
296 forAllRow(pointCells, pointI, pcI)
297 if( useCell[pointCells(pointI, pcI)] == layerI )
299 eData[neiProc].append(globalPointLabel[pointI]);
305 //- exchange data with other processors
306 labelLongList receivedData;
307 help::exchangeMap(eData, receivedData);
309 forAll(receivedData, i)
311 const label pointI = globalToLocal[receivedData[i]];
313 forAllRow(pointCells, pointI, pcI)
315 const label cLabel = pointCells(pointI, pcI);
316 if( !useCell[cLabel] )
317 useCell[cLabel] = layerI + 1;
323 boolList lockedPoint(mesh.points().size(), false);
324 forAll(lockedPoints, i)
325 lockedPoint[lockedPoints[i]] = true;
327 createPointsAndTets(useCell, lockedPoint);
330 partTetMesh::~partTetMesh()
332 deleteDemandDrivenData(internalPointsOrderPtr_);
333 deleteDemandDrivenData(boundaryPointsOrderPtr_);
334 deleteDemandDrivenData(globalPointLabelPtr_);
335 deleteDemandDrivenData(pAtProcsPtr_);
336 deleteDemandDrivenData(globalToLocalPointAddressingPtr_);
337 deleteDemandDrivenData(neiProcsPtr_);
338 deleteDemandDrivenData(pAtParallelBoundariesPtr_);
339 deleteDemandDrivenData(pAtBufferLayersPtr_);
342 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
344 const VRWGraph& partTetMesh::internalPointOrdering() const
347 if( omp_in_parallel() )
351 "const VRWGraph& partTetMesh::internalPointOrdering() const"
352 ) << "Calculating addressing inside a parallel region."
353 << " This is not thread safe" << exit(FatalError);
357 if( !internalPointsOrderPtr_ )
358 createSMOOTHPointsOrdering();
360 return *internalPointsOrderPtr_;
363 const VRWGraph& partTetMesh::boundaryPointOrdering() const
366 if( omp_in_parallel() )
370 "const VRWGraph& partTetMesh::boundaryPointOrdering() const"
371 ) << "Calculating addressing inside a parallel region."
372 << " This is not thread safe" << exit(FatalError);
376 if( !boundaryPointsOrderPtr_ )
377 createBOUNDARYPointsOrdering();
379 return *boundaryPointsOrderPtr_;
381 void partTetMesh::updateVertex(const label pointI, const point& newP)
383 points_[pointI] = newP;
385 if( smoothVertex_[pointI] & (FACECENTRE+CELLCENTRE) )
387 Warning << "Smoothing auxiliary vertex."
388 << " This has no effect on the original mesh" << endl;
392 //- find face centres attached
393 DynList<label, 64> helper;
394 forAllRow(pointTets_, pointI, ptI)
396 const label centreI = tets_[pointTets_(pointI, ptI)][2];
397 if( smoothVertex_[centreI] & FACECENTRE )
398 helper.appendIfNotIn(centreI);
401 //- update coordinates of FACECENTRE vertices
404 const label centreI = helper[i];
406 point centre(vector::zero);
407 scalar faceArea(0.0);
408 forAllRow(pointTets_, centreI, ptI)
410 const partTet& tet = tets_[pointTets_(centreI, ptI)];
411 point c(vector::zero);
412 for(label i=0;i<3;++i)
413 c += points_[tet[i]];
415 const scalar area = Foam::mag(tet.Sd(points_)) + VSMALL;
421 points_[centreI] = centre / faceArea;
424 //- find cell centres attached
426 forAllRow(pointTets_, pointI, ptI)
428 const label centreI = tets_[pointTets_(pointI, ptI)][3];
429 if( smoothVertex_[centreI] & CELLCENTRE )
430 helper.appendIfNotIn(centreI);
433 //- update coordinates of CELLCENTRE vertices
436 const label centreI = helper[i];
438 point centre(vector::zero);
440 forAllRow(pointTets_, centreI, ptI)
442 const partTet& tet = tets_[pointTets_(centreI, ptI)];
443 const point c = tet.centroid(points_);
444 const scalar vol = Foam::mag(tet.mag(points_)) + VSMALL;
450 points_[centreI] = centre / cellVol;
454 void partTetMesh::updateVerticesSMP(const List<LongList<labelledPoint> >& np)
456 List<direction> updateType(points_.size(), direction(0));
459 # pragma omp parallel num_threads(np.size())
463 const LongList<labelledPoint>& newPoints = np[omp_get_thread_num()];
465 const LongList<labelledPoint>& newPoints = np[0];
470 const labelledPoint& lp = newPoints[i];
471 const label pointI = lp.pointLabel();
473 points_[pointI] = lp.coordinates();
475 forAllRow(pointTets_, pointI, ptI)
477 const partTet& pt = tets_[pointTets_(pointI, ptI)];
479 if( smoothVertex_[pt[3]] & CELLCENTRE )
480 updateType[pt[3]] |= CELLCENTRE;
481 if( smoothVertex_[pt[2]] & FACECENTRE )
482 updateType[pt[2]] |= FACECENTRE;
489 # pragma omp flush(updateType)
491 //- update coordinates of CELLCENTRE and FACECENTRE vertices
492 # pragma omp for schedule(dynamic, 20)
494 forAll(updateType, pI)
496 if( updateType[pI] & CELLCENTRE )
498 point centre(vector::zero);
500 forAllRow(pointTets_, pI, ptI)
502 const partTet& tet = tets_[pointTets_(pI, ptI)];
503 const point c = tet.centroid(points_);
504 const scalar vol = Foam::mag(tet.mag(points_)) + VSMALL;
510 points_[pI] = centre / cellVol;
512 else if( updateType[pI] & FACECENTRE )
514 point centre(vector::zero);
515 scalar faceArea(0.0);
516 forAllRow(pointTets_, pI, ptI)
518 const partTet& tet = tets_[pointTets_(pI, ptI)];
519 point c(vector::zero);
520 for(label i=0;i<3;++i)
521 c += points_[tet[i]];
523 const scalar area = Foam::mag(tet.Sd(points_)) + VSMALL;
529 points_[pI] = centre / faceArea;
535 void partTetMesh::updateOrigMesh(boolList* changedFacePtr)
537 pointFieldPMG& pts = origMesh_.points();
539 boolList changedNode(pts.size(), false);
542 # pragma omp parallel for if( pts.size() > 1000 ) \
545 forAll(nodeLabelInOrigMesh_, pI)
546 if( nodeLabelInOrigMesh_[pI] != -1 )
548 changedNode[nodeLabelInOrigMesh_[pI]] = true;
549 pts[nodeLabelInOrigMesh_[pI]] = points_[pI];
554 boolList& chF = *changedFacePtr;
557 const cellListPMG& cells = origMesh_.cells();
558 const VRWGraph& pointCells = origMesh_.addressingData().pointCells();
561 # pragma omp parallel for if( pointCells.size() > 100 ) \
562 schedule(dynamic, 20)
564 forAll(pointCells, pointI)
566 if( changedNode[pointI] )
568 forAllRow(pointCells, pointI, pcI)
570 const cell& c = cells[pointCells(pointI, pcI)];
578 //- make sure that neighbouring processors get the same information
579 const PtrList<processorBoundaryPatch>& pBnd = origMesh_.procBoundaries();
582 const label start = pBnd[patchI].patchStart();
583 const label size = pBnd[patchI].patchSize();
585 labelLongList sendData;
586 for(label faceI=0;faceI<size;++faceI)
588 if( chF[start+faceI] )
589 sendData.append(faceI);
595 pBnd[patchI].neiProcNo(),
599 toOtherProc << sendData;
604 labelList receivedData;
606 IPstream fromOtherProc
609 pBnd[patchI].neiProcNo()
612 fromOtherProc >> receivedData;
614 const label start = pBnd[patchI].patchStart();
615 forAll(receivedData, i)
616 chF[start+receivedData[i]] = true;
619 //- update geometry information
620 const_cast<polyMeshGenAddressing&>
622 origMesh_.addressingData()
623 ).updateGeometry(chF);
627 const_cast<polyMeshGenAddressing&>
629 origMesh_.addressingData()
634 void partTetMesh::createPolyMesh(polyMeshGen& pmg) const
636 polyMeshGenModifier meshModifier(pmg);
638 pointFieldPMG& pAccess = meshModifier.pointsAccess();
639 pAccess.setSize(points_.size());
641 pAccess[pI] = points_[pI];
643 VRWGraphList cellFaces;
647 const partTet& tet = tets_[tetI];
649 FixedList<FixedList<label, 3>, 4> tetFaces;
652 tetFaces[0][0] = tet[0];
653 tetFaces[0][1] = tet[2];
654 tetFaces[0][2] = tet[1];
657 tetFaces[1][0] = tet[0];
658 tetFaces[1][1] = tet[1];
659 tetFaces[1][2] = tet[3];
662 tetFaces[2][0] = tet[0];
663 tetFaces[2][1] = tet[3];
664 tetFaces[2][2] = tet[2];
667 tetFaces[3][0] = tet[1];
668 tetFaces[3][1] = tet[2];
669 tetFaces[3][2] = tet[3];
671 cellFaces.appendGraph(tetFaces);
674 meshModifier.addCells(cellFaces);
675 meshModifier.reorderBoundaryFaces();
677 //- store points into subsets
678 const label bndPointID = pmg.addPointSubset("boundaryPoints");
679 const label smoothPointID = pmg.addPointSubset("smoothPoints");
680 const label faceCentreID = pmg.addPointSubset("faceCentres");
681 const label cellCentreID = pmg.addPointSubset("cellCentres");
683 forAll(smoothVertex_, pointI)
685 if( smoothVertex_[pointI] & SMOOTH )
686 pmg.addPointToSubset(smoothPointID, pointI);
687 if( smoothVertex_[pointI] & BOUNDARY )
688 pmg.addPointToSubset(bndPointID, pointI);
689 if( smoothVertex_[pointI] & FACECENTRE )
690 pmg.addPointToSubset(faceCentreID, pointI);
691 if( smoothVertex_[pointI] & CELLCENTRE )
692 pmg.addPointToSubset(cellCentreID, pointI);
695 const VRWGraph& internalOrdering = internalPointOrdering();
696 const VRWGraph& boundaryOrdering = boundaryPointOrdering();
698 forAll(internalOrdering, i)
700 const word name = "smoothPoints_"+help::scalarToText(i);
701 const label orderID = pmg.addPointSubset(name);
703 forAllRow(internalOrdering, i, nI)
704 pmg.addPointToSubset(orderID, internalOrdering(i, nI));
707 forAll(boundaryOrdering, i)
709 const word name = "boundaryPoints_"+help::scalarToText(i);
710 const label orderID = pmg.addPointSubset(name);
712 forAllRow(boundaryOrdering, i, nI)
713 pmg.addPointToSubset(orderID, boundaryOrdering(i, nI));
717 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
719 } // End namespace Foam
721 // ************************************************************************* //