This repository has been archived on 2023-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
foam-extend4.1-coherent-io/applications/utilities/postProcessing/miscellaneous/postChannel/channelIndex.C

292 lines
7.8 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | foam-extend: Open Source CFD
\\ / O peration | Version: 3.2
\\ / A nd | Web: http://www.foam-extend.org
\\/ M anipulation | For copyright notice see file Copyright
-------------------------------------------------------------------------------
License
This file is part of foam-extend.
foam-extend 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.
foam-extend 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 foam-extend. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "channelIndex.H"
#include "boolList.H"
#include "syncTools.H"
#include "OFstream.H"
#include "meshTools.H"
#include "foamTime.H"
#include "SortableList.H"
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
template<>
const char* Foam::NamedEnum<Foam::vector::components, 3>::names[] =
{
"x",
"y",
"z"
};
const Foam::NamedEnum<Foam::vector::components, 3>
Foam::channelIndex::vectorComponentsNames_;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Determines face blocking
void Foam::channelIndex::walkOppositeFaces
(
const polyMesh& mesh,
const labelList& startFaces,
boolList& blockedFace
)
{
const cellList& cells = mesh.cells();
const faceList& faces = mesh.faces();
label nBnd = mesh.nFaces() - mesh.nInternalFaces();
DynamicList<label> frontFaces(startFaces);
forAll(frontFaces, i)
{
label faceI = frontFaces[i];
blockedFace[faceI] = true;
}
while (returnReduce(frontFaces.size(), sumOp<label>()) > 0)
{
// Transfer across.
boolList isFrontBndFace(nBnd, false);
forAll(frontFaces, i)
{
label faceI = frontFaces[i];
if (!mesh.isInternalFace(faceI))
{
isFrontBndFace[faceI-mesh.nInternalFaces()] = true;
}
}
syncTools::swapBoundaryFaceList(mesh, isFrontBndFace, false);
// Add
forAll(isFrontBndFace, i)
{
label faceI = mesh.nInternalFaces()+i;
if (isFrontBndFace[i] && !blockedFace[faceI])
{
blockedFace[faceI] = true;
frontFaces.append(faceI);
}
}
// Transfer across cells
DynamicList<label> newFrontFaces(frontFaces.size());
forAll(frontFaces, i)
{
label faceI = frontFaces[i];
{
const cell& ownCell = cells[mesh.faceOwner()[faceI]];
label oppositeFaceI = ownCell.opposingFaceLabel(faceI, faces);
if (oppositeFaceI == -1)
{
FatalErrorIn("channelIndex::walkOppositeFaces(..)")
<< "Face:" << faceI << " owner cell:" << ownCell
<< " is not a hex?" << abort(FatalError);
}
else
{
if (!blockedFace[oppositeFaceI])
{
blockedFace[oppositeFaceI] = true;
newFrontFaces.append(oppositeFaceI);
}
}
}
if (mesh.isInternalFace(faceI))
{
const cell& neiCell = mesh.cells()[mesh.faceNeighbour()[faceI]];
label oppositeFaceI = neiCell.opposingFaceLabel(faceI, faces);
if (oppositeFaceI == -1)
{
FatalErrorIn("channelIndex::walkOppositeFaces(..)")
<< "Face:" << faceI << " neighbour cell:" << neiCell
<< " is not a hex?" << abort(FatalError);
}
else
{
if (!blockedFace[oppositeFaceI])
{
blockedFace[oppositeFaceI] = true;
newFrontFaces.append(oppositeFaceI);
}
}
}
}
frontFaces.transfer(newFrontFaces);
}
}
// Calculate regions.
void Foam::channelIndex::calcLayeredRegions
(
const polyMesh& mesh,
const labelList& startFaces
)
{
boolList blockedFace(mesh.nFaces(), false);
walkOppositeFaces
(
mesh,
startFaces,
blockedFace
);
if (false)
{
OFstream str(mesh.time().path()/"blockedFaces.obj");
label vertI = 0;
forAll(blockedFace, faceI)
{
if (blockedFace[faceI])
{
const face& f = mesh.faces()[faceI];
forAll(f, fp)
{
meshTools::writeOBJ(str, mesh.points()[f[fp]]);
}
str<< 'f';
forAll(f, fp)
{
str << ' ' << vertI+fp+1;
}
str << nl;
vertI += f.size();
}
}
}
// Do analysis for connected regions
cellRegion_.reset(new regionSplit(mesh, blockedFace));
Info<< "Detected " << cellRegion_().nRegions() << " layers." << nl << endl;
// Sum number of entries per region
regionCount_ = regionSum(scalarField(mesh.nCells(), 1.0));
// Average cell centres to determine ordering.
pointField regionCc
(
regionSum(mesh.cellCentres())
/ regionCount_
);
SortableList<scalar> sortComponent(regionCc.component(dir_));
sortMap_ = sortComponent.indices();
y_ = sortComponent;
if (symmetric_)
{
y_.setSize(cellRegion_().nRegions()/2);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::channelIndex::channelIndex
(
const polyMesh& mesh,
const dictionary& dict
)
:
symmetric_(readBool(dict.lookup("symmetric"))),
dir_(vectorComponentsNames_.read(dict.lookup("component")))
{
const polyBoundaryMesh& patches = mesh.boundaryMesh();
const wordList patchNames(dict.lookup("patches"));
label nFaces = 0;
forAll(patchNames, i)
{
label patchI = patches.findPatchID(patchNames[i]);
if (patchI == -1)
{
FatalErrorIn("channelIndex::channelIndex(const polyMesh&)")
<< "Illegal patch " << patchNames[i]
<< ". Valid patches are " << patches.name()
<< exit(FatalError);
}
nFaces += patches[patchI].size();
}
labelList startFaces(nFaces);
nFaces = 0;
forAll(patchNames, i)
{
const polyPatch& pp = patches[patches.findPatchID(patchNames[i])];
forAll(pp, j)
{
startFaces[nFaces++] = pp.start()+j;
}
}
// Calculate regions.
calcLayeredRegions(mesh, startFaces);
}
Foam::channelIndex::channelIndex
(
const polyMesh& mesh,
const labelList& startFaces,
const bool symmetric,
const direction dir
)
:
symmetric_(symmetric),
dir_(dir)
{
// Calculate regions.
calcLayeredRegions(mesh, startFaces);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// ************************************************************************* //