ENH: refactor coordSet writers (#2347)

- the very old 'writer' class was fully stateless and always templated
  on an particular output type.

  This is now replaced with a 'coordSetWriter' with similar concepts
  as previously introduced for surface writers (#1206).

  - writers change from being a generic state-less set of routines to
    more properly conforming to the normal notion of a writer.

  - Parallel data is done *outside* of the writers, since they are used
    in a wide variety of contexts and the caller is currently still in
    a better position for deciding how to combine parallel data.

ENH: update sampleSets to sample on per-field basis (#2347)

- sample/write a field in a single step.

- support for 'sampleOnExecute' to obtain values at execution
  intervals without writing.

- support 'sets' input as a dictionary entry (as well as a list),
  which is similar to the changes for sampled-surface and permits use
  of changeDictionary to modify content.

- globalIndex for gather to reduce parallel communication, less code

- qualify the sampleSet results (properties) with the name of the set.
  The sample results were previously without a qualifier, which meant
  that only the last property value was actually saved (previous ones
  overwritten).

  For example,
  ```
    sample1
    {
        scalar
        {
            average(line,T) 349.96521;
            min(line,T)     349.9544281;
            max(line,T)     350;
            average(cells,T) 349.9854619;
            min(cells,T)    349.6589286;
            max(cells,T)    350.4967271;
            average(line,epsilon) 0.04947733869;
            min(line,epsilon) 0.04449639927;
            max(line,epsilon) 0.06452856475;
        }
        label
        {
            size(line,T)    79;
            size(cells,T)   1720;
            size(line,epsilon) 79;
        }
    }
  ```

ENH: update particleTracks application

- use globalIndex to manage original parcel addressing and
  for gathering. Simplify code by introducing a helper class,
  storing intermediate fields in hash tables instead of
  separate lists.

ADDITIONAL NOTES:

- the regionSizeDistribution largely retains separate writers since
  the utility of placing sum/dev/count for all fields into a single file
  is questionable.

- the streamline writing remains a "soft" upgrade, which means that
  scalar and vector fields are still collected a priori and not
  on-the-fly.  This is due to how the streamline infrastructure is
  currently handled (should be upgraded in the future).
This commit is contained in:
Mark Olesen
2022-02-25 14:50:01 +01:00
parent 8a9ae839ce
commit c3e14ffdd5
96 changed files with 8735 additions and 5178 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,6 +28,7 @@ License
#include "histogram.H"
#include "volFields.H"
#include "ListOps.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -42,41 +43,6 @@ namespace functionObjects
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::functionObjects::histogram::writeGraph
(
const coordSet& coords,
const word& fieldName,
const scalarField& normalizedValues,
const scalarField& absoluteValues
) const
{
fileName outputPath = baseTimeDir();
mkDir(outputPath);
OFstream graphFile
(
outputPath
/formatterPtr_().getFileName
(
coords,
wordList(1, fieldName)
)
);
Log << " Writing histogram of " << fieldName
<< " to " << graphFile.name() << endl;
wordList fieldNames(2);
fieldNames[0] = fieldName;
fieldNames[1] = fieldName + "Count";
List<const scalarField*> yPtrs(2);
yPtrs[0] = &normalizedValues;
yPtrs[1] = &absoluteValues;
formatterPtr_().write(coords, fieldNames, yPtrs, graphFile);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::histogram::histogram
@ -86,10 +52,11 @@ Foam::functionObjects::histogram::histogram
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict),
writeFile(obr_, name),
functionObjects::fvMeshFunctionObject(name, runTime, dict),
functionObjects::writeFile(obr_, name),
max_(-GREAT),
min_(GREAT)
min_(GREAT),
setWriterPtr_(nullptr)
{
read(dict);
}
@ -116,8 +83,13 @@ bool Foam::functionObjects::histogram::read(const dictionary& dict)
<< abort(FatalError);
}
const word format(dict.get<word>("setFormat"));
formatterPtr_ = writer<scalar>::New(format);
const word writeType(dict.get<word>("setFormat"));
setWriterPtr_ = coordSetWriter::New
(
writeType,
dict.subOrEmptyDict("formatOptions").optionalSubDict(writeType)
);
return true;
}
@ -133,38 +105,30 @@ bool Foam::functionObjects::histogram::write()
{
Log << type() << " " << name() << " write:" << nl;
autoPtr<volScalarField> fieldPtr;
if (obr_.foundObject<volScalarField>(fieldName_))
tmp<volScalarField> tfield;
tfield.cref(obr_.cfindObject<volScalarField>(fieldName_));
if (tfield)
{
Log << " Looking up field " << fieldName_ << endl;
}
else
{
Log << " Reading field " << fieldName_ << endl;
fieldPtr.reset
tfield = tmp<volScalarField>::New
(
new volScalarField
IOobject
(
IOobject
(
fieldName_,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
mesh_
)
fieldName_,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
mesh_
);
}
const volScalarField& field =
(
fieldPtr
? fieldPtr()
: obr_.lookupObject<volScalarField>(fieldName_)
);
const auto& field = tfield();
scalar histMax = max_;
scalar histMin = min_;
@ -188,14 +152,16 @@ bool Foam::functionObjects::histogram::write()
}
// Calculate the mid-points of bins for the graph axis
pointField xBin(nBins_);
const scalar delta = (histMax- histMin)/nBins_;
pointField xBin(nBins_, Zero);
const scalar delta = (histMax - histMin)/nBins_;
scalar x = histMin + 0.5*delta;
forAll(xBin, i)
{
xBin[i] = point(x, 0, 0);
x += delta;
scalar x = histMin + 0.5*delta;
for (point& p : xBin)
{
p.x() = x;
x += delta;
}
}
scalarField dataNormalized(nBins_, Zero);
@ -223,23 +189,27 @@ bool Foam::functionObjects::histogram::write()
{
dataNormalized /= sumData;
const coordSet coords
const coordSet coords(fieldName_, "x", xBin, mag(xBin));
auto& writer = *setWriterPtr_;
writer.open
(
fieldName_,
"x",
xBin,
mag(xBin)
coords,
(
writeFile::baseTimeDir()
/ (coords.name() + coordSetWriter::suffix(fieldName_))
)
);
Log << " Writing histogram of " << fieldName_
<< " to " << writer.path() << endl;
// Convert count field from labelField to scalarField
scalarField count(dataCount.size());
forAll(count, i)
{
count[i] = 1.0*dataCount[i];
}
writer.nFields(2);
writer.write(fieldName_, dataNormalized);
writer.write(fieldName_ + "Count", dataCount);
writeGraph(coords, fieldName_, dataNormalized, count);
writer.close(true);
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -100,12 +100,12 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_histogram_H
#define functionObjects_histogram_H
#ifndef Foam_functionObjects_histogram_H
#define Foam_functionObjects_histogram_H
#include "fvMeshFunctionObject.H"
#include "writeFile.H"
#include "writer.H"
#include "coordSetWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -120,8 +120,8 @@ namespace functionObjects
class histogram
:
public fvMeshFunctionObject,
public writeFile
public functionObjects::fvMeshFunctionObject,
public functionObjects::writeFile
{
// Private Data
@ -138,18 +138,7 @@ class histogram
scalar min_;
//- Output formatter to write
autoPtr<writer<scalar>> formatterPtr_;
// Private Member Functions
void writeGraph
(
const coordSet& coords,
const word& valueName,
const scalarField& normalizedValues,
const scalarField& absoluteValues
) const;
mutable autoPtr<coordSetWriter> setWriterPtr_;
public:

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -78,8 +78,13 @@ bool Foam::functionObjects::particleDistribution::read(const dictionary& dict)
dict.readEntry("cloud", cloudName_);
dict.readIfPresent("tagField", tagFieldName_);
dict.readEntry("nameVsBinWidth", nameVsBinWidth_);
const word format(dict.get<word>("setFormat"));
writerPtr_ = writer<scalar>::New(format);
const word setFormat(dict.get<word>("setFormat"));
writerPtr_ = coordSetWriter::New
(
setFormat,
dict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
);
Info<< type() << " " << name() << " output:" << nl
<< " Processing cloud : " << cloudName_ << nl
@ -104,12 +109,10 @@ bool Foam::functionObjects::particleDistribution::write()
if (!mesh_.foundObject<cloud>(cloudName_))
{
wordList cloudNames(mesh_.names<cloud>());
WarningInFunction
<< "Unable to find cloud " << cloudName_
<< " in the mesh database. Available clouds include:"
<< cloudNames << endl;
<< flatOutput(mesh_.sortedNames<cloud>()) << endl;
return false;
}
@ -153,16 +156,17 @@ bool Foam::functionObjects::particleDistribution::write()
}
bool ok = false;
forAll(nameVsBinWidth_, i)
{
ok = false;
ok = ok || processField<scalar>(cloudObr, i, tagAddr);
ok = ok || processField<vector>(cloudObr, i, tagAddr);
ok = ok || processField<tensor>(cloudObr, i, tagAddr);
ok = ok || processField<sphericalTensor>(cloudObr, i, tagAddr);
ok = ok || processField<symmTensor>(cloudObr, i, tagAddr);
ok = ok || processField<tensor>(cloudObr, i, tagAddr);
const bool ok
(
processField<scalar>(cloudObr, i, tagAddr)
|| processField<vector>(cloudObr, i, tagAddr)
|| processField<tensor>(cloudObr, i, tagAddr)
|| processField<sphericalTensor>(cloudObr, i, tagAddr)
|| processField<symmTensor>(cloudObr, i, tagAddr)
|| processField<tensor>(cloudObr, i, tagAddr)
);
if (log && !ok)
{
@ -189,10 +193,10 @@ void Foam::functionObjects::particleDistribution::generateDistribution
return;
}
word fName(fieldName);
word fldName(fieldName);
if (tag != -1)
{
fName = fName + '_' + Foam::name(tag);
fldName += '_' + Foam::name(tag);
}
distributionModels::general distribution
@ -202,31 +206,20 @@ void Foam::functionObjects::particleDistribution::generateDistribution
rndGen_
);
const Field<scalar> distX(distribution.x());
const Field<scalar> distY(distribution.y());
Field<scalar> distX(distribution.x());
Field<scalar> distY(distribution.y());
pointField xBin(distX.size(), Zero);
xBin.replace(0, distX);
const coordSet coords
(
fName,
"x",
xBin,
distX
);
xBin.replace(vector::X, distX);
const wordList fieldNames(1, fName);
const coordSet coords(fldName, "x", std::move(xBin), std::move(distX));
fileName outputPath(baseTimeDir());
mkDir(outputPath);
OFstream graphFile(outputPath/writerPtr_->getFileName(coords, fieldNames));
writerPtr_->open(coords, baseTimeDir() / fldName);
fileName outFile = writerPtr_->write(fldName, distY);
writerPtr_->close(true);
Log << " Writing distribution of " << fieldName
<< " to " << graphFile.name() << endl;
List<const scalarField*> yPtrs(1);
yPtrs[0] = &distY;
writerPtr_->write(coords, fieldNames, yPtrs, graphFile);
Log << " Wrote distribution of " << fieldName
<< " to " << time_.relativePath(outFile) << endl;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -103,7 +103,7 @@ SourceFiles
#include "scalarField.H"
#include "Random.H"
#include "Tuple2.H"
#include "writer.H"
#include "coordSetWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -118,7 +118,7 @@ namespace functionObjects
class particleDistribution
:
public fvMeshFunctionObject,
public functionObjects::fvMeshFunctionObject,
public writeFile
{
protected:
@ -138,7 +138,7 @@ protected:
List<Tuple2<word, scalar>> nameVsBinWidth_;
//- Writer
autoPtr<writer<scalar>> writerPtr_;
mutable autoPtr<coordSetWriter> writerPtr_;
// Protected Member Functions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,8 @@ License
\*---------------------------------------------------------------------------*/
#include "regionSizeDistribution.H"
#include "regionSplit.H"
#include "volFields.H"
#include "fvcVolumeIntegrate.H"
#include "addToRunTimeSelectionTable.H"
@ -47,31 +49,47 @@ namespace Foam
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
void Foam::functionObjects::regionSizeDistribution::writeGraph
(
const coordSet& coords,
const word& valueName,
const scalarField& values
) const
namespace Foam
{
const wordList valNames(1, valueName);
fileName outputPath = baseTimeDir();
mkDir(outputPath);
template<class Type>
static Map<Type> regionSum(const regionSplit& regions, const Field<Type>& fld)
{
// Per region the sum of fld
Map<Type> regionToSum(regions.nRegions()/Pstream::nProcs());
OFstream str(outputPath/formatterPtr_().getFileName(coords, valNames));
forAll(fld, celli)
{
const label regioni = regions[celli];
regionToSum(regioni, Type(Zero)) += fld[celli];
}
Log << " Writing distribution of " << valueName << " to " << str.name()
<< endl;
Pstream::mapCombineGather(regionToSum, plusEqOp<Type>());
Pstream::mapCombineScatter(regionToSum);
List<const scalarField*> valPtrs(1);
valPtrs[0] = &values;
formatterPtr_().write(coords, valNames, valPtrs, str);
return regionToSum;
}
template<class Type>
static List<Type> extractData(const labelUList& keys, const Map<Type>& regionData)
{
List<Type> sortedData(keys.size());
forAll(keys, i)
{
sortedData[i] = regionData[keys[i]];
}
return sortedData;
}
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::functionObjects::regionSizeDistribution::writeAlphaFields
(
const regionSplit& regions,
@ -222,7 +240,7 @@ Foam::functionObjects::regionSizeDistribution::divide
}
else
{
result[i] = 0.0;
result[i] = 0;
}
}
return tresult;
@ -232,8 +250,9 @@ Foam::functionObjects::regionSizeDistribution::divide
void Foam::functionObjects::regionSizeDistribution::writeGraphs
(
const word& fieldName, // name of field
const labelList& indices, // index of bin for each region
const scalarField& sortedField, // per region field data
const labelList& indices, // index of bin for each region
const scalarField& binCount, // per bin number of regions
const coordSet& coords // graph data for bins
) const
@ -260,12 +279,44 @@ void Foam::functionObjects::regionSizeDistribution::writeGraphs
sqrt(divide(binSqrSum, binCount) - Foam::sqr(binAvg))
);
// Write average
writeGraph(coords, fieldName + "_sum", binSum);
// Write average
writeGraph(coords, fieldName + "_avg", binAvg);
// Write deviation
writeGraph(coords, fieldName + "_dev", binDev);
auto& writer = formatterPtr_();
word outputName;
if (writer.buffering())
{
outputName =
(
coords.name()
+ coordSetWriter::suffix
(
wordList
({
fieldName + "_sum",
fieldName + "_avg",
fieldName + "_dev"
})
)
);
}
else
{
outputName = coords.name();
}
writer.open
(
coords,
(baseTimeDir() / outputName)
);
Log << " Writing distribution of "
<< fieldName << " to " << writer.path() << endl;
writer.write(fieldName + "_sum", binSum);
writer.write(fieldName + "_avg", binAvg);
writer.write(fieldName + "_dev", binDev);
writer.close(true);
}
}
@ -290,18 +341,15 @@ void Foam::functionObjects::regionSizeDistribution::writeGraphs
scalarField sortedField
(
sortedNormalisation
* extractData
(
sortedRegions,
regionField
)
* extractData(sortedRegions, regionField)
);
writeGraphs
(
fieldName, // name of field
indices, // index of bin for each region
sortedField, // per region field data
indices, // index of bin for each region
binCount, // per bin number of regions
coords // graph data for bins
);
@ -343,8 +391,12 @@ bool Foam::functionObjects::regionSizeDistribution::read(const dictionary& dict)
dict.readEntry("patches", patchNames_);
dict.readEntry("fields", fields_);
const word format(dict.get<word>("setFormat"));
formatterPtr_ = writer<scalar>::New(format);
const word setFormat(dict.get<word>("setFormat"));
formatterPtr_ = coordSetWriter::New
(
setFormat,
dict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
);
if (dict.found(coordinateSystem::typeName_()))
{
@ -385,15 +437,16 @@ bool Foam::functionObjects::regionSizeDistribution::write()
{
Log << type() << " " << name() << " write:" << nl;
autoPtr<volScalarField> alphaPtr;
if (obr_.foundObject<volScalarField>(alphaName_))
tmp<volScalarField> talpha;
talpha.cref(obr_.cfindObject<volScalarField>(alphaName_));
if (talpha)
{
Log << " Looking up field " << alphaName_ << endl;
}
else
{
Info<< " Reading field " << alphaName_ << endl;
alphaPtr.reset
talpha.reset
(
new volScalarField
(
@ -409,14 +462,7 @@ bool Foam::functionObjects::regionSizeDistribution::write()
)
);
}
const volScalarField& alpha =
(
alphaPtr
? *alphaPtr
: obr_.lookupObject<volScalarField>(alphaName_)
);
const auto& alpha = talpha();
Log << " Volume of alpha = "
<< fvc::domainIntegrate(alpha).value()
@ -460,10 +506,9 @@ bool Foam::functionObjects::regionSizeDistribution::write()
if (fvp.coupled())
{
tmp<scalarField> townFld(fvp.patchInternalField());
const scalarField& ownFld = townFld();
tmp<scalarField> tnbrFld(fvp.patchNeighbourField());
const scalarField& nbrFld = tnbrFld();
const auto& ownFld = townFld();
const auto& nbrFld = tnbrFld();
label start = fvp.patch().patch().start();
@ -663,13 +708,15 @@ bool Foam::functionObjects::regionSizeDistribution::write()
if (allRegionVolume.size())
{
// Construct mids of bins for plotting
pointField xBin(nBins_);
pointField xBin(nBins_, Zero);
scalar x = 0.5*delta;
forAll(xBin, i)
{
xBin[i] = point(x, 0, 0);
x += delta;
scalar x = 0.5*delta;
for (point& p : xBin)
{
p.x() = x;
x += delta;
}
}
const coordSet coords("diameter", "x", xBin, mag(xBin));
@ -682,11 +729,7 @@ bool Foam::functionObjects::regionSizeDistribution::write()
scalarField sortedVols
(
extractData
(
sortedRegions,
allRegionAlphaVolume
)
extractData(sortedRegions, allRegionAlphaVolume)
);
vectorField centroids(sortedVols.size(), Zero);
@ -712,11 +755,7 @@ bool Foam::functionObjects::regionSizeDistribution::write()
// 2. centroid
vectorField sortedMoment
(
extractData
(
sortedRegions,
allRegionAlphaDistance
)
extractData(sortedRegions, allRegionAlphaDistance)
);
centroids = sortedMoment/sortedVols + origin_;
@ -756,17 +795,30 @@ bool Foam::functionObjects::regionSizeDistribution::write()
if (Pstream::master())
{
// Construct mids of bins for plotting
pointField xBin(nDownstreamBins_);
pointField xBin(nDownstreamBins_, Zero);
scalar x = 0.5*deltaX;
forAll(xBin, i)
{
xBin[i] = point(x, 0, 0);
x += deltaX;
scalar x = 0.5*deltaX;
for (point& p : xBin)
{
p.x() = x;
x += deltaX;
}
}
const coordSet coords("distance", "x", xBin, mag(xBin));
writeGraph(coords, "isoPlanes", binDownCount);
auto& writer = formatterPtr_();
writer.nFields(1);
writer.open
(
coords,
writeFile::baseTimeDir() / (coords.name() + "_isoPlanes")
);
writer.write("isoPlanes", binDownCount);
writer.close(true);
}
// Write to log
@ -819,7 +871,17 @@ bool Foam::functionObjects::regionSizeDistribution::write()
// Write counts
if (Pstream::master())
{
writeGraph(coords, "count", binCount);
auto& writer = formatterPtr_();
writer.nFields(1);
writer.open
(
coords,
writeFile::baseTimeDir() / (coords.name() + "_count")
);
writer.write("count", binCount);
writer.close(true);
}
// Write to log
@ -849,28 +911,28 @@ bool Foam::functionObjects::regionSizeDistribution::write()
writeGraphs
(
"volume", // name of field
indices, // per region the bin index
sortedVols, // per region field data
indices, // per region the bin index
binCount, // per bin number of regions
coords // graph data for bins
);
// Collect some more field
// Collect some more fields
{
wordList scalarNames(obr_.names(volScalarField::typeName));
const labelList selected(fields_.matching(scalarNames));
for (const label fieldi : selected)
for
(
const word& fldName
: obr_.sortedNames<volScalarField>(fields_)
)
{
const word& fldName = scalarNames[fieldi];
Log << " Scalar field " << fldName << endl;
const scalarField& fld = obr_.lookupObject
<
volScalarField
>(fldName).primitiveField();
tmp<Field<scalar>> tfld
(
obr_.lookupObject<volScalarField>(fldName).primitiveField()
);
const auto& fld = tfld();
writeGraphs
(
@ -887,21 +949,20 @@ bool Foam::functionObjects::regionSizeDistribution::write()
);
}
}
{
wordList vectorNames(obr_.names(volVectorField::typeName));
const labelList selected(fields_.matching(vectorNames));
for (const label fieldi : selected)
for
(
const word& fldName
: obr_.sortedNames<volVectorField>(fields_)
)
{
const word& fldName = vectorNames[fieldi];
Log << " Vector field " << fldName << endl;
vectorField fld = obr_.lookupObject
<
volVectorField
>(fldName).primitiveField();
tmp<Field<vector>> tfld
(
obr_.lookupObject<volVectorField>(fldName).primitiveField()
);
if (csysPtr_)
{
@ -910,18 +971,18 @@ bool Foam::functionObjects::regionSizeDistribution::write()
<< csysPtr_->name()
<< endl;
fld = csysPtr_->localVector(fld);
tfld = csysPtr_->localVector(tfld());
}
const auto& fld = tfld();
// Components
for (direction cmp = 0; cmp < vector::nComponents; cmp++)
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
{
writeGraphs
(
fldName + vector::componentNames[cmp],
alphaVol*fld.component(cmp),// per cell field data
fldName + vector::componentNames[cmpt],
alphaVol*fld.component(cmpt),// per cell field data
regions, // per cell the region(=droplet)
sortedRegions, // valid regions in sorted order

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -169,17 +169,16 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_regionSizeDistribution_H
#define functionObjects_regionSizeDistribution_H
#ifndef Foam_functionObjects_regionSizeDistribution_H
#define Foam_functionObjects_regionSizeDistribution_H
#include "fvMeshFunctionObject.H"
#include "writeFile.H"
#include "writer.H"
#include "coordSetWriter.H"
#include "Map.H"
#include "volFieldsFwd.H"
#include "wordRes.H"
#include "coordinateSystem.H"
#include "Switch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -197,7 +196,7 @@ namespace functionObjects
class regionSizeDistribution
:
public fvMeshFunctionObject,
public functionObjects::fvMeshFunctionObject,
public writeFile
{
// Private Data
@ -224,7 +223,7 @@ class regionSizeDistribution
wordRes fields_;
//- Output formatter to write
autoPtr<writer<scalar>> formatterPtr_;
mutable autoPtr<coordSetWriter> formatterPtr_;
//- Optional coordinate system
autoPtr<coordinateSystem> csysPtr_;
@ -253,20 +252,6 @@ class regionSizeDistribution
// Private Member Functions
template<class Type>
Map<Type> regionSum(const regionSplit&, const Field<Type>&) const;
//- Get data in order
template<class Type>
List<Type> extractData(const labelUList& keys, const Map<Type>&) const;
void writeGraph
(
const coordSet& coords,
const word& valueName,
const scalarField& values
) const;
//- Write volfields with the parts of alpha which are not
//- droplets (liquidCore, backGround)
void writeAlphaFields
@ -287,8 +272,9 @@ class regionSizeDistribution
void writeGraphs
(
const word& fieldName, // name of field
const labelList& indices, // index of bin for each region
const scalarField& sortedField, // per region field data
const labelList& indices, // index of bin for each region
const scalarField& binCount, // per bin number of regions
const coordSet& coords // graph data for bins
) const;
@ -301,6 +287,7 @@ class regionSizeDistribution
const regionSplit& regions, // per cell the region(=droplet)
const labelList& sortedRegions, // valid regions in sorted order
const scalarField& sortedNormalisation,
const labelList& indices, // index of bin for each region
const scalarField& binCount, // per bin number of regions
const coordSet& coords // graph data for bins
@ -355,12 +342,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "regionSizeDistributionTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,75 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "regionSizeDistribution.H"
#include "regionSplit.H"
#include "volFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::Map<Type> Foam::functionObjects::regionSizeDistribution::regionSum
(
const regionSplit& regions,
const Field<Type>& fld
) const
{
// Per region the sum of fld
Map<Type> regionToSum(regions.nRegions()/Pstream::nProcs());
forAll(fld, celli)
{
const label regioni = regions[celli];
regionToSum(regioni, Type(Zero)) += fld[celli];
}
Pstream::mapCombineGather(regionToSum, plusEqOp<Type>());
Pstream::mapCombineScatter(regionToSum);
return regionToSum;
}
template<class Type>
Foam::List<Type> Foam::functionObjects::regionSizeDistribution::extractData
(
const labelUList& keys,
const Map<Type>& regionData
) const
{
List<Type> sortedData(keys.size());
forAll(keys, i)
{
sortedData[i] = regionData[keys[i]];
}
return sortedData;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2015-2021 OpenCFD Ltd.
Copyright (C) 2015-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +29,7 @@ License
#include "streamLineBase.H"
#include "fvMesh.H"
#include "ReadFields.H"
#include "OFstream.H"
#include "sampledSet.H"
#include "globalIndex.H"
#include "mapDistribute.H"
@ -626,8 +627,7 @@ bool Foam::functionObjects::streamLineBase::writeToFile()
// Note: filenames scattered below since used in global call
fileName scalarVtkFile;
fileName vectorVtkFile;
HashTable<fileName> outputFileNames;
if (Pstream::master())
{
@ -706,117 +706,112 @@ bool Foam::functionObjects::streamLineBase::writeToFile()
}
}
// Convert scalar values
if (!allScalars_.empty() && !tracks.empty())
const bool canWrite =
(
!tracks.empty()
&& trackWriterPtr_
&& trackWriterPtr_->enabled()
&& (!allScalars_.empty() || !allVectors_.empty())
);
if (canWrite)
{
List<List<scalarField>> scalarValues(allScalars_.size());
auto& writer = trackWriterPtr_();
forAll(allScalars_, scalari)
writer.nFields(allScalars_.size() + allVectors_.size());
writer.open
(
tracks,
(vtkPath / tracks[0].name())
);
// Temporary measure
if (!allScalars_.empty())
{
DynamicList<scalarList>& allTrackVals = allScalars_[scalari];
scalarValues[scalari].setSize(nTracks);
List<List<scalarField>> scalarValues(allScalars_.size());
forAll(allTrackVals, tracki)
forAll(allScalars_, scalari)
{
scalarList& vals = allTrackVals[tracki];
if (vals.size())
DynamicList<scalarList>& allTrackVals = allScalars_[scalari];
scalarValues[scalari].resize(nTracks);
forAll(allTrackVals, tracki)
{
const label newTracki = oldToNewTrack[tracki];
scalarValues[scalari][newTracki].transfer(vals);
scalarList& vals = allTrackVals[tracki];
if (vals.size())
{
const label newTracki = oldToNewTrack[tracki];
scalarValues[scalari][newTracki].transfer(vals);
}
}
}
forAll(scalarNames_, i)
{
fileName outFile =
writer.write(scalarNames_[i], scalarValues[i]);
outputFileNames.insert
(
scalarNames_[i],
time_.relativePath(outFile, true)
);
}
}
scalarVtkFile = fileName
(
vtkPath
/ scalarFormatterPtr_().getFileName
(
tracks[0],
scalarNames_
)
);
Log << " Writing data to " << scalarVtkFile.path() << endl;
scalarFormatterPtr_().write
(
true, // writeTracks
List<scalarField>(), // times
tracks,
scalarNames_,
scalarValues,
OFstream(scalarVtkFile)()
);
}
// Convert vector values
if (!allVectors_.empty() && !tracks.empty())
{
List<List<vectorField>> vectorValues(allVectors_.size());
forAll(allVectors_, vectori)
if (!allVectors_.empty())
{
DynamicList<vectorList>& allTrackVals = allVectors_[vectori];
vectorValues[vectori].setSize(nTracks);
List<List<vectorField>> vectorValues(allVectors_.size());
forAll(allTrackVals, tracki)
forAll(allVectors_, vectori)
{
vectorList& vals = allTrackVals[tracki];
if (vals.size())
DynamicList<vectorList>& allTrackVals = allVectors_[vectori];
vectorValues[vectori].setSize(nTracks);
forAll(allTrackVals, tracki)
{
const label newTracki = oldToNewTrack[tracki];
vectorValues[vectori][newTracki].transfer(vals);
vectorList& vals = allTrackVals[tracki];
if (vals.size())
{
const label newTracki = oldToNewTrack[tracki];
vectorValues[vectori][newTracki].transfer(vals);
}
}
}
forAll(vectorNames_, i)
{
fileName outFile =
writer.write(vectorNames_[i], vectorValues[i]);
outputFileNames.insert
(
scalarNames_[i],
time_.relativePath(outFile, true)
);
}
}
vectorVtkFile = fileName
(
vtkPath
/ vectorFormatterPtr_().getFileName(tracks[0], vectorNames_)
);
//Info<< " Writing vector data to " << vectorVtkFile << endl;
vectorFormatterPtr_().write
(
true, // writeTracks
List<scalarField>(), // times
tracks,
vectorNames_,
vectorValues,
OFstream(vectorVtkFile)()
);
writer.close(true);
}
// Log << " Writing data to " << scalarVtkFile.path() << endl;
}
// File names are generated on the master but setProperty needs to
// be across all procs
Pstream::scatter(scalarVtkFile);
for (const word& fieldName : scalarNames_)
{
dictionary propsDict;
propsDict.add
(
"file",
time_.relativePath(scalarVtkFile, true)
);
setProperty(fieldName, propsDict);
}
// File names generated on the master but setProperty needed everywher
Pstream::scatter(outputFileNames);
Pstream::scatter(vectorVtkFile);
for (const word& fieldName : vectorNames_)
forAllConstIters(outputFileNames, iter)
{
const word& fieldName = iter.key();
const fileName& outputName = iter.val();
dictionary propsDict;
propsDict.add
(
"file",
time_.relativePath(vectorVtkFile, true)
);
propsDict.add("file", outputName);
setProperty(fieldName, propsDict);
}
@ -844,7 +839,7 @@ Foam::functionObjects::streamLineBase::streamLineBase
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict),
functionObjects::fvMeshFunctionObject(name, runTime, dict),
dict_(dict),
fields_()
{}
@ -858,7 +853,7 @@ Foam::functionObjects::streamLineBase::streamLineBase
const wordList& fieldNames
)
:
fvMeshFunctionObject(name, runTime, dict),
functionObjects::fvMeshFunctionObject(name, runTime, dict),
dict_(dict),
fields_(fieldNames)
{}
@ -959,8 +954,13 @@ bool Foam::functionObjects::streamLineBase::read(const dictionary& dict)
sampledSetPtr_.clear();
sampledSetAxis_.clear();
scalarFormatterPtr_ = writer<scalar>::New(dict.get<word>("setFormat"));
vectorFormatterPtr_ = writer<vector>::New(dict.get<word>("setFormat"));
const word setFormat(dict.get<word>("setFormat"));
trackWriterPtr_ = coordSetWriter::New
(
setFormat,
dict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
);
return true;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2016 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,14 +36,14 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef streamLineBase_H
#define streamLineBase_H
#ifndef Foam_functionObjects_streamLineBase_H
#define Foam_functionObjects_streamLineBase_H
#include "fvMeshFunctionObject.H"
#include "DynamicList.H"
#include "scalarList.H"
#include "vectorList.H"
#include "writer.H"
#include "coordSetWriter.H"
#include "indirectPrimitivePatch.H"
#include "interpolation.H"
#include "Enum.H"
@ -53,6 +53,7 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class meshSearch;
class sampledSet;
@ -65,7 +66,7 @@ namespace functionObjects
class streamLineBase
:
public fvMeshFunctionObject
public functionObjects::fvMeshFunctionObject
{
public:
@ -128,16 +129,13 @@ protected:
wordList vectorNames_;
// Demand driven
// Demand driven
//- File writer for scalar data
autoPtr<writer<scalar>> scalarFormatterPtr_;
//- File writer for vector data
autoPtr<writer<vector>> vectorFormatterPtr_;
//- File writer for tracks data
mutable autoPtr<coordSetWriter> trackWriterPtr_;
// Generated data
// Generated Data
//- All tracks. Per track the points it passed through
DynamicList<List<point>> allTracks_;