From e6f8d27553542c6edbcb53779e468ec9f9024ad5 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@Germany> Date: Thu, 15 Dec 2016 12:59:35 +0100 Subject: [PATCH] ENH: integrate surfField-based fluxSummary - additional surface and surfaceAndDirection modes --- .../field/fluxSummary/fluxSummary.C | 289 ++++++++++++++++-- .../field/fluxSummary/fluxSummary.H | 39 ++- 2 files changed, 300 insertions(+), 28 deletions(-) diff --git a/src/functionObjects/field/fluxSummary/fluxSummary.C b/src/functionObjects/field/fluxSummary/fluxSummary.C index 5950b33c4a5..f176b2dda45 100644 --- a/src/functionObjects/field/fluxSummary/fluxSummary.C +++ b/src/functionObjects/field/fluxSummary/fluxSummary.C @@ -25,6 +25,8 @@ License #include "fluxSummary.H" #include "surfaceFields.H" +#include "surfFields.H" +#include "surfMesh.H" #include "dictionary.H" #include "Time.H" #include "syncTools.H" @@ -54,33 +56,59 @@ template<> const char* NamedEnum < functionObjects::fluxSummary::modeType, - 3 + 5 >::names[] = { "faceZone", "faceZoneAndDirection", - "cellZoneAndDirection" + "cellZoneAndDirection", + "surface", + "surfaceAndDirection" }; } -const Foam::NamedEnum<Foam::functionObjects::fluxSummary::modeType, 3> +const Foam::NamedEnum<Foam::functionObjects::fluxSummary::modeType, 5> Foam::functionObjects::fluxSummary::modeTypeNames_; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +bool Foam::functionObjects::fluxSummary::isSurfaceMode() const +{ + bool isSurf = false; + + switch (mode_) + { + case mdSurface: + case mdSurfaceAndDirection: + isSurf = true; + break; + + default: + break; + } + + return isSurf; +} + + Foam::word Foam::functionObjects::fluxSummary::checkFlowType ( - const dimensionSet& dims, + const dimensionSet& fieldDims, const word& fieldName ) const { - if (dims == dimVolume/dimTime) + // Surfaces are multipled by their area, so account for that + // in the dimension checking + dimensionSet dims = + fieldDims * (isSurfaceMode() ? dimTime*dimArea : dimTime); + + if (dims == dimVolume) { return "volumetric"; } - else if (dims == dimMass/dimTime) + else if (dims == dimMass) { return "mass"; } @@ -88,7 +116,7 @@ Foam::word Foam::functionObjects::fluxSummary::checkFlowType { FatalErrorInFunction << "Unsupported flux field " << fieldName << " with dimensions " - << dims + << fieldDims << ". Expected either mass flow or volumetric flow rate." << abort(FatalError); @@ -97,6 +125,76 @@ Foam::word Foam::functionObjects::fluxSummary::checkFlowType } +void Foam::functionObjects::fluxSummary::initialiseSurface +( + const word& surfName, + DynamicList<word>& names, + DynamicList<vector>& directions, + DynamicList<boolList>& faceFlip +) const +{ + const surfMesh* sPtr = mesh_.lookupObjectPtr<surfMesh>(surfName); + if (!sPtr) + { + FatalErrorInFunction + << "Unable to find surface " << surfName + << ". Valid surfaces are: " << mesh_.sortedNames<surfMesh>() + << '.' + << exit(FatalError); + } + + names.append(surfName); + directions.append(Zero); // dummy value + faceFlip.append(boolList(0)); // no flip-map +} + + +void Foam::functionObjects::fluxSummary::initialiseSurfaceAndDirection +( + const word& surfName, + const vector& dir, + DynamicList<word>& names, + DynamicList<vector>& directions, + DynamicList<boolList>& faceFlip +) const +{ + const surfMesh* sPtr = mesh_.lookupObjectPtr<surfMesh>(surfName); + if (!sPtr) + { + FatalErrorInFunction + << "Unable to find surface " << surfName + << ". Valid surfaces are: " << mesh_.sortedNames<surfMesh>() + << '.' + << exit(FatalError); + } + + const surfMesh& s = *sPtr; + const vector refDir = dir/(mag(dir) + ROOTVSMALL); + + names.append(surfName); + directions.append(refDir); + faceFlip.append(boolList(0)); + + boolList& flips = faceFlip[faceFlip.size()-1]; + flips.setSize(s.size(), false); + + forAll(s, i) + { + // orientation set by comparison with reference direction + const vector& n = s.faceNormals()[i]; + + if ((n & refDir) > tolerance_) + { + flips[i] = false; + } + else + { + flips[i] = true; + } + } +} + + void Foam::functionObjects::fluxSummary::initialiseFaceZone ( const word& faceZoneName, @@ -570,31 +668,120 @@ void Foam::functionObjects::fluxSummary::initialiseCellZoneAndDirection Foam::scalar Foam::functionObjects::fluxSummary::totalArea ( - const label zonei + const label idx ) const { - const surfaceScalarField& magSf = mesh_.magSf(); + scalar sumMagSf = 0; + + if (isSurfaceMode()) + { + const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[idx]); + sumMagSf = sum(s.magSf()); + } + else + { + const surfaceScalarField& magSf = mesh_.magSf(); - const labelList& faceIDs = faceID_[zonei]; - const labelList& facePatchIDs = facePatchID_[zonei]; + const labelList& faceIDs = faceID_[idx]; + const labelList& facePatchIDs = facePatchID_[idx]; - scalar sumMagSf = 0; - forAll(faceIDs, i) + forAll(faceIDs, i) + { + label facei = faceIDs[i]; + + if (facePatchIDs[i] == -1) + { + sumMagSf += magSf[facei]; + } + else + { + label patchi = facePatchIDs[i]; + sumMagSf += magSf.boundaryField()[patchi][facei]; + } + } + } + + return returnReduce(sumMagSf, sumOp<scalar>()); +} + + +bool Foam::functionObjects::fluxSummary::surfaceModeWrite() +{ + if (zoneNames_.size()) + { + const label surfi = 0; + const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[surfi]); + const surfVectorField& phi = s.lookupObject<surfVectorField>(phiName_); + + Log << type() << ' ' << name() << ' ' + << checkFlowType(phi.dimensions(), phi.name()) << " write:" << nl; + } + + + forAll(zoneNames_, surfi) { - label facei = faceIDs[i]; + const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[surfi]); + const surfVectorField& phi = s.lookupObject<surfVectorField>(phiName_); + + checkFlowType(phi.dimensions(), phi.name()); + + const boolList& flips = faceFlip_[surfi]; + + scalar phiPos = scalar(0); + scalar phiNeg = scalar(0); - if (facePatchIDs[i] == -1) + tmp<scalarField> tphis = phi & s.Sf(); + const scalarField& phis = tphis(); + + forAll(s, i) { - sumMagSf += magSf[facei]; + scalar phif = phis[i]; + if (flips[i]) + { + phif *= -1; + } + + if (phif > 0) + { + phiPos += phif; + } + else + { + phiNeg += phif; + } } - else + + reduce(phiPos, sumOp<scalar>()); + reduce(phiNeg, sumOp<scalar>()); + + phiPos *= scaleFactor_; + phiNeg *= scaleFactor_; + + scalar netFlux = phiPos + phiNeg; + scalar absoluteFlux = phiPos - phiNeg; + + Log << " surface " << zoneNames_[surfi] << ':' << nl + << " positive : " << phiPos << nl + << " negative : " << phiNeg << nl + << " net : " << netFlux << nl + << " absolute : " << absoluteFlux + << nl << endl; + + if (writeToFile()) { - label patchi = facePatchIDs[i]; - sumMagSf += magSf.boundaryField()[patchi][facei]; + filePtrs_[surfi] + << time_.value() << token::TAB + << phiPos << token::TAB + << phiNeg << token::TAB + << netFlux << token::TAB + << absoluteFlux + << endl; } } - return returnReduce(sumMagSf, sumOp<scalar>()); + Log << endl; + + return true; } @@ -708,6 +895,40 @@ bool Foam::functionObjects::fluxSummary::read(const dictionary& dict) } break; } + case mdSurface: + { + List<word> surfs(dict.lookup("surfaces")); + + forAll(surfs, i) + { + initialiseSurface + ( + surfs[i], + faceZoneName, + refDir, + faceFlips + ); + } + break; + } + case mdSurfaceAndDirection: + { + List<Tuple2<word, vector>> + surfAndDirection(dict.lookup("surfaceAndDirection")); + + forAll(surfAndDirection, i) + { + initialiseSurfaceAndDirection + ( + surfAndDirection[i].first(), + surfAndDirection[i].second(), + faceZoneName, + refDir, + faceFlips + ); + } + break; + } default: { FatalIOErrorInFunction(dict) @@ -730,7 +951,16 @@ bool Foam::functionObjects::fluxSummary::read(const dictionary& dict) const word& zoneName = zoneNames_[zonei]; areas[zonei] = totalArea(zonei); - Info<< " Zone: " << zoneName << ", area: " << areas[zonei] << nl; + if (isSurfaceMode()) + { + Info<< " Surface: " << zoneName + << ", area: " << areas[zonei] << nl; + } + else + { + Info<< " Zone: " << zoneName + << ", area: " << areas[zonei] << nl; + } } Info<< endl; @@ -752,7 +982,7 @@ bool Foam::functionObjects::fluxSummary::read(const dictionary& dict) } } - return true; + return !zoneNames_.empty(); } @@ -765,13 +995,21 @@ void Foam::functionObjects::fluxSummary::writeFileHeader ) const { writeHeader(os, "Flux summary"); - writeHeaderValue(os, "Face zone", zoneName); + if (isSurfaceMode()) + { + writeHeaderValue(os, "Surface", zoneName); + } + else + { + writeHeaderValue(os, "Face zone", zoneName); + } writeHeaderValue(os, "Total area", area); switch (mode_) { case mdFaceZoneAndDirection: case mdCellZoneAndDirection: + case mdSurfaceAndDirection: { writeHeaderValue(os, "Reference direction", refDir); break; @@ -799,6 +1037,11 @@ bool Foam::functionObjects::fluxSummary::execute() bool Foam::functionObjects::fluxSummary::write() { + if (isSurfaceMode()) + { + return surfaceModeWrite(); + } + const surfaceScalarField& phi = lookupObject<surfaceScalarField>(phiName_); Log << type() << ' ' << name() << ' ' diff --git a/src/functionObjects/field/fluxSummary/fluxSummary.H b/src/functionObjects/field/fluxSummary/fluxSummary.H index 2e135d2300a..287c6a3782f 100644 --- a/src/functionObjects/field/fluxSummary/fluxSummary.H +++ b/src/functionObjects/field/fluxSummary/fluxSummary.H @@ -68,6 +68,8 @@ Usage - faceZone - faceZoneAndDirection - cellZoneAndDirection + - surface + - surfaceAndDirection Output data is written to files of the form \<timeDir\>/<faceZoneName>.dat @@ -116,11 +118,13 @@ public: { mdFaceZone, //!< face zone mdFaceZoneAndDirection, //!< face zone with prescribed direction - mdCellZoneAndDirection //!< cell zone with prescribed direction + mdCellZoneAndDirection, //!< cell zone with prescribed direction + mdSurface, //!< surfMesh + mdSurfaceAndDirection //!< surfMesh with prescribed direction }; //- Mode type names - static const NamedEnum<modeType, 3> modeTypeNames_; + static const NamedEnum<modeType, 5> modeTypeNames_; protected: @@ -161,14 +165,36 @@ protected: // Private Member Functions + //- Check if surface mode instead of zone mode + bool isSurfaceMode() const; + //- Check flowType (mass or volume). // Return name on success, fatal error on failure. word checkFlowType ( - const dimensionSet& dims, + const dimensionSet& fieldDims, const word& fieldName ) const; + //- Initialise for given surface name + void initialiseSurface + ( + const word& surfName, + DynamicList<word>& names, + DynamicList<vector>& dir, + DynamicList<boolList>& faceFlip + ) const; + + //- Initialise for given surface name and direction + void initialiseSurfaceAndDirection + ( + const word& surfName, + const vector& refDir, + DynamicList<word>& names, + DynamicList<vector>& dir, + DynamicList<boolList>& faceFlip + ) const; + //- Initialise face set from face zone void initialiseFaceZone ( @@ -204,8 +230,8 @@ protected: DynamicList<boolList>& faceFlip ) const; - //- Calculate the total area for the derived faceZone - scalar totalArea(const label zonei) const; + //- Calculate the total area for the surface or derived faceZone + scalar totalArea(const label idx) const; //- Output file header information virtual void writeFileHeader @@ -216,6 +242,9 @@ protected: Ostream& os ) const; + //- Specialized write for surfaces + bool surfaceModeWrite(); + //- Disallow default bitwise copy construct fluxSummary(const fluxSummary&) = delete; -- GitLab