mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: integrate surfField-based fluxSummary
- additional surface and surfaceAndDirection modes
This commit is contained in:
@ -25,6 +25,8 @@ License
|
|||||||
|
|
||||||
#include "fluxSummary.H"
|
#include "fluxSummary.H"
|
||||||
#include "surfaceFields.H"
|
#include "surfaceFields.H"
|
||||||
|
#include "surfFields.H"
|
||||||
|
#include "surfMesh.H"
|
||||||
#include "dictionary.H"
|
#include "dictionary.H"
|
||||||
#include "Time.H"
|
#include "Time.H"
|
||||||
#include "syncTools.H"
|
#include "syncTools.H"
|
||||||
@ -54,33 +56,59 @@ template<>
|
|||||||
const char* NamedEnum
|
const char* NamedEnum
|
||||||
<
|
<
|
||||||
functionObjects::fluxSummary::modeType,
|
functionObjects::fluxSummary::modeType,
|
||||||
3
|
5
|
||||||
>::names[] =
|
>::names[] =
|
||||||
{
|
{
|
||||||
"faceZone",
|
"faceZone",
|
||||||
"faceZoneAndDirection",
|
"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_;
|
Foam::functionObjects::fluxSummary::modeTypeNames_;
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * 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
|
Foam::word Foam::functionObjects::fluxSummary::checkFlowType
|
||||||
(
|
(
|
||||||
const dimensionSet& dims,
|
const dimensionSet& fieldDims,
|
||||||
const word& fieldName
|
const word& fieldName
|
||||||
) const
|
) 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";
|
return "volumetric";
|
||||||
}
|
}
|
||||||
else if (dims == dimMass/dimTime)
|
else if (dims == dimMass)
|
||||||
{
|
{
|
||||||
return "mass";
|
return "mass";
|
||||||
}
|
}
|
||||||
@ -88,7 +116,7 @@ Foam::word Foam::functionObjects::fluxSummary::checkFlowType
|
|||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "Unsupported flux field " << fieldName << " with dimensions "
|
<< "Unsupported flux field " << fieldName << " with dimensions "
|
||||||
<< dims
|
<< fieldDims
|
||||||
<< ". Expected either mass flow or volumetric flow rate."
|
<< ". Expected either mass flow or volumetric flow rate."
|
||||||
<< abort(FatalError);
|
<< 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
|
void Foam::functionObjects::fluxSummary::initialiseFaceZone
|
||||||
(
|
(
|
||||||
const word& faceZoneName,
|
const word& faceZoneName,
|
||||||
@ -570,15 +668,23 @@ void Foam::functionObjects::fluxSummary::initialiseCellZoneAndDirection
|
|||||||
|
|
||||||
Foam::scalar Foam::functionObjects::fluxSummary::totalArea
|
Foam::scalar Foam::functionObjects::fluxSummary::totalArea
|
||||||
(
|
(
|
||||||
const label zonei
|
const label idx
|
||||||
) const
|
) const
|
||||||
|
{
|
||||||
|
scalar sumMagSf = 0;
|
||||||
|
|
||||||
|
if (isSurfaceMode())
|
||||||
|
{
|
||||||
|
const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[idx]);
|
||||||
|
sumMagSf = sum(s.magSf());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
const surfaceScalarField& magSf = mesh_.magSf();
|
const surfaceScalarField& magSf = mesh_.magSf();
|
||||||
|
|
||||||
const labelList& faceIDs = faceID_[zonei];
|
const labelList& faceIDs = faceID_[idx];
|
||||||
const labelList& facePatchIDs = facePatchID_[zonei];
|
const labelList& facePatchIDs = facePatchID_[idx];
|
||||||
|
|
||||||
scalar sumMagSf = 0;
|
|
||||||
forAll(faceIDs, i)
|
forAll(faceIDs, i)
|
||||||
{
|
{
|
||||||
label facei = faceIDs[i];
|
label facei = faceIDs[i];
|
||||||
@ -593,11 +699,92 @@ Foam::scalar Foam::functionObjects::fluxSummary::totalArea
|
|||||||
sumMagSf += magSf.boundaryField()[patchi][facei];
|
sumMagSf += magSf.boundaryField()[patchi][facei];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return returnReduce(sumMagSf, sumOp<scalar>());
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
tmp<scalarField> tphis = phi & s.Sf();
|
||||||
|
const scalarField& phis = tphis();
|
||||||
|
|
||||||
|
forAll(s, i)
|
||||||
|
{
|
||||||
|
scalar phif = phis[i];
|
||||||
|
if (flips[i])
|
||||||
|
{
|
||||||
|
phif *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phif > 0)
|
||||||
|
{
|
||||||
|
phiPos += phif;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phiNeg += phif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
filePtrs_[surfi]
|
||||||
|
<< time_.value() << token::TAB
|
||||||
|
<< phiPos << token::TAB
|
||||||
|
<< phiNeg << token::TAB
|
||||||
|
<< netFlux << token::TAB
|
||||||
|
<< absoluteFlux
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log << endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::functionObjects::fluxSummary::fluxSummary
|
Foam::functionObjects::fluxSummary::fluxSummary
|
||||||
@ -708,6 +895,40 @@ bool Foam::functionObjects::fluxSummary::read(const dictionary& dict)
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(dict)
|
FatalIOErrorInFunction(dict)
|
||||||
@ -730,7 +951,16 @@ bool Foam::functionObjects::fluxSummary::read(const dictionary& dict)
|
|||||||
const word& zoneName = zoneNames_[zonei];
|
const word& zoneName = zoneNames_[zonei];
|
||||||
areas[zonei] = totalArea(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;
|
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
|
) const
|
||||||
{
|
{
|
||||||
writeHeader(os, "Flux summary");
|
writeHeader(os, "Flux summary");
|
||||||
|
if (isSurfaceMode())
|
||||||
|
{
|
||||||
|
writeHeaderValue(os, "Surface", zoneName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
writeHeaderValue(os, "Face zone", zoneName);
|
writeHeaderValue(os, "Face zone", zoneName);
|
||||||
|
}
|
||||||
writeHeaderValue(os, "Total area", area);
|
writeHeaderValue(os, "Total area", area);
|
||||||
|
|
||||||
switch (mode_)
|
switch (mode_)
|
||||||
{
|
{
|
||||||
case mdFaceZoneAndDirection:
|
case mdFaceZoneAndDirection:
|
||||||
case mdCellZoneAndDirection:
|
case mdCellZoneAndDirection:
|
||||||
|
case mdSurfaceAndDirection:
|
||||||
{
|
{
|
||||||
writeHeaderValue(os, "Reference direction", refDir);
|
writeHeaderValue(os, "Reference direction", refDir);
|
||||||
break;
|
break;
|
||||||
@ -799,6 +1037,11 @@ bool Foam::functionObjects::fluxSummary::execute()
|
|||||||
|
|
||||||
bool Foam::functionObjects::fluxSummary::write()
|
bool Foam::functionObjects::fluxSummary::write()
|
||||||
{
|
{
|
||||||
|
if (isSurfaceMode())
|
||||||
|
{
|
||||||
|
return surfaceModeWrite();
|
||||||
|
}
|
||||||
|
|
||||||
const surfaceScalarField& phi = lookupObject<surfaceScalarField>(phiName_);
|
const surfaceScalarField& phi = lookupObject<surfaceScalarField>(phiName_);
|
||||||
|
|
||||||
Log << type() << ' ' << name() << ' '
|
Log << type() << ' ' << name() << ' '
|
||||||
|
|||||||
@ -68,6 +68,8 @@ Usage
|
|||||||
- faceZone
|
- faceZone
|
||||||
- faceZoneAndDirection
|
- faceZoneAndDirection
|
||||||
- cellZoneAndDirection
|
- cellZoneAndDirection
|
||||||
|
- surface
|
||||||
|
- surfaceAndDirection
|
||||||
|
|
||||||
Output data is written to files of the form \<timeDir\>/<faceZoneName>.dat
|
Output data is written to files of the form \<timeDir\>/<faceZoneName>.dat
|
||||||
|
|
||||||
@ -116,11 +118,13 @@ public:
|
|||||||
{
|
{
|
||||||
mdFaceZone, //!< face zone
|
mdFaceZone, //!< face zone
|
||||||
mdFaceZoneAndDirection, //!< face zone with prescribed direction
|
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
|
//- Mode type names
|
||||||
static const NamedEnum<modeType, 3> modeTypeNames_;
|
static const NamedEnum<modeType, 5> modeTypeNames_;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -161,14 +165,36 @@ protected:
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Check if surface mode instead of zone mode
|
||||||
|
bool isSurfaceMode() const;
|
||||||
|
|
||||||
//- Check flowType (mass or volume).
|
//- Check flowType (mass or volume).
|
||||||
// Return name on success, fatal error on failure.
|
// Return name on success, fatal error on failure.
|
||||||
word checkFlowType
|
word checkFlowType
|
||||||
(
|
(
|
||||||
const dimensionSet& dims,
|
const dimensionSet& fieldDims,
|
||||||
const word& fieldName
|
const word& fieldName
|
||||||
) const;
|
) 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
|
//- Initialise face set from face zone
|
||||||
void initialiseFaceZone
|
void initialiseFaceZone
|
||||||
(
|
(
|
||||||
@ -204,8 +230,8 @@ protected:
|
|||||||
DynamicList<boolList>& faceFlip
|
DynamicList<boolList>& faceFlip
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Calculate the total area for the derived faceZone
|
//- Calculate the total area for the surface or derived faceZone
|
||||||
scalar totalArea(const label zonei) const;
|
scalar totalArea(const label idx) const;
|
||||||
|
|
||||||
//- Output file header information
|
//- Output file header information
|
||||||
virtual void writeFileHeader
|
virtual void writeFileHeader
|
||||||
@ -216,6 +242,9 @@ protected:
|
|||||||
Ostream& os
|
Ostream& os
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Specialized write for surfaces
|
||||||
|
bool surfaceModeWrite();
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct
|
//- Disallow default bitwise copy construct
|
||||||
fluxSummary(const fluxSummary&) = delete;
|
fluxSummary(const fluxSummary&) = delete;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user