diff --git a/applications/utilities/mesh/manipulation/singleCellMesh/Make/files b/applications/utilities/mesh/manipulation/singleCellMesh/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..db941393b0800179cca310b587885dab85390ac7 --- /dev/null +++ b/applications/utilities/mesh/manipulation/singleCellMesh/Make/files @@ -0,0 +1,3 @@ +singleCellMesh.C + +EXE = $(FOAM_APPBIN)/singleCellMesh diff --git a/applications/utilities/mesh/manipulation/singleCellMesh/Make/options b/applications/utilities/mesh/manipulation/singleCellMesh/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..89e52b6d520dc088e6516df08f0f521f188a6353 --- /dev/null +++ b/applications/utilities/mesh/manipulation/singleCellMesh/Make/options @@ -0,0 +1,6 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude + +EXE_LIBS = \ + -lfiniteVolume + diff --git a/applications/utilities/mesh/manipulation/singleCellMesh/singleCellMesh.C b/applications/utilities/mesh/manipulation/singleCellMesh/singleCellMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..fe1e2850b97cccd5304e6809d91b01649ee97a37 --- /dev/null +++ b/applications/utilities/mesh/manipulation/singleCellMesh/singleCellMesh.C @@ -0,0 +1,142 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + singleCellMesh + +Description + Removes all but one cells of the mesh. Used to generate mesh and fields + that can be used for boundary-only data. + Might easily result in illegal mesh though so only look at boundaries + in paraview. + +\*---------------------------------------------------------------------------*/ + + +#include "argList.H" +#include "fvMesh.H" +#include "volFields.H" +#include "Time.H" +#include "ReadFields.H" +#include "singleCellFvMesh.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class GeoField> +void interpolateFields +( + const singleCellFvMesh& scMesh, + const PtrList<GeoField>& flds +) +{ + forAll(flds, i) + { + tmp<GeoField> scFld = scMesh.interpolate(flds[i]); + GeoField* scFldPtr = scFld.ptr(); + scFldPtr->writeOpt() = IOobject::AUTO_WRITE; + scFldPtr->store(); + } +} + + +// Main program: + +int main(int argc, char *argv[]) +{ + Foam::argList::validOptions.insert("overwrite", ""); +# include "addTimeOptions.H" +# include "setRootCase.H" +# include "createTime.H" + // Get times list + instantList Times = runTime.times(); +# include "checkTimeOptions.H" + runTime.setTime(Times[startTime], startTime); +# include "createMesh.H" + const word oldInstance = mesh.pointsInstance(); + + bool overwrite = args.optionFound("overwrite"); + + + // Read objects in time directory + IOobjectList objects(mesh, runTime.timeName()); + + // Read vol fields. + PtrList<volScalarField> vsFlds; + ReadFields(mesh, objects, vsFlds); + + PtrList<volVectorField> vvFlds; + ReadFields(mesh, objects, vvFlds); + + PtrList<volSphericalTensorField> vstFlds; + ReadFields(mesh, objects, vstFlds); + + PtrList<volSymmTensorField> vsymtFlds; + ReadFields(mesh, objects, vsymtFlds); + + PtrList<volTensorField> vtFlds; + ReadFields(mesh, objects, vtFlds); + + + if (!overwrite) + { + runTime++; + } + + // Create the mesh + singleCellFvMesh scMesh + ( + IOobject + ( + mesh.name(), + mesh.polyMesh::instance(), + runTime, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + + // Map and store the fields on the scMesh. + interpolateFields(scMesh, vsFlds); + interpolateFields(scMesh, vvFlds); + interpolateFields(scMesh, vstFlds); + interpolateFields(scMesh, vsymtFlds); + interpolateFields(scMesh, vtFlds); + + + // Write + Info<< "Writing mesh to time " << runTime.timeName() << endl; + scMesh.write(); + + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/primitiveMesh/primitivePatch/uindirectPrimitivePatch.H b/src/OpenFOAM/meshes/primitiveMesh/primitivePatch/uindirectPrimitivePatch.H new file mode 100644 index 0000000000000000000000000000000000000000..4afb30dd22888ee7cff0cf4357fe2ad5560ba186 --- /dev/null +++ b/src/OpenFOAM/meshes/primitiveMesh/primitivePatch/uindirectPrimitivePatch.H @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Typedef + Foam::uindirectPrimitivePatch + +Description + Foam::uindirectPrimitivePatch + +\*---------------------------------------------------------------------------*/ + +#ifndef uindirectPrimitivePatch_H +#define uindirectPrimitivePatch_H + +#include "PrimitivePatch.H" +#include "face.H" +#include "UIndirectList.H" +#include "pointField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + typedef PrimitivePatch<face, UIndirectList, const pointField&> + uindirectPrimitivePatch; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index c387ac994d85f7ec289e4540a869539167ca71d2..5fe44b935751f8c95bdc23e7e561c1b40ac7b359 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -1,6 +1,7 @@ fvMesh/fvMeshGeometry.C fvMesh/fvMesh.C +fvMesh/singleCellFvMesh/singleCellFvMesh.C fvMesh/fvMeshSubset/fvMeshSubset.C fvBoundaryMesh = fvMesh/fvBoundaryMesh diff --git a/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.C b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..65965f15d94612cdee4cee766e017666dc73a4df --- /dev/null +++ b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.C @@ -0,0 +1,640 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "singleCellFvMesh.H" +#include "syncTools.H" +#include "uindirectPrimitivePatch.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// Conversion is a two step process: +// - from original (fine) patch faces to agglomerations (aggloms might not +// be in correct patch order) +// - from agglomerations to coarse patch faces +void Foam::singleCellFvMesh::agglomerateMesh +( + const fvMesh& mesh, + const labelListList& agglom +) +{ + const polyBoundaryMesh& oldPatches = mesh.boundaryMesh(); + + // Check agglomeration within patch face range and continuous + labelList nAgglom(oldPatches.size()); + + forAll(oldPatches, patchI) + { + const polyPatch& pp = oldPatches[patchI]; + + nAgglom[patchI] = max(agglom[patchI])+1; + + forAll(pp, i) + { + if (agglom[patchI][i] < 0 || agglom[patchI][i] >= pp.size()) + { + FatalErrorIn + ( + "singleCellFvMesh::agglomerateMesh(..)" + ) << "agglomeration on patch " << patchI + << " is out of range 0.." << pp.size()-1 + << exit(FatalError); + } + } + } + + // Check agglomeration is sync + { + // Get neighbouring agglomeration + labelList nbrAgglom(mesh.nFaces()-mesh.nInternalFaces()); + forAll(oldPatches, patchI) + { + const polyPatch& pp = oldPatches[patchI]; + + if (pp.coupled()) + { + label offset = pp.start()-mesh.nInternalFaces(); + forAll(pp, i) + { + nbrAgglom[offset+i] = agglom[patchI][i]; + } + } + } + syncTools::swapBoundaryFaceList(mesh, nbrAgglom, false); + + + // Get correspondence between this agglomeration and remote one + Map<label> localToNbr(nbrAgglom.size()/10); + + forAll(oldPatches, patchI) + { + const polyPatch& pp = oldPatches[patchI]; + + if (pp.coupled()) + { + label offset = pp.start()-mesh.nInternalFaces(); + + forAll(pp, i) + { + label bFaceI = offset+i; + label myZone = agglom[patchI][i]; + label nbrZone = nbrAgglom[bFaceI]; + + Map<label>::const_iterator iter = localToNbr.find(myZone); + + if (iter == localToNbr.end()) + { + // First occurence of this zone. Store correspondence + // to remote zone number. + localToNbr.insert(myZone, nbrZone); + } + else + { + // Check that zone numbers are still the same. + if (iter() != nbrZone) + { + FatalErrorIn + ( + "singleCellFvMesh::agglomerateMesh(..)" + ) << "agglomeration is not synchronised across" + << " coupled patch " << pp.name() + << endl + << "Local agglomeration " << myZone + << ". Remote agglomeration " << nbrZone + << exit(FatalError); + } + } + } + } + } + } + + + label coarseI = 0; + forAll(nAgglom, patchI) + { + coarseI += nAgglom[patchI]; + } + // New faces + faceList patchFaces(coarseI); + // New patch start and size + labelList patchStarts(oldPatches.size()); + labelList patchSizes(oldPatches.size()); + + // From new patch face back to agglomeration + patchFaceMap_.setSize(oldPatches.size()); + + // Face counter + coarseI = 0; + + + forAll(oldPatches, patchI) + { + const polyPatch& pp = oldPatches[patchI]; + + if (pp.size() > 0) + { + patchFaceMap_[patchI].setSize(nAgglom[patchI]); + + // Patchfaces per agglomeration + labelListList agglomToPatch + ( + invertOneToMany(nAgglom[patchI], agglom[patchI]) + ); + + // From agglomeration to compact patch face + labelList agglomToFace(nAgglom[patchI], -1); + + patchStarts[patchI] = coarseI; + + forAll(pp, i) + { + label myAgglom = agglom[patchI][i]; + + if (agglomToFace[myAgglom] == -1) + { + // Agglomeration not yet done. We now have: + // - coarseI : current coarse mesh face + // - patchStarts[patchI] : coarse mesh patch start + // - myAgglom : agglomeration + // - agglomToPatch[myAgglom] : fine mesh faces for zone + label coarsePatchFaceI = coarseI - patchStarts[patchI]; + patchFaceMap_[patchI][coarsePatchFaceI] = myAgglom; + agglomToFace[myAgglom] = coarsePatchFaceI; + + const labelList& fineFaces = agglomToPatch[myAgglom]; + + // Create overall map from fine mesh faces to coarseI. + forAll(fineFaces, fineI) + { + reverseFaceMap_[pp.start()+fineFaces[fineI]] = coarseI; + } + + // Construct single face + uindirectPrimitivePatch upp + ( + UIndirectList<face>(pp, fineFaces), + pp.points() + ); + + if (upp.edgeLoops().size() != 1) + { + FatalErrorIn + ( + "singleCellFvMesh::agglomerateMesh(..)" + ) << "agglomeration does not create a" + << " single, non-manifold" + << " face for agglomeration " << coarseI + << exit(FatalError); + } + + patchFaces[coarseI++] = face + ( + renumber + ( + upp.meshPoints(), + upp.edgeLoops()[0] + ) + ); + } + } + + patchSizes[patchI] = coarseI-patchStarts[patchI]; + } + } + + //Pout<< "patchStarts:" << patchStarts << endl; + //Pout<< "patchSizes:" << patchSizes << endl; + + // Compact numbering for points + reversePointMap_.setSize(mesh.nPoints()); + reversePointMap_.labelList::operator=(-1); + label newI = 0; + + forAll(patchFaces, coarseI) + { + face& f = patchFaces[coarseI]; + + forAll(f, fp) + { + if (reversePointMap_[f[fp]] == -1) + { + reversePointMap_[f[fp]] = newI++; + } + + f[fp] = reversePointMap_[f[fp]]; + } + } + + pointMap_ = invert(newI, reversePointMap_); + + // Subset used points + pointField boundaryPoints(mesh.points(), pointMap_); + + // Add patches (on still zero sized mesh) + List<polyPatch*> newPatches(oldPatches.size()); + forAll(oldPatches, patchI) + { + newPatches[patchI] = oldPatches[patchI].clone + ( + boundaryMesh(), + patchI, + 0, + 0 + ).ptr(); + } + addFvPatches(newPatches); + + // Owner, neighbour is trivial + labelList owner(patchFaces.size(), 0); + labelList neighbour(0); + + + // actually change the mesh + resetPrimitives + ( + xferMove(boundaryPoints), + xferMove(patchFaces), + xferMove(owner), + xferMove(neighbour), + patchSizes, + patchStarts, + true //syncPar + ); + + + // Adapt the zones + cellZones().clear(); + cellZones().setSize(mesh.cellZones().size()); + { + forAll(mesh.cellZones(), zoneI) + { + const cellZone& oldFz = mesh.cellZones()[zoneI]; + + DynamicList<label> newAddressing; + + //Note: uncomment if you think it makes sense. Note that value + // of cell0 is the average. + //// Was old cell0 in this cellZone? + //if (oldFz.localID(0) != -1) + //{ + // newAddressing.append(0); + //} + + cellZones().set + ( + zoneI, + oldFz.clone + ( + newAddressing, + zoneI, + cellZones() + ) + ); + } + } + + faceZones().clear(); + faceZones().setSize(mesh.faceZones().size()); + { + forAll(mesh.faceZones(), zoneI) + { + const faceZone& oldFz = mesh.faceZones()[zoneI]; + + DynamicList<label> newAddressing(oldFz.size()); + DynamicList<bool> newFlipMap(oldFz.size()); + + forAll(oldFz, i) + { + label newFaceI = reverseFaceMap_[oldFz[i]]; + + if (newFaceI != -1) + { + newAddressing.append(newFaceI); + newFlipMap.append(oldFz.flipMap()[i]); + } + } + + faceZones().set + ( + zoneI, + oldFz.clone + ( + newAddressing, + newFlipMap, + zoneI, + faceZones() + ) + ); + } + } + + + pointZones().clear(); + pointZones().setSize(mesh.pointZones().size()); + { + forAll(mesh.pointZones(), zoneI) + { + const pointZone& oldFz = mesh.pointZones()[zoneI]; + + DynamicList<label> newAddressing(oldFz.size()); + + forAll(oldFz, i) + { + label newPointI = reversePointMap_[oldFz[i]]; + if (newPointI != -1) + { + newAddressing.append(newPointI); + } + } + + pointZones().set + ( + zoneI, + oldFz.clone + ( + pointZones(), + zoneI, + newAddressing + ) + ); + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::singleCellFvMesh::singleCellFvMesh +( + const IOobject& io, + const fvMesh& mesh +) +: + fvMesh + ( + io, + xferCopy(pointField()), //points + xferCopy(faceList()), //faces + xferCopy(labelList()), //allOwner + xferCopy(labelList()), //allNeighbour + false //syncPar + ), + patchFaceAgglomeration_ + ( + IOobject + ( + "patchFaceAgglomeration", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + 0 + ), + patchFaceMap_ + ( + IOobject + ( + "patchFaceMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.boundaryMesh().size() + ), + reverseFaceMap_ + ( + IOobject + ( + "reverseFaceMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.nFaces() + ), + pointMap_ + ( + IOobject + ( + "pointMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.nPoints() + ), + reversePointMap_ + ( + IOobject + ( + "reversePointMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.nPoints() + ) +{ + const polyBoundaryMesh& oldPatches = mesh.boundaryMesh(); + + labelListList agglom(oldPatches.size()); + + forAll(oldPatches, patchI) + { + agglom[patchI] = identity(oldPatches[patchI].size()); + } + + agglomerateMesh(mesh, agglom); +} + + +Foam::singleCellFvMesh::singleCellFvMesh +( + const IOobject& io, + const fvMesh& mesh, + const labelListList& patchFaceAgglomeration +) +: + fvMesh + ( + io, + xferCopy(pointField()), //points + xferCopy(faceList()), //faces + xferCopy(labelList()), //allOwner + xferCopy(labelList()), //allNeighbour + false //syncPar + ), + patchFaceAgglomeration_ + ( + IOobject + ( + "patchFaceAgglomeration", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + patchFaceAgglomeration + ), + patchFaceMap_ + ( + IOobject + ( + "patchFaceMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.boundaryMesh().size() + ), + reverseFaceMap_ + ( + IOobject + ( + "reverseFaceMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.nFaces() + ), + pointMap_ + ( + IOobject + ( + "pointMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.nPoints() + ), + reversePointMap_ + ( + IOobject + ( + "reversePointMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ), + mesh.nPoints() + ) +{ + agglomerateMesh(mesh, patchFaceAgglomeration); +} + + +Foam::singleCellFvMesh::singleCellFvMesh(const IOobject& io) +: + fvMesh(io), + patchFaceAgglomeration_ + ( + IOobject + ( + "patchFaceAgglomeration", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ) + ), + patchFaceMap_ + ( + IOobject + ( + "patchFaceMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ) + ), + reverseFaceMap_ + ( + IOobject + ( + "reverseFaceMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ) + ), + pointMap_ + ( + IOobject + ( + "pointMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ) + ), + reversePointMap_ + ( + IOobject + ( + "reversePointMap", + io.instance(), + fvMesh::meshSubDir, + *this, + io.readOpt(), + io.writeOpt() + ) + ) +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + + + +// ************************************************************************* // diff --git a/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.H b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.H new file mode 100644 index 0000000000000000000000000000000000000000..2a412f1f933c2043d811a48496a0dd26a3c5532a --- /dev/null +++ b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.H @@ -0,0 +1,245 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::singleCellFvMesh + +Description + fvMesh as subset of other mesh. Consists of one cell and all original + bounday faces. Useful when manipulating boundary data. Single internal + cell only needed to be able to manipulate in a standard way. + +SourceFiles + singleCellFvMesh.C + singleCellFvMeshInterpolate.C + +\*---------------------------------------------------------------------------*/ + +#ifndef singleCellFvMesh_H +#define singleCellFvMesh_H + +#include "fvPatchFieldMapper.H" +#include "fvMesh.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class singleCellFvMesh Declaration +\*---------------------------------------------------------------------------*/ + +class singleCellFvMesh +: + public fvMesh +{ + // Private data + + const labelListIOList patchFaceAgglomeration_; + + //- From patch faces back to agglomeration or fine mesh + labelListIOList patchFaceMap_; + + //- From fine mesh faces to coarse mesh + labelIOList reverseFaceMap_; + + //- From coarse points back to original mesh + labelIOList pointMap_; + + //- From fine points to coarse mesh + labelIOList reversePointMap_; + + + // Private Member Functions + + //- Calculate agglomerated mesh + void agglomerateMesh(const fvMesh&, const labelListList&); + + + //- Disallow default bitwise copy construct + singleCellFvMesh(const singleCellFvMesh&); + + //- Disallow default bitwise assignment + void operator=(const singleCellFvMesh&); + + +public: + + //- Patch field mapper class for non-agglomerated meshes + class directPatchFieldMapper + : + public fvPatchFieldMapper + { + // Private data + + const unallocLabelList& directAddressing_; + + public: + + //- Construct given addressing + directPatchFieldMapper(const unallocLabelList& directAddressing) + : + directAddressing_(directAddressing) + {} + + virtual label size() const + { + return directAddressing_.size(); + } + + virtual bool direct() const + { + return true; + } + + virtual const unallocLabelList& directAddressing() const + { + return directAddressing_; + } + }; + + //- Patch field mapper class for agglomerated meshes + class agglomPatchFieldMapper + : + public fvPatchFieldMapper + { + // Private data + + const labelListList& addressing_; + const scalarListList& weights_; + + public: + + //- Construct given addressing + agglomPatchFieldMapper + ( + const labelListList& addressing, + const scalarListList& weights + ) + : + addressing_(addressing), + weights_(weights) + {} + + virtual label size() const + { + return addressing_.size(); + } + + virtual bool direct() const + { + return false; + } + + virtual const labelListList& addressing() const + { + return addressing_; + } + + virtual const scalarListList& weights() const + { + return weights_; + } + }; + + + + // Constructors + + //- Construct from fvMesh and no agglomeration + singleCellFvMesh(const IOobject& io, const fvMesh&); + + //- Construct from fvMesh and agglomeration of boundary faces. + // agglomeration is per patch, per patch face index the agglomeration + // the face goes into. + singleCellFvMesh + ( + const IOobject& io, + const fvMesh&, + const labelListList& patchFaceAgglomeration + ); + + //- Read from IOobject + singleCellFvMesh(const IOobject& io); + + // Member Functions + + bool agglomerate() const + { + return patchFaceAgglomeration_.size() > 0; + } + + //- From patchFace on this back to original mesh or agglomeration + const labelListList& patchFaceMap() const + { + return patchFaceMap_; + } + + //- From point on this back to original mesh + const labelList& pointMap() const + { + return pointMap_; + } + + //- From face on original mesh to face on this + const labelList& reverseFaceMap() const + { + return reverseFaceMap_; + } + + //- From point on original mesh to point on this (or -1 for removed + // points) + const labelList& reversePointMap() const + { + return reversePointMap_; + } + + //- Map volField. Internal field set to average, patch fields straight + // copies. + template<class Type> + tmp<GeometricField<Type, fvPatchField, volMesh> > + interpolate + ( + const GeometricField<Type, fvPatchField, volMesh>& + ) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "singleCellFvMeshInterpolate.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMeshInterpolate.C b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMeshInterpolate.C new file mode 100644 index 0000000000000000000000000000000000000000..9e3a21a7b8711261d07377482390a7f3c7302109 --- /dev/null +++ b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMeshInterpolate.C @@ -0,0 +1,132 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "singleCellFvMesh.H" +#include "Time.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +tmp<GeometricField<Type, fvPatchField, volMesh> > singleCellFvMesh::interpolate +( + const GeometricField<Type, fvPatchField, volMesh>& vf +) const +{ + // Create internal-field values + Field<Type> internalField(1, gAverage(vf)); + + // Create and map the patch field values + PtrList<fvPatchField<Type> > patchFields(vf.boundaryField().size()); + + if (agglomerate()) + { + forAll(vf.boundaryField(), patchI) + { + const labelList& agglom = patchFaceAgglomeration_[patchI]; + label nAgglom = max(agglom)+1; + + // Use inverse of agglomeration. This is from agglomeration to + // original (fine) mesh patch face. + labelListList coarseToFine(invertOneToMany(nAgglom, agglom)); + inplaceReorder(patchFaceMap_[patchI], coarseToFine); + scalarListList coarseWeights(nAgglom); + forAll(coarseToFine, coarseI) + { + const labelList& fineFaces = coarseToFine[coarseI]; + coarseWeights[coarseI] = scalarList + ( + fineFaces.size(), + 1.0/fineFaces.size() + ); + } + + patchFields.set + ( + patchI, + fvPatchField<Type>::New + ( + vf.boundaryField()[patchI], + boundary()[patchI], + DimensionedField<Type, volMesh>::null(), + agglomPatchFieldMapper(coarseToFine, coarseWeights) + ) + ); + } + } + else + { + forAll(vf.boundaryField(), patchI) + { + labelList map(identity(vf.boundaryField()[patchI].size())); + + patchFields.set + ( + patchI, + fvPatchField<Type>::New + ( + vf.boundaryField()[patchI], + boundary()[patchI], + DimensionedField<Type, volMesh>::null(), + directPatchFieldMapper(map) + ) + ); + } + } + + // Create the complete field from the pieces + tmp<GeometricField<Type, fvPatchField, volMesh> > tresF + ( + new GeometricField<Type, fvPatchField, volMesh> + ( + IOobject + ( + vf.name(), + time().timeName(), + *this, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + *this, + vf.dimensions(), + internalField, + patchFields + ) + ); + + return tresF; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* //