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 <OpenFOAM/polyMesh.H>
00028 #include <OpenFOAM/syncTools.H>
00029 #include <finiteVolume/surfaceFields.H>
00030 #include <OpenFOAM/OFstream.H>
00031 #include <meshTools/meshTools.H>
00032
00033
00034
00035 template<class Type>
00036 Foam::tmp<Foam::SlicedGeometricField
00037 <
00038 Type,
00039 Foam::fvPatchField,
00040 Foam::slicedFvPatchField,
00041 Foam::volMesh
00042 > >
00043 Foam::isoSurface::adaptPatchFields
00044 (
00045 const GeometricField<Type, fvPatchField, volMesh>& fld
00046 ) const
00047 {
00048 typedef SlicedGeometricField
00049 <
00050 Type,
00051 fvPatchField,
00052 slicedFvPatchField,
00053 volMesh
00054 > FieldType;
00055
00056 tmp<FieldType> tsliceFld
00057 (
00058 new FieldType
00059 (
00060 IOobject
00061 (
00062 fld.name(),
00063 fld.instance(),
00064 fld.db(),
00065 IOobject::NO_READ,
00066 IOobject::NO_WRITE,
00067 false
00068 ),
00069 fld,
00070 true
00071 )
00072 );
00073 FieldType& sliceFld = tsliceFld();
00074
00075 const fvMesh& mesh = fld.mesh();
00076
00077 const polyBoundaryMesh& patches = mesh.boundaryMesh();
00078
00079 forAll(patches, patchI)
00080 {
00081 const polyPatch& pp = patches[patchI];
00082
00083 if
00084 (
00085 isA<emptyPolyPatch>(pp)
00086 && pp.size() != sliceFld.boundaryField()[patchI].size()
00087 )
00088 {
00089
00090 sliceFld.boundaryField().set(patchI, NULL);
00091
00092
00093 sliceFld.boundaryField().set
00094 (
00095 patchI,
00096 new calculatedFvPatchField<Type>
00097 (
00098 mesh.boundary()[patchI],
00099 sliceFld
00100 )
00101 );
00102
00103
00104
00105 const unallocLabelList& faceCells =
00106 mesh.boundary()[patchI].patch().faceCells();
00107
00108 Field<Type>& pfld = sliceFld.boundaryField()[patchI];
00109 pfld.setSize(faceCells.size());
00110 forAll(faceCells, i)
00111 {
00112 pfld[i] = sliceFld[faceCells[i]];
00113 }
00114 }
00115 else if (isA<cyclicPolyPatch>(pp))
00116 {
00117
00118 }
00119 else if (isA<processorPolyPatch>(pp) && !collocatedPatch(pp))
00120 {
00121 fvPatchField<Type>& pfld = const_cast<fvPatchField<Type>&>
00122 (
00123 fld.boundaryField()[patchI]
00124 );
00125
00126 const scalarField& w = mesh.weights().boundaryField()[patchI];
00127
00128 tmp<Field<Type> > f =
00129 w*pfld.patchInternalField()
00130 + (1.0-w)*pfld.patchNeighbourField();
00131
00132 PackedBoolList isCollocated
00133 (
00134 collocatedFaces(refCast<const processorPolyPatch>(pp))
00135 );
00136
00137 forAll(isCollocated, i)
00138 {
00139 if (!isCollocated[i])
00140 {
00141 pfld[i] = f()[i];
00142 }
00143 }
00144 }
00145 }
00146 return tsliceFld;
00147 }
00148
00149
00150 template<class Type>
00151 Type Foam::isoSurface::generatePoint
00152 (
00153 const scalar s0,
00154 const Type& p0,
00155 const bool hasSnap0,
00156 const Type& snapP0,
00157
00158 const scalar s1,
00159 const Type& p1,
00160 const bool hasSnap1,
00161 const Type& snapP1
00162 ) const
00163 {
00164 scalar d = s1-s0;
00165
00166 if (mag(d) > VSMALL)
00167 {
00168 scalar s = (iso_-s0)/d;
00169
00170 if (hasSnap1 && s >= 0.5 && s <= 1)
00171 {
00172 return snapP1;
00173 }
00174 else if (hasSnap0 && s >= 0.0 && s <= 0.5)
00175 {
00176 return snapP0;
00177 }
00178 else
00179 {
00180 return s*p1 + (1.0-s)*p0;
00181 }
00182 }
00183 else
00184 {
00185 scalar s = 0.4999;
00186
00187 return s*p1 + (1.0-s)*p0;
00188 }
00189 }
00190
00191
00192 template<class Type>
00193 void Foam::isoSurface::generateTriPoints
00194 (
00195 const scalar s0,
00196 const Type& p0,
00197 const bool hasSnap0,
00198 const Type& snapP0,
00199
00200 const scalar s1,
00201 const Type& p1,
00202 const bool hasSnap1,
00203 const Type& snapP1,
00204
00205 const scalar s2,
00206 const Type& p2,
00207 const bool hasSnap2,
00208 const Type& snapP2,
00209
00210 const scalar s3,
00211 const Type& p3,
00212 const bool hasSnap3,
00213 const Type& snapP3,
00214
00215 DynamicList<Type>& points
00216 ) const
00217 {
00218 int triIndex = 0;
00219 if (s0 < iso_)
00220 {
00221 triIndex |= 1;
00222 }
00223 if (s1 < iso_)
00224 {
00225 triIndex |= 2;
00226 }
00227 if (s2 < iso_)
00228 {
00229 triIndex |= 4;
00230 }
00231 if (s3 < iso_)
00232 {
00233 triIndex |= 8;
00234 }
00235
00236
00237 switch (triIndex)
00238 {
00239 case 0x00:
00240 case 0x0F:
00241 break;
00242
00243 case 0x0E:
00244 case 0x01:
00245 points.append
00246 (
00247 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1)
00248 );
00249 points.append
00250 (
00251 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
00252 );
00253 points.append
00254 (
00255 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
00256 );
00257 break;
00258
00259 case 0x0D:
00260 case 0x02:
00261 points.append
00262 (
00263 generatePoint(s1,p1,hasSnap1,snapP1,s0,p0,hasSnap0,snapP0)
00264 );
00265 points.append
00266 (
00267 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
00268 );
00269 points.append
00270 (
00271 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
00272 );
00273 break;
00274
00275 case 0x0C:
00276 case 0x03:
00277 {
00278 Type tp1 =
00279 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2);
00280 Type tp2 =
00281 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3);
00282
00283 points.append
00284 (
00285 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
00286 );
00287 points.append(tp1);
00288 points.append(tp2);
00289 points.append(tp2);
00290 points.append
00291 (
00292 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
00293 );
00294 points.append(tp1);
00295 }
00296 break;
00297
00298 case 0x0B:
00299 case 0x04:
00300 {
00301 points.append
00302 (
00303 generatePoint(s2,p2,hasSnap2,snapP2,s0,p0,hasSnap0,snapP0)
00304 );
00305 points.append
00306 (
00307 generatePoint(s2,p2,hasSnap2,snapP2,s1,p1,hasSnap1,snapP1)
00308 );
00309 points.append
00310 (
00311 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3)
00312 );
00313 }
00314 break;
00315
00316 case 0x0A:
00317 case 0x05:
00318 {
00319 Type tp0 =
00320 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
00321 Type tp1 =
00322 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
00323
00324 points.append(tp0);
00325 points.append(tp1);
00326 points.append
00327 (
00328 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
00329 );
00330 points.append(tp0);
00331 points.append
00332 (
00333 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
00334 );
00335 points.append(tp1);
00336 }
00337 break;
00338
00339 case 0x09:
00340 case 0x06:
00341 {
00342 Type tp0 =
00343 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
00344 Type tp1 =
00345 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
00346
00347 points.append(tp0);
00348 points.append
00349 (
00350 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
00351 );
00352 points.append(tp1);
00353 points.append(tp0);
00354 points.append
00355 (
00356 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
00357 );
00358 points.append(tp1);
00359 }
00360 break;
00361
00362 case 0x07:
00363 case 0x08:
00364 points.append
00365 (
00366 generatePoint(s3,p3,hasSnap3,snapP3,s0,p0,hasSnap0,snapP0)
00367 );
00368 points.append
00369 (
00370 generatePoint(s3,p3,hasSnap3,snapP3,s2,p2,hasSnap2,snapP2)
00371 );
00372 points.append
00373 (
00374 generatePoint(s3,p3,hasSnap3,snapP3,s1,p1,hasSnap1,snapP1)
00375 );
00376 break;
00377 }
00378 }
00379
00380
00381 template<class Type>
00382 Foam::label Foam::isoSurface::generateFaceTriPoints
00383 (
00384 const volScalarField& cVals,
00385 const scalarField& pVals,
00386
00387 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
00388 const Field<Type>& pCoords,
00389
00390 const DynamicList<Type>& snappedPoints,
00391 const labelList& snappedCc,
00392 const labelList& snappedPoint,
00393 const label faceI,
00394
00395 const scalar neiVal,
00396 const Type& neiPt,
00397 const bool hasNeiSnap,
00398 const Type& neiSnapPt,
00399
00400 DynamicList<Type>& triPoints,
00401 DynamicList<label>& triMeshCells
00402 ) const
00403 {
00404 label own = mesh_.faceOwner()[faceI];
00405
00406 label oldNPoints = triPoints.size();
00407
00408 const face& f = mesh_.faces()[faceI];
00409
00410 forAll(f, fp)
00411 {
00412 label pointI = f[fp];
00413 label nextPointI = f[f.fcIndex(fp)];
00414
00415 generateTriPoints
00416 (
00417 pVals[pointI],
00418 pCoords[pointI],
00419 snappedPoint[pointI] != -1,
00420 (
00421 snappedPoint[pointI] != -1
00422 ? snappedPoints[snappedPoint[pointI]]
00423 : pTraits<Type>::zero
00424 ),
00425
00426 pVals[nextPointI],
00427 pCoords[nextPointI],
00428 snappedPoint[nextPointI] != -1,
00429 (
00430 snappedPoint[nextPointI] != -1
00431 ? snappedPoints[snappedPoint[nextPointI]]
00432 : pTraits<Type>::zero
00433 ),
00434
00435 cVals[own],
00436 cCoords[own],
00437 snappedCc[own] != -1,
00438 (
00439 snappedCc[own] != -1
00440 ? snappedPoints[snappedCc[own]]
00441 : pTraits<Type>::zero
00442 ),
00443
00444 neiVal,
00445 neiPt,
00446 hasNeiSnap,
00447 neiSnapPt,
00448
00449 triPoints
00450 );
00451 }
00452
00453
00454 label nTris = (triPoints.size()-oldNPoints)/3;
00455 for (label i = 0; i < nTris; i++)
00456 {
00457 triMeshCells.append(own);
00458 }
00459
00460 return nTris;
00461 }
00462
00463
00464 template<class Type>
00465 void Foam::isoSurface::generateTriPoints
00466 (
00467 const volScalarField& cVals,
00468 const scalarField& pVals,
00469
00470 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
00471 const Field<Type>& pCoords,
00472
00473 const DynamicList<Type>& snappedPoints,
00474 const labelList& snappedCc,
00475 const labelList& snappedPoint,
00476
00477 DynamicList<Type>& triPoints,
00478 DynamicList<label>& triMeshCells
00479 ) const
00480 {
00481 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00482 const labelList& own = mesh_.faceOwner();
00483 const labelList& nei = mesh_.faceNeighbour();
00484
00485 if
00486 (
00487 (cVals.size() != mesh_.nCells())
00488 || (pVals.size() != mesh_.nPoints())
00489 || (cCoords.size() != mesh_.nCells())
00490 || (pCoords.size() != mesh_.nPoints())
00491 || (snappedCc.size() != mesh_.nCells())
00492 || (snappedPoint.size() != mesh_.nPoints())
00493 )
00494 {
00495 FatalErrorIn("isoSurface::generateTriPoints(..)")
00496 << "Incorrect size." << endl
00497 << "mesh: nCells:" << mesh_.nCells()
00498 << " points:" << mesh_.nPoints() << endl
00499 << "cVals:" << cVals.size() << endl
00500 << "cCoords:" << cCoords.size() << endl
00501 << "snappedCc:" << snappedCc.size() << endl
00502 << "pVals:" << pVals.size() << endl
00503 << "pCoords:" << pCoords.size() << endl
00504 << "snappedPoint:" << snappedPoint.size() << endl
00505 << abort(FatalError);
00506 }
00507
00508
00509
00510
00511 triPoints.clear();
00512 triMeshCells.clear();
00513
00514 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00515 {
00516 if (faceCutType_[faceI] != NOTCUT)
00517 {
00518 generateFaceTriPoints
00519 (
00520 cVals,
00521 pVals,
00522
00523 cCoords,
00524 pCoords,
00525
00526 snappedPoints,
00527 snappedCc,
00528 snappedPoint,
00529 faceI,
00530
00531 cVals[nei[faceI]],
00532 cCoords[nei[faceI]],
00533 snappedCc[nei[faceI]] != -1,
00534 (
00535 snappedCc[nei[faceI]] != -1
00536 ? snappedPoints[snappedCc[nei[faceI]]]
00537 : pTraits<Type>::zero
00538 ),
00539
00540 triPoints,
00541 triMeshCells
00542 );
00543 }
00544 }
00545
00546
00547
00548 boolList neiSnapped(mesh_.nFaces()-mesh_.nInternalFaces(), false);
00549 List<Type> neiSnappedPoint(neiSnapped.size(), pTraits<Type>::zero);
00550 forAll(patches, patchI)
00551 {
00552 const polyPatch& pp = patches[patchI];
00553
00554 if (pp.coupled())
00555 {
00556 label faceI = pp.start();
00557 forAll(pp, i)
00558 {
00559 label bFaceI = faceI-mesh_.nInternalFaces();
00560 label snappedIndex = snappedCc[own[faceI]];
00561
00562 if (snappedIndex != -1)
00563 {
00564 neiSnapped[bFaceI] = true;
00565 neiSnappedPoint[bFaceI] = snappedPoints[snappedIndex];
00566 }
00567 faceI++;
00568 }
00569 }
00570 }
00571 syncTools::swapBoundaryFaceList(mesh_, neiSnapped, false);
00572 syncTools::swapBoundaryFaceList(mesh_, neiSnappedPoint, false);
00573
00574
00575
00576 forAll(patches, patchI)
00577 {
00578 const polyPatch& pp = patches[patchI];
00579
00580 if (isA<processorPolyPatch>(pp))
00581 {
00582 const processorPolyPatch& cpp =
00583 refCast<const processorPolyPatch>(pp);
00584
00585 PackedBoolList isCollocated(collocatedFaces(cpp));
00586
00587 forAll(isCollocated, i)
00588 {
00589 label faceI = pp.start()+i;
00590
00591 if (faceCutType_[faceI] != NOTCUT)
00592 {
00593 if (isCollocated[i])
00594 {
00595 generateFaceTriPoints
00596 (
00597 cVals,
00598 pVals,
00599
00600 cCoords,
00601 pCoords,
00602
00603 snappedPoints,
00604 snappedCc,
00605 snappedPoint,
00606 faceI,
00607
00608 cVals.boundaryField()[patchI][i],
00609 cCoords.boundaryField()[patchI][i],
00610 neiSnapped[faceI-mesh_.nInternalFaces()],
00611 neiSnappedPoint[faceI-mesh_.nInternalFaces()],
00612
00613 triPoints,
00614 triMeshCells
00615 );
00616 }
00617 else
00618 {
00619 generateFaceTriPoints
00620 (
00621 cVals,
00622 pVals,
00623
00624 cCoords,
00625 pCoords,
00626
00627 snappedPoints,
00628 snappedCc,
00629 snappedPoint,
00630 faceI,
00631
00632 cVals.boundaryField()[patchI][i],
00633 cCoords.boundaryField()[patchI][i],
00634 false,
00635 pTraits<Type>::zero,
00636
00637 triPoints,
00638 triMeshCells
00639 );
00640 }
00641 }
00642 }
00643 }
00644 else
00645 {
00646 label faceI = pp.start();
00647
00648 forAll(pp, i)
00649 {
00650 if (faceCutType_[faceI] != NOTCUT)
00651 {
00652 generateFaceTriPoints
00653 (
00654 cVals,
00655 pVals,
00656
00657 cCoords,
00658 pCoords,
00659
00660 snappedPoints,
00661 snappedCc,
00662 snappedPoint,
00663 faceI,
00664
00665 cVals.boundaryField()[patchI][i],
00666 cCoords.boundaryField()[patchI][i],
00667 false,
00668 pTraits<Type>::zero,
00669
00670 triPoints,
00671 triMeshCells
00672 );
00673 }
00674 faceI++;
00675 }
00676 }
00677 }
00678
00679 triPoints.shrink();
00680 triMeshCells.shrink();
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 template <class Type>
00693 Foam::tmp<Foam::Field<Type> >
00694 Foam::isoSurface::interpolate
00695 (
00696 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
00697 const Field<Type>& pCoords
00698 ) const
00699 {
00700
00701 tmp<SlicedGeometricField
00702 <
00703 Type,
00704 fvPatchField,
00705 slicedFvPatchField,
00706 volMesh
00707 > > c2(adaptPatchFields(cCoords));
00708
00709
00710 DynamicList<Type> triPoints(nCutCells_);
00711 DynamicList<label> triMeshCells(nCutCells_);
00712
00713
00714 DynamicList<Type> snappedPoints;
00715 labelList snappedCc(mesh_.nCells(), -1);
00716 labelList snappedPoint(mesh_.nPoints(), -1);
00717
00718 generateTriPoints
00719 (
00720 cValsPtr_(),
00721 pVals_,
00722
00723 c2(),
00724 pCoords,
00725
00726 snappedPoints,
00727 snappedCc,
00728 snappedPoint,
00729
00730 triPoints,
00731 triMeshCells
00732 );
00733
00734
00735
00736 tmp<Field<Type> > tvalues
00737 (
00738 new Field<Type>(points().size(), pTraits<Type>::zero)
00739 );
00740 Field<Type>& values = tvalues();
00741 labelList nValues(values.size(), 0);
00742
00743 forAll(triPoints, i)
00744 {
00745 label mergedPointI = triPointMergeMap_[i];
00746
00747 if (mergedPointI >= 0)
00748 {
00749 values[mergedPointI] += triPoints[i];
00750 nValues[mergedPointI]++;
00751 }
00752 }
00753
00754 if (debug)
00755 {
00756 Pout<< "nValues:" << values.size() << endl;
00757 label nMult = 0;
00758 forAll(nValues, i)
00759 {
00760 if (nValues[i] == 0)
00761 {
00762 FatalErrorIn("isoSurface::interpolate(..)")
00763 << "point:" << i << " nValues:" << nValues[i]
00764 << abort(FatalError);
00765 }
00766 else if (nValues[i] > 1)
00767 {
00768 nMult++;
00769 }
00770 }
00771 Pout<< "Of which mult:" << nMult << endl;
00772 }
00773
00774 forAll(values, i)
00775 {
00776 values[i] /= scalar(nValues[i]);
00777 }
00778
00779 return tvalues;
00780 }
00781
00782
00783