1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "isoSurface.H"
29 #include "syncTools.H"
30 #include "surfaceFields.H"
32 #include "meshTools.H"
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 Foam::tmp<Foam::SlicedGeometricField
41 Foam::slicedFvPatchField,
44 Foam::isoSurface::adaptPatchFields
46 const GeometricField<Type, fvPatchField, volMesh>& fld
49 typedef SlicedGeometricField
57 tmp<FieldType> tsliceFld
70 fld, // internal field
71 true // preserveCouples
74 FieldType& sliceFld = tsliceFld();
76 const fvMesh& mesh = fld.mesh();
78 const polyBoundaryMesh& patches = mesh.boundaryMesh();
80 forAll(patches, patchI)
82 const polyPatch& pp = patches[patchI];
86 isA<emptyPolyPatch>(pp)
87 && pp.size() != sliceFld.boundaryField()[patchI].size()
90 // Clear old value. Cannot resize it since is a slice.
91 sliceFld.boundaryField().set(patchI, NULL);
93 // Set new value we can change
94 sliceFld.boundaryField().set
97 new calculatedFvPatchField<Type>
99 mesh.boundary()[patchI],
104 // Note: cannot use patchInternalField since uses emptyFvPatch::size
105 // Do our own internalField instead.
106 const unallocLabelList& faceCells =
107 mesh.boundary()[patchI].patch().faceCells();
109 Field<Type>& pfld = sliceFld.boundaryField()[patchI];
110 pfld.setSize(faceCells.size());
113 pfld[i] = sliceFld[faceCells[i]];
116 else if (isA<cyclicPolyPatch>(pp))
118 // Already has interpolate as value
120 else if (isA<processorPolyPatch>(pp) && !collocatedPatch(pp))
122 fvPatchField<Type>& pfld = const_cast<fvPatchField<Type>&>
124 fld.boundaryField()[patchI]
127 const scalarField& w = mesh.weights().boundaryField()[patchI];
129 tmp<Field<Type> > f =
130 w*pfld.patchInternalField()
131 + (1.0-w)*pfld.patchNeighbourField();
133 PackedBoolList isCollocated
135 collocatedFaces(refCast<const processorPolyPatch>(pp))
138 forAll(isCollocated, i)
140 if (!isCollocated[i])
152 Type Foam::isoSurface::generatePoint
169 scalar s = (iso_-s0)/d;
171 if (hasSnap1 && s >= 0.5 && s <= 1)
175 else if (hasSnap0 && s >= 0.0 && s <= 0.5)
181 return s*p1 + (1.0-s)*p0;
188 return s*p1 + (1.0-s)*p0;
194 void Foam::isoSurface::generateTriPoints
216 DynamicList<Type>& points
237 /* Form the vertices of the triangles for each case */
248 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1)
252 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
256 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
264 generatePoint(s1,p1,hasSnap1,snapP1,s0,p0,hasSnap0,snapP0)
268 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
272 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
280 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2);
282 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3);
286 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
293 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
304 generatePoint(s2,p2,hasSnap2,snapP2,s0,p0,hasSnap0,snapP0)
308 generatePoint(s2,p2,hasSnap2,snapP2,s1,p1,hasSnap1,snapP1)
312 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3)
321 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
323 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
329 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
334 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
344 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
346 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
351 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
357 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
367 generatePoint(s3,p3,hasSnap3,snapP3,s0,p0,hasSnap0,snapP0)
371 generatePoint(s3,p3,hasSnap3,snapP3,s2,p2,hasSnap2,snapP2)
375 generatePoint(s3,p3,hasSnap3,snapP3,s1,p1,hasSnap1,snapP1)
383 Foam::label Foam::isoSurface::generateFaceTriPoints
385 const volScalarField& cVals,
386 const scalarField& pVals,
388 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
389 const Field<Type>& pCoords,
391 const DynamicList<Type>& snappedPoints,
392 const labelList& snappedCc,
393 const labelList& snappedPoint,
398 const bool hasNeiSnap,
399 const Type& neiSnapPt,
401 DynamicList<Type>& triPoints,
402 DynamicList<label>& triMeshCells
405 label own = mesh_.faceOwner()[faceI];
407 label oldNPoints = triPoints.size();
409 const face& f = mesh_.faces()[faceI];
413 label pointI = f[fp];
414 label nextPointI = f[f.fcIndex(fp)];
420 snappedPoint[pointI] != -1,
422 snappedPoint[pointI] != -1
423 ? snappedPoints[snappedPoint[pointI]]
424 : pTraits<Type>::zero
429 snappedPoint[nextPointI] != -1,
431 snappedPoint[nextPointI] != -1
432 ? snappedPoints[snappedPoint[nextPointI]]
433 : pTraits<Type>::zero
438 snappedCc[own] != -1,
441 ? snappedPoints[snappedCc[own]]
442 : pTraits<Type>::zero
454 // Every three triPoints is a triangle
455 label nTris = (triPoints.size()-oldNPoints)/3;
456 for (label i = 0; i < nTris; i++)
458 triMeshCells.append(own);
466 void Foam::isoSurface::generateTriPoints
468 const volScalarField& cVals,
469 const scalarField& pVals,
471 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
472 const Field<Type>& pCoords,
474 const DynamicList<Type>& snappedPoints,
475 const labelList& snappedCc,
476 const labelList& snappedPoint,
478 DynamicList<Type>& triPoints,
479 DynamicList<label>& triMeshCells
482 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
483 const labelList& own = mesh_.faceOwner();
484 const labelList& nei = mesh_.faceNeighbour();
488 (cVals.size() != mesh_.nCells())
489 || (pVals.size() != mesh_.nPoints())
490 || (cCoords.size() != mesh_.nCells())
491 || (pCoords.size() != mesh_.nPoints())
492 || (snappedCc.size() != mesh_.nCells())
493 || (snappedPoint.size() != mesh_.nPoints())
496 FatalErrorIn("isoSurface::generateTriPoints(..)")
497 << "Incorrect size." << endl
498 << "mesh: nCells:" << mesh_.nCells()
499 << " points:" << mesh_.nPoints() << endl
500 << "cVals:" << cVals.size() << endl
501 << "cCoords:" << cCoords.size() << endl
502 << "snappedCc:" << snappedCc.size() << endl
503 << "pVals:" << pVals.size() << endl
504 << "pCoords:" << pCoords.size() << endl
505 << "snappedPoint:" << snappedPoint.size() << endl
506 << abort(FatalError);
510 // Generate triangle points
513 triMeshCells.clear();
515 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
517 if (faceCutType_[faceI] != NOTCUT)
519 generateFaceTriPoints
534 snappedCc[nei[faceI]] != -1,
536 snappedCc[nei[faceI]] != -1
537 ? snappedPoints[snappedCc[nei[faceI]]]
538 : pTraits<Type>::zero
548 // Determine neighbouring snap status
549 boolList neiSnapped(mesh_.nFaces()-mesh_.nInternalFaces(), false);
550 List<Type> neiSnappedPoint(neiSnapped.size(), pTraits<Type>::zero);
551 forAll(patches, patchI)
553 const polyPatch& pp = patches[patchI];
557 label faceI = pp.start();
560 label bFaceI = faceI-mesh_.nInternalFaces();
561 label snappedIndex = snappedCc[own[faceI]];
563 if (snappedIndex != -1)
565 neiSnapped[bFaceI] = true;
566 neiSnappedPoint[bFaceI] = snappedPoints[snappedIndex];
572 syncTools::swapBoundaryFaceList(mesh_, neiSnapped, false);
573 syncTools::swapBoundaryFaceList(mesh_, neiSnappedPoint, false);
577 forAll(patches, patchI)
579 const polyPatch& pp = patches[patchI];
581 if (isA<processorPolyPatch>(pp))
583 const processorPolyPatch& cpp =
584 refCast<const processorPolyPatch>(pp);
586 PackedBoolList isCollocated(collocatedFaces(cpp));
588 forAll(isCollocated, i)
590 label faceI = pp.start()+i;
592 if (faceCutType_[faceI] != NOTCUT)
596 generateFaceTriPoints
609 cVals.boundaryField()[patchI][i],
610 cCoords.boundaryField()[patchI][i],
611 neiSnapped[faceI-mesh_.nInternalFaces()],
612 neiSnappedPoint[faceI-mesh_.nInternalFaces()],
620 generateFaceTriPoints
633 cVals.boundaryField()[patchI][i],
634 cCoords.boundaryField()[patchI][i],
647 label faceI = pp.start();
651 if (faceCutType_[faceI] != NOTCUT)
653 generateFaceTriPoints
666 cVals.boundaryField()[patchI][i],
667 cCoords.boundaryField()[patchI][i],
668 false, // fc not snapped
681 triMeshCells.shrink();
685 //template <class Type>
686 //Foam::tmp<Foam::Field<Type> >
687 //Foam::isoSurface::sample(const Field<Type>& vField) const
689 // return tmp<Field<Type> >(new Field<Type>(vField, meshCells()));
693 template <class Type>
694 Foam::tmp<Foam::Field<Type> >
695 Foam::isoSurface::interpolate
697 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
698 const Field<Type>& pCoords
701 // Recalculate boundary values
702 tmp<SlicedGeometricField
708 > > c2(adaptPatchFields(cCoords));
711 DynamicList<Type> triPoints(nCutCells_);
712 DynamicList<label> triMeshCells(nCutCells_);
715 DynamicList<Type> snappedPoints;
716 labelList snappedCc(mesh_.nCells(), -1);
717 labelList snappedPoint(mesh_.nPoints(), -1);
736 // One value per point
737 tmp<Field<Type> > tvalues
739 new Field<Type>(points().size(), pTraits<Type>::zero)
741 Field<Type>& values = tvalues();
742 labelList nValues(values.size(), 0);
746 label mergedPointI = triPointMergeMap_[i];
748 if (mergedPointI >= 0)
750 values[mergedPointI] += triPoints[i];
751 nValues[mergedPointI]++;
757 Pout<< "nValues:" << values.size() << endl;
763 FatalErrorIn("isoSurface::interpolate(..)")
764 << "point:" << i << " nValues:" << nValues[i]
765 << abort(FatalError);
767 else if (nValues[i] > 1)
772 Pout<< "Of which mult:" << nMult << endl;
777 values[i] /= scalar(nValues[i]);
784 // ************************************************************************* //