mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add probes sampleOnExecute option (#2358)
- supports sampling/probing of values to obtain min/max/average/size at execution intervals without writing any output or generating output directories. - 'verbose' option for additional output
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
probes/probes.C
|
||||
probes/patchProbes.C
|
||||
probes/probesGrouping.C
|
||||
|
||||
sampledSet/circle/circleSet.C
|
||||
sampledSet/cloud/cloudSet.C
|
||||
|
||||
@ -201,13 +201,16 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
|
||||
// - faceList_ : faces (now patch faces)
|
||||
// - patchIDList_ : patch corresponding to faceList
|
||||
// - processor_ : processor
|
||||
elementList_.setSize(nearest.size());
|
||||
elementList_.resize_nocopy(nearest.size());
|
||||
elementList_ = -1;
|
||||
faceList_.setSize(nearest.size());
|
||||
|
||||
faceList_.resize_nocopy(nearest.size());
|
||||
faceList_ = -1;
|
||||
processor_.setSize(nearest.size());
|
||||
|
||||
processor_.resize_nocopy(nearest.size());
|
||||
processor_ = -1;
|
||||
patchIDList_.setSize(nearest.size());
|
||||
|
||||
patchIDList_.resize_nocopy(nearest.size());
|
||||
patchIDList_ = -1;
|
||||
|
||||
forAll(nearest, sampleI)
|
||||
@ -236,13 +239,13 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
|
||||
Foam::patchProbes::patchProbes
|
||||
(
|
||||
const word& name,
|
||||
const Time& t,
|
||||
const Time& runTime,
|
||||
const dictionary& dict,
|
||||
const bool loadFromFiles,
|
||||
const bool readFields
|
||||
)
|
||||
:
|
||||
probes(name, t, dict, loadFromFiles, false)
|
||||
probes(name, runTime, dict, loadFromFiles, false)
|
||||
{
|
||||
if (readFields)
|
||||
{
|
||||
@ -253,27 +256,43 @@ Foam::patchProbes::patchProbes
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::patchProbes::write()
|
||||
bool Foam::patchProbes::performAction(unsigned request)
|
||||
{
|
||||
if (this->size() && prepare())
|
||||
if (!pointField::empty() && request && prepare(request))
|
||||
{
|
||||
sampleAndWrite(scalarFields_);
|
||||
sampleAndWrite(vectorFields_);
|
||||
sampleAndWrite(sphericalTensorFields_);
|
||||
sampleAndWrite(symmTensorFields_);
|
||||
sampleAndWrite(tensorFields_);
|
||||
performAction(scalarFields_, request);
|
||||
performAction(vectorFields_, request);
|
||||
performAction(sphericalTensorFields_, request);
|
||||
performAction(symmTensorFields_, request);
|
||||
performAction(tensorFields_, request);
|
||||
|
||||
sampleAndWriteSurfaceFields(surfaceScalarFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceVectorFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceSphericalTensorFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceSymmTensorFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceTensorFields_);
|
||||
performAction(surfaceScalarFields_, request);
|
||||
performAction(surfaceVectorFields_, request);
|
||||
performAction(surfaceSphericalTensorFields_, request);
|
||||
performAction(surfaceSymmTensorFields_, request);
|
||||
performAction(surfaceTensorFields_, request);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::patchProbes::execute()
|
||||
{
|
||||
if (onExecute_)
|
||||
{
|
||||
return performAction(ACTION_ALL & ~ACTION_WRITE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::patchProbes::write()
|
||||
{
|
||||
return performAction(ACTION_ALL);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::patchProbes::read(const dictionary& dict)
|
||||
{
|
||||
if (!dict.readIfPresent("patches", patchNames_))
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -64,14 +64,14 @@ Description
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
|
||||
SourceFiles
|
||||
patchProbes.C
|
||||
patchProbesTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef patchProbes_H
|
||||
#define patchProbes_H
|
||||
#ifndef Foam_patchProbes_H
|
||||
#define Foam_patchProbes_H
|
||||
|
||||
#include "probes.H"
|
||||
|
||||
@ -80,12 +80,6 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class objectRegistry;
|
||||
class dictionary;
|
||||
class fvMesh;
|
||||
class mapPolyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class patchProbes Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -96,7 +90,7 @@ class patchProbes
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
// Protected Data
|
||||
|
||||
//- Patches to sample
|
||||
wordRes patchNames_;
|
||||
@ -104,52 +98,35 @@ protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Sample and write a particular volume field
|
||||
template<class Type>
|
||||
void sampleAndWrite
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>&
|
||||
);
|
||||
|
||||
//- Sample and write a particular surface field
|
||||
template<class Type>
|
||||
void sampleAndWrite
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>&
|
||||
);
|
||||
|
||||
//- Sample and write all the fields of the given type
|
||||
template<class Type>
|
||||
void sampleAndWrite(const fieldGroup<Type>&);
|
||||
|
||||
//- Sample and write all the surface fields of the given type
|
||||
template<class Type>
|
||||
void sampleAndWriteSurfaceFields(const fieldGroup<Type>&);
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>&
|
||||
) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>&
|
||||
) const;
|
||||
|
||||
//- Sample a single field on all sample locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Find elements containing patchProbes
|
||||
virtual void findElements(const fvMesh&);
|
||||
virtual void findElements(const fvMesh& mesh); // override
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Write field values
|
||||
template<class Type>
|
||||
void writeValues
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
);
|
||||
|
||||
//- Sample and store/write applicable volume/surface fields
|
||||
template<class GeoField>
|
||||
void performAction
|
||||
(
|
||||
const fieldGroup<GeoField>& fieldNames, /* must be sorted */
|
||||
unsigned request
|
||||
);
|
||||
|
||||
//- Perform sampling action with store/write
|
||||
bool performAction(unsigned request);
|
||||
|
||||
|
||||
//- No copy construct
|
||||
patchProbes(const patchProbes&) = delete;
|
||||
|
||||
@ -169,7 +146,7 @@ public:
|
||||
patchProbes
|
||||
(
|
||||
const word& name,
|
||||
const Time& time,
|
||||
const Time& runTime,
|
||||
const dictionary& dict,
|
||||
const bool loadFromFiles = false,
|
||||
const bool readFields = true
|
||||
@ -179,13 +156,35 @@ public:
|
||||
virtual ~patchProbes() = default;
|
||||
|
||||
|
||||
//- Public members
|
||||
// Member Functions
|
||||
|
||||
//- Sample and store result if the sampleOnExecute is enabled.
|
||||
virtual bool execute();
|
||||
|
||||
//- Sample and write
|
||||
virtual bool write();
|
||||
|
||||
//- Read
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
|
||||
// Sampling
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const VolumeField<Type>&) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
|
||||
|
||||
//- Sample a single field on all sample locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceField(const word& fieldName) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,153 +28,57 @@ License
|
||||
|
||||
#include "patchProbes.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::patchProbes::sampleAndWrite
|
||||
void Foam::patchProbes::writeValues
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& vField
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
)
|
||||
{
|
||||
Field<Type> values(sample(vField));
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& probeStream = *probeFilePtrs_[vField.name()];
|
||||
const unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& os = *probeFilePtrs_[fieldName];
|
||||
|
||||
probeStream
|
||||
<< setw(w)
|
||||
<< vField.time().timeOutputValue();
|
||||
os << setw(w) << timeValue;
|
||||
|
||||
for (const auto& v : values)
|
||||
{
|
||||
probeStream << ' ' << setw(w) << v;
|
||||
os << ' ' << setw(w) << v;
|
||||
}
|
||||
probeStream << endl;
|
||||
os << endl;
|
||||
}
|
||||
|
||||
const word& fieldName = vField.name();
|
||||
this->setResult("average(" + fieldName + ")", average(values));
|
||||
this->setResult("min(" + fieldName + ")", min(values));
|
||||
this->setResult("max(" + fieldName + ")", max(values));
|
||||
this->setResult("size(" + fieldName + ")", values.size());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::patchProbes::sampleAndWrite
|
||||
template<class GeoField>
|
||||
void Foam::patchProbes::performAction
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
|
||||
const fieldGroup<GeoField>& fieldNames,
|
||||
unsigned request
|
||||
)
|
||||
{
|
||||
Field<Type> values(sample(sField));
|
||||
|
||||
if (Pstream::master())
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& probeStream = *probeFilePtrs_[sField.name()];
|
||||
tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
|
||||
|
||||
probeStream
|
||||
<< setw(w)
|
||||
<< sField.time().timeOutputValue();
|
||||
|
||||
for (const auto& v : values)
|
||||
if (tfield)
|
||||
{
|
||||
probeStream << ' ' << setw(w) << v;
|
||||
}
|
||||
probeStream << endl;
|
||||
}
|
||||
const auto& field = tfield();
|
||||
const scalar timeValue = field.time().timeOutputValue();
|
||||
|
||||
const word& fieldName = sField.name();
|
||||
this->setResult("average(" + fieldName + ")", average(values));
|
||||
this->setResult("min(" + fieldName + ")", min(values));
|
||||
this->setResult("max(" + fieldName + ")", max(values));
|
||||
this->setResult("size(" + fieldName + ")", values.size());
|
||||
}
|
||||
Field<typename GeoField::value_type> values(sample(field));
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::patchProbes::sampleAndWrite
|
||||
(
|
||||
const fieldGroup<Type>& fields
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||
|
||||
for (const auto& fieldName : fields)
|
||||
{
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
sampleAndWrite
|
||||
(
|
||||
VolFieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectRegistry::const_iterator iter = mesh_.find(fieldName);
|
||||
|
||||
if (iter.found() && iter()->type() == VolFieldType::typeName)
|
||||
this->storeResults(fieldName, values);
|
||||
if (request & ACTION_WRITE)
|
||||
{
|
||||
sampleAndWrite(mesh_.lookupObject<VolFieldType>(fieldName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::patchProbes::sampleAndWriteSurfaceFields
|
||||
(
|
||||
const fieldGroup<Type>& fields
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
||||
|
||||
for (const auto& fieldName : fields)
|
||||
{
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
sampleAndWrite
|
||||
(
|
||||
SurfaceFieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectRegistry::const_iterator iter = mesh_.find(fieldName);
|
||||
|
||||
if (iter.found() && iter()->type() == SurfaceFieldType::typeName)
|
||||
{
|
||||
sampleAndWrite(mesh_.lookupObject<SurfaceFieldType>(fieldName));
|
||||
this->writeValues(fieldName, values, timeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,17 +89,15 @@ void Foam::patchProbes::sampleAndWriteSurfaceFields
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchProbes::sample
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& vField
|
||||
) const
|
||||
Foam::patchProbes::sample(const VolumeField<Type>& vField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tValues.ref();
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||
const auto& bField = vField.boundaryField();
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
@ -205,14 +107,45 @@ Foam::patchProbes::sample
|
||||
{
|
||||
label patchi = patches.whichPatch(facei);
|
||||
label localFacei = patches[patchi].whichFace(facei);
|
||||
values[probei] = vField.boundaryField()[patchi][localFacei];
|
||||
values[probei] = bField[patchi][localFacei];
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineGather(values, isNotEqOp<Type>());
|
||||
Pstream::listCombineScatter(values);
|
||||
|
||||
return tValues;
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchProbes::sample(const SurfaceField<Type>& sField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||
const auto& bField = sField.boundaryField();
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
label facei = faceList_[probei];
|
||||
|
||||
if (facei >= 0)
|
||||
{
|
||||
label patchi = patches.whichPatch(facei);
|
||||
label localFacei = patches[patchi].whichFace(facei);
|
||||
values[probei] = bField[patchi][localFacei];
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineGather(values, isNotEqOp<Type>());
|
||||
Pstream::listCombineScatter(values);
|
||||
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
@ -220,46 +153,15 @@ template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchProbes::sample(const word& fieldName) const
|
||||
{
|
||||
return sample
|
||||
(
|
||||
mesh_.lookupObject<GeometricField<Type, fvPatchField, volMesh>>
|
||||
(
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchProbes::sample
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
|
||||
) const
|
||||
Foam::patchProbes::sampleSurfaceField(const word& fieldName) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tValues.ref();
|
||||
|
||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
label facei = faceList_[probei];
|
||||
|
||||
if (facei >= 0)
|
||||
{
|
||||
label patchi = patches.whichPatch(facei);
|
||||
label localFacei = patches[patchi].whichFace(facei);
|
||||
values[probei] = sField.boundaryField()[patchi][localFacei];
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineGather(values, isNotEqOp<Type>());
|
||||
Pstream::listCombineScatter(values);
|
||||
|
||||
return tValues;
|
||||
return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -27,8 +27,9 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "probes.H"
|
||||
#include "volFields.H"
|
||||
#include "dictionary.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "Time.H"
|
||||
#include "IOmanip.H"
|
||||
#include "mapPolyMesh.H"
|
||||
@ -55,18 +56,14 @@ void Foam::probes::findElements(const fvMesh& mesh)
|
||||
{
|
||||
DebugInfo<< "probes: resetting sample locations" << endl;
|
||||
|
||||
elementList_.clear();
|
||||
elementList_.setSize(size());
|
||||
|
||||
faceList_.clear();
|
||||
faceList_.setSize(size());
|
||||
|
||||
processor_.setSize(size());
|
||||
elementList_.resize_nocopy(pointField::size());
|
||||
faceList_.resize_nocopy(pointField::size());
|
||||
processor_.resize_nocopy(pointField::size());
|
||||
processor_ = -1;
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
const vector& location = operator[](probei);
|
||||
const point& location = (*this)[probei];
|
||||
|
||||
const label celli = mesh.findCell(location);
|
||||
|
||||
@ -107,7 +104,7 @@ void Foam::probes::findElements(const fvMesh& mesh)
|
||||
// Check if all probes have been found.
|
||||
forAll(elementList_, probei)
|
||||
{
|
||||
const vector& location = operator[](probei);
|
||||
const point& location = operator[](probei);
|
||||
label celli = elementList_[probei];
|
||||
label facei = faceList_[probei];
|
||||
|
||||
@ -171,15 +168,53 @@ void Foam::probes::findElements(const fvMesh& mesh)
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::probes::prepare()
|
||||
Foam::label Foam::probes::prepare(unsigned request)
|
||||
{
|
||||
const label nFields = classifyFields();
|
||||
// Prefilter on selection
|
||||
HashTable<wordHashSet> selected =
|
||||
(
|
||||
loadFromFiles_
|
||||
? IOobjectList(mesh_, mesh_.time().timeName()).classes(fieldSelection_)
|
||||
: mesh_.classes(fieldSelection_)
|
||||
);
|
||||
|
||||
// adjust file streams
|
||||
// Classify and count fields
|
||||
label nFields = 0;
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(InputType, Target) \
|
||||
{ \
|
||||
Target.clear(); /* Remove old values */ \
|
||||
const auto iter = selected.cfind(InputType::typeName); \
|
||||
if (iter.found()) \
|
||||
{ \
|
||||
/* Add new (current) values */ \
|
||||
Target.append(iter.val().sortedToc()); \
|
||||
nFields += Target.size(); \
|
||||
} \
|
||||
}
|
||||
|
||||
doLocalCode(volScalarField, scalarFields_);
|
||||
doLocalCode(volVectorField, vectorFields_)
|
||||
doLocalCode(volSphericalTensorField, sphericalTensorFields_);
|
||||
doLocalCode(volSymmTensorField, symmTensorFields_);
|
||||
doLocalCode(volTensorField, tensorFields_);
|
||||
|
||||
doLocalCode(surfaceScalarField, surfaceScalarFields_);
|
||||
doLocalCode(surfaceVectorField, surfaceVectorFields_);
|
||||
doLocalCode(surfaceSphericalTensorField, surfaceSphericalTensorFields_);
|
||||
doLocalCode(surfaceSymmTensorField, surfaceSymmTensorFields_);
|
||||
doLocalCode(surfaceTensorField, surfaceTensorFields_);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
|
||||
|
||||
// Adjust file streams
|
||||
if (Pstream::master())
|
||||
{
|
||||
wordHashSet currentFields;
|
||||
|
||||
wordHashSet currentFields(2*nFields);
|
||||
currentFields.insert(scalarFields_);
|
||||
currentFields.insert(vectorFields_);
|
||||
currentFields.insert(sphericalTensorFields_);
|
||||
@ -197,27 +232,7 @@ Foam::label Foam::probes::prepare()
|
||||
<< "Probing locations: " << *this << nl
|
||||
<< endl;
|
||||
|
||||
|
||||
fileName probeSubDir = name();
|
||||
|
||||
if (mesh_.name() != polyMesh::defaultRegion)
|
||||
{
|
||||
probeSubDir = probeSubDir/mesh_.name();
|
||||
}
|
||||
|
||||
// Put in undecomposed case
|
||||
// (Note: gives problems for distributed data running)
|
||||
|
||||
fileName probeDir
|
||||
(
|
||||
mesh_.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ probeSubDir
|
||||
/ mesh_.time().timeName()
|
||||
);
|
||||
probeDir.clean(); // Remove unneeded ".."
|
||||
|
||||
// ignore known fields, close streams for fields that no longer exist
|
||||
// Close streams for fields that no longer exist
|
||||
forAllIters(probeFilePtrs_, iter)
|
||||
{
|
||||
if (!currentFields.erase(iter.key()))
|
||||
@ -228,28 +243,59 @@ Foam::label Foam::probes::prepare()
|
||||
}
|
||||
}
|
||||
|
||||
// currentFields now just has the new fields - open streams for them
|
||||
for (const word& fieldName : currentFields)
|
||||
if (!(request & ACTION_WRITE))
|
||||
{
|
||||
// Create directory if does not exist.
|
||||
mkDir(probeDir);
|
||||
// No writing - can return now
|
||||
return nFields;
|
||||
}
|
||||
else if (currentFields.empty())
|
||||
{
|
||||
// No new fields - can return now
|
||||
return nFields;
|
||||
}
|
||||
|
||||
auto fPtr = autoPtr<OFstream>::New(probeDir/fieldName);
|
||||
auto& fout = *fPtr;
|
||||
|
||||
DebugInfo<< "open probe stream: " << fout.name() << endl;
|
||||
// Have new fields - open streams for them
|
||||
|
||||
probeFilePtrs_.insert(fieldName, fPtr);
|
||||
// Put in undecomposed case
|
||||
// (Note: gives problems for distributed data running)
|
||||
|
||||
unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
fileName probeSubDir = name();
|
||||
if (mesh_.name() != polyMesh::defaultRegion)
|
||||
{
|
||||
probeSubDir = probeSubDir/mesh_.name();
|
||||
}
|
||||
|
||||
fileName probeDir
|
||||
(
|
||||
mesh_.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ probeSubDir
|
||||
/ mesh_.time().timeName()
|
||||
);
|
||||
probeDir.clean(); // Remove unneeded ".."
|
||||
|
||||
// Create directory if needed
|
||||
mkDir(probeDir);
|
||||
|
||||
for (const word& fieldName : currentFields.sortedToc())
|
||||
{
|
||||
auto osPtr = autoPtr<OFstream>::New(probeDir/fieldName);
|
||||
auto& os = *osPtr;
|
||||
|
||||
probeFilePtrs_.insert(fieldName, osPtr);
|
||||
|
||||
DebugInfo<< "open probe stream: " << os.name() << endl;
|
||||
|
||||
const unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
fout<< "# Probe " << probei << ' ' << operator[](probei);
|
||||
os << "# Probe " << probei << ' ' << operator[](probei);
|
||||
|
||||
if (processor_[probei] == -1)
|
||||
{
|
||||
fout<< " # Not Found";
|
||||
os << " # Not Found";
|
||||
}
|
||||
// Only for patchProbes
|
||||
else if (probei < patchIDList_.size())
|
||||
@ -264,31 +310,31 @@ Foam::label Foam::probes::prepare()
|
||||
|| processor_[probei] == Pstream::myProcNo()
|
||||
)
|
||||
{
|
||||
fout<< " at patch " << bm[patchi].name();
|
||||
os << " at patch " << bm[patchi].name();
|
||||
}
|
||||
fout<< " with a distance of "
|
||||
os << " with a distance of "
|
||||
<< mag(operator[](probei)-oldPoints_[probei])
|
||||
<< " m to the original point "
|
||||
<< oldPoints_[probei];
|
||||
}
|
||||
}
|
||||
|
||||
fout<< endl;
|
||||
os << nl;
|
||||
}
|
||||
|
||||
fout<< '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
os << '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
<< "Probe";
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (includeOutOfBounds_ || processor_[probei] != -1)
|
||||
{
|
||||
fout<< ' ' << setw(w) << probei;
|
||||
os << ' ' << setw(w) << probei;
|
||||
}
|
||||
}
|
||||
fout<< endl;
|
||||
os << nl;
|
||||
|
||||
fout<< '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
os << '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
<< "Time" << endl;
|
||||
}
|
||||
}
|
||||
@ -308,23 +354,15 @@ Foam::probes::probes
|
||||
const bool readFields
|
||||
)
|
||||
:
|
||||
stateFunctionObject(name, runTime),
|
||||
pointField(0),
|
||||
mesh_
|
||||
(
|
||||
refCast<const fvMesh>
|
||||
(
|
||||
runTime.lookupObject<objectRegistry>
|
||||
(
|
||||
dict.getOrDefault("region", polyMesh::defaultRegion)
|
||||
)
|
||||
)
|
||||
),
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
pointField(),
|
||||
loadFromFiles_(loadFromFiles),
|
||||
fieldSelection_(),
|
||||
fixedLocations_(true),
|
||||
interpolationScheme_("cell"),
|
||||
includeOutOfBounds_(true)
|
||||
includeOutOfBounds_(true),
|
||||
verbose_(false),
|
||||
onExecute_(false),
|
||||
fieldSelection_(),
|
||||
samplePointScheme_("cell")
|
||||
{
|
||||
if (readFields)
|
||||
{
|
||||
@ -335,15 +373,28 @@ Foam::probes::probes
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::probes::verbose(const bool on) noexcept
|
||||
{
|
||||
bool old(verbose_);
|
||||
verbose_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::read(const dictionary& dict)
|
||||
{
|
||||
dict.readEntry("probeLocations", static_cast<pointField&>(*this));
|
||||
dict.readEntry("fields", fieldSelection_);
|
||||
|
||||
dict.readIfPresent("fixedLocations", fixedLocations_);
|
||||
if (dict.readIfPresent("interpolationScheme", interpolationScheme_))
|
||||
dict.readIfPresent("includeOutOfBounds", includeOutOfBounds_);
|
||||
|
||||
verbose_ = dict.getOrDefault("verbose", false);
|
||||
onExecute_ = dict.getOrDefault("sampleOnExecute", false);
|
||||
|
||||
if (dict.readIfPresent("interpolationScheme", samplePointScheme_))
|
||||
{
|
||||
if (!fixedLocations_ && interpolationScheme_ != "cell")
|
||||
if (!fixedLocations_ && samplePointScheme_ != "cell")
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Only cell interpolation can be applied when "
|
||||
@ -352,41 +403,51 @@ bool Foam::probes::read(const dictionary& dict)
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
dict.readIfPresent("includeOutOfBounds", includeOutOfBounds_);
|
||||
|
||||
// Initialise cells to sample from supplied locations
|
||||
findElements(mesh_);
|
||||
|
||||
prepare();
|
||||
// Close old (ununsed) streams
|
||||
prepare(ACTION_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::performAction(unsigned request)
|
||||
{
|
||||
if (!pointField::empty() && request && prepare(request))
|
||||
{
|
||||
performAction(scalarFields_, request);
|
||||
performAction(vectorFields_, request);
|
||||
performAction(sphericalTensorFields_, request);
|
||||
performAction(symmTensorFields_, request);
|
||||
performAction(tensorFields_, request);
|
||||
|
||||
performAction(surfaceScalarFields_, request);
|
||||
performAction(surfaceVectorFields_, request);
|
||||
performAction(surfaceSphericalTensorFields_, request);
|
||||
performAction(surfaceSymmTensorFields_, request);
|
||||
performAction(surfaceTensorFields_, request);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::execute()
|
||||
{
|
||||
if (onExecute_)
|
||||
{
|
||||
return performAction(ACTION_ALL & ~ACTION_WRITE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::write()
|
||||
{
|
||||
if (size() && prepare())
|
||||
{
|
||||
sampleAndWrite(scalarFields_);
|
||||
sampleAndWrite(vectorFields_);
|
||||
sampleAndWrite(sphericalTensorFields_);
|
||||
sampleAndWrite(symmTensorFields_);
|
||||
sampleAndWrite(tensorFields_);
|
||||
|
||||
sampleAndWriteSurfaceFields(surfaceScalarFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceVectorFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceSphericalTensorFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceSymmTensorFields_);
|
||||
sampleAndWriteSurfaceFields(surfaceTensorFields_);
|
||||
}
|
||||
|
||||
return true;
|
||||
return performAction(ACTION_ALL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -50,7 +50,7 @@ Description
|
||||
writeInterval 1;
|
||||
|
||||
// Fields to be probed
|
||||
fields (p U);
|
||||
fields (U "p.*");
|
||||
|
||||
// Optional: do not recalculate cells if mesh moves
|
||||
fixedLocations false;
|
||||
@ -72,15 +72,28 @@ Description
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Entries:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
type | Type-name: probes | yes |
|
||||
probeLocations | Probe locations | yes |
|
||||
fields | word/regex list of fields to sample | yes |
|
||||
interpolationScheme | scheme to obtain values | no | cell
|
||||
fixedLocations | Do not recalculate cells if mesh moves | no | true
|
||||
includeOutOfBounds | Include out-of-bounds locations | no | true
|
||||
sampleOnExecute | Sample on execution and store results | no | false
|
||||
\endtable
|
||||
|
||||
SourceFiles
|
||||
probes.C
|
||||
probesTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef probes_H
|
||||
#define probes_H
|
||||
#ifndef Foam_probes_H
|
||||
#define Foam_probes_H
|
||||
|
||||
#include "stateFunctionObject.H"
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "OFstream.H"
|
||||
#include "polyMesh.H"
|
||||
@ -89,15 +102,14 @@ SourceFiles
|
||||
#include "surfaceFieldsFwd.H"
|
||||
#include "surfaceMesh.H"
|
||||
#include "wordRes.H"
|
||||
|
||||
using namespace Foam::functionObjects;
|
||||
#include "IOobjectList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
// Forward Declarations
|
||||
class Time;
|
||||
class objectRegistry;
|
||||
class dictionary;
|
||||
@ -110,70 +122,75 @@ class mapPolyMesh;
|
||||
|
||||
class probes
|
||||
:
|
||||
public stateFunctionObject,
|
||||
public functionObjects::fvMeshFunctionObject,
|
||||
public pointField
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected classes
|
||||
// Protected Classes
|
||||
|
||||
//- Class used for grouping field types
|
||||
template<class Type>
|
||||
class fieldGroup
|
||||
:
|
||||
public DynamicList<word>
|
||||
//- Grouping of field names by GeometricField type
|
||||
template<class GeoField>
|
||||
struct fieldGroup : public DynamicList<word> {};
|
||||
|
||||
|
||||
// Data Types
|
||||
|
||||
//- Local control for sampling actions
|
||||
enum sampleActionType : unsigned
|
||||
{
|
||||
public:
|
||||
//- Construct null
|
||||
fieldGroup()
|
||||
:
|
||||
DynamicList<word>(0)
|
||||
{}
|
||||
ACTION_NONE = 0,
|
||||
ACTION_WRITE = 0x1,
|
||||
ACTION_STORE = 0x2,
|
||||
ACTION_ALL = 0xF
|
||||
};
|
||||
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Const reference to fvMesh
|
||||
const fvMesh& mesh_;
|
||||
// Protected Data
|
||||
|
||||
//- Load fields from files (not from objectRegistry)
|
||||
bool loadFromFiles_;
|
||||
|
||||
|
||||
// Read from dictionary
|
||||
|
||||
//- Names of fields to probe
|
||||
wordRes fieldSelection_;
|
||||
|
||||
//- Fixed locations, default = yes
|
||||
//- Fixed locations (default: true)
|
||||
// Note: set to false for moving mesh calculations where locations
|
||||
// should move with the mesh
|
||||
bool fixedLocations_;
|
||||
|
||||
//- Interpolation scheme name
|
||||
// Note: only possible when fixedLocations_ is true
|
||||
word interpolationScheme_;
|
||||
|
||||
//- Include probes that were not found
|
||||
//- Include probes that were not found (default: true)
|
||||
bool includeOutOfBounds_;
|
||||
|
||||
//- Output verbosity
|
||||
bool verbose_;
|
||||
|
||||
// Calculated
|
||||
//- Perform sample actions on execute as well
|
||||
bool onExecute_;
|
||||
|
||||
//- Categorized scalar/vector/tensor vol fields
|
||||
fieldGroup<scalar> scalarFields_;
|
||||
fieldGroup<vector> vectorFields_;
|
||||
fieldGroup<sphericalTensor> sphericalTensorFields_;
|
||||
fieldGroup<symmTensor> symmTensorFields_;
|
||||
fieldGroup<tensor> tensorFields_;
|
||||
//- Requested names of fields to probe
|
||||
wordRes fieldSelection_;
|
||||
|
||||
//- Categorized scalar/vector/tensor surf fields
|
||||
fieldGroup<scalar> surfaceScalarFields_;
|
||||
fieldGroup<vector> surfaceVectorFields_;
|
||||
fieldGroup<sphericalTensor> surfaceSphericalTensorFields_;
|
||||
fieldGroup<symmTensor> surfaceSymmTensorFields_;
|
||||
fieldGroup<tensor> surfaceTensorFields_;
|
||||
//- Interpolation/sample scheme to obtain values at the points
|
||||
// Note: only possible when fixedLocations_ is true
|
||||
word samplePointScheme_;
|
||||
|
||||
|
||||
// Calculated
|
||||
|
||||
//- Current list of field names selected for sampling
|
||||
DynamicList<word> selectedFieldNames_;
|
||||
|
||||
//- Categorized scalar/vector/tensor volume fields
|
||||
fieldGroup<volScalarField> scalarFields_;
|
||||
fieldGroup<volVectorField> vectorFields_;
|
||||
fieldGroup<volSphericalTensorField> sphericalTensorFields_;
|
||||
fieldGroup<volSymmTensorField> symmTensorFields_;
|
||||
fieldGroup<volTensorField> tensorFields_;
|
||||
|
||||
//- Categorized scalar/vector/tensor surface fields
|
||||
fieldGroup<surfaceScalarField> surfaceScalarFields_;
|
||||
fieldGroup<surfaceVectorField> surfaceVectorFields_;
|
||||
fieldGroup<surfaceSphericalTensorField> surfaceSphericalTensorFields_;
|
||||
fieldGroup<surfaceSymmTensorField> surfaceSymmTensorFields_;
|
||||
fieldGroup<surfaceTensorField> surfaceTensorFields_;
|
||||
|
||||
//- Cells to be probed (obtained from the locations)
|
||||
labelList elementList_;
|
||||
@ -185,58 +202,57 @@ protected:
|
||||
// on any processor)
|
||||
labelList processor_;
|
||||
|
||||
//- Current open files
|
||||
//- Current open files (non-empty on master only)
|
||||
HashPtrTable<OFstream> probeFilePtrs_;
|
||||
|
||||
// Additional fields for patchProbes
|
||||
//- Patch IDs on which the new probes are located (for patchProbes)
|
||||
labelList patchIDList_;
|
||||
|
||||
//- Patch IDs on which the new probes are located
|
||||
labelList patchIDList_;
|
||||
|
||||
//- Original probes location (only used for patchProbes)
|
||||
pointField oldPoints_;
|
||||
//- Original probes location (only used for patchProbes)
|
||||
pointField oldPoints_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Clear old field groups
|
||||
void clearFieldGroups();
|
||||
|
||||
//- Classify field types, returns the number of fields
|
||||
label classifyFields();
|
||||
|
||||
//- Find cells and faces containing probes
|
||||
virtual void findElements(const fvMesh& mesh);
|
||||
|
||||
//- Classify field type and open/close file streams,
|
||||
// returns number of fields to sample
|
||||
label prepare();
|
||||
//- Classify field types, close/open file streams
|
||||
// \return number of fields to sample
|
||||
label prepare(unsigned request);
|
||||
|
||||
//- Get from registry or load from disk
|
||||
template<class GeoField>
|
||||
tmp<GeoField> getOrLoadField(const word& fieldName) const;
|
||||
|
||||
//- Store results: min/max/average/size
|
||||
template<class Type>
|
||||
void storeResults(const word& fieldName, const Field<Type>& values);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//- Sample and write a particular volume field
|
||||
// Private Member Functions
|
||||
|
||||
//- Write field values
|
||||
template<class Type>
|
||||
void sampleAndWrite
|
||||
void writeValues
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>&
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
);
|
||||
|
||||
|
||||
//- Sample and write a particular surface field
|
||||
template<class Type>
|
||||
void sampleAndWrite
|
||||
//- Sample and store/write all applicable sampled fields
|
||||
template<class GeoField>
|
||||
void performAction
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>&
|
||||
const fieldGroup<GeoField>& fieldNames, /* must be sorted */
|
||||
unsigned request
|
||||
);
|
||||
|
||||
//- Sample and write all the fields of the given type
|
||||
template<class Type>
|
||||
void sampleAndWrite(const fieldGroup<Type>&);
|
||||
|
||||
//- Sample and write all the surface fields of the given type
|
||||
template<class Type>
|
||||
void sampleAndWriteSurfaceFields(const fieldGroup<Type>&);
|
||||
//- Perform sampling action with store/write
|
||||
bool performAction(unsigned request);
|
||||
|
||||
//- No copy construct
|
||||
probes(const probes&) = delete;
|
||||
@ -244,7 +260,6 @@ private:
|
||||
//- No copy assignment
|
||||
void operator=(const probes&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
@ -270,14 +285,18 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Enable/disable verbose output
|
||||
// \return old value
|
||||
bool verbose(const bool on) noexcept;
|
||||
|
||||
//- Return names of fields to probe
|
||||
virtual const wordRes& fieldNames() const
|
||||
virtual const wordRes& fieldNames() const noexcept
|
||||
{
|
||||
return fieldSelection_;
|
||||
}
|
||||
|
||||
//- Return locations to probe
|
||||
virtual const pointField& probeLocations() const
|
||||
virtual const pointField& probeLocations() const noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
@ -289,7 +308,7 @@ public:
|
||||
}
|
||||
|
||||
//- Cells to be probed (obtained from the locations)
|
||||
const labelList& elements() const
|
||||
const labelList& elements() const noexcept
|
||||
{
|
||||
return elementList_;
|
||||
}
|
||||
@ -297,7 +316,7 @@ public:
|
||||
//- Read the probes
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
//- Execute, currently does nothing
|
||||
//- Sample and store result if the sampleOnExecute is enabled.
|
||||
virtual bool execute();
|
||||
|
||||
//- Sample and write
|
||||
@ -313,27 +332,24 @@ public:
|
||||
virtual void readUpdate(const polyMesh::readUpdateState state)
|
||||
{}
|
||||
|
||||
|
||||
// Sampling
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>&
|
||||
) const;
|
||||
|
||||
//- Sample a single vol field on all sample locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a single scalar field on all sample locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceFields(const word& fieldName) const;
|
||||
tmp<Field<Type>> sample(const VolumeField<Type>&) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>&
|
||||
) const;
|
||||
tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceField(const word& fieldName) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "probes.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "stringListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::probes::clearFieldGroups()
|
||||
{
|
||||
scalarFields_.clear();
|
||||
vectorFields_.clear();
|
||||
sphericalTensorFields_.clear();
|
||||
symmTensorFields_.clear();
|
||||
tensorFields_.clear();
|
||||
|
||||
surfaceScalarFields_.clear();
|
||||
surfaceVectorFields_.clear();
|
||||
surfaceSphericalTensorFields_.clear();
|
||||
surfaceSymmTensorFields_.clear();
|
||||
surfaceTensorFields_.clear();
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::probes::classifyFields()
|
||||
{
|
||||
label nFields = 0;
|
||||
clearFieldGroups();
|
||||
|
||||
HashTable<wordHashSet> available =
|
||||
(
|
||||
loadFromFiles_
|
||||
? IOobjectList(mesh_, mesh_.time().timeName()).classes(fieldSelection_)
|
||||
: mesh_.classes(fieldSelection_)
|
||||
);
|
||||
|
||||
forAllConstIters(available, iter)
|
||||
{
|
||||
const word& fieldType = iter.key();
|
||||
const wordList fieldNames = iter.val().sortedToc();
|
||||
|
||||
const label count = fieldNames.size(); // pre-filtered, so non-empty
|
||||
|
||||
if (fieldType == volScalarField::typeName)
|
||||
{
|
||||
scalarFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volVectorField::typeName)
|
||||
{
|
||||
vectorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volSphericalTensorField::typeName)
|
||||
{
|
||||
sphericalTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volSymmTensorField::typeName)
|
||||
{
|
||||
symmTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volTensorField::typeName)
|
||||
{
|
||||
tensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == surfaceScalarField::typeName)
|
||||
{
|
||||
surfaceScalarFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == surfaceVectorField::typeName)
|
||||
{
|
||||
surfaceVectorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == surfaceSphericalTensorField::typeName)
|
||||
{
|
||||
surfaceSphericalTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == surfaceSymmTensorField::typeName)
|
||||
{
|
||||
surfaceSymmTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == surfaceTensorField::typeName)
|
||||
{
|
||||
surfaceTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
}
|
||||
|
||||
return nFields;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -38,10 +38,8 @@ namespace Foam
|
||||
{
|
||||
|
||||
template<class T>
|
||||
class isNotEqOp
|
||||
struct isNotEqOp
|
||||
{
|
||||
public:
|
||||
|
||||
void operator()(T& x, const T& y) const
|
||||
{
|
||||
const T unsetVal(-VGREAT*pTraits<T>::one);
|
||||
@ -61,25 +59,87 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class GeoField>
|
||||
Foam::tmp<GeoField>
|
||||
Foam::probes::getOrLoadField(const word& fieldName) const
|
||||
{
|
||||
tmp<GeoField> tfield;
|
||||
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
tfield.reset
|
||||
(
|
||||
new GeoField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slightly paranoid here
|
||||
tfield.cref(mesh_.cfindObject<GeoField>(fieldName));
|
||||
}
|
||||
|
||||
return tfield;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::probes::storeResults
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
const MinMax<Type> limits(values);
|
||||
const Type avgVal = average(values);
|
||||
|
||||
this->setResult("average(" + fieldName + ")", avgVal);
|
||||
this->setResult("min(" + fieldName + ")", limits.min());
|
||||
this->setResult("max(" + fieldName + ")", limits.max());
|
||||
this->setResult("size(" + fieldName + ")", values.size());
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< name() << " : " << fieldName << nl
|
||||
<< " avg: " << avgVal << nl
|
||||
<< " min: " << limits.min() << nl
|
||||
<< " max: " << limits.max() << nl << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::probes::sampleAndWrite
|
||||
void Foam::probes::writeValues
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& vField
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
)
|
||||
{
|
||||
Field<Type> values(sample(vField));
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& os = *probeFilePtrs_[vField.name()];
|
||||
const unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& os = *probeFilePtrs_[fieldName];
|
||||
|
||||
os << setw(w) << vField.time().timeOutputValue();
|
||||
os << setw(w) << timeValue;
|
||||
|
||||
forAll(values, probei)
|
||||
{
|
||||
@ -90,144 +150,53 @@ void Foam::probes::sampleAndWrite
|
||||
}
|
||||
os << endl;
|
||||
}
|
||||
|
||||
const word& fieldName = vField.name();
|
||||
this->setResult("average(" + fieldName + ")", average(values));
|
||||
this->setResult("min(" + fieldName + ")", min(values));
|
||||
this->setResult("max(" + fieldName + ")", max(values));
|
||||
this->setResult("size(" + fieldName + ")", values.size());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::probes::sampleAndWrite
|
||||
template<class GeoField>
|
||||
void Foam::probes::performAction
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
|
||||
const fieldGroup<GeoField>& fieldNames,
|
||||
unsigned request
|
||||
)
|
||||
{
|
||||
Field<Type> values(sample(sField));
|
||||
|
||||
if (Pstream::master())
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& os = *probeFilePtrs_[sField.name()];
|
||||
tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
|
||||
|
||||
os << setw(w) << sField.time().timeOutputValue();
|
||||
|
||||
forAll(values, probei)
|
||||
if (tfield)
|
||||
{
|
||||
if (includeOutOfBounds_ || processor_[probei] != -1)
|
||||
const auto& field = tfield();
|
||||
const scalar timeValue = field.time().timeOutputValue();
|
||||
|
||||
Field<typename GeoField::value_type> values(sample(field));
|
||||
|
||||
this->storeResults(fieldName, values);
|
||||
if (request & ACTION_WRITE)
|
||||
{
|
||||
os << ' ' << setw(w) << values[probei];
|
||||
}
|
||||
}
|
||||
os << endl;
|
||||
}
|
||||
|
||||
const word& fieldName = sField.name();
|
||||
this->setResult("average(" + fieldName + ")", average(values));
|
||||
this->setResult("min(" + fieldName + ")", min(values));
|
||||
this->setResult("max(" + fieldName + ")", max(values));
|
||||
this->setResult("size(" + fieldName + ")", values.size());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::probes::sampleAndWrite(const fieldGroup<Type>& fields)
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||
|
||||
for (const auto& fieldName : fields)
|
||||
{
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
sampleAndWrite
|
||||
(
|
||||
VolFieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectRegistry::const_iterator iter = mesh_.find(fieldName);
|
||||
|
||||
if (iter.found() && iter()->type() == VolFieldType::typeName)
|
||||
{
|
||||
sampleAndWrite(mesh_.lookupObject<VolFieldType>(fieldName));
|
||||
this->writeValues(fieldName, values, timeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::probes::sampleAndWriteSurfaceFields(const fieldGroup<Type>& fields)
|
||||
{
|
||||
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
||||
|
||||
for (const auto& fieldName : fields)
|
||||
{
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
sampleAndWrite
|
||||
(
|
||||
SurfaceFieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectRegistry::const_iterator iter = mesh_.find(fieldName);
|
||||
|
||||
if (iter.found() && iter()->type() == SurfaceFieldType::typeName)
|
||||
{
|
||||
sampleAndWrite(mesh_.lookupObject<SurfaceFieldType>(fieldName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sample
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& vField
|
||||
) const
|
||||
Foam::probes::sample(const VolumeField<Type>& vField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tValues.ref();
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
if (fixedLocations_)
|
||||
{
|
||||
autoPtr<interpolation<Type>> interpolator
|
||||
autoPtr<interpolation<Type>> interpPtr
|
||||
(
|
||||
interpolation<Type>::New(interpolationScheme_, vField)
|
||||
interpolation<Type>::New(samplePointScheme_, vField)
|
||||
);
|
||||
|
||||
forAll(*this, probei)
|
||||
@ -236,7 +205,7 @@ Foam::probes::sample
|
||||
{
|
||||
const vector& position = operator[](probei);
|
||||
|
||||
values[probei] = interpolator().interpolate
|
||||
values[probei] = interpPtr().interpolate
|
||||
(
|
||||
position,
|
||||
elementList_[probei],
|
||||
@ -259,35 +228,18 @@ Foam::probes::sample
|
||||
Pstream::listCombineGather(values, isNotEqOp<Type>());
|
||||
Pstream::listCombineScatter(values);
|
||||
|
||||
return tValues;
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sample(const word& fieldName) const
|
||||
{
|
||||
return sample
|
||||
(
|
||||
mesh_.lookupObject<GeometricField<Type, fvPatchField, volMesh>>
|
||||
(
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sample
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
|
||||
) const
|
||||
Foam::probes::sample(const SurfaceField<Type>& sField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tValues.ref();
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
@ -300,21 +252,24 @@ Foam::probes::sample
|
||||
Pstream::listCombineGather(values, isNotEqOp<Type>());
|
||||
Pstream::listCombineScatter(values);
|
||||
|
||||
return tValues;
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sampleSurfaceFields(const word& fieldName) const
|
||||
Foam::probes::sample(const word& fieldName) const
|
||||
{
|
||||
return sample
|
||||
(
|
||||
mesh_.lookupObject<GeometricField<Type, fvsPatchField, surfaceMesh>>
|
||||
(
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sampleSurfaceField(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -36,46 +36,40 @@ Volume3_v_fins
|
||||
|
||||
probesFins
|
||||
{
|
||||
type probes;
|
||||
type probes;
|
||||
libs (sampling);
|
||||
writeControl timeStep;
|
||||
writeInterval 1;
|
||||
interpolationScheme cell;
|
||||
region v_fins;
|
||||
setFormat raw;
|
||||
log true;
|
||||
valueOutput false;
|
||||
writeFields false;
|
||||
region v_fins;
|
||||
|
||||
fields ( T );
|
||||
|
||||
probeLocations
|
||||
(
|
||||
(0.118 0.01 -0.125)
|
||||
(0.118 0.03 -0.125)
|
||||
);
|
||||
|
||||
fields ( T );
|
||||
}
|
||||
|
||||
probesFluid
|
||||
{
|
||||
type probes;
|
||||
type probes;
|
||||
libs (sampling);
|
||||
writeControl timeStep;
|
||||
writeInterval 1;
|
||||
interpolationScheme cell;
|
||||
region domain0;
|
||||
setFormat raw;
|
||||
region domain0;
|
||||
log true;
|
||||
valueOutput false;
|
||||
writeFields false;
|
||||
verbose true;
|
||||
|
||||
fields (T U);
|
||||
|
||||
probeLocations
|
||||
(
|
||||
(0.118 0.035 -0.125)
|
||||
(0.118 0.07 -0.125)
|
||||
);
|
||||
|
||||
fields ( T U);
|
||||
}
|
||||
#remove (_volFieldValue _surfaceFieldValue)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user