1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "isoSurface.H"
28 #include "syncTools.H"
29 #include "surfaceFields.H"
31 #include "meshTools.H"
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 Foam::tmp<Foam::SlicedGeometricField
40 Foam::slicedFvPatchField,
43 Foam::isoSurface::adaptPatchFields
45 const GeometricField<Type, fvPatchField, volMesh>& fld
48 typedef SlicedGeometricField
56 tmp<FieldType> tsliceFld
69 fld, // internal field
70 true // preserveCouples
73 FieldType& sliceFld = tsliceFld();
75 const fvMesh& mesh = fld.mesh();
77 const polyBoundaryMesh& patches = mesh.boundaryMesh();
79 forAll(patches, patchI)
81 const polyPatch& pp = patches[patchI];
85 isA<emptyPolyPatch>(pp)
86 && pp.size() != sliceFld.boundaryField()[patchI].size()
89 // Clear old value. Cannot resize it since is a slice.
90 sliceFld.boundaryField().set(patchI, NULL);
92 // Set new value we can change
93 sliceFld.boundaryField().set
96 new calculatedFvPatchField<Type>
98 mesh.boundary()[patchI],
103 // Note: cannot use patchInternalField since uses emptyFvPatch::size
104 // Do our own internalField instead.
105 const labelUList& faceCells =
106 mesh.boundary()[patchI].patch().faceCells();
108 Field<Type>& pfld = sliceFld.boundaryField()[patchI];
109 pfld.setSize(faceCells.size());
112 pfld[i] = sliceFld[faceCells[i]];
115 else if (isA<cyclicPolyPatch>(pp))
117 // Already has interpolate as value
119 else if (isA<processorPolyPatch>(pp))
121 fvPatchField<Type>& pfld = const_cast<fvPatchField<Type>&>
123 fld.boundaryField()[patchI]
126 const scalarField& w = mesh.weights().boundaryField()[patchI];
128 tmp<Field<Type> > f =
129 w*pfld.patchInternalField()
130 + (1.0-w)*pfld.patchNeighbourField();
132 PackedBoolList isCollocated
134 collocatedFaces(refCast<const processorPolyPatch>(pp))
137 forAll(isCollocated, i)
139 if (!isCollocated[i])
151 Type Foam::isoSurface::generatePoint
168 scalar s = (iso_-s0)/d;
170 if (hasSnap1 && s >= 0.5 && s <= 1)
174 else if (hasSnap0 && s >= 0.0 && s <= 0.5)
180 return s*p1 + (1.0-s)*p0;
187 return s*p1 + (1.0-s)*p0;
193 void Foam::isoSurface::generateTriPoints
215 DynamicList<Type>& points
236 /* Form the vertices of the triangles for each case */
247 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1)
251 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
255 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
263 generatePoint(s1,p1,hasSnap1,snapP1,s0,p0,hasSnap0,snapP0)
267 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
271 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
279 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2);
281 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3);
285 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
292 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
303 generatePoint(s2,p2,hasSnap2,snapP2,s0,p0,hasSnap0,snapP0)
307 generatePoint(s2,p2,hasSnap2,snapP2,s1,p1,hasSnap1,snapP1)
311 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3)
320 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
322 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
328 generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
333 generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
343 generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
345 generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
350 generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
356 generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
366 generatePoint(s3,p3,hasSnap3,snapP3,s0,p0,hasSnap0,snapP0)
370 generatePoint(s3,p3,hasSnap3,snapP3,s2,p2,hasSnap2,snapP2)
374 generatePoint(s3,p3,hasSnap3,snapP3,s1,p1,hasSnap1,snapP1)
382 Foam::label Foam::isoSurface::generateFaceTriPoints
384 const volScalarField& cVals,
385 const scalarField& pVals,
387 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
388 const Field<Type>& pCoords,
390 const DynamicList<Type>& snappedPoints,
391 const labelList& snappedCc,
392 const labelList& snappedPoint,
397 const bool hasNeiSnap,
398 const Type& neiSnapPt,
400 DynamicList<Type>& triPoints,
401 DynamicList<label>& triMeshCells
404 label own = mesh_.faceOwner()[faceI];
406 label oldNPoints = triPoints.size();
408 const face& f = mesh_.faces()[faceI];
412 label pointI = f[fp];
413 label nextPointI = f[f.fcIndex(fp)];
419 snappedPoint[pointI] != -1,
421 snappedPoint[pointI] != -1
422 ? snappedPoints[snappedPoint[pointI]]
423 : pTraits<Type>::zero
428 snappedPoint[nextPointI] != -1,
430 snappedPoint[nextPointI] != -1
431 ? snappedPoints[snappedPoint[nextPointI]]
432 : pTraits<Type>::zero
437 snappedCc[own] != -1,
440 ? snappedPoints[snappedCc[own]]
441 : pTraits<Type>::zero
453 // Every three triPoints is a triangle
454 label nTris = (triPoints.size()-oldNPoints)/3;
455 for (label i = 0; i < nTris; i++)
457 triMeshCells.append(own);
465 void Foam::isoSurface::generateTriPoints
467 const volScalarField& cVals,
468 const scalarField& pVals,
470 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
471 const Field<Type>& pCoords,
473 const DynamicList<Type>& snappedPoints,
474 const labelList& snappedCc,
475 const labelList& snappedPoint,
477 DynamicList<Type>& triPoints,
478 DynamicList<label>& triMeshCells
481 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
482 const labelList& own = mesh_.faceOwner();
483 const labelList& nei = mesh_.faceNeighbour();
487 (cVals.size() != mesh_.nCells())
488 || (pVals.size() != mesh_.nPoints())
489 || (cCoords.size() != mesh_.nCells())
490 || (pCoords.size() != mesh_.nPoints())
491 || (snappedCc.size() != mesh_.nCells())
492 || (snappedPoint.size() != mesh_.nPoints())
495 FatalErrorIn("isoSurface::generateTriPoints(..)")
496 << "Incorrect size." << endl
497 << "mesh: nCells:" << mesh_.nCells()
498 << " points:" << mesh_.nPoints() << endl
499 << "cVals:" << cVals.size() << endl
500 << "cCoords:" << cCoords.size() << endl
501 << "snappedCc:" << snappedCc.size() << endl
502 << "pVals:" << pVals.size() << endl
503 << "pCoords:" << pCoords.size() << endl
504 << "snappedPoint:" << snappedPoint.size() << endl
505 << abort(FatalError);
509 // Generate triangle points
512 triMeshCells.clear();
514 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
516 if (faceCutType_[faceI] != NOTCUT)
518 generateFaceTriPoints
533 snappedCc[nei[faceI]] != -1,
535 snappedCc[nei[faceI]] != -1
536 ? snappedPoints[snappedCc[nei[faceI]]]
537 : pTraits<Type>::zero
547 // Determine neighbouring snap status
548 boolList neiSnapped(mesh_.nFaces()-mesh_.nInternalFaces(), false);
549 List<Type> neiSnappedPoint(neiSnapped.size(), pTraits<Type>::zero);
550 forAll(patches, patchI)
552 const polyPatch& pp = patches[patchI];
556 label faceI = pp.start();
559 label bFaceI = faceI-mesh_.nInternalFaces();
560 label snappedIndex = snappedCc[own[faceI]];
562 if (snappedIndex != -1)
564 neiSnapped[bFaceI] = true;
565 neiSnappedPoint[bFaceI] = snappedPoints[snappedIndex];
571 syncTools::swapBoundaryFaceList(mesh_, neiSnapped);
572 syncTools::swapBoundaryFaceList(mesh_, neiSnappedPoint);
576 forAll(patches, patchI)
578 const polyPatch& pp = patches[patchI];
580 if (isA<processorPolyPatch>(pp))
582 const processorPolyPatch& cpp =
583 refCast<const processorPolyPatch>(pp);
585 PackedBoolList isCollocated(collocatedFaces(cpp));
587 forAll(isCollocated, i)
589 label faceI = pp.start()+i;
591 if (faceCutType_[faceI] != NOTCUT)
595 generateFaceTriPoints
608 cVals.boundaryField()[patchI][i],
609 cCoords.boundaryField()[patchI][i],
610 neiSnapped[faceI-mesh_.nInternalFaces()],
611 neiSnappedPoint[faceI-mesh_.nInternalFaces()],
619 generateFaceTriPoints
632 cVals.boundaryField()[patchI][i],
633 cCoords.boundaryField()[patchI][i],
646 label faceI = pp.start();
650 if (faceCutType_[faceI] != NOTCUT)
652 generateFaceTriPoints
665 cVals.boundaryField()[patchI][i],
666 cCoords.boundaryField()[patchI][i],
667 false, // fc not snapped
680 triMeshCells.shrink();
684 //template <class Type>
685 //Foam::tmp<Foam::Field<Type> >
686 //Foam::isoSurface::sample(const Field<Type>& vField) const
688 // return tmp<Field<Type> >(new Field<Type>(vField, meshCells()));
692 template <class Type>
693 Foam::tmp<Foam::Field<Type> >
694 Foam::isoSurface::interpolate
696 const GeometricField<Type, fvPatchField, volMesh>& cCoords,
697 const Field<Type>& pCoords
700 // Recalculate boundary values
701 tmp<SlicedGeometricField
707 > > c2(adaptPatchFields(cCoords));
710 DynamicList<Type> triPoints(nCutCells_);
711 DynamicList<label> triMeshCells(nCutCells_);
714 DynamicList<Type> snappedPoints;
715 labelList snappedCc(mesh_.nCells(), -1);
716 labelList snappedPoint(mesh_.nPoints(), -1);
735 // One value per point
736 tmp<Field<Type> > tvalues
738 new Field<Type>(points().size(), pTraits<Type>::zero)
740 Field<Type>& values = tvalues();
741 labelList nValues(values.size(), 0);
745 label mergedPointI = triPointMergeMap_[i];
747 if (mergedPointI >= 0)
749 values[mergedPointI] += triPoints[i];
750 nValues[mergedPointI]++;
756 Pout<< "nValues:" << values.size() << endl;
762 FatalErrorIn("isoSurface::interpolate(..)")
763 << "point:" << i << " nValues:" << nValues[i]
764 << abort(FatalError);
766 else if (nValues[i] > 1)
771 Pout<< "Of which mult:" << nMult << endl;
776 values[i] /= scalar(nValues[i]);
783 // ************************************************************************* //