/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2016-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "sampledCuttingPlane.H" #include "dictionary.H" #include "fvMesh.H" #include "volFields.H" #include "volPointInterpolation.H" #include "cartesianCS.H" #include "addToRunTimeSelectionTable.H" #include "PtrList.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(sampledCuttingPlane, 0); addNamedToRunTimeSelectionTable ( sampledSurface, sampledCuttingPlane, word, cuttingPlane ); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::plane Foam::sampledCuttingPlane::definePlane ( const polyMesh& mesh, const dictionary& dict ) { plane pln(dict); // Optional (cartesian) coordinate transform. // - with registry to allow lookup from globally defined systems auto csysPtr = coordinateSystem::NewIfPresent(mesh, dict); if (!csysPtr) { csysPtr = coordinateSystem::NewIfPresent(dict, "transform"); } // Make plane relative to the Cartesian coordinate system if (csysPtr) { coordSystem::cartesian cs(csysPtr()); const point orig = cs.globalPosition(pln.origin()); const vector norm = cs.globalVector(pln.normal()); DebugInfo << "plane " << " origin:" << pln.origin() << " normal:" << pln.normal() << " =>" << " origin:" << orig << " normal:" << norm << endl; // Reassign the plane pln = plane(orig, norm); } return pln; } void Foam::sampledCuttingPlane::checkBoundsIntersection ( const plane& pln, const boundBox& meshBb ) const { // Verify specified bounding box const boundBox& clipBb = isoParams_.getClipBounds(); if (clipBb.good()) { // Bounding box does not overlap with (global) mesh! if (!clipBb.overlaps(meshBb)) { WarningInFunction << nl << name() << " : " << "Bounds " << clipBb << " do not overlap the mesh bounding box " << meshBb << nl << endl; } // Plane does not intersect the bounding box if (!clipBb.intersects(pln)) { WarningInFunction << nl << name() << " : " << "Plane "<< pln << " does not intersect the bounds " << clipBb << nl << endl; } } // Plane does not intersect the (global) mesh! if (!meshBb.intersects(pln)) { WarningInFunction << nl << name() << " : " << "Plane "<< pln << " does not intersect the mesh bounds " << meshBb << nl << endl; } } void Foam::sampledCuttingPlane::setDistanceFields(const plane& pln) { volScalarField& cellDistance = cellDistancePtr_(); // Get mesh from volField, // so automatically submesh or baseMesh const fvMesh& mesh = cellDistance.mesh(); // Distance to cell centres // ~~~~~~~~~~~~~~~~~~~~~~~~ // Internal field { const auto& cc = mesh.cellCentres(); scalarField& fld = cellDistance.primitiveFieldRef(); forAll(cc, i) { fld[i] = pln.signedDistance(cc[i]); } } // Patch fields { volScalarField::Boundary& cellDistanceBf = cellDistance.boundaryFieldRef(); forAll(cellDistanceBf, patchi) { if ( isA ( cellDistanceBf[patchi] ) ) { cellDistanceBf.set ( patchi, new calculatedFvPatchScalarField ( mesh.boundary()[patchi], cellDistance ) ); const polyPatch& pp = mesh.boundary()[patchi].patch(); pointField::subField cc = pp.patchSlice(mesh.faceCentres()); fvPatchScalarField& fld = cellDistanceBf[patchi]; fld.setSize(pp.size()); forAll(fld, i) { fld[i] = pln.signedDistance(cc[i]); } } else { // Other side cell centres? const pointField& cc = mesh.C().boundaryField()[patchi]; fvPatchScalarField& fld = cellDistanceBf[patchi]; forAll(fld, i) { fld[i] = pln.signedDistance(cc[i]); } } } } // On processor patches the mesh.C() will already be the cell centre // on the opposite side so no need to swap cellDistance. // Distance to points pointDistance_.resize(mesh.nPoints()); { const pointField& pts = mesh.points(); forAll(pointDistance_, i) { pointDistance_[i] = pln.signedDistance(pts[i]); } } } void Foam::sampledCuttingPlane::combineSurfaces ( PtrList& isoSurfPtrs ) { isoSurfacePtr_.reset(nullptr); // Already checked previously for ALGO_POINT, but do it again // - ALGO_POINT still needs fields (for interpolate) // The others can do straight transfer if ( isoParams_.algorithm() == isoSurfaceParams::ALGO_POINT && isoSurfPtrs.size() == 1 ) { // Shift ownership from list to autoPtr isoSurfacePtr_.reset(isoSurfPtrs.release(0)); } else if (isoSurfPtrs.size() == 1) { autoPtr ptr(isoSurfPtrs.release(0)); auto& surf = *ptr; surface_.transfer(static_cast(surf)); meshCells_.transfer(surf.meshCells()); } else { // Combine faces with point offsets // // Note: use points().size() from surface, not nPoints() // since there may be uncompacted dangling nodes label nFaces = 0, nPoints = 0; for (const auto& surf : isoSurfPtrs) { nFaces += surf.size(); nPoints += surf.points().size(); } faceList newFaces(nFaces); pointField newPoints(nPoints); meshCells_.resize(nFaces); surfZoneList newZones(isoSurfPtrs.size()); nFaces = 0; nPoints = 0; forAll(isoSurfPtrs, surfi) { autoPtr ptr(isoSurfPtrs.release(surfi)); auto& surf = *ptr; SubList subFaces(newFaces, surf.size(), nFaces); SubList subPoints(newPoints, surf.points().size(), nPoints); SubList