/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2016-2021 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 "FacePostProcessing.H" #include "Pstream.H" #include "ListListOps.H" #include "globalIndex.H" #include "surfaceWriter.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template void Foam::FacePostProcessing::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()) { // Create directory if does not exist mkDir(this->writeTimeDir()); // Open new file at start up outputFilePtr_.set ( zoneI, new OFstream ( this->writeTimeDir()/(type() + '_' + zoneName + ".dat") ) ); outputFilePtr_[zoneI] << "# Source : " << type() << nl << "# Face zone : " << zoneName << nl << "# Faces : " << nFaces << nl << "# Area : " << totArea << nl << "# Time" << tab << "mass" << tab << "massFlowRate" << endl; } } } // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // template void Foam::FacePostProcessing::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 zoneMassTotal(mass_.size()); List 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 ( allProcMass, accessOp() ); const scalar sumMassTotal = sum(zoneMassTotal[zoneI]); scalarListList allProcMassFlowRate(Pstream::nProcs()); allProcMassFlowRate[proci] = massFlowRate_[zoneI]; Pstream::gatherList(allProcMassFlowRate); zoneMassFlowRate[zoneI] = ListListOps::combine ( allProcMassFlowRate, accessOp() ); 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 globalPointsPtr = mesh.globalData().mergePoints ( fZone().meshPoints(), fZone().meshPointMap(), pointToGlobal, uniqueMeshPointLabels ); pointField uniquePoints(mesh.points(), uniqueMeshPointLabels); List allProcPoints(Pstream::nProcs()); allProcPoints[proci] = uniquePoints; Pstream::gatherList(allProcPoints); faceList faces(fZone().localFaces()); forAll(faces, i) { inplaceRenumber(pointToGlobal, faces[i]); } List allProcFaces(Pstream::nProcs()); allProcFaces[proci] = faces; Pstream::gatherList(allProcFaces); if (Pstream::master()) { pointField allPoints ( ListListOps::combine ( allProcPoints, accessOp() ) ); faceList allFaces ( ListListOps::combine ( allProcFaces, accessOp() ) ); auto writer = surfaceWriter::New ( surfaceFormat_, this->coeffDict().subOrEmptyDict("formatOptions") .subOrEmptyDict(surfaceFormat_) ); if (debug) { writer->verbose(true); } writer->open ( allPoints, allFaces, (this->writeTimeDir() / fZone.name()), false // serial - already merged ); writer->nFields(2); // Legacy VTK writer->write("massTotal", zoneMassTotal[zoneI]); writer->write("massFlowRate", zoneMassFlowRate[zoneI]); } } } if (resetOnWrite_) { forAll(faceZoneIDs_, zoneI) { massFlowRate_[zoneI] = 0.0; } timeOld_ = timeNew; totalTime_ = 0.0; } forAll(mass_, zoneI) { mass_[zoneI] = 0.0; } // writeProperties(); } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template Foam::FacePostProcessing::FacePostProcessing ( const dictionary& dict, CloudType& owner, const word& modelName ) : CloudFunctionObject(dict, owner, modelName, typeName), faceZoneIDs_(), surfaceFormat_(this->coeffDict().lookup("surfaceFormat")), resetOnWrite_(this->coeffDict().getBool("resetOnWrite")), log_(this->coeffDict().getBool("log")), totalTime_(0.0), mass_(), massTotal_(), massFlowRate_(), outputFilePtr_(), 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()); DynamicList