singleCellFvMesh and application

This commit is contained in:
mattijs
2009-11-11 11:29:22 +00:00
parent 5a2eff8e17
commit 13bddac8f0
8 changed files with 1222 additions and 0 deletions

View File

@ -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
// ************************************************************************* //

View File

@ -1,6 +1,7 @@
fvMesh/fvMeshGeometry.C
fvMesh/fvMesh.C
fvMesh/singleCellFvMesh/singleCellFvMesh.C
fvMesh/fvMeshSubset/fvMeshSubset.C
fvBoundaryMesh = fvMesh/fvBoundaryMesh

View File

@ -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 * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //