69 const cellShapeControlMesh& cellSizeMesh =
72 DynamicList<Foam::point> pts(number_of_vertices());
76 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
77 vit != finite_vertices_end();
81 if (vit->internalOrBoundaryPoint() && !vit->referred())
83 pts.append(
topoint(vit->point()));
89 boundBox cellSizeMeshBb = cellSizeMesh.bounds();
91 bool fullyContained =
true;
93 if (!cellSizeMeshBb.contains(bb))
95 Pout<<
"Triangulation not fully contained in cell size mesh."
98 Pout<<
"Cell Size Mesh Bounds = " << cellSizeMesh.bounds() <<
endl;
99 Pout<<
"foamyHexMesh Bounds = " << bb <<
endl;
101 fullyContained =
false;
104 reduce(fullyContained, andOp<unsigned int>());
106 Info<<
"Triangulation is "
107 << (fullyContained ?
"fully" :
"not fully")
108 <<
" contained in the cell size mesh"
141 decomposition_().distributePoints(transferPoints)
144 transferPoints.clear();
149 label nVert = number_of_vertices();
153 label nInserted(number_of_vertices() - nVert);
157 reduce(nInserted, sumOp<label>());
160 Info<<
" " << nInserted <<
" points inserted"
161 <<
", failed to insert " <<
nPoints - nInserted
163 << 100.0*(
nPoints - nInserted)/(nInserted + SMALL)
168 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
169 vit != finite_vertices_end();
175 vit->index() = getNewVertexIndex();
176 vit->type() = Vb::vtInternal;
191 autoPtr<mapDistribute> mapDist =
192 decomposition_().distributePoints(vertices);
206 label preReinsertionSize(number_of_vertices());
208 Map<label> oldToNewIndices =
213 label(number_of_vertices()) - preReinsertionSize,
217 Info<<
" Reinserted " << nReinserted <<
" vertices out of "
221 return oldToNewIndices;
227 const pointIndexHitAndFeatureList& surfaceHits,
228 const fileName fName,
237 const label featureIndex = surfaceHits[i].second();
239 allGeometry_[featureIndex].getNormal
247 const Foam::point& surfacePt(surfaceHit.hitPoint());
250 geometryToConformTo_.meshableSide(featureIndex, surfaceHit);
254 createBafflePointPair
256 pointPairDistance(surfacePt),
267 pointPairDistance(surfacePt),
278 pointPairDistance(surfacePt),
288 << meshableSide <<
", bad"
293 if (foamyHexMeshControls().objOutput() && fName !=
fileName::null)
302 const pointIndexHitAndFeatureList& edgeHits,
303 const fileName fName,
309 if (edgeHits[i].first().hit())
311 const extendedFeatureEdgeMesh& feMesh
313 geometryToConformTo_.features()[edgeHits[i].second()]
328 if (foamyHexMeshControls().objOutput() && fName !=
fileName::null)
337 scalar exclusionRangeSqr = featurePointExclusionDistanceSqr(pt);
342 geometryToConformTo_.findFeaturePointNearest
359 scalar exclusionRangeSqr = surfacePtExclusionDistanceSqr(pt);
364 geometryToConformTo_.findEdgeNearest
378 Info<<
nl <<
"Inserting initial points" <<
endl;
380 timeCheck(
"Before initial points call");
382 List<Point> initPts = initialPointsMethod_->initialPoints();
384 timeCheck(
"After initial points call");
388 insertInternalPoints(initPts);
390 if (initialPointsMethod_->fixInitialPoints())
394 Finite_vertices_iterator vit = finite_vertices_begin();
395 vit != finite_vertices_end();
403 if (foamyHexMeshControls().objOutput())
407 time().
path()/
"initialPoints.obj",
422 DynamicList<Foam::point>
points(number_of_vertices());
423 DynamicList<Foam::indexedVertexEnum::vertexType> types
427 DynamicList<scalar> sizes(number_of_vertices());
428 DynamicList<tensor> alignments(number_of_vertices());
432 Finite_vertices_iterator vit = finite_vertices_begin();
433 vit != finite_vertices_end();
440 types.append(vit->type());
441 sizes.append(vit->targetCellSize());
442 alignments.append(vit->alignment());
446 autoPtr<mapDistribute> mapDist =
449 mapDist().distribute(types);
450 mapDist().distribute(sizes);
451 mapDist().distribute(alignments);
456 Info<<
nl <<
" Inserting distributed tessellation" <<
endl;
460 DynamicList<Vb> verticesToInsert(
points.size());
464 verticesToInsert.append
475 verticesToInsert.last().targetCellSize() = sizes[pI];
476 verticesToInsert.last().alignment() = alignments[pI];
479 this->rangeInsertWithInfo
481 verticesToInsert.begin(),
482 verticesToInsert.end(),
486 Info<<
" Total number of vertices after redistribution "
489 label(number_of_vertices()), sumOp<label>()
497 controlMeshRefinement meshRefinement
502 smoothAlignmentSolver meshAlignmentSmoother
504 cellShapeControl_.shapeControlMesh()
507 meshRefinement.initialMeshPopulation(decomposition_);
509 cellShapeControlMesh& cellSizeMesh = cellShapeControl_.shapeControlMesh();
513 if (!distributeBackground(cellSizeMesh))
516 cellSizeMesh.distribute(decomposition_);
520 const dictionary& motionControlDict
521 = foamyHexMeshControls().foamyHexMeshDict().subDict(
"motionControl");
525 motionControlDict.lookup(
"maxRefinementIterations")
528 Info<<
"Maximum number of refinement iterations : " << nMaxIter <<
endl;
530 for (
label i = 0; i < nMaxIter; ++i)
532 label nAdded = meshRefinement.refineMesh(decomposition_);
534 reduce(nAdded, sumOp<label>());
538 cellSizeMesh.distribute(decomposition_);
541 Info<<
" Iteration " << i
542 <<
" Added = " << nAdded <<
" points"
554 if (!distributeBackground(cellSizeMesh))
556 cellSizeMesh.distribute(decomposition_);
562 motionControlDict.lookup(
"maxSmoothingIterations")
564 meshAlignmentSmoother.smoothAlignments(maxSmoothingIterations);
566 Info<<
"Background cell size and alignment mesh:" <<
endl;
567 cellSizeMesh.printInfo(
Info);
569 Info<<
"Triangulation is "
570 << (cellSizeMesh.is_valid() ?
"valid" :
"not valid!" )
573 if (foamyHexMeshControls().writeCellShapeControlMesh())
576 cellSizeMesh.
write();
579 if (foamyHexMeshControls().printVertexInfo())
581 cellSizeMesh.printVertexInfo(
Info);
596 Info<<
nl <<
"Calculating target cell alignment and size" <<
endl;
600 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
601 vit != finite_vertices_end();
605 if (vit->internalOrBoundaryPoint())
609 cellShapeControls().cellSizeAndAlignment
612 vit->targetCellSize(),
622 const Delaunay::Finite_edges_iterator& eit
625 Cell_circulator ccStart = incident_cells(*eit);
626 Cell_circulator cc1 = ccStart;
627 Cell_circulator cc2 = cc1;
633 DynamicList<label> verticesOnFace;
635 label nUniqueVertices = 0;
641 cc1->hasFarPoint() || cc2->hasFarPoint()
642 || is_infinite(cc1) || is_infinite(cc2)
645 Cell_handle
c = eit->first;
646 Vertex_handle vA =
c->vertex(eit->second);
647 Vertex_handle vB =
c->vertex(eit->third);
653 <<
"Dual face uses circumcenter defined by a "
654 <<
"Delaunay tetrahedron with no internal "
655 <<
"or boundary points. Defining Delaunay edge ends: "
662 label cc1I = cc1->cellIndex();
663 label cc2I = cc2->cellIndex();
667 if (
findIndex(verticesOnFace, cc1I) == -1)
672 verticesOnFace.append(cc1I);
679 }
while (cc1 != ccStart);
681 verticesOnFace.shrink();
683 if (verticesOnFace.size() >= 3 && nUniqueVertices < 3)
698 verticesOnFace.setSize(nUniqueVertices);
701 return face(verticesOnFace);
707 const Delaunay::Finite_edges_iterator& eit
710 Cell_circulator ccStart = incident_cells(*eit);
711 Cell_circulator cc = ccStart;
717 if (cc->hasFarPoint())
719 Cell_handle
c = eit->first;
720 Vertex_handle vA =
c->vertex(eit->second);
721 Vertex_handle vB =
c->vertex(eit->third);
724 <<
"Dual face uses circumcenter defined by a "
725 <<
"Delaunay tetrahedron with no internal "
726 <<
"or boundary points. Defining Delaunay edge ends: "
732 if (cc->filterCount() > maxFC)
734 maxFC = cc->filterCount();
739 }
while (cc != ccStart);
758 label dualCellIndexA = vA->index();
760 if (!vA->internalOrBoundaryPoint() || vA->referred())
762 if (!vA->constrained())
768 label dualCellIndexB = vB->index();
770 if (!vB->internalOrBoundaryPoint() || vB->referred())
772 if (!vB->constrained())
778 if (dualCellIndexA == -1 && dualCellIndexB == -1)
781 <<
"Attempting to create a face joining "
782 <<
"two unindexed dual cells "
785 else if (dualCellIndexA == -1 || dualCellIndexB == -1)
789 if (dualCellIndexA == -1)
791 owner = dualCellIndexB;
797 owner = dualCellIndexA;
804 if (dualCellIndexB > dualCellIndexA)
806 owner = dualCellIndexA;
807 neighbour = dualCellIndexB;
811 owner = dualCellIndexB;
812 neighbour = dualCellIndexA;
828 const dictionary& foamyHexMeshDict,
829 const fileName& decompDictFile
832 DistributedDelaunayMesh<
Delaunay>(runTime),
834 rndGen_(64293*Pstream::myProcNo()),
835 foamyHexMeshControls_(foamyHexMeshDict),
840 "cvSearchableSurfaces",
847 foamyHexMeshDict.subDict(
"geometry"),
848 foamyHexMeshDict.lookupOrDefault(
"singleRegionName", true)
855 foamyHexMeshDict.subDict(
"surfaceConformation")
860 ? new backgroundMeshDecomposition
864 geometryToConformTo_,
865 foamyHexMeshControls().foamyHexMeshDict().subDict
867 "backgroundMeshDecomposition"
876 foamyHexMeshControls_,
882 ftPtConformer_(*this),
883 edgeLocationTreePtr_(),
884 surfacePtLocationTreePtr_(),
885 surfaceConformationVertices_(),
888 initialPointsMethod::
New
890 foamyHexMeshDict.subDict(
"initialPoints"),
893 geometryToConformTo_,
902 foamyHexMeshDict.subDict(
"motionControl"),
908 faceAreaWeightModel::
New
910 foamyHexMeshDict.subDict(
"motionControl")
926 if (foamyHexMeshControls().objOutput())
928 geometryToConformTo_.writeFeatureObj(
"foamyHexMesh");
931 buildCellSizeAndAlignmentMesh();
933 insertInitialPoints();
935 insertFeaturePoints(
true);
937 setVertexSizeAndAlignment();
939 cellSizeMeshOverlapsBackground();
944 distributeBackground(*
this);
946 buildSurfaceConformation();
950 distributeBackground(*
this);
959 storeSurfaceConformation();
965 cellSizeMeshOverlapsBackground();
967 if (foamyHexMeshControls().printVertexInfo())
969 printVertexInfo(
Info);
972 if (foamyHexMeshControls().objOutput())
976 time().
path()/
"internalPoints_" + time().
timeName() +
".obj",
991 new backgroundMeshDecomposition
995 geometryToConformTo_,
996 foamyHexMeshControls().foamyHexMeshDict().subDict
998 "backgroundMeshDecomposition"
1004 insertInitialPoints();
1006 insertFeaturePoints();
1011 distributeBackground(*
this);
1013 buildSurfaceConformation();
1017 distributeBackground(*
this);
1024 cellSizeMeshOverlapsBackground();
1026 if (foamyHexMeshControls().printVertexInfo())
1028 printVertexInfo(
Info);
1035 timeCheck(
"Start of move");
1037 scalar relaxation = relaxationModel_->relaxation();
1039 Info<<
nl <<
"Relaxation = " << relaxation <<
endl;
1041 pointField dualVertices(number_of_finite_cells());
1043 this->resetCellCount();
1048 Delaunay::Finite_cells_iterator cit = finite_cells_begin();
1049 cit != finite_cells_end();
1053 cit->cellIndex() = Cb::ctUnassigned;
1055 if (cit->anyInternalOrBoundaryDualVertex())
1057 cit->cellIndex() = getNewCellIndex();
1059 dualVertices[cit->cellIndex()] = cit->dual();
1062 if (cit->hasFarPoint())
1064 cit->cellIndex() = Cb::ctFar;
1068 dualVertices.setSize(cellCount());
1070 setVertexSizeAndAlignment();
1072 timeCheck(
"Determined sizes and alignments");
1074 Info<<
nl <<
"Determining vertex displacements" <<
endl;
1078 cartesianDirections[0] =
vector(1, 0, 0);
1079 cartesianDirections[1] =
vector(0, 1, 0);
1080 cartesianDirections[2] =
vector(0, 0, 1);
1084 number_of_vertices(),
1088 PackedBoolList pointToBeRetained
1090 number_of_vertices(),
1094 DynamicList<Point> pointsToInsert(number_of_vertices());
1098 Delaunay::Finite_edges_iterator eit = finite_edges_begin();
1099 eit != finite_edges_end();
1103 Cell_handle
c = eit->first;
1104 Vertex_handle vA =
c->vertex(eit->second);
1105 Vertex_handle vB =
c->vertex(eit->third);
1110 vA->internalPoint() && !vA->referred()
1111 && vB->internalOrBoundaryPoint()
1114 vB->internalPoint() && !vB->referred()
1115 && vA->internalOrBoundaryPoint()
1122 Field<vector> alignmentDirsA
1124 vA->alignment().T() & cartesianDirections
1126 Field<vector> alignmentDirsB
1128 vB->alignment().T() & cartesianDirections
1131 Field<vector> alignmentDirs(alignmentDirsA);
1133 forAll(alignmentDirsA, aA)
1135 const vector& a = alignmentDirsA[aA];
1137 scalar maxDotProduct = 0.0;
1139 forAll(alignmentDirsB, aB)
1141 const vector&
b = alignmentDirsB[aB];
1143 const scalar dotProduct = a &
b;
1145 if (
mag(dotProduct) > maxDotProduct)
1147 maxDotProduct =
mag(dotProduct);
1149 alignmentDirs[aA] = a +
sign(dotProduct)*
b;
1151 alignmentDirs[aA] /=
mag(alignmentDirs[aA]);
1158 scalar rABMag =
mag(rAB);
1166 vA->internalPoint() && !vA->referred() && !vA->fixed()
1167 && vB->internalPoint() && !vB->referred() && !vB->fixed()
1177 pointToBeRetained[vA->index()] ==
true
1178 && pointToBeRetained[vB->index()] ==
true
1183 if (internalPointIsInside(pt))
1185 pointsToInsert.append(
toPoint(pt));
1190 if (vA->internalPoint() && !vA->referred() && !vA->fixed())
1192 pointToBeRetained[vA->index()] =
false;
1195 if (vB->internalPoint() && !vB->referred() && !vB->fixed())
1197 pointToBeRetained[vB->index()] =
false;
1205 forAll(alignmentDirs, aD)
1207 vector& alignmentDir = alignmentDirs[aD];
1209 scalar dotProd = rAB & alignmentDir;
1219 const scalar alignmentDotProd = dotProd/rABMag;
1224 > foamyHexMeshControls().cosAlignmentAcceptanceAngle()
1227 scalar targetCellSize =
1230 scalar targetFaceArea =
sqr(targetCellSize);
1232 const vector originalAlignmentDir = alignmentDir;
1235 cellShapeControls().aspectRatio().updateCellSizeAndFaceArea
1247 face dualFace = buildDualFace(eit);
1253 const scalar faceArea = dualFace.mag(dualVertices);
1256 cellShapeControls().aspectRatio().updateDeltaVector
1258 originalAlignmentDir,
1281 delta *= faceAreaWeightModel_->faceAreaWeight
1283 faceArea/targetFaceArea
1289 (vA->internalPoint() && vB->internalPoint())
1290 && (!vA->referred() || !vB->referred())
1298 > foamyHexMeshControls().insertionDistCoeff()
1301 > foamyHexMeshControls().faceAreaRatioCoeff()
1304 > foamyHexMeshControls().cosInsertionAcceptanceAngle()
1310 !geometryToConformTo_.findSurfaceAnyIntersection
1320 if (internalPointIsInside(newPt))
1326 decomposition().positionOnThisProcessor
1332 pointsToInsert.append(
toPoint(newPt));
1337 pointsToInsert.append(
toPoint(newPt));
1345 (vA->internalPoint() && !vA->referred())
1346 || (vB->internalPoint() && !vB->referred())
1349 < foamyHexMeshControls().removalDistCoeff()
1375 pointToBeRetained[vA->index()] ==
true
1376 && pointToBeRetained[vB->index()] ==
true
1381 if (internalPointIsInside(pt))
1383 pointsToInsert.append(
toPoint(pt));
1395 pointToBeRetained[vA->index()] =
false;
1405 pointToBeRetained[vB->index()] =
false;
1419 displacementAccumulator[vA->index()] += 2*
delta;
1423 displacementAccumulator[vA->index()] +=
delta;
1436 displacementAccumulator[vB->index()] -= 2*
delta;
1440 displacementAccumulator[vB->index()] -=
delta;
1449 Info<<
"Limit displacements" <<
endl;
1454 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1455 vit != finite_vertices_end();
1459 if (vit->internalPoint() && !vit->referred() && !vit->fixed())
1461 if (pointToBeRetained[vit->index()] ==
true)
1466 displacementAccumulator[vit->index()]
1472 vector totalDisp =
gSum(displacementAccumulator);
1473 scalar totalDist =
gSum(
mag(displacementAccumulator));
1475 displacementAccumulator *= relaxation;
1477 Info<<
"Sum displacements" <<
endl;
1479 label nPointsToRetain = 0;
1480 label nPointsToRemove = 0;
1484 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1485 vit != finite_vertices_end();
1489 if (vit->internalPoint() && !vit->referred() && !vit->fixed())
1491 if (pointToBeRetained[vit->index()] ==
true)
1505 + displacementAccumulator[vit->index()]
1508 if (internalPointIsInside(pt))
1510 pointsToInsert.append(
toPoint(pt));
1519 pointsToInsert.shrink();
1523 nPointsToRetain - nPointsToRemove,
1526 <<
" internal points are outside the domain. "
1527 <<
"They will not be inserted." <<
endl;
1530 if (foamyHexMeshControls().objOutput() && time().outputTime())
1532 Info<<
"Writing point displacement vectors to file." <<
endl;
1535 time().
path()/
"displacements_" + runTime_.timeName() +
".obj"
1540 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1541 vit != finite_vertices_end();
1545 if (vit->internalPoint() && !vit->referred())
1547 if (pointToBeRetained[vit->index()] ==
true)
1552 << displacementAccumulator[vit->index()][0] <<
" "
1553 << displacementAccumulator[vit->index()][1] <<
" "
1554 << displacementAccumulator[vit->index()][2] <<
" "
1564 timeCheck(
"Displacement calculated");
1566 Info<<
nl<<
"Inserting displaced tessellation" <<
endl;
1568 insertFeaturePoints(
true);
1570 insertInternalPoints(pointsToInsert,
true);
1593 timeCheck(
"Internal points inserted");
1600 Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1601 vit != finite_vertices_end();
1605 if (!vit->referred() && !usedIndices.insert(vit->index()))
1608 <<
"Index already used! Could not insert: " <<
nl
1617 if (foamyHexMeshControls().objOutput())
1621 time().
path()/
"internalPoints_" + time().
timeName() +
".obj",
1626 if (reconformToSurface())
1630 time().
path()/
"boundaryPoints_" + time().
timeName() +
".obj",
1636 time().
path()/
"internalBoundaryPoints_" + time().
timeName()
1645 time().
path()/
"externalBoundaryPoints_" + time().
timeName()
1652 OBJstream multipleIntersections
1654 "multipleIntersections_"
1661 Delaunay::Finite_edges_iterator eit = finite_edges_begin();
1662 eit != finite_edges_end();
1666 Cell_handle
c = eit->first;
1667 Vertex_handle vA =
c->vertex(eit->second);
1668 Vertex_handle vB =
c->vertex(eit->third);
1676 geometryToConformTo().findSurfaceAllIntersections
1686 surfHits.
size() >= 2
1688 surfHits.
size() == 0
1690 (vA->externalBoundaryPoint()
1691 && vB->internalBoundaryPoint())
1692 || (vB->externalBoundaryPoint()
1693 && vA->internalBoundaryPoint())
1704 timeCheck(
"After conformToSurface");
1706 if (foamyHexMeshControls().printVertexInfo())
1708 printVertexInfo(
Info);
1711 if (time().outputTime())
1717 <<
"Total displacement = " << totalDisp <<
nl
1718 <<
"Total distance = " << totalDist <<
nl
1725 typedef CGAL::Exact_predicates_exact_constructions_kernel Kexact;
1726 typedef CGAL::Point_3<Kexact> PointExact;
1730 Pout<<
"Triangulation is invalid!" <<
endl;
1733 OFstream str(
"badCells.obj");
1739 Delaunay::Finite_cells_iterator cit = finite_cells_begin();
1740 cit != finite_cells_end();
1749 <<
" quality = " << quality <<
nl
1754 FixedList<PointExact, 4> cellVerticesExact(PointExact(0,0,0));
1755 forAll(cellVerticesExact, vI)
1757 cellVerticesExact[vI] = PointExact
1759 cit->vertex(vI)->point().x(),
1760 cit->vertex(vI)->point().y(),
1761 cit->vertex(vI)->point().z()
1765 PointExact synchronisedDual = CGAL::circumcenter<Kexact>
1767 cellVerticesExact[0],
1768 cellVerticesExact[1],
1769 cellVerticesExact[2],
1770 cellVerticesExact[3]
1775 CGAL::to_double(synchronisedDual.x()),
1776 CGAL::to_double(synchronisedDual.y()),
1777 CGAL::to_double(synchronisedDual.z())
1780 Info<<
"inexact = " << cit->dual() <<
nl
1781 <<
"exact = " << exactPt <<
endl;
1785 Pout<<
"There are " << badCells <<
" bad cells out of "
1786 << number_of_finite_cells() <<
endl;
1789 label nNonGabriel = 0;
1792 Delaunay::Finite_facets_iterator fit = finite_facets_begin();
1793 fit != finite_facets_end();
1797 if (!is_Gabriel(*fit))
1803 Pout<<
"There are " << nNonGabriel <<
" non-Gabriel faces out of "
1804 << number_of_finite_facets() <<
endl;