00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "isoSurface.H"
00027 #include <finiteVolume/fvMesh.H>
00028 #include <OpenFOAM/mergePoints.H>
00029 #include <OpenFOAM/syncTools.H>
00030 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00031 #include <finiteVolume/slicedVolFields.H>
00032 #include <finiteVolume/volFields.H>
00033 #include <finiteVolume/surfaceFields.H>
00034 #include <OpenFOAM/OFstream.H>
00035 #include <meshTools/meshTools.H>
00036
00037
00038
00039 namespace Foam
00040 {
00041 defineTypeNameAndDebug(isoSurface, 0);
00042 }
00043
00044
00045
00046 bool Foam::isoSurface::noTransform(const tensor& tt) const
00047 {
00048 return
00049 (mag(tt.xx()-1) < mergeDistance_)
00050 && (mag(tt.yy()-1) < mergeDistance_)
00051 && (mag(tt.zz()-1) < mergeDistance_)
00052 && (mag(tt.xy()) < mergeDistance_)
00053 && (mag(tt.xz()) < mergeDistance_)
00054 && (mag(tt.yx()) < mergeDistance_)
00055 && (mag(tt.yz()) < mergeDistance_)
00056 && (mag(tt.zx()) < mergeDistance_)
00057 && (mag(tt.zy()) < mergeDistance_);
00058 }
00059
00060
00061 bool Foam::isoSurface::collocatedPatch(const polyPatch& pp)
00062 {
00063 const coupledPolyPatch& cpp = refCast<const coupledPolyPatch>(pp);
00064
00065 return cpp.parallel() && !cpp.separated();
00066 }
00067
00068
00069
00070 Foam::PackedBoolList Foam::isoSurface::collocatedFaces
00071 (
00072 const coupledPolyPatch& pp
00073 ) const
00074 {
00075
00076 PackedBoolList collocated(pp.size());
00077
00078 const vectorField& separation = pp.separation();
00079 const tensorField& forwardT = pp.forwardT();
00080
00081 if (forwardT.size() == 0)
00082 {
00083
00084 if (separation.size() == 0)
00085 {
00086 collocated = 1u;
00087 }
00088 else if (separation.size() == 1)
00089 {
00090
00091 }
00092 else
00093 {
00094
00095 forAll(pp, faceI)
00096 {
00097 if (mag(separation[faceI]) < mergeDistance_)
00098 {
00099 collocated[faceI] = 1u;
00100 }
00101 }
00102 }
00103 }
00104 else if (forwardT.size() == 1)
00105 {
00106
00107 }
00108 else
00109 {
00110
00111 forAll(pp, faceI)
00112 {
00113 if (noTransform(forwardT[faceI]))
00114 {
00115 collocated[faceI] = 1u;
00116 }
00117 }
00118 }
00119 return collocated;
00120 }
00121
00122
00123
00124
00125 void Foam::isoSurface::insertPointData
00126 (
00127 const processorPolyPatch& pp,
00128 const Map<label>& meshToShared,
00129 const pointField& pointValues,
00130 const label patchPointI,
00131 pointField& patchValues,
00132 pointField& sharedValues
00133 ) const
00134 {
00135 label meshPointI = pp.meshPoints()[patchPointI];
00136
00137
00138 label nbrPointI = pp.neighbPoints()[patchPointI];
00139 if (nbrPointI >= 0 && nbrPointI < patchValues.size())
00140 {
00141 minEqOp<point>()(patchValues[nbrPointI], pointValues[meshPointI]);
00142 }
00143
00144
00145 Map<label>::const_iterator iter = meshToShared.find(meshPointI);
00146 if (iter != meshToShared.end())
00147 {
00148 minEqOp<point>()(sharedValues[iter()], pointValues[meshPointI]);
00149 }
00150 }
00151
00152
00153 void Foam::isoSurface::syncUnseparatedPoints
00154 (
00155 pointField& pointValues,
00156 const point& nullValue
00157 ) const
00158 {
00159
00160
00161 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00162 const globalMeshData& pd = mesh_.globalData();
00163 const labelList& sharedPtAddr = pd.sharedPointAddr();
00164 const labelList& sharedPtLabels = pd.sharedPointLabels();
00165
00166
00167 Map<label> meshToShared(2*sharedPtLabels.size());
00168 forAll(sharedPtLabels, i)
00169 {
00170 meshToShared.insert(sharedPtLabels[i], sharedPtAddr[i]);
00171 }
00172
00173
00174 pointField sharedInfo(pd.nGlobalPoints(), nullValue);
00175
00176
00177 if (Pstream::parRun())
00178 {
00179
00180 forAll(patches, patchI)
00181 {
00182 if
00183 (
00184 isA<processorPolyPatch>(patches[patchI])
00185 && patches[patchI].nPoints() > 0
00186 )
00187 {
00188 const processorPolyPatch& pp =
00189 refCast<const processorPolyPatch>(patches[patchI]);
00190 const labelList& meshPts = pp.meshPoints();
00191
00192 pointField patchInfo(meshPts.size(), nullValue);
00193
00194 PackedBoolList isCollocated(collocatedFaces(pp));
00195
00196 forAll(isCollocated, faceI)
00197 {
00198 if (isCollocated[faceI])
00199 {
00200 const face& f = pp.localFaces()[faceI];
00201
00202 forAll(f, fp)
00203 {
00204 label pointI = f[fp];
00205
00206 insertPointData
00207 (
00208 pp,
00209 meshToShared,
00210 pointValues,
00211 pointI,
00212 patchInfo,
00213 sharedInfo
00214 );
00215 }
00216 }
00217 }
00218
00219 OPstream toNbr(Pstream::blocking, pp.neighbProcNo());
00220 toNbr << patchInfo;
00221 }
00222 }
00223
00224
00225
00226 forAll(patches, patchI)
00227 {
00228 if
00229 (
00230 isA<processorPolyPatch>(patches[patchI])
00231 && patches[patchI].nPoints() > 0
00232 )
00233 {
00234 const processorPolyPatch& pp =
00235 refCast<const processorPolyPatch>(patches[patchI]);
00236
00237 pointField nbrPatchInfo(pp.nPoints());
00238 {
00239
00240
00241 IPstream fromNbr(Pstream::blocking, pp.neighbProcNo());
00242 fromNbr >> nbrPatchInfo;
00243 }
00244
00245
00246 nbrPatchInfo.setSize(pp.nPoints(), nullValue);
00247
00248 const labelList& meshPts = pp.meshPoints();
00249
00250 forAll(meshPts, pointI)
00251 {
00252 label meshPointI = meshPts[pointI];
00253 minEqOp<point>()
00254 (
00255 pointValues[meshPointI],
00256 nbrPatchInfo[pointI]
00257 );
00258 }
00259 }
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270 Pstream::listCombineGather(sharedInfo, minEqOp<point>());
00271 Pstream::listCombineScatter(sharedInfo);
00272
00273
00274
00275 forAll(sharedPtLabels, i)
00276 {
00277 label meshPointI = sharedPtLabels[i];
00278 pointValues[meshPointI] = sharedInfo[sharedPtAddr[i]];
00279 }
00280 }
00281
00282
00283 Foam::scalar Foam::isoSurface::isoFraction
00284 (
00285 const scalar s0,
00286 const scalar s1
00287 ) const
00288 {
00289 scalar d = s1-s0;
00290
00291 if (mag(d) > VSMALL)
00292 {
00293 return (iso_-s0)/d;
00294 }
00295 else
00296 {
00297 return -1.0;
00298 }
00299 }
00300
00301
00302 bool Foam::isoSurface::isEdgeOfFaceCut
00303 (
00304 const scalarField& pVals,
00305 const face& f,
00306 const bool ownLower,
00307 const bool neiLower
00308 ) const
00309 {
00310 forAll(f, fp)
00311 {
00312 bool fpLower = (pVals[f[fp]] < iso_);
00313 if
00314 (
00315 (fpLower != ownLower)
00316 || (fpLower != neiLower)
00317 || (fpLower != (pVals[f[f.fcIndex(fp)]] < iso_))
00318 )
00319 {
00320 return true;
00321 }
00322 }
00323 return false;
00324 }
00325
00326
00327
00328 void Foam::isoSurface::getNeighbour
00329 (
00330 const labelList& boundaryRegion,
00331 const volVectorField& meshC,
00332 const volScalarField& cVals,
00333 const label cellI,
00334 const label faceI,
00335 scalar& nbrValue,
00336 point& nbrPoint
00337 ) const
00338 {
00339 const labelList& own = mesh_.faceOwner();
00340 const labelList& nei = mesh_.faceNeighbour();
00341
00342 if (mesh_.isInternalFace(faceI))
00343 {
00344 label nbr = (own[faceI] == cellI ? nei[faceI] : own[faceI]);
00345 nbrValue = cVals[nbr];
00346 nbrPoint = meshC[nbr];
00347 }
00348 else
00349 {
00350 label bFaceI = faceI-mesh_.nInternalFaces();
00351 label patchI = boundaryRegion[bFaceI];
00352 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
00353 label patchFaceI = faceI-pp.start();
00354
00355 nbrValue = cVals.boundaryField()[patchI][patchFaceI];
00356 nbrPoint = meshC.boundaryField()[patchI][patchFaceI];
00357 }
00358 }
00359
00360
00361
00362 void Foam::isoSurface::calcCutTypes
00363 (
00364 const labelList& boundaryRegion,
00365 const volVectorField& meshC,
00366 const volScalarField& cVals,
00367 const scalarField& pVals
00368 )
00369 {
00370 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00371 const labelList& own = mesh_.faceOwner();
00372 const labelList& nei = mesh_.faceNeighbour();
00373
00374 faceCutType_.setSize(mesh_.nFaces());
00375 faceCutType_ = NOTCUT;
00376
00377 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00378 {
00379
00380 bool ownLower = (cVals[own[faceI]] < iso_);
00381
00382 scalar nbrValue;
00383 point nbrPoint;
00384 getNeighbour
00385 (
00386 boundaryRegion,
00387 meshC,
00388 cVals,
00389 own[faceI],
00390 faceI,
00391 nbrValue,
00392 nbrPoint
00393 );
00394
00395 bool neiLower = (nbrValue < iso_);
00396
00397 if (ownLower != neiLower)
00398 {
00399 faceCutType_[faceI] = CUT;
00400 }
00401 else
00402 {
00403
00404
00405 const face f = mesh_.faces()[faceI];
00406
00407 if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
00408 {
00409 faceCutType_[faceI] = CUT;
00410 }
00411 }
00412 }
00413
00414 forAll(patches, patchI)
00415 {
00416 const polyPatch& pp = patches[patchI];
00417
00418 label faceI = pp.start();
00419
00420 forAll(pp, i)
00421 {
00422 bool ownLower = (cVals[own[faceI]] < iso_);
00423
00424 scalar nbrValue;
00425 point nbrPoint;
00426 getNeighbour
00427 (
00428 boundaryRegion,
00429 meshC,
00430 cVals,
00431 own[faceI],
00432 faceI,
00433 nbrValue,
00434 nbrPoint
00435 );
00436
00437 bool neiLower = (nbrValue < iso_);
00438
00439 if (ownLower != neiLower)
00440 {
00441 faceCutType_[faceI] = CUT;
00442 }
00443 else
00444 {
00445
00446 const face f = mesh_.faces()[faceI];
00447
00448 if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
00449 {
00450 faceCutType_[faceI] = CUT;
00451 }
00452 }
00453
00454 faceI++;
00455 }
00456 }
00457
00458
00459
00460 nCutCells_ = 0;
00461 cellCutType_.setSize(mesh_.nCells());
00462 cellCutType_ = NOTCUT;
00463
00464 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00465 {
00466 if (faceCutType_[faceI] != NOTCUT)
00467 {
00468 if (cellCutType_[own[faceI]] == NOTCUT)
00469 {
00470 cellCutType_[own[faceI]] = CUT;
00471 nCutCells_++;
00472 }
00473 if (cellCutType_[nei[faceI]] == NOTCUT)
00474 {
00475 cellCutType_[nei[faceI]] = CUT;
00476 nCutCells_++;
00477 }
00478 }
00479 }
00480 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
00481 {
00482 if (faceCutType_[faceI] != NOTCUT)
00483 {
00484 if (cellCutType_[own[faceI]] == NOTCUT)
00485 {
00486 cellCutType_[own[faceI]] = CUT;
00487 nCutCells_++;
00488 }
00489 }
00490 }
00491
00492 if (debug)
00493 {
00494 Pout<< "isoSurface : detected " << nCutCells_
00495 << " candidate cut cells (out of " << mesh_.nCells()
00496 << ")." << endl;
00497 }
00498 }
00499
00500
00501
00502 Foam::labelPair Foam::isoSurface::findCommonPoints
00503 (
00504 const labelledTri& tri0,
00505 const labelledTri& tri1
00506 )
00507 {
00508 labelPair common(-1, -1);
00509
00510 label fp0 = 0;
00511 label fp1 = findIndex(tri1, tri0[fp0]);
00512
00513 if (fp1 == -1)
00514 {
00515 fp0 = 1;
00516 fp1 = findIndex(tri1, tri0[fp0]);
00517 }
00518
00519 if (fp1 != -1)
00520 {
00521
00522
00523
00524 label fp0p1 = tri0.fcIndex(fp0);
00525 label fp1p1 = tri1.fcIndex(fp1);
00526 label fp1m1 = tri1.rcIndex(fp1);
00527
00528 if (tri0[fp0p1] == tri1[fp1p1] || tri0[fp0p1] == tri1[fp1m1])
00529 {
00530 common[0] = tri0[fp0];
00531 common[1] = tri0[fp0p1];
00532 }
00533 }
00534 return common;
00535 }
00536
00537
00538
00539 Foam::point Foam::isoSurface::calcCentre(const triSurface& s)
00540 {
00541 vector sum = vector::zero;
00542
00543 forAll(s, i)
00544 {
00545 sum += s[i].centre(s.points());
00546 }
00547 return sum/s.size();
00548 }
00549
00550
00551
00552
00553 Foam::pointIndexHit Foam::isoSurface::collapseSurface
00554 (
00555 pointField& localPoints,
00556 DynamicList<labelledTri, 64>& localTris
00557 )
00558 {
00559 pointIndexHit info(false, vector::zero, localTris.size());
00560
00561 if (localTris.size() == 1)
00562 {
00563 const labelledTri& tri = localTris[0];
00564 info.setPoint(tri.centre(localPoints));
00565 info.setHit();
00566 }
00567 else if (localTris.size() == 2)
00568 {
00569
00570 const labelledTri& tri0 = localTris[0];
00571 const labelledTri& tri1 = localTris[0];
00572
00573 labelPair shared = findCommonPoints(tri0, tri1);
00574
00575 if (shared[0] != -1)
00576 {
00577 info.setPoint
00578 (
00579 0.5
00580 * (
00581 tri0.centre(localPoints)
00582 + tri1.centre(localPoints)
00583 )
00584 );
00585 info.setHit();
00586 }
00587 }
00588 else if (localTris.size())
00589 {
00590
00591 triSurface surf
00592 (
00593 localTris,
00594 geometricSurfacePatchList(0),
00595 localPoints,
00596 true
00597 );
00598 localTris.clearStorage();
00599
00600 labelList faceZone;
00601 label nZones = surf.markZones
00602 (
00603 boolList(surf.nEdges(), false),
00604 faceZone
00605 );
00606
00607 if (nZones == 1)
00608 {
00609 info.setPoint(calcCentre(surf));
00610 info.setHit();
00611 }
00612 }
00613
00614 return info;
00615 }
00616
00617
00618
00619
00620 void Foam::isoSurface::calcSnappedCc
00621 (
00622 const labelList& boundaryRegion,
00623 const volVectorField& meshC,
00624 const volScalarField& cVals,
00625 const scalarField& pVals,
00626
00627 DynamicList<point>& snappedPoints,
00628 labelList& snappedCc
00629 ) const
00630 {
00631 const pointField& pts = mesh_.points();
00632 const pointField& cc = mesh_.cellCentres();
00633
00634 snappedCc.setSize(mesh_.nCells());
00635 snappedCc = -1;
00636
00637
00638 DynamicList<point, 64> localTriPoints(64);
00639
00640 forAll(mesh_.cells(), cellI)
00641 {
00642 if (cellCutType_[cellI] == CUT)
00643 {
00644 scalar cVal = cVals[cellI];
00645
00646 const cell& cFaces = mesh_.cells()[cellI];
00647
00648 localTriPoints.clear();
00649 label nOther = 0;
00650 point otherPointSum = vector::zero;
00651
00652
00653
00654
00655 forAll(cFaces, cFaceI)
00656 {
00657 label faceI = cFaces[cFaceI];
00658
00659 scalar nbrValue;
00660 point nbrPoint;
00661 getNeighbour
00662 (
00663 boundaryRegion,
00664 meshC,
00665 cVals,
00666 cellI,
00667 faceI,
00668 nbrValue,
00669 nbrPoint
00670 );
00671
00672
00673 FixedList<scalar, 3> s;
00674 FixedList<point, 3> pt;
00675
00676
00677 s[2] = isoFraction(cVal, nbrValue);
00678 pt[2] = (1.0-s[2])*cc[cellI] + s[2]*nbrPoint;
00679
00680 const face& f = mesh_.faces()[cFaces[cFaceI]];
00681
00682 forAll(f, fp)
00683 {
00684
00685 label p0 = f[fp];
00686 s[0] = isoFraction(cVal, pVals[p0]);
00687 pt[0] = (1.0-s[0])*cc[cellI] + s[0]*pts[p0];
00688
00689
00690 label p1 = f[f.fcIndex(fp)];
00691 s[1] = isoFraction(cVal, pVals[p1]);
00692 pt[1] = (1.0-s[1])*cc[cellI] + s[1]*pts[p1];
00693
00694 if
00695 (
00696 (s[0] >= 0.0 && s[0] <= 0.5)
00697 && (s[1] >= 0.0 && s[1] <= 0.5)
00698 && (s[2] >= 0.0 && s[2] <= 0.5)
00699 )
00700 {
00701 localTriPoints.append(pt[0]);
00702 localTriPoints.append(pt[1]);
00703 localTriPoints.append(pt[2]);
00704 }
00705 else
00706 {
00707
00708 forAll(s, i)
00709 {
00710 if (s[i] >= 0.0 && s[i] <= 0.5)
00711 {
00712 otherPointSum += pt[i];
00713 nOther++;
00714 }
00715 }
00716 }
00717 }
00718 }
00719
00720 if (localTriPoints.size() == 0)
00721 {
00722
00723
00724 if (nOther > 0)
00725 {
00726 snappedCc[cellI] = snappedPoints.size();
00727 snappedPoints.append(otherPointSum/nOther);
00728
00729
00730
00731
00732 }
00733 }
00734 else if (localTriPoints.size() == 3)
00735 {
00736
00737 pointField points;
00738 points.transfer(localTriPoints);
00739 snappedCc[cellI] = snappedPoints.size();
00740 snappedPoints.append(sum(points)/points.size());
00741
00742
00743
00744
00745 }
00746 else
00747 {
00748
00749
00750
00751 labelList triMap;
00752 labelList triPointReverseMap;
00753 triSurface surf
00754 (
00755 stitchTriPoints
00756 (
00757 false,
00758 localTriPoints,
00759 triPointReverseMap,
00760 triMap
00761 )
00762 );
00763
00764 labelList faceZone;
00765 label nZones = surf.markZones
00766 (
00767 boolList(surf.nEdges(), false),
00768 faceZone
00769 );
00770
00771 if (nZones == 1)
00772 {
00773 snappedCc[cellI] = snappedPoints.size();
00774 snappedPoints.append(calcCentre(surf));
00775
00776
00777
00778 }
00779 }
00780 }
00781 }
00782 }
00783
00784
00785
00786
00787 void Foam::isoSurface::calcSnappedPoint
00788 (
00789 const PackedBoolList& isBoundaryPoint,
00790 const labelList& boundaryRegion,
00791 const volVectorField& meshC,
00792 const volScalarField& cVals,
00793 const scalarField& pVals,
00794
00795 DynamicList<point>& snappedPoints,
00796 labelList& snappedPoint
00797 ) const
00798 {
00799 const pointField& pts = mesh_.points();
00800 const pointField& cc = mesh_.cellCentres();
00801
00802
00803 const point greatPoint(VGREAT, VGREAT, VGREAT);
00804 pointField collapsedPoint(mesh_.nPoints(), greatPoint);
00805
00806
00807
00808 DynamicList<point, 64> localTriPoints(100);
00809
00810 forAll(mesh_.pointFaces(), pointI)
00811 {
00812 if (isBoundaryPoint.get(pointI) == 1)
00813 {
00814 continue;
00815 }
00816
00817 const labelList& pFaces = mesh_.pointFaces()[pointI];
00818
00819 bool anyCut = false;
00820
00821 forAll(pFaces, i)
00822 {
00823 label faceI = pFaces[i];
00824
00825 if (faceCutType_[faceI] == CUT)
00826 {
00827 anyCut = true;
00828 break;
00829 }
00830 }
00831
00832 if (!anyCut)
00833 {
00834 continue;
00835 }
00836
00837
00838 localTriPoints.clear();
00839 label nOther = 0;
00840 point otherPointSum = vector::zero;
00841
00842 forAll(pFaces, pFaceI)
00843 {
00844
00845
00846
00847 label faceI = pFaces[pFaceI];
00848 const face& f = mesh_.faces()[faceI];
00849 label own = mesh_.faceOwner()[faceI];
00850
00851
00852 scalar nbrValue;
00853 point nbrPoint;
00854 getNeighbour
00855 (
00856 boundaryRegion,
00857 meshC,
00858 cVals,
00859 own,
00860 faceI,
00861 nbrValue,
00862 nbrPoint
00863 );
00864
00865
00866 FixedList<scalar, 4> s;
00867 FixedList<point, 4> pt;
00868
00869 label fp = findIndex(f, pointI);
00870 s[0] = isoFraction(pVals[pointI], cVals[own]);
00871 pt[0] = (1.0-s[0])*pts[pointI] + s[0]*cc[own];
00872
00873 s[1] = isoFraction(pVals[pointI], nbrValue);
00874 pt[1] = (1.0-s[1])*pts[pointI] + s[1]*nbrPoint;
00875
00876 label nextPointI = f[f.fcIndex(fp)];
00877 s[2] = isoFraction(pVals[pointI], pVals[nextPointI]);
00878 pt[2] = (1.0-s[2])*pts[pointI] + s[2]*pts[nextPointI];
00879
00880 label prevPointI = f[f.rcIndex(fp)];
00881 s[3] = isoFraction(pVals[pointI], pVals[prevPointI]);
00882 pt[3] = (1.0-s[3])*pts[pointI] + s[3]*pts[prevPointI];
00883
00884 if
00885 (
00886 (s[0] >= 0.0 && s[0] <= 0.5)
00887 && (s[1] >= 0.0 && s[1] <= 0.5)
00888 && (s[2] >= 0.0 && s[2] <= 0.5)
00889 )
00890 {
00891 localTriPoints.append(pt[0]);
00892 localTriPoints.append(pt[1]);
00893 localTriPoints.append(pt[2]);
00894 }
00895 if
00896 (
00897 (s[0] >= 0.0 && s[0] <= 0.5)
00898 && (s[1] >= 0.0 && s[1] <= 0.5)
00899 && (s[3] >= 0.0 && s[3] <= 0.5)
00900 )
00901 {
00902 localTriPoints.append(pt[3]);
00903 localTriPoints.append(pt[0]);
00904 localTriPoints.append(pt[1]);
00905 }
00906
00907
00908 forAll(s, i)
00909 {
00910 if (s[i] >= 0.0 && s[i] <= 0.5)
00911 {
00912 otherPointSum += pt[i];
00913 nOther++;
00914 }
00915 }
00916 }
00917
00918 if (localTriPoints.size() == 0)
00919 {
00920
00921
00922 if (nOther > 0)
00923 {
00924 collapsedPoint[pointI] = otherPointSum/nOther;
00925 }
00926 }
00927 else if (localTriPoints.size() == 3)
00928 {
00929
00930 pointField points;
00931 points.transfer(localTriPoints);
00932 collapsedPoint[pointI] = sum(points)/points.size();
00933 }
00934 else
00935 {
00936
00937
00938
00939 labelList triMap;
00940 labelList triPointReverseMap;
00941 triSurface surf
00942 (
00943 stitchTriPoints
00944 (
00945 false,
00946 localTriPoints,
00947 triPointReverseMap,
00948 triMap
00949 )
00950 );
00951
00952 labelList faceZone;
00953 label nZones = surf.markZones
00954 (
00955 boolList(surf.nEdges(), false),
00956 faceZone
00957 );
00958
00959 if (nZones == 1)
00960 {
00961 collapsedPoint[pointI] = calcCentre(surf);
00962 }
00963 }
00964 }
00965
00966
00967
00968 syncUnseparatedPoints(collapsedPoint, greatPoint);
00969
00970
00971 snappedPoint.setSize(mesh_.nPoints());
00972 snappedPoint = -1;
00973
00974 forAll(collapsedPoint, pointI)
00975 {
00976 if (collapsedPoint[pointI] != greatPoint)
00977 {
00978 snappedPoint[pointI] = snappedPoints.size();
00979 snappedPoints.append(collapsedPoint[pointI]);
00980 }
00981 }
00982 }
00983
00984
00985 Foam::triSurface Foam::isoSurface::stitchTriPoints
00986 (
00987 const bool checkDuplicates,
00988 const List<point>& triPoints,
00989 labelList& triPointReverseMap,
00990 labelList& triMap
00991 ) const
00992 {
00993 label nTris = triPoints.size()/3;
00994
00995 if ((triPoints.size() % 3) != 0)
00996 {
00997 FatalErrorIn("isoSurface::stitchTriPoints(..)")
00998 << "Problem: number of points " << triPoints.size()
00999 << " not a multiple of 3." << abort(FatalError);
01000 }
01001
01002 pointField newPoints;
01003 mergePoints
01004 (
01005 triPoints,
01006 mergeDistance_,
01007 false,
01008 triPointReverseMap,
01009 newPoints
01010 );
01011
01012
01013 if (debug)
01014 {
01015 pointField newNewPoints;
01016 labelList oldToNew;
01017 bool hasMerged = mergePoints
01018 (
01019 newPoints,
01020 mergeDistance_,
01021 true,
01022 oldToNew,
01023 newNewPoints
01024 );
01025
01026 if (hasMerged)
01027 {
01028 FatalErrorIn("isoSurface::stitchTriPoints(..)")
01029 << "Merged points contain duplicates"
01030 << " when merging with distance " << mergeDistance_ << endl
01031 << "merged:" << newPoints.size() << " re-merged:"
01032 << newNewPoints.size()
01033 << abort(FatalError);
01034 }
01035 }
01036
01037
01038 List<labelledTri> tris;
01039 {
01040 DynamicList<labelledTri> dynTris(nTris);
01041 label rawPointI = 0;
01042 DynamicList<label> newToOldTri(nTris);
01043
01044 for (label oldTriI = 0; oldTriI < nTris; oldTriI++)
01045 {
01046 labelledTri tri
01047 (
01048 triPointReverseMap[rawPointI],
01049 triPointReverseMap[rawPointI+1],
01050 triPointReverseMap[rawPointI+2],
01051 0
01052 );
01053 rawPointI += 3;
01054
01055 if ((tri[0] != tri[1]) && (tri[0] != tri[2]) && (tri[1] != tri[2]))
01056 {
01057 newToOldTri.append(oldTriI);
01058 dynTris.append(tri);
01059 }
01060 }
01061
01062 triMap.transfer(newToOldTri);
01063 tris.transfer(dynTris);
01064 }
01065
01066
01067
01068
01069
01070
01071
01072 if (checkDuplicates)
01073 {
01074 labelListList pointFaces;
01075 invertManyToMany(newPoints.size(), tris, pointFaces);
01076
01077
01078 DynamicList<label> newToOldTri(tris.size());
01079
01080 forAll(tris, triI)
01081 {
01082 const labelledTri& tri = tris[triI];
01083 const labelList& pFaces = pointFaces[tri[0]];
01084
01085
01086
01087
01088 label dupTriI = -1;
01089 forAll(pFaces, i)
01090 {
01091 label nbrTriI = pFaces[i];
01092
01093 if (nbrTriI > triI && (tris[nbrTriI] == tri))
01094 {
01095
01096
01097
01098 dupTriI = nbrTriI;
01099 break;
01100 }
01101 }
01102
01103 if (dupTriI == -1)
01104 {
01105
01106 label newTriI = newToOldTri.size();
01107 newToOldTri.append(triI);
01108 tris[newTriI] = tris[triI];
01109 }
01110 }
01111
01112 triMap.transfer(newToOldTri);
01113 tris.setSize(triMap.size());
01114
01115 if (debug)
01116 {
01117 Pout<< "isoSurface : merged from " << nTris
01118 << " down to " << tris.size() << " unique triangles." << endl;
01119 }
01120
01121
01122 if (debug)
01123 {
01124 triSurface surf(tris, geometricSurfacePatchList(0), newPoints);
01125
01126 forAll(surf, faceI)
01127 {
01128 const labelledTri& f = surf[faceI];
01129 const labelList& fFaces = surf.faceFaces()[faceI];
01130
01131 forAll(fFaces, i)
01132 {
01133 label nbrFaceI = fFaces[i];
01134
01135 if (nbrFaceI <= faceI)
01136 {
01137
01138 continue;
01139 }
01140
01141 const labelledTri& nbrF = surf[nbrFaceI];
01142
01143 if (f == nbrF)
01144 {
01145 FatalErrorIn("validTri(const triSurface&, const label)")
01146 << "Check : "
01147 << " triangle " << faceI << " vertices " << f
01148 << " fc:" << f.centre(surf.points())
01149 << " has the same vertices as triangle " << nbrFaceI
01150 << " vertices " << nbrF
01151 << " fc:" << nbrF.centre(surf.points())
01152 << abort(FatalError);
01153 }
01154 }
01155 }
01156 }
01157 }
01158
01159 return triSurface(tris, geometricSurfacePatchList(0), newPoints, true);
01160 }
01161
01162
01163
01164 bool Foam::isoSurface::validTri(const triSurface& surf, const label faceI)
01165 {
01166
01167
01168 const labelledTri& f = surf[faceI];
01169
01170 if
01171 (
01172 (f[0] < 0) || (f[0] >= surf.points().size())
01173 || (f[1] < 0) || (f[1] >= surf.points().size())
01174 || (f[2] < 0) || (f[2] >= surf.points().size())
01175 )
01176 {
01177 WarningIn("validTri(const triSurface&, const label)")
01178 << "triangle " << faceI << " vertices " << f
01179 << " uses point indices outside point range 0.."
01180 << surf.points().size()-1 << endl;
01181
01182 return false;
01183 }
01184
01185 if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
01186 {
01187 WarningIn("validTri(const triSurface&, const label)")
01188 << "triangle " << faceI
01189 << " uses non-unique vertices " << f
01190 << endl;
01191 return false;
01192 }
01193
01194
01195
01196 const labelList& fFaces = surf.faceFaces()[faceI];
01197
01198
01199
01200 forAll(fFaces, i)
01201 {
01202 label nbrFaceI = fFaces[i];
01203
01204 if (nbrFaceI <= faceI)
01205 {
01206
01207 continue;
01208 }
01209
01210 const labelledTri& nbrF = surf[nbrFaceI];
01211
01212 if
01213 (
01214 ((f[0] == nbrF[0]) || (f[0] == nbrF[1]) || (f[0] == nbrF[2]))
01215 && ((f[1] == nbrF[0]) || (f[1] == nbrF[1]) || (f[1] == nbrF[2]))
01216 && ((f[2] == nbrF[0]) || (f[2] == nbrF[1]) || (f[2] == nbrF[2]))
01217 )
01218 {
01219 WarningIn("validTri(const triSurface&, const label)")
01220 << "triangle " << faceI << " vertices " << f
01221 << " fc:" << f.centre(surf.points())
01222 << " has the same vertices as triangle " << nbrFaceI
01223 << " vertices " << nbrF
01224 << " fc:" << nbrF.centre(surf.points())
01225 << endl;
01226
01227 return false;
01228 }
01229 }
01230 return true;
01231 }
01232
01233
01234 void Foam::isoSurface::calcAddressing
01235 (
01236 const triSurface& surf,
01237 List<FixedList<label, 3> >& faceEdges,
01238 labelList& edgeFace0,
01239 labelList& edgeFace1,
01240 Map<labelList>& edgeFacesRest
01241 ) const
01242 {
01243 const pointField& points = surf.points();
01244
01245 pointField edgeCentres(3*surf.size());
01246 label edgeI = 0;
01247 forAll(surf, triI)
01248 {
01249 const labelledTri& tri = surf[triI];
01250 edgeCentres[edgeI++] = 0.5*(points[tri[0]]+points[tri[1]]);
01251 edgeCentres[edgeI++] = 0.5*(points[tri[1]]+points[tri[2]]);
01252 edgeCentres[edgeI++] = 0.5*(points[tri[2]]+points[tri[0]]);
01253 }
01254
01255 pointField mergedCentres;
01256 labelList oldToMerged;
01257 bool hasMerged = mergePoints
01258 (
01259 edgeCentres,
01260 mergeDistance_,
01261 false,
01262 oldToMerged,
01263 mergedCentres
01264 );
01265
01266 if (debug)
01267 {
01268 Pout<< "isoSurface : detected "
01269 << mergedCentres.size()
01270 << " geometric edges on " << surf.size() << " triangles." << endl;
01271 }
01272
01273 if (!hasMerged)
01274 {
01275 if (surf.size() == 1)
01276 {
01277 faceEdges.setSize(1);
01278 faceEdges[0][0] = 0;
01279 faceEdges[0][1] = 1;
01280 faceEdges[0][2] = 2;
01281 edgeFace0.setSize(1);
01282 edgeFace0[0] = 0;
01283 edgeFace1.setSize(1);
01284 edgeFace1[0] = -1;
01285 edgeFacesRest.clear();
01286 }
01287 return;
01288 }
01289
01290
01291
01292 faceEdges.setSize(surf.size());
01293 edgeI = 0;
01294 forAll(surf, triI)
01295 {
01296 faceEdges[triI][0] = oldToMerged[edgeI++];
01297 faceEdges[triI][1] = oldToMerged[edgeI++];
01298 faceEdges[triI][2] = oldToMerged[edgeI++];
01299 }
01300
01301
01302
01303 edgeFace0.setSize(mergedCentres.size());
01304 edgeFace0 = -1;
01305 edgeFace1.setSize(mergedCentres.size());
01306 edgeFace1 = -1;
01307 edgeFacesRest.clear();
01308
01309
01310
01311 EdgeMap<labelList> extraEdgeFaces(mergedCentres.size()/100);
01312
01313 forAll(oldToMerged, oldEdgeI)
01314 {
01315 label triI = oldEdgeI / 3;
01316 label edgeI = oldToMerged[oldEdgeI];
01317
01318 if (edgeFace0[edgeI] == -1)
01319 {
01320
01321 edgeFace0[edgeI] = triI;
01322 }
01323 else
01324 {
01325
01326
01327 const labelledTri& prevTri = surf[edgeFace0[edgeI]];
01328 const labelledTri& tri = surf[triI];
01329
01330 label fp = oldEdgeI % 3;
01331
01332 edge e(tri[fp], tri[tri.fcIndex(fp)]);
01333
01334 label prevTriIndex = -1;
01335
01336 forAll(prevTri, i)
01337 {
01338 if (edge(prevTri[i], prevTri[prevTri.fcIndex(i)]) == e)
01339 {
01340 prevTriIndex = i;
01341 break;
01342 }
01343 }
01344
01345 if (prevTriIndex == -1)
01346 {
01347
01348 EdgeMap<labelList>::iterator iter = extraEdgeFaces.find(e);
01349
01350 if (iter != extraEdgeFaces.end())
01351 {
01352 labelList& eFaces = iter();
01353 label sz = eFaces.size();
01354 eFaces.setSize(sz+1);
01355 eFaces[sz] = triI;
01356 }
01357 else
01358 {
01359 extraEdgeFaces.insert(e, labelList(1, triI));
01360 }
01361 }
01362 else if (edgeFace1[edgeI] == -1)
01363 {
01364 edgeFace1[edgeI] = triI;
01365 }
01366 else
01367 {
01368
01369
01370
01371
01372
01373
01374 Map<labelList>::iterator iter = edgeFacesRest.find(edgeI);
01375
01376 if (iter != edgeFacesRest.end())
01377 {
01378 labelList& eFaces = iter();
01379 label sz = eFaces.size();
01380 eFaces.setSize(sz+1);
01381 eFaces[sz] = triI;
01382 }
01383 else
01384 {
01385 edgeFacesRest.insert(edgeI, labelList(1, triI));
01386 }
01387 }
01388 }
01389 }
01390
01391
01392 edgeI = edgeFace0.size();
01393
01394 edgeFace0.setSize(edgeI + extraEdgeFaces.size());
01395 edgeFace1.setSize(edgeI + extraEdgeFaces.size(), -1);
01396
01397 forAllConstIter(EdgeMap<labelList>, extraEdgeFaces, iter)
01398 {
01399 const labelList& eFaces = iter();
01400
01401
01402
01403 forAll(eFaces, i)
01404 {
01405 label triI = eFaces[i];
01406 const labelledTri& tri = surf[triI];
01407
01408 FixedList<label, 3>& fEdges = faceEdges[triI];
01409 forAll(tri, fp)
01410 {
01411 edge e(tri[fp], tri[tri.fcIndex(fp)]);
01412
01413 if (e == iter.key())
01414 {
01415 fEdges[fp] = edgeI;
01416 break;
01417 }
01418 }
01419 }
01420
01421
01422
01423
01424 edgeFace0[edgeI] = eFaces[0];
01425
01426 if (eFaces.size() >= 2)
01427 {
01428 edgeFace1[edgeI] = eFaces[1];
01429
01430 if (eFaces.size() > 2)
01431 {
01432 edgeFacesRest.insert
01433 (
01434 edgeI,
01435 SubList<label>(eFaces, eFaces.size()-2, 2)
01436 );
01437 }
01438 }
01439
01440 edgeI++;
01441 }
01442 }
01443
01444
01445 void Foam::isoSurface::walkOrientation
01446 (
01447 const triSurface& surf,
01448 const List<FixedList<label, 3> >& faceEdges,
01449 const labelList& edgeFace0,
01450 const labelList& edgeFace1,
01451 const label seedTriI,
01452 labelList& flipState
01453 )
01454 {
01455
01456 DynamicList<label> changedFaces(surf.size());
01457
01458 changedFaces.append(seedTriI);
01459
01460 while (changedFaces.size())
01461 {
01462 DynamicList<label> newChangedFaces(changedFaces.size());
01463
01464 forAll(changedFaces, i)
01465 {
01466 label triI = changedFaces[i];
01467 const labelledTri& tri = surf[triI];
01468 const FixedList<label, 3>& fEdges = faceEdges[triI];
01469
01470 forAll(fEdges, fp)
01471 {
01472 label edgeI = fEdges[fp];
01473
01474
01475 label p0 = tri[fp];
01476 label p1 = tri[tri.fcIndex(fp)];
01477
01478 label nbrI =
01479 (
01480 edgeFace0[edgeI] != triI
01481 ? edgeFace0[edgeI]
01482 : edgeFace1[edgeI]
01483 );
01484
01485 if (nbrI != -1 && flipState[nbrI] == -1)
01486 {
01487 const labelledTri& nbrTri = surf[nbrI];
01488
01489
01490 label nbrFp = findIndex(nbrTri, p0);
01491
01492 if (nbrFp == -1)
01493 {
01494 FatalErrorIn("isoSurface::walkOrientation(..)")
01495 << "triI:" << triI
01496 << " tri:" << tri
01497 << " p0:" << p0
01498 << " p1:" << p1
01499 << " fEdges:" << fEdges
01500 << " edgeI:" << edgeI
01501 << " edgeFace0:" << edgeFace0[edgeI]
01502 << " edgeFace1:" << edgeFace1[edgeI]
01503 << " nbrI:" << nbrI
01504 << " nbrTri:" << nbrTri
01505 << abort(FatalError);
01506 }
01507
01508
01509 label nbrP1 = nbrTri[nbrTri.rcIndex(nbrFp)];
01510
01511 bool sameOrientation = (p1 == nbrP1);
01512
01513 if (flipState[triI] == 0)
01514 {
01515 flipState[nbrI] = (sameOrientation ? 0 : 1);
01516 }
01517 else
01518 {
01519 flipState[nbrI] = (sameOrientation ? 1 : 0);
01520 }
01521 newChangedFaces.append(nbrI);
01522 }
01523 }
01524 }
01525
01526 changedFaces.transfer(newChangedFaces);
01527 }
01528 }
01529
01530
01531 void Foam::isoSurface::orientSurface
01532 (
01533 triSurface& surf,
01534 const List<FixedList<label, 3> >& faceEdges,
01535 const labelList& edgeFace0,
01536 const labelList& edgeFace1,
01537 const Map<labelList>& edgeFacesRest
01538 )
01539 {
01540
01541
01542
01543 labelList flipState(surf.size(), -1);
01544
01545 label seedTriI = 0;
01546
01547 while (true)
01548 {
01549
01550 for
01551 (
01552 ;
01553 seedTriI < surf.size() && flipState[seedTriI] != -1;
01554 seedTriI++
01555 )
01556 {}
01557
01558 if (seedTriI == surf.size())
01559 {
01560 break;
01561 }
01562
01563
01564
01565 flipState[seedTriI] = 0;
01566
01567 walkOrientation
01568 (
01569 surf,
01570 faceEdges,
01571 edgeFace0,
01572 edgeFace1,
01573 seedTriI,
01574 flipState
01575 );
01576 }
01577
01578
01579 surf.clearOut();
01580 forAll(surf, triI)
01581 {
01582 if (flipState[triI] == 1)
01583 {
01584 labelledTri tri(surf[triI]);
01585
01586 surf[triI][0] = tri[0];
01587 surf[triI][1] = tri[2];
01588 surf[triI][2] = tri[1];
01589 }
01590 else if (flipState[triI] == -1)
01591 {
01592 FatalErrorIn
01593 (
01594 "isoSurface::orientSurface(triSurface&, const label)"
01595 ) << "problem" << abort(FatalError);
01596 }
01597 }
01598 }
01599
01600
01601
01602 bool Foam::isoSurface::danglingTriangle
01603 (
01604 const FixedList<label, 3>& fEdges,
01605 const labelList& edgeFace1
01606 )
01607 {
01608 label nOpen = 0;
01609 forAll(fEdges, i)
01610 {
01611 if (edgeFace1[fEdges[i]] == -1)
01612 {
01613 nOpen++;
01614 }
01615 }
01616
01617 if (nOpen == 1 || nOpen == 2 || nOpen == 3)
01618 {
01619 return true;
01620 }
01621 else
01622 {
01623 return false;
01624 }
01625 }
01626
01627
01628
01629 Foam::label Foam::isoSurface::markDanglingTriangles
01630 (
01631 const List<FixedList<label, 3> >& faceEdges,
01632 const labelList& edgeFace0,
01633 const labelList& edgeFace1,
01634 const Map<labelList>& edgeFacesRest,
01635 boolList& keepTriangles
01636 )
01637 {
01638 keepTriangles.setSize(faceEdges.size());
01639 keepTriangles = true;
01640
01641 label nDangling = 0;
01642
01643
01644 forAllConstIter(Map<labelList>, edgeFacesRest, iter)
01645 {
01646
01647
01648
01649 label edgeI = iter.key();
01650 const labelList& otherEdgeFaces = iter();
01651
01652
01653 if (danglingTriangle(faceEdges[edgeFace0[edgeI]], edgeFace1))
01654 {
01655 keepTriangles[edgeFace0[edgeI]] = false;
01656 nDangling++;
01657 }
01658 if (danglingTriangle(faceEdges[edgeFace1[edgeI]], edgeFace1))
01659 {
01660 keepTriangles[edgeFace1[edgeI]] = false;
01661 nDangling++;
01662 }
01663 forAll(otherEdgeFaces, i)
01664 {
01665 label triI = otherEdgeFaces[i];
01666 if (danglingTriangle(faceEdges[triI], edgeFace1))
01667 {
01668 keepTriangles[triI] = false;
01669 nDangling++;
01670 }
01671 }
01672 }
01673 return nDangling;
01674 }
01675
01676
01677 Foam::triSurface Foam::isoSurface::subsetMesh
01678 (
01679 const triSurface& s,
01680 const labelList& newToOldFaces,
01681 labelList& oldToNewPoints,
01682 labelList& newToOldPoints
01683 )
01684 {
01685 const boolList include
01686 (
01687 createWithValues<boolList>
01688 (
01689 s.size(),
01690 false,
01691 newToOldFaces,
01692 true
01693 )
01694 );
01695
01696 newToOldPoints.setSize(s.points().size());
01697 oldToNewPoints.setSize(s.points().size());
01698 oldToNewPoints = -1;
01699 {
01700 label pointI = 0;
01701
01702 forAll(include, oldFacei)
01703 {
01704 if (include[oldFacei])
01705 {
01706
01707 const labelledTri& tri = s[oldFacei];
01708
01709 forAll(tri, fp)
01710 {
01711 label oldPointI = tri[fp];
01712
01713 if (oldToNewPoints[oldPointI] == -1)
01714 {
01715 oldToNewPoints[oldPointI] = pointI;
01716 newToOldPoints[pointI++] = oldPointI;
01717 }
01718 }
01719 }
01720 }
01721 newToOldPoints.setSize(pointI);
01722 }
01723
01724
01725 pointField newPoints(newToOldPoints.size());
01726 forAll(newToOldPoints, i)
01727 {
01728 newPoints[i] = s.points()[newToOldPoints[i]];
01729 }
01730
01731 List<labelledTri> newTriangles(newToOldFaces.size());
01732
01733 forAll(newToOldFaces, i)
01734 {
01735
01736 const labelledTri& tri = s[newToOldFaces[i]];
01737
01738 newTriangles[i][0] = oldToNewPoints[tri[0]];
01739 newTriangles[i][1] = oldToNewPoints[tri[1]];
01740 newTriangles[i][2] = oldToNewPoints[tri[2]];
01741 newTriangles[i].region() = tri.region();
01742 }
01743
01744
01745 return triSurface(newTriangles, s.patches(), newPoints, true);
01746 }
01747
01748
01749
01750
01751 Foam::isoSurface::isoSurface
01752 (
01753 const volScalarField& cVals,
01754 const scalarField& pVals,
01755 const scalar iso,
01756 const bool regularise,
01757 const scalar mergeTol
01758 )
01759 :
01760 mesh_(cVals.mesh()),
01761 pVals_(pVals),
01762 iso_(iso),
01763 regularise_(regularise),
01764 mergeDistance_(mergeTol*mesh_.bounds().mag())
01765 {
01766 if (debug)
01767 {
01768 Pout<< "isoSurface:" << nl
01769 << " isoField : " << cVals.name() << nl
01770 << " cell min/max : "
01771 << min(cVals.internalField()) << " / "
01772 << max(cVals.internalField()) << nl
01773 << " point min/max : "
01774 << min(pVals_) << " / "
01775 << max(pVals_) << nl
01776 << " isoValue : " << iso << nl
01777 << " regularise : " << regularise_ << nl
01778 << " mergeTol : " << mergeTol << nl
01779 << endl;
01780 }
01781
01782 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
01783
01784
01785
01786
01787
01788
01789
01790 cValsPtr_.reset(adaptPatchFields(cVals).ptr());
01791
01792
01793
01794
01795
01796
01797
01798 slicedVolVectorField meshC
01799 (
01800 IOobject
01801 (
01802 "C",
01803 mesh_.pointsInstance(),
01804 mesh_.meshSubDir,
01805 mesh_,
01806 IOobject::NO_READ,
01807 IOobject::NO_WRITE,
01808 false
01809 ),
01810 mesh_,
01811 dimLength,
01812 mesh_.cellCentres(),
01813 mesh_.faceCentres()
01814 );
01815 forAll(patches, patchI)
01816 {
01817 const polyPatch& pp = patches[patchI];
01818
01819
01820 if (isA<coupledPolyPatch>(pp) && !collocatedPatch(pp))
01821 {
01822 fvPatchVectorField& pfld = const_cast<fvPatchVectorField&>
01823 (
01824 meshC.boundaryField()[patchI]
01825 );
01826
01827 PackedBoolList isCollocated
01828 (
01829 collocatedFaces(refCast<const coupledPolyPatch>(pp))
01830 );
01831
01832 forAll(isCollocated, i)
01833 {
01834 if (!isCollocated[i])
01835 {
01836 pfld[i] = mesh_.faceCentres()[pp.start()+i];
01837 }
01838 }
01839 }
01840 else if (isA<emptyPolyPatch>(pp))
01841 {
01842 typedef slicedVolVectorField::GeometricBoundaryField bType;
01843
01844 bType& bfld = const_cast<bType&>(meshC.boundaryField());
01845
01846
01847 bfld.set(patchI, NULL);
01848
01849
01850 bfld.set
01851 (
01852 patchI,
01853 new calculatedFvPatchField<vector>
01854 (
01855 mesh_.boundary()[patchI],
01856 meshC
01857 )
01858 );
01859
01860
01861 bfld[patchI] = pp.patchSlice(mesh_.faceCentres());
01862 }
01863 }
01864
01865
01866
01867
01868 labelList boundaryRegion(mesh_.nFaces()-mesh_.nInternalFaces());
01869
01870 forAll(patches, patchI)
01871 {
01872 const polyPatch& pp = patches[patchI];
01873
01874 label faceI = pp.start();
01875
01876 forAll(pp, i)
01877 {
01878 boundaryRegion[faceI-mesh_.nInternalFaces()] = patchI;
01879 faceI++;
01880 }
01881 }
01882
01883
01884
01885
01886 calcCutTypes(boundaryRegion, meshC, cValsPtr_(), pVals_);
01887
01888
01889 DynamicList<point> snappedPoints(nCutCells_);
01890
01891
01892 labelList snappedCc;
01893 if (regularise_)
01894 {
01895 calcSnappedCc
01896 (
01897 boundaryRegion,
01898 meshC,
01899 cValsPtr_(),
01900 pVals_,
01901
01902 snappedPoints,
01903 snappedCc
01904 );
01905 }
01906 else
01907 {
01908 snappedCc.setSize(mesh_.nCells());
01909 snappedCc = -1;
01910 }
01911
01912
01913
01914 if (debug)
01915 {
01916 Pout<< "isoSurface : shifted " << snappedPoints.size()
01917 << " cell centres to intersection." << endl;
01918 }
01919
01920 label nCellSnaps = snappedPoints.size();
01921
01922
01923
01924 labelList snappedPoint;
01925 if (regularise_)
01926 {
01927
01928 PackedBoolList isBoundaryPoint(mesh_.nPoints());
01929
01930 forAll(patches, patchI)
01931 {
01932
01933
01934
01935 if (patches[patchI].coupled())
01936 {
01937 if (!collocatedPatch(patches[patchI]))
01938 {
01939 const coupledPolyPatch& cpp =
01940 refCast<const coupledPolyPatch>
01941 (
01942 patches[patchI]
01943 );
01944
01945 PackedBoolList isCollocated(collocatedFaces(cpp));
01946
01947 forAll(isCollocated, i)
01948 {
01949 if (!isCollocated[i])
01950 {
01951 const face& f = mesh_.faces()[cpp.start()+i];
01952
01953 forAll(f, fp)
01954 {
01955 isBoundaryPoint.set(f[fp], 1);
01956 }
01957 }
01958 }
01959 }
01960 }
01961 else
01962 {
01963 const polyPatch& pp = patches[patchI];
01964
01965 forAll(pp, i)
01966 {
01967 const face& f = mesh_.faces()[pp.start()+i];
01968
01969 forAll(f, fp)
01970 {
01971 isBoundaryPoint.set(f[fp], 1);
01972 }
01973 }
01974 }
01975 }
01976
01977 calcSnappedPoint
01978 (
01979 isBoundaryPoint,
01980 boundaryRegion,
01981 meshC,
01982 cValsPtr_(),
01983 pVals_,
01984
01985 snappedPoints,
01986 snappedPoint
01987 );
01988 }
01989 else
01990 {
01991 snappedPoint.setSize(mesh_.nPoints());
01992 snappedPoint = -1;
01993 }
01994
01995 if (debug)
01996 {
01997 Pout<< "isoSurface : shifted " << snappedPoints.size()-nCellSnaps
01998 << " vertices to intersection." << endl;
01999 }
02000
02001
02002
02003 DynamicList<point> triPoints(nCutCells_);
02004 DynamicList<label> triMeshCells(nCutCells_);
02005
02006 generateTriPoints
02007 (
02008 cValsPtr_(),
02009 pVals_,
02010
02011 meshC,
02012 mesh_.points(),
02013
02014 snappedPoints,
02015 snappedCc,
02016 snappedPoint,
02017
02018 triPoints,
02019 triMeshCells
02020 );
02021
02022 if (debug)
02023 {
02024 Pout<< "isoSurface : generated " << triMeshCells.size()
02025 << " unmerged triangles from " << triPoints.size()
02026 << " unmerged points." << endl;
02027 }
02028
02029
02030
02031 labelList triMap;
02032 triSurface::operator=
02033 (
02034 stitchTriPoints
02035 (
02036 true,
02037 triPoints,
02038 triPointMergeMap_,
02039 triMap
02040 )
02041 );
02042
02043 if (debug)
02044 {
02045 Pout<< "isoSurface : generated " << triMap.size()
02046 << " merged triangles." << endl;
02047 }
02048
02049 meshCells_.setSize(triMap.size());
02050 forAll(triMap, i)
02051 {
02052 meshCells_[i] = triMeshCells[triMap[i]];
02053 }
02054
02055 if (debug)
02056 {
02057 Pout<< "isoSurface : checking " << size()
02058 << " triangles for validity." << endl;
02059
02060 forAll(*this, triI)
02061 {
02062
02063 validTri(*this, triI);
02064 }
02065 }
02066
02067
02068
02069 {
02070 List<FixedList<label, 3> > faceEdges;
02071 labelList edgeFace0, edgeFace1;
02072 Map<labelList> edgeFacesRest;
02073
02074
02075 while (true)
02076 {
02077
02078 calcAddressing(*this, faceEdges, edgeFace0, edgeFace1, edgeFacesRest);
02079
02080
02081 boolList keepTriangles;
02082 label nDangling = markDanglingTriangles
02083 (
02084 faceEdges,
02085 edgeFace0,
02086 edgeFace1,
02087 edgeFacesRest,
02088 keepTriangles
02089 );
02090
02091 if (debug)
02092 {
02093 Pout<< "isoSurface : detected " << nDangling
02094 << " dangling triangles." << endl;
02095 }
02096
02097 if (nDangling == 0)
02098 {
02099 break;
02100 }
02101
02102
02103 labelList subsetTriMap(findIndices(keepTriangles, true));
02104
02105 labelList subsetPointMap;
02106 labelList reversePointMap;
02107 triSurface::operator=
02108 (
02109 subsetMesh
02110 (
02111 *this,
02112 subsetTriMap,
02113 reversePointMap,
02114 subsetPointMap
02115 )
02116 );
02117 meshCells_ = labelField(meshCells_, subsetTriMap);
02118 inplaceRenumber(reversePointMap, triPointMergeMap_);
02119 }
02120
02121 orientSurface(*this, faceEdges, edgeFace0, edgeFace1, edgeFacesRest);
02122 }
02123
02124
02125 if (debug)
02126 {
02127 fileName stlFile = mesh_.time().path() + ".stl";
02128 Pout<< "Dumping surface to " << stlFile << endl;
02129 triSurface::write(stlFile);
02130 }
02131 }
02132
02133
02134