Commit a4dc9966 authored by Andrew Heather's avatar Andrew Heather
Browse files

ENH: Added new AMIWeights function object

Reports the min|max|average AMI weights to text file and optionally
writes VTK surfaces of the sum of the weights, and mask field for
ACMI patches.

Example usage:

    AMIWeights
    {
        type            AMIWeights;
        libs            ("libfieldFunctionObjects.so");
        writeControl    writeTime;
        writeFields     yes;
    }
parent afc373d6
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Version: v1806
\\ / A nd | Web: www.OpenFOAM.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Description
Calculates and writes the second largest eigenvalue of the sum of the
square of the symmetrical and anti-symmetrical parts of the velocity
gradient tensor.
\*---------------------------------------------------------------------------*/
type AMIWeights;
libs ("libfieldFunctionObjects.so");
writeFields yes;
writeControl writeTime;
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ 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 "AMIWeights.H"
#include "fvMesh.H"
#include "vtkSurfaceWriter.H"
#include "PatchTools.H"
#include "cyclicACMIPolyPatch.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(AMIWeights, 0);
addToRunTimeSelectionTable(functionObject, AMIWeights, dictionary);
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::functionObjects::AMIWeights::writeFileHeader(Ostream& os)
{
writeHeader(os, "AMI");
writeCommented(os, "Time");
forAll(patchIDs_, patchi)
{
writeTabbed(os, "Patch");
writeTabbed(os, "nbr_patch");
if (Pstream::parRun())
{
writeTabbed(os, "distributed");
}
writeTabbed(os, "src_min_weight");
writeTabbed(os, "src_max_weight");
writeTabbed(os, "src_average_weight");
writeTabbed(os, "src_min_neighbours");
writeTabbed(os, "src_max_neighbours");
writeTabbed(os, "src_average_neighbours");
writeTabbed(os, "tgt_min_weight");
writeTabbed(os, "tgt_max_weight");
writeTabbed(os, "tgt_average_weight");
writeTabbed(os, "tgt_min_neighbours");
writeTabbed(os, "tgt_max_neighbours");
writeTabbed(os, "tgt_average_neighbours");
}
os << endl;
}
void Foam::functionObjects::AMIWeights::reportPatch
(
const cyclicAMIPolyPatch& pp
)
{
const word& nbrPatchName = pp.neighbPatchName();
const Switch distributed = pp.AMI().singlePatchProc() == -1;
const scalarField& srcWeightsSum = pp.AMI().srcWeightsSum();
const scalar srcMinWeight = gMin(srcWeightsSum);
const scalar srcMaxWeight = gMax(srcWeightsSum);
const scalar srcAveWeight = gAverage(srcWeightsSum);
const labelListList& srcAddress = pp.AMI().srcAddress();
label srcMinNbr = labelMax;
label srcMaxNbr = labelMin;
scalar srcAveNbr = 0;
for (const labelList& srcFace : srcAddress)
{
const label n = srcFace.size();
srcAveNbr += n;
srcMinNbr = min(srcMinNbr, n);
srcMaxNbr = max(srcMaxNbr, n);
}
reduce(srcMinNbr, minOp<label>());
reduce(srcMaxNbr, maxOp<label>());
srcAveNbr =
returnReduce(srcAveNbr, sumOp<scalar>())
/(returnReduce(srcAddress.size(), sumOp<scalar>()) + ROOTVSMALL);
const scalarField& tgtWeightsSum = pp.AMI().tgtWeightsSum();
const scalar tgtMinWeight = gMin(tgtWeightsSum);
const scalar tgtMaxWeight = gMax(tgtWeightsSum);
const scalar tgtAveWeight = gAverage(tgtWeightsSum);
const labelListList& tgtAddress = pp.AMI().tgtAddress();
label tgtMinNbr = labelMax;
label tgtMaxNbr = labelMin;
scalar tgtAveNbr = 0;
for (const labelList& tgtFace : tgtAddress)
{
const label n = tgtFace.size();
tgtAveNbr += n;
tgtMinNbr = min(tgtMinNbr, n);
tgtMaxNbr = max(tgtMaxNbr, n);
}
reduce(tgtMinNbr, minOp<label>());
reduce(tgtMaxNbr, maxOp<label>());
tgtAveNbr =
returnReduce(tgtAveNbr, sumOp<scalar>())
/(returnReduce(tgtAddress.size(), sumOp<scalar>()) + ROOTVSMALL);
file()
<< mesh_.time().timeName() << tab
<< pp.name() << tab
<< nbrPatchName << tab;
if (Pstream::parRun())
{
file() << distributed << tab;
}
file()
<< srcMinWeight << tab
<< srcMaxWeight << tab
<< srcAveWeight << tab
<< srcMinNbr << tab
<< srcMaxNbr << tab
<< srcAveNbr << tab
<< tgtMinWeight << tab
<< tgtMaxWeight << tab
<< tgtAveWeight << tab
<< tgtMinNbr << tab
<< tgtMaxNbr << tab
<< tgtAveNbr << tab
<< endl;
Log << " Patches: " << nl
<< " Source: " << pp.name() << nl
<< " Target: " << nbrPatchName << nl;
if (Pstream::parRun())
{
Log << " Parallel distributed: " << distributed << nl;
}
Log << nl;
const label w = IOstream::defaultPrecision() + 8;
Log << " | " << setw(w) << pp.name()
<< " | " << setw(w) << nbrPatchName << " | " << nl
<< " min(weight) | " << setw(w) << srcMinWeight
<< " | " << setw(w) << tgtMinWeight << " | " << nl
<< " max(weight) | " << setw(w) << srcMaxWeight
<< " | " << setw(w) << tgtMaxWeight << " | " << nl
<< " ave(weight) | " << setw(w) << srcAveWeight
<< " | " << setw(w) << tgtAveWeight << " | " << nl
<< " min(address) | " << setw(w) << srcMinNbr
<< " | " << setw(w) << tgtMinNbr << " | " << nl
<< " max(address) | " << setw(w) << srcMaxNbr
<< " | " << setw(w) << tgtMaxNbr << " | " << nl
<< " ave(address) | " << setw(w) << srcAveNbr
<< " | " << setw(w) << tgtAveNbr << " | " << nl
<< endl;
setResult(pp.name() + ":src", pp.name());
setResult(pp.name() + ":tgt", nbrPatchName);
setResult(pp.name() + ":src:min(weight)", srcMinWeight);
setResult(pp.name() + ":src:max(weight)", srcMaxWeight);
setResult(pp.name() + ":src:ave(weight)", srcAveWeight);
setResult(pp.name() + ":src:min(address)", srcMinNbr);
setResult(pp.name() + ":src:max(address)", srcMaxNbr);
setResult(pp.name() + ":src:ave(address)", srcAveNbr);
setResult(pp.name() + ":tgt:min(weight)", tgtMinWeight);
setResult(pp.name() + ":tgt:max(weight)", tgtMaxWeight);
setResult(pp.name() + ":tgt:ave(weight)", tgtAveWeight);
setResult(pp.name() + ":tgt:min(address)", tgtMinNbr);
setResult(pp.name() + ":tgt:max(address)", tgtMaxNbr);
setResult(pp.name() + ":tgt:ave(address)", tgtAveNbr);
}
void Foam::functionObjects::AMIWeights::writeWeightField
(
const cyclicAMIPolyPatch& cpp,
const scalarField& weightSum,
const word& side
) const
{
vtkSurfaceWriter writer;
// Collect geometry
labelList pointToGlobal;
labelList uniqueMeshPointLabels;
autoPtr<globalIndex> globalPoints;
autoPtr<globalIndex> globalFaces;
faceList mergedFaces;
pointField mergedPoints;
Foam::PatchTools::gatherAndMerge
(
mesh_,
cpp.localFaces(),
cpp.meshPoints(),
cpp.meshPointMap(),
pointToGlobal,
uniqueMeshPointLabels,
globalPoints,
globalFaces,
mergedFaces,
mergedPoints
);
// Collect field
scalarField mergedWeights;
globalFaces().gather
(
UPstream::worldComm,
ListOps::create<label>
(
UPstream::procID(UPstream::worldComm),
labelOp<int>() // int -> label
),
weightSum,
mergedWeights
);
if (Pstream::master())
{
writer.write
(
baseTimeDir(),
cpp.name() + "_" + side,
meshedSurfRef(mergedPoints, mergedFaces),
"weightsSum",
mergedWeights,
false
);
}
if (isA<cyclicACMIPolyPatch>(cpp))
{
const cyclicACMIPolyPatch& pp = refCast<const cyclicACMIPolyPatch>(cpp);
scalarField mergedMask;
globalFaces().gather
(
UPstream::worldComm,
ListOps::create<label>
(
UPstream::procID(UPstream::worldComm),
labelOp<int>() // int -> label
),
pp.mask(),
mergedMask
);
if (Pstream::master())
{
writer.write
(
baseTimeDir(),
cpp.name() + "_" + side,
meshedSurfRef(mergedPoints, mergedFaces),
"mask",
mergedMask,
false
);
}
}
}
void Foam::functionObjects::AMIWeights::writeWeightFields
(
const cyclicAMIPolyPatch& cpp
) const
{
if (cpp.owner())
{
writeWeightField(cpp, cpp.AMI().srcWeightsSum(), "src");
writeWeightField(cpp.neighbPatch(), cpp.AMI().tgtWeightsSum(), "tgt");
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::AMIWeights::AMIWeights
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict),
writeFile(mesh_, name, typeName, dict),
writeFields_(false),
patchIDs_()
{
read(dict);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::AMIWeights::read(const dictionary& dict)
{
if (fvMeshFunctionObject::read(dict) && writeFile::read(dict))
{
const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
patchIDs_.clear();
labelHashSet ids;
forAll(pbm, patchi)
{
if (isA<cyclicAMIPolyPatch>(pbm[patchi]))
{
const auto& ami =
static_cast<const cyclicAMIPolyPatch&>(pbm[patchi]);
if (ami.owner())
{
ids.insert(patchi);
}
}
}
patchIDs_ = ids.sortedToc();
writeFileHeader(file());
writeFields_ = dict.get<bool>("writeFields");
return true;
}
return false;
}
bool Foam::functionObjects::AMIWeights::execute()
{
return true;
}
bool Foam::functionObjects::AMIWeights::write()
{
Log << type() << " " << name() << " write:" << nl;
const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
for (const label patchi : patchIDs_)
{
const polyPatch& pp = pbm[patchi];
const auto& cpp = static_cast<const cyclicAMIPolyPatch&>(pp);
reportPatch(cpp);
if (writeFields_)
{
writeWeightFields(cpp);
}
}
return true;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ 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/>.
Class
Foam::functionObjects::AMIWeights
Group
grpFieldFunctionObjects
Description
Usage
Example of function object specification:
\verbatim
AMIWeights1
{
type AMIWeights;
libs ("libfieldFunctionObjects.so");
writeFields yes;
}
\endverbatim
Where the entries comprise:
\table
Property | Description | Required | Default value
type | type name: AMIWeights | yes |
writeFields | write weights as VTK fields | yes |
\endtable
Output data is written to the file \<timeDir\>/AMIWeights.dat
See also
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::writeFile
SourceFiles
AMIWeights.C
AMIWeightsTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_AMIWeights_H
#define functionObjects_AMIWeights_H
#include "fvMeshFunctionObject.H"
#include "writeFile.H"
#include "cyclicAMIPolyPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
/*---------------------------------------------------------------------------*\
Class AMIWeights Declaration
\*---------------------------------------------------------------------------*/
class AMIWeights
:
public fvMeshFunctionObject,
public writeFile
{
protected:
// Protected data
//- Flag to write AMI fields (as VTK files)
bool writeFields_;
//- List of AMI patch IDs
labelList patchIDs_;
// Protected Member Functions
//- Output file header information
virtual void writeFileHeader(Ostream& os);
//- Helper function to report patch information
virtual void reportPatch(const cyclicAMIPolyPatch& pp);
void writeWeightField
(
const cyclicAMIPolyPatch& cpp,
const scalarField& weightSum,
const word& side
) const;
void writeWeightFields(const cyclicAMIPolyPatch& cpp) const;
//- No copy construct
AMIWeights(const AMIWeights&) = delete;
//- No copy assignment
void operator=(const AMIWeights&) = delete;
public:
//- Runtime type information
TypeName("AMIWeights");
// Constructors
//- Construct from Time and dictionary
AMIWeights
(
const word& name,
const Time& runTime,
const dictionary& dict
);
//- Destructor
virtual ~AMIWeights() = default;
// Member Functions
//- Read the field min/max data
virtual bool read(const dictionary&);
//- Execute, currently does nothing
virtual bool execute();
//- Write the AMIWeights
virtual bool write();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
AMIWeights/AMIWeights.C
fieldAverage/fieldAverage.C
fieldAverage/fieldAverageItem/fieldAverageItem.C
fieldAverage/fieldAverageItem/fieldAverageItemIO.C
......
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1806 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
AMIWeights
{
type AMIWeights;
libs ("libfieldFunctionObjects.so");
writeControl writeTime;
writeFields no;
}
// ************************************************************************* //
......@@ -57,6 +57,7 @@ functions
#includeFunc Q
#include "surfaces"
#include "forces"
#include "AMIWeights"