-
andy authored3a960a33
FacePostProcessing.C 11.68 KiB
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ 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 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "FacePostProcessing.H"
#include "Pstream.H"
#include "ListListOps.H"
#include "surfaceWriter.H"
#include "globalIndex.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class CloudType>
void Foam::FacePostProcessing<CloudType>::makeLogFile
(
const word& zoneName,
const label zoneI,
const label nFaces,
const scalar totArea
)
{
// Create the output file if not already created
if (log_)
{
if (debug)
{
Info<< "Creating output file." << endl;
}
if (Pstream::master())
{
const fileName logDir = outputDir_/this->owner().time().timeName();
// Create directory if does not exist
mkDir(logDir);
// Open new file at start up
outputFilePtr_.set
(
zoneI,
new OFstream(logDir/(type() + '_' + zoneName + ".dat"))
);
outputFilePtr_[zoneI]
<< "# Source : " << type() << nl
<< "# Face zone : " << zoneName << nl
<< "# Faces : " << nFaces << nl
<< "# Area : " << totArea << nl
<< "# Time" << tab << "mass" << tab << "massFlowRate" << endl;
}
}
}
template<class CloudType>
void Foam::FacePostProcessing<CloudType>::write()
{
const fvMesh& mesh = this->owner().mesh();
const Time& time = mesh.time();
const faceZoneMesh& fzm = mesh.faceZones();
scalar timeNew = time.value();
scalar timeElapsed = timeNew - timeOld_;
totalTime_ += timeElapsed;
const scalar alpha = (totalTime_ - timeElapsed)/totalTime_;
const scalar beta = timeElapsed/totalTime_;
forAll(faceZoneIDs_, zoneI)
{
massFlowRate_[zoneI] =
alpha*massFlowRate_[zoneI] + beta*mass_[zoneI]/timeElapsed;
massTotal_[zoneI] += mass_[zoneI];
}
const label procI = Pstream::myProcNo();
Info<< type() << " output:" << nl;
List<scalarField> zoneMassTotal(mass_.size());
List<scalarField> zoneMassFlowRate(massFlowRate_.size());
forAll(faceZoneIDs_, zoneI)
{
const word& zoneName = fzm[faceZoneIDs_[zoneI]].name();
scalarListList allProcMass(Pstream::nProcs());
allProcMass[procI] = massTotal_[zoneI];
Pstream::gatherList(allProcMass);
zoneMassTotal[zoneI] =
ListListOps::combine<scalarList>
(
allProcMass, accessOp<scalarList>()
);
const scalar sumMassTotal = sum(zoneMassTotal[zoneI]);
scalarListList allProcMassFlowRate(Pstream::nProcs());
allProcMassFlowRate[procI] = massFlowRate_[zoneI];
Pstream::gatherList(allProcMassFlowRate);
zoneMassFlowRate[zoneI] =
ListListOps::combine<scalarList>
(
allProcMassFlowRate, accessOp<scalarList>()
);
const scalar sumMassFlowRate = sum(zoneMassFlowRate[zoneI]);
Info<< " " << zoneName
<< ": total mass = " << sumMassTotal
<< "; average mass flow rate = " << sumMassFlowRate
<< nl;
if (outputFilePtr_.set(zoneI))
{
OFstream& os = outputFilePtr_[zoneI];
os << time.timeName() << token::TAB << sumMassTotal << token::TAB
<< sumMassFlowRate<< endl;
}
}
Info<< endl;
if (surfaceFormat_ != "none")
{
forAll(faceZoneIDs_, zoneI)
{
const faceZone& fZone = fzm[faceZoneIDs_[zoneI]];
labelList pointToGlobal;
labelList uniqueMeshPointLabels;
autoPtr<globalIndex> globalPointsPtr =
mesh.globalData().mergePoints
(
fZone().meshPoints(),
fZone().meshPointMap(),
pointToGlobal,
uniqueMeshPointLabels
);
pointField uniquePoints(mesh.points(), uniqueMeshPointLabels);
List<pointField> allProcPoints(Pstream::nProcs());
allProcPoints[procI] = uniquePoints;
Pstream::gatherList(allProcPoints);
faceList faces(fZone().localFaces());
forAll(faces, i)
{
inplaceRenumber(pointToGlobal, faces[i]);
}
List<faceList> allProcFaces(Pstream::nProcs());
allProcFaces[procI] = faces;
Pstream::gatherList(allProcFaces);
if (Pstream::master())
{
pointField allPoints
(
ListListOps::combine<pointField>
(
allProcPoints, accessOp<pointField>()
)
);
faceList allFaces
(
ListListOps::combine<faceList>
(
allProcFaces, accessOp<faceList>()
)
);
autoPtr<surfaceWriter> writer
(
surfaceWriter::New(surfaceFormat_)
);
writer->write
(
outputDir_/time.timeName(),
fZone.name(),
allPoints,
allFaces,
"massTotal",
zoneMassTotal[zoneI],
false
);
writer->write
(
outputDir_/time.timeName(),
fZone.name(),
allPoints,
allFaces,
"massFlowRate",
zoneMassFlowRate[zoneI],
false
);
}
}
}
if (resetOnWrite_)
{
forAll(faceZoneIDs_, zoneI)
{
massFlowRate_[zoneI] = 0.0;
}
timeOld_ = timeNew;
totalTime_ = 0.0;
}
forAll(mass_, zoneI)
{
mass_[zoneI] = 0.0;
}
// writeProperties();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::FacePostProcessing<CloudType>::FacePostProcessing
(
const dictionary& dict,
CloudType& owner
)
:
CloudFunctionObject<CloudType>(dict, owner, typeName),
faceZoneIDs_(),
surfaceFormat_(this->coeffDict().lookup("surfaceFormat")),
resetOnWrite_(this->coeffDict().lookup("resetOnWrite")),
totalTime_(0.0),
mass_(),
massTotal_(),
massFlowRate_(),
log_(this->coeffDict().lookup("log")),
outputFilePtr_(),
outputDir_(owner.mesh().time().path()),
timeOld_(owner.mesh().time().value())
{
wordList faceZoneNames(this->coeffDict().lookup("faceZones"));
mass_.setSize(faceZoneNames.size());
massTotal_.setSize(faceZoneNames.size());
massFlowRate_.setSize(faceZoneNames.size());
outputFilePtr_.setSize(faceZoneNames.size());
if (Pstream::parRun())
{
// Put in undecomposed case (Note: gives problems for
// distributed data running)
outputDir_ =
outputDir_/".."/"postProcessing"/cloud::prefix/owner.name();
}
else
{
outputDir_ =
outputDir_/"postProcessing"/cloud::prefix/owner.name();
}
DynamicList<label> zoneIDs;
const faceZoneMesh& fzm = owner.mesh().faceZones();
const surfaceScalarField& magSf = owner.mesh().magSf();
const polyBoundaryMesh& pbm = owner.mesh().boundaryMesh();
forAll(faceZoneNames, i)
{
const word& zoneName = faceZoneNames[i];
label zoneI = fzm.findZoneID(zoneName);
if (zoneI != -1)
{
zoneIDs.append(zoneI);
const faceZone& fz = fzm[zoneI];
mass_[i].setSize(fz.size(), 0.0);
massTotal_[i].setSize(fz.size(), 0.0);
massFlowRate_[i].setSize(fz.size(), 0.0);
label nFaces = returnReduce(fz.size(), sumOp<label>());
Info<< " " << zoneName << " faces: " << nFaces << nl;
scalar totArea = 0.0;
forAll(fz, j)
{
label faceI = fz[j];
if (faceI < owner.mesh().nInternalFaces())
{
totArea += magSf[fz[j]];
}
else
{
label bFaceI = faceI - owner.mesh().nInternalFaces();
label patchI = pbm.patchID()[bFaceI];
const polyPatch& pp = pbm[patchI];
if
(
!pp.coupled()
|| refCast<const coupledPolyPatch>(pp).owner()
)
{
label localFaceI = pp.whichFace(faceI);
totArea += magSf.boundaryField()[patchI][localFaceI];
}
}
}
totArea = returnReduce(totArea, sumOp<scalar>());
makeLogFile(zoneName, i, nFaces, totArea);
}
}
faceZoneIDs_.transfer(zoneIDs);
// readProperties(); AND initialise mass... fields
}
template<class CloudType>
Foam::FacePostProcessing<CloudType>::FacePostProcessing
(
const FacePostProcessing<CloudType>& pff
)
:
CloudFunctionObject<CloudType>(pff),
faceZoneIDs_(pff.faceZoneIDs_),
surfaceFormat_(pff.surfaceFormat_),
resetOnWrite_(pff.resetOnWrite_),
totalTime_(pff.totalTime_),
mass_(pff.mass_),
massTotal_(pff.massTotal_),
massFlowRate_(pff.massFlowRate_),
log_(pff.log_),
outputFilePtr_(),
outputDir_(pff.outputDir_),
timeOld_(0.0)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class CloudType>
Foam::FacePostProcessing<CloudType>::~FacePostProcessing()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::FacePostProcessing<CloudType>::postFace
(
const parcelType& p,
const label faceI
)
{
if
(
this->owner().solution().output()
|| this->owner().solution().transient()
)
{
const faceZoneMesh& fzm = this->owner().mesh().faceZones();
forAll(faceZoneIDs_, i)
{
const faceZone& fz = fzm[faceZoneIDs_[i]];
label faceId = -1;
forAll(fz, j)
{
if (fz[j] == faceI)
{
faceId = j;
break;
}
}
if (faceId != -1)
{
mass_[i][faceId] += p.mass()*p.nParticle();
}
}
}
}
// ************************************************************************* //