FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

isoSurfaceTemplates.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
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 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
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,        // internal field
00070             true        // preserveCouples
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             // Clear old value. Cannot resize it since is a slice.
00090             sliceFld.boundaryField().set(patchI, NULL);
00091 
00092             // Set new value we can change
00093             sliceFld.boundaryField().set
00094             (
00095                 patchI,
00096                 new calculatedFvPatchField<Type>
00097                 (
00098                     mesh.boundary()[patchI],
00099                     sliceFld
00100                 )
00101             );
00102 
00103             // Note: cannot use patchInternalField since uses emptyFvPatch::size
00104             // Do our own internalField instead.
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             // Already has interpolate as value
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     /* Form the vertices of the triangles for each case */
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     // Every three triPoints is a triangle
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     // Generate triangle points
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     // Determine neighbouring snap status
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,  // fc not snapped
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 //template <class Type>
00685 //Foam::tmp<Foam::Field<Type> >
00686 //Foam::isoSurface::sample(const Field<Type>& vField) const
00687 //{
00688 //    return tmp<Field<Type> >(new Field<Type>(vField, meshCells()));
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     // Recalculate boundary values
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     // Dummy snap data
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     // One value per point
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 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines