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:
Mark Olesen
2022-02-09 13:48:31 +01:00
parent e147ac52e9
commit 0511aebd86
9 changed files with 539 additions and 721 deletions

View File

@ -1,6 +1,5 @@
probes/probes.C probes/probes.C
probes/patchProbes.C probes/patchProbes.C
probes/probesGrouping.C
sampledSet/circle/circleSet.C sampledSet/circle/circleSet.C
sampledSet/cloud/cloudSet.C sampledSet/cloud/cloudSet.C

View File

@ -201,13 +201,16 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
// - faceList_ : faces (now patch faces) // - faceList_ : faces (now patch faces)
// - patchIDList_ : patch corresponding to faceList // - patchIDList_ : patch corresponding to faceList
// - processor_ : processor // - processor_ : processor
elementList_.setSize(nearest.size()); elementList_.resize_nocopy(nearest.size());
elementList_ = -1; elementList_ = -1;
faceList_.setSize(nearest.size());
faceList_.resize_nocopy(nearest.size());
faceList_ = -1; faceList_ = -1;
processor_.setSize(nearest.size());
processor_.resize_nocopy(nearest.size());
processor_ = -1; processor_ = -1;
patchIDList_.setSize(nearest.size());
patchIDList_.resize_nocopy(nearest.size());
patchIDList_ = -1; patchIDList_ = -1;
forAll(nearest, sampleI) forAll(nearest, sampleI)
@ -236,13 +239,13 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
Foam::patchProbes::patchProbes Foam::patchProbes::patchProbes
( (
const word& name, const word& name,
const Time& t, const Time& runTime,
const dictionary& dict, const dictionary& dict,
const bool loadFromFiles, const bool loadFromFiles,
const bool readFields const bool readFields
) )
: :
probes(name, t, dict, loadFromFiles, false) probes(name, runTime, dict, loadFromFiles, false)
{ {
if (readFields) if (readFields)
{ {
@ -253,27 +256,43 @@ Foam::patchProbes::patchProbes
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::patchProbes::write() bool Foam::patchProbes::performAction(unsigned request)
{ {
if (this->size() && prepare()) if (!pointField::empty() && request && prepare(request))
{ {
sampleAndWrite(scalarFields_); performAction(scalarFields_, request);
sampleAndWrite(vectorFields_); performAction(vectorFields_, request);
sampleAndWrite(sphericalTensorFields_); performAction(sphericalTensorFields_, request);
sampleAndWrite(symmTensorFields_); performAction(symmTensorFields_, request);
sampleAndWrite(tensorFields_); performAction(tensorFields_, request);
sampleAndWriteSurfaceFields(surfaceScalarFields_); performAction(surfaceScalarFields_, request);
sampleAndWriteSurfaceFields(surfaceVectorFields_); performAction(surfaceVectorFields_, request);
sampleAndWriteSurfaceFields(surfaceSphericalTensorFields_); performAction(surfaceSphericalTensorFields_, request);
sampleAndWriteSurfaceFields(surfaceSymmTensorFields_); performAction(surfaceSymmTensorFields_, request);
sampleAndWriteSurfaceFields(surfaceTensorFields_); performAction(surfaceTensorFields_, request);
}
return true;
}
bool Foam::patchProbes::execute()
{
if (onExecute_)
{
return performAction(ACTION_ALL & ~ACTION_WRITE);
} }
return true; return true;
} }
bool Foam::patchProbes::write()
{
return performAction(ACTION_ALL);
}
bool Foam::patchProbes::read(const dictionary& dict) bool Foam::patchProbes::read(const dictionary& dict)
{ {
if (!dict.readIfPresent("patches", patchNames_)) if (!dict.readIfPresent("patches", patchNames_))

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -64,14 +64,14 @@ Description
} }
\endverbatim \endverbatim
SourceFiles SourceFiles
patchProbes.C patchProbes.C
patchProbesTemplates.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef patchProbes_H #ifndef Foam_patchProbes_H
#define patchProbes_H #define Foam_patchProbes_H
#include "probes.H" #include "probes.H"
@ -80,12 +80,6 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward declaration of classes
class objectRegistry;
class dictionary;
class fvMesh;
class mapPolyMesh;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class patchProbes Declaration Class patchProbes Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -96,7 +90,7 @@ class patchProbes
{ {
protected: protected:
// Protected data // Protected Data
//- Patches to sample //- Patches to sample
wordRes patchNames_; wordRes patchNames_;
@ -104,52 +98,35 @@ protected:
// Protected Member Functions // 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 //- Find elements containing patchProbes
virtual void findElements(const fvMesh&); virtual void findElements(const fvMesh& mesh); // override
private: 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 //- No copy construct
patchProbes(const patchProbes&) = delete; patchProbes(const patchProbes&) = delete;
@ -169,7 +146,7 @@ public:
patchProbes patchProbes
( (
const word& name, const word& name,
const Time& time, const Time& runTime,
const dictionary& dict, const dictionary& dict,
const bool loadFromFiles = false, const bool loadFromFiles = false,
const bool readFields = true const bool readFields = true
@ -179,13 +156,35 @@ public:
virtual ~patchProbes() = default; virtual ~patchProbes() = default;
//- Public members // Member Functions
//- Sample and store result if the sampleOnExecute is enabled.
virtual bool execute();
//- Sample and write //- Sample and write
virtual bool write(); virtual bool write();
//- Read //- Read
virtual bool read(const dictionary&); 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;
}; };

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd. Copyright (C) 2021-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -28,153 +28,57 @@ License
#include "patchProbes.H" #include "patchProbes.H"
#include "volFields.H" #include "volFields.H"
#include "surfaceFields.H"
#include "IOmanip.H" #include "IOmanip.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type> 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()) if (Pstream::master())
{ {
unsigned int w = IOstream::defaultPrecision() + 7; const unsigned int w = IOstream::defaultPrecision() + 7;
OFstream& probeStream = *probeFilePtrs_[vField.name()]; OFstream& os = *probeFilePtrs_[fieldName];
probeStream os << setw(w) << timeValue;
<< setw(w)
<< vField.time().timeOutputValue();
for (const auto& v : values) 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> template<class GeoField>
void Foam::patchProbes::sampleAndWrite void Foam::patchProbes::performAction
( (
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField const fieldGroup<GeoField>& fieldNames,
unsigned request
) )
{ {
Field<Type> values(sample(sField)); for (const word& fieldName : fieldNames)
if (Pstream::master())
{ {
unsigned int w = IOstream::defaultPrecision() + 7; tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
OFstream& probeStream = *probeFilePtrs_[sField.name()];
probeStream if (tfield)
<< setw(w)
<< sField.time().timeOutputValue();
for (const auto& v : values)
{ {
probeStream << ' ' << setw(w) << v; const auto& field = tfield();
} const scalar timeValue = field.time().timeOutputValue();
probeStream << endl;
}
const word& fieldName = sField.name(); Field<typename GeoField::value_type> values(sample(field));
this->setResult("average(" + fieldName + ")", average(values));
this->setResult("min(" + fieldName + ")", min(values));
this->setResult("max(" + fieldName + ")", max(values));
this->setResult("size(" + fieldName + ")", values.size());
}
this->storeResults(fieldName, values);
template<class Type> if (request & ACTION_WRITE)
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)
{ {
sampleAndWrite(mesh_.lookupObject<VolFieldType>(fieldName)); this->writeValues(fieldName, values, timeValue);
}
}
}
}
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));
} }
} }
} }
@ -185,17 +89,15 @@ void Foam::patchProbes::sampleAndWriteSurfaceFields
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
Foam::patchProbes::sample Foam::patchProbes::sample(const VolumeField<Type>& vField) const
(
const GeometricField<Type, fvPatchField, volMesh>& vField
) const
{ {
const Type unsetVal(-VGREAT*pTraits<Type>::one); const Type unsetVal(-VGREAT*pTraits<Type>::one);
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal)); auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
auto& values = tValues.ref(); auto& values = tvalues.ref();
const polyBoundaryMesh& patches = mesh_.boundaryMesh(); const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const auto& bField = vField.boundaryField();
forAll(*this, probei) forAll(*this, probei)
{ {
@ -205,14 +107,45 @@ Foam::patchProbes::sample
{ {
label patchi = patches.whichPatch(facei); label patchi = patches.whichPatch(facei);
label localFacei = patches[patchi].whichFace(facei); label localFacei = patches[patchi].whichFace(facei);
values[probei] = vField.boundaryField()[patchi][localFacei]; values[probei] = bField[patchi][localFacei];
} }
} }
Pstream::listCombineGather(values, isNotEqOp<Type>()); Pstream::listCombineGather(values, isNotEqOp<Type>());
Pstream::listCombineScatter(values); 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::tmp<Foam::Field<Type>>
Foam::patchProbes::sample(const word& fieldName) const Foam::patchProbes::sample(const word& fieldName) const
{ {
return sample return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
(
mesh_.lookupObject<GeometricField<Type, fvPatchField, volMesh>>
(
fieldName
)
);
} }
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
Foam::patchProbes::sample Foam::patchProbes::sampleSurfaceField(const word& fieldName) const
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
) const
{ {
const Type unsetVal(-VGREAT*pTraits<Type>::one); return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
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;
} }

View File

@ -27,8 +27,9 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "probes.H" #include "probes.H"
#include "volFields.H"
#include "dictionary.H" #include "dictionary.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "Time.H" #include "Time.H"
#include "IOmanip.H" #include "IOmanip.H"
#include "mapPolyMesh.H" #include "mapPolyMesh.H"
@ -55,18 +56,14 @@ void Foam::probes::findElements(const fvMesh& mesh)
{ {
DebugInfo<< "probes: resetting sample locations" << endl; DebugInfo<< "probes: resetting sample locations" << endl;
elementList_.clear(); elementList_.resize_nocopy(pointField::size());
elementList_.setSize(size()); faceList_.resize_nocopy(pointField::size());
processor_.resize_nocopy(pointField::size());
faceList_.clear();
faceList_.setSize(size());
processor_.setSize(size());
processor_ = -1; processor_ = -1;
forAll(*this, probei) forAll(*this, probei)
{ {
const vector& location = operator[](probei); const point& location = (*this)[probei];
const label celli = mesh.findCell(location); const label celli = mesh.findCell(location);
@ -107,7 +104,7 @@ void Foam::probes::findElements(const fvMesh& mesh)
// Check if all probes have been found. // Check if all probes have been found.
forAll(elementList_, probei) forAll(elementList_, probei)
{ {
const vector& location = operator[](probei); const point& location = operator[](probei);
label celli = elementList_[probei]; label celli = elementList_[probei];
label facei = faceList_[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()) if (Pstream::master())
{ {
wordHashSet currentFields; wordHashSet currentFields(2*nFields);
currentFields.insert(scalarFields_); currentFields.insert(scalarFields_);
currentFields.insert(vectorFields_); currentFields.insert(vectorFields_);
currentFields.insert(sphericalTensorFields_); currentFields.insert(sphericalTensorFields_);
@ -197,27 +232,7 @@ Foam::label Foam::probes::prepare()
<< "Probing locations: " << *this << nl << "Probing locations: " << *this << nl
<< endl; << endl;
// Close streams for fields that no longer exist
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
forAllIters(probeFilePtrs_, iter) forAllIters(probeFilePtrs_, iter)
{ {
if (!currentFields.erase(iter.key())) 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 if (!(request & ACTION_WRITE))
for (const word& fieldName : currentFields)
{ {
// Create directory if does not exist. // No writing - can return now
mkDir(probeDir); 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) forAll(*this, probei)
{ {
fout<< "# Probe " << probei << ' ' << operator[](probei); os << "# Probe " << probei << ' ' << operator[](probei);
if (processor_[probei] == -1) if (processor_[probei] == -1)
{ {
fout<< " # Not Found"; os << " # Not Found";
} }
// Only for patchProbes // Only for patchProbes
else if (probei < patchIDList_.size()) else if (probei < patchIDList_.size())
@ -264,31 +310,31 @@ Foam::label Foam::probes::prepare()
|| processor_[probei] == Pstream::myProcNo() || 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]) << mag(operator[](probei)-oldPoints_[probei])
<< " m to the original point " << " m to the original point "
<< oldPoints_[probei]; << oldPoints_[probei];
} }
} }
fout<< endl; os << nl;
} }
fout<< '#' << setw(IOstream::defaultPrecision() + 6) os << '#' << setw(IOstream::defaultPrecision() + 6)
<< "Probe"; << "Probe";
forAll(*this, probei) forAll(*this, probei)
{ {
if (includeOutOfBounds_ || processor_[probei] != -1) 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; << "Time" << endl;
} }
} }
@ -308,23 +354,15 @@ Foam::probes::probes
const bool readFields const bool readFields
) )
: :
stateFunctionObject(name, runTime), functionObjects::fvMeshFunctionObject(name, runTime, dict),
pointField(0), pointField(),
mesh_
(
refCast<const fvMesh>
(
runTime.lookupObject<objectRegistry>
(
dict.getOrDefault("region", polyMesh::defaultRegion)
)
)
),
loadFromFiles_(loadFromFiles), loadFromFiles_(loadFromFiles),
fieldSelection_(),
fixedLocations_(true), fixedLocations_(true),
interpolationScheme_("cell"), includeOutOfBounds_(true),
includeOutOfBounds_(true) verbose_(false),
onExecute_(false),
fieldSelection_(),
samplePointScheme_("cell")
{ {
if (readFields) if (readFields)
{ {
@ -335,15 +373,28 @@ Foam::probes::probes
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::probes::verbose(const bool on) noexcept
{
bool old(verbose_);
verbose_ = on;
return old;
}
bool Foam::probes::read(const dictionary& dict) bool Foam::probes::read(const dictionary& dict)
{ {
dict.readEntry("probeLocations", static_cast<pointField&>(*this)); dict.readEntry("probeLocations", static_cast<pointField&>(*this));
dict.readEntry("fields", fieldSelection_); dict.readEntry("fields", fieldSelection_);
dict.readIfPresent("fixedLocations", fixedLocations_); 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 WarningInFunction
<< "Only cell interpolation can be applied when " << "Only cell interpolation can be applied when "
@ -352,41 +403,51 @@ bool Foam::probes::read(const dictionary& dict)
<< endl; << endl;
} }
} }
dict.readIfPresent("includeOutOfBounds", includeOutOfBounds_);
// Initialise cells to sample from supplied locations // Initialise cells to sample from supplied locations
findElements(mesh_); findElements(mesh_);
prepare(); // Close old (ununsed) streams
prepare(ACTION_NONE);
return true; 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() bool Foam::probes::execute()
{ {
if (onExecute_)
{
return performAction(ACTION_ALL & ~ACTION_WRITE);
}
return true; return true;
} }
bool Foam::probes::write() bool Foam::probes::write()
{ {
if (size() && prepare()) return performAction(ACTION_ALL);
{
sampleAndWrite(scalarFields_);
sampleAndWrite(vectorFields_);
sampleAndWrite(sphericalTensorFields_);
sampleAndWrite(symmTensorFields_);
sampleAndWrite(tensorFields_);
sampleAndWriteSurfaceFields(surfaceScalarFields_);
sampleAndWriteSurfaceFields(surfaceVectorFields_);
sampleAndWriteSurfaceFields(surfaceSphericalTensorFields_);
sampleAndWriteSurfaceFields(surfaceSymmTensorFields_);
sampleAndWriteSurfaceFields(surfaceTensorFields_);
}
return true;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2021 OpenCFD Ltd. Copyright (C) 2016-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -50,7 +50,7 @@ Description
writeInterval 1; writeInterval 1;
// Fields to be probed // Fields to be probed
fields (p U); fields (U "p.*");
// Optional: do not recalculate cells if mesh moves // Optional: do not recalculate cells if mesh moves
fixedLocations false; fixedLocations false;
@ -72,15 +72,28 @@ Description
} }
\endverbatim \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 SourceFiles
probes.C probes.C
probesTemplates.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef probes_H #ifndef Foam_probes_H
#define probes_H #define Foam_probes_H
#include "stateFunctionObject.H" #include "fvMeshFunctionObject.H"
#include "HashPtrTable.H" #include "HashPtrTable.H"
#include "OFstream.H" #include "OFstream.H"
#include "polyMesh.H" #include "polyMesh.H"
@ -89,15 +102,14 @@ SourceFiles
#include "surfaceFieldsFwd.H" #include "surfaceFieldsFwd.H"
#include "surfaceMesh.H" #include "surfaceMesh.H"
#include "wordRes.H" #include "wordRes.H"
#include "IOobjectList.H"
using namespace Foam::functionObjects;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Forward declaration of classes // Forward Declarations
class Time; class Time;
class objectRegistry; class objectRegistry;
class dictionary; class dictionary;
@ -110,70 +122,75 @@ class mapPolyMesh;
class probes class probes
: :
public stateFunctionObject, public functionObjects::fvMeshFunctionObject,
public pointField public pointField
{ {
protected: protected:
// Protected classes // Protected Classes
//- Class used for grouping field types //- Grouping of field names by GeometricField type
template<class Type> template<class GeoField>
class fieldGroup struct fieldGroup : public DynamicList<word> {};
:
public DynamicList<word>
// Data Types
//- Local control for sampling actions
enum sampleActionType : unsigned
{ {
public: ACTION_NONE = 0,
//- Construct null ACTION_WRITE = 0x1,
fieldGroup() ACTION_STORE = 0x2,
: ACTION_ALL = 0xF
DynamicList<word>(0)
{}
}; };
// Protected data // Protected Data
//- Const reference to fvMesh
const fvMesh& mesh_;
//- Load fields from files (not from objectRegistry) //- Load fields from files (not from objectRegistry)
bool loadFromFiles_; bool loadFromFiles_;
//- Fixed locations (default: true)
// Read from dictionary
//- Names of fields to probe
wordRes fieldSelection_;
//- Fixed locations, default = yes
// Note: set to false for moving mesh calculations where locations // Note: set to false for moving mesh calculations where locations
// should move with the mesh // should move with the mesh
bool fixedLocations_; bool fixedLocations_;
//- Interpolation scheme name //- Include probes that were not found (default: true)
// Note: only possible when fixedLocations_ is true
word interpolationScheme_;
//- Include probes that were not found
bool includeOutOfBounds_; bool includeOutOfBounds_;
//- Output verbosity
bool verbose_;
// Calculated //- Perform sample actions on execute as well
bool onExecute_;
//- Categorized scalar/vector/tensor vol fields //- Requested names of fields to probe
fieldGroup<scalar> scalarFields_; wordRes fieldSelection_;
fieldGroup<vector> vectorFields_;
fieldGroup<sphericalTensor> sphericalTensorFields_;
fieldGroup<symmTensor> symmTensorFields_;
fieldGroup<tensor> tensorFields_;
//- Categorized scalar/vector/tensor surf fields //- Interpolation/sample scheme to obtain values at the points
fieldGroup<scalar> surfaceScalarFields_; // Note: only possible when fixedLocations_ is true
fieldGroup<vector> surfaceVectorFields_; word samplePointScheme_;
fieldGroup<sphericalTensor> surfaceSphericalTensorFields_;
fieldGroup<symmTensor> surfaceSymmTensorFields_;
fieldGroup<tensor> surfaceTensorFields_; // 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) //- Cells to be probed (obtained from the locations)
labelList elementList_; labelList elementList_;
@ -185,58 +202,57 @@ protected:
// on any processor) // on any processor)
labelList processor_; labelList processor_;
//- Current open files //- Current open files (non-empty on master only)
HashPtrTable<OFstream> probeFilePtrs_; 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 //- Original probes location (only used for patchProbes)
labelList patchIDList_; pointField oldPoints_;
//- Original probes location (only used for patchProbes)
pointField oldPoints_;
// Protected Member Functions // 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 //- Find cells and faces containing probes
virtual void findElements(const fvMesh& mesh); virtual void findElements(const fvMesh& mesh);
//- Classify field type and open/close file streams, //- Classify field types, close/open file streams
// returns number of fields to sample // \return number of fields to sample
label prepare(); 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: private:
//- Sample and write a particular volume field // Private Member Functions
//- Write field values
template<class Type> template<class Type>
void sampleAndWrite void writeValues
( (
const GeometricField<Type, fvPatchField, volMesh>& const word& fieldName,
const Field<Type>& values,
const scalar timeValue
); );
//- Sample and store/write all applicable sampled fields
//- Sample and write a particular surface field template<class GeoField>
template<class Type> void performAction
void sampleAndWrite
( (
const GeometricField<Type, fvsPatchField, surfaceMesh>& const fieldGroup<GeoField>& fieldNames, /* must be sorted */
unsigned request
); );
//- Sample and write all the fields of the given type //- Perform sampling action with store/write
template<class Type> bool performAction(unsigned request);
void sampleAndWrite(const fieldGroup<Type>&);
//- Sample and write all the surface fields of the given type
template<class Type>
void sampleAndWriteSurfaceFields(const fieldGroup<Type>&);
//- No copy construct //- No copy construct
probes(const probes&) = delete; probes(const probes&) = delete;
@ -244,7 +260,6 @@ private:
//- No copy assignment //- No copy assignment
void operator=(const probes&) = delete; void operator=(const probes&) = delete;
public: public:
//- Runtime type information //- Runtime type information
@ -270,14 +285,18 @@ public:
// Member Functions // Member Functions
//- Enable/disable verbose output
// \return old value
bool verbose(const bool on) noexcept;
//- Return names of fields to probe //- Return names of fields to probe
virtual const wordRes& fieldNames() const virtual const wordRes& fieldNames() const noexcept
{ {
return fieldSelection_; return fieldSelection_;
} }
//- Return locations to probe //- Return locations to probe
virtual const pointField& probeLocations() const virtual const pointField& probeLocations() const noexcept
{ {
return *this; return *this;
} }
@ -289,7 +308,7 @@ public:
} }
//- Cells to be probed (obtained from the locations) //- Cells to be probed (obtained from the locations)
const labelList& elements() const const labelList& elements() const noexcept
{ {
return elementList_; return elementList_;
} }
@ -297,7 +316,7 @@ public:
//- Read the probes //- Read the probes
virtual bool read(const dictionary&); virtual bool read(const dictionary&);
//- Execute, currently does nothing //- Sample and store result if the sampleOnExecute is enabled.
virtual bool execute(); virtual bool execute();
//- Sample and write //- Sample and write
@ -313,27 +332,24 @@ public:
virtual void readUpdate(const polyMesh::readUpdateState state) virtual void readUpdate(const polyMesh::readUpdateState state)
{} {}
// Sampling
//- Sample a volume field at all locations //- Sample a volume field at all locations
template<class Type> template<class Type>
tmp<Field<Type>> sample tmp<Field<Type>> sample(const VolumeField<Type>&) const;
(
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;
//- Sample a surface field at all locations //- Sample a surface field at all locations
template<class Type> template<class Type>
tmp<Field<Type>> sample tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& //- Sample a volume field at all locations
) const; 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;
}; };

View File

@ -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;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd. Copyright (C) 2017-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -38,10 +38,8 @@ namespace Foam
{ {
template<class T> template<class T>
class isNotEqOp struct isNotEqOp
{ {
public:
void operator()(T& x, const T& y) const void operator()(T& x, const T& y) const
{ {
const T unsetVal(-VGREAT*pTraits<T>::one); 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 * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type> 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()) if (Pstream::master())
{ {
unsigned int w = IOstream::defaultPrecision() + 7; const unsigned int w = IOstream::defaultPrecision() + 7;
OFstream& os = *probeFilePtrs_[vField.name()]; OFstream& os = *probeFilePtrs_[fieldName];
os << setw(w) << vField.time().timeOutputValue(); os << setw(w) << timeValue;
forAll(values, probei) forAll(values, probei)
{ {
@ -90,144 +150,53 @@ void Foam::probes::sampleAndWrite
} }
os << 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> template<class GeoField>
void Foam::probes::sampleAndWrite void Foam::probes::performAction
( (
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField const fieldGroup<GeoField>& fieldNames,
unsigned request
) )
{ {
Field<Type> values(sample(sField)); for (const word& fieldName : fieldNames)
if (Pstream::master())
{ {
unsigned int w = IOstream::defaultPrecision() + 7; tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
OFstream& os = *probeFilePtrs_[sField.name()];
os << setw(w) << sField.time().timeOutputValue(); if (tfield)
forAll(values, probei)
{ {
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]; this->writeValues(fieldName, values, timeValue);
}
}
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));
} }
} }
} }
} }
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 * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
Foam::probes::sample Foam::probes::sample(const VolumeField<Type>& vField) const
(
const GeometricField<Type, fvPatchField, volMesh>& vField
) const
{ {
const Type unsetVal(-VGREAT*pTraits<Type>::one); const Type unsetVal(-VGREAT*pTraits<Type>::one);
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal)); auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
auto& values = tValues.ref(); auto& values = tvalues.ref();
if (fixedLocations_) if (fixedLocations_)
{ {
autoPtr<interpolation<Type>> interpolator autoPtr<interpolation<Type>> interpPtr
( (
interpolation<Type>::New(interpolationScheme_, vField) interpolation<Type>::New(samplePointScheme_, vField)
); );
forAll(*this, probei) forAll(*this, probei)
@ -236,7 +205,7 @@ Foam::probes::sample
{ {
const vector& position = operator[](probei); const vector& position = operator[](probei);
values[probei] = interpolator().interpolate values[probei] = interpPtr().interpolate
( (
position, position,
elementList_[probei], elementList_[probei],
@ -259,35 +228,18 @@ Foam::probes::sample
Pstream::listCombineGather(values, isNotEqOp<Type>()); Pstream::listCombineGather(values, isNotEqOp<Type>());
Pstream::listCombineScatter(values); Pstream::listCombineScatter(values);
return tValues; return tvalues;
} }
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
Foam::probes::sample(const word& fieldName) const Foam::probes::sample(const SurfaceField<Type>& sField) 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
{ {
const Type unsetVal(-VGREAT*pTraits<Type>::one); const Type unsetVal(-VGREAT*pTraits<Type>::one);
auto tValues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal)); auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
auto& values = tValues.ref(); auto& values = tvalues.ref();
forAll(*this, probei) forAll(*this, probei)
{ {
@ -300,21 +252,24 @@ Foam::probes::sample
Pstream::listCombineGather(values, isNotEqOp<Type>()); Pstream::listCombineGather(values, isNotEqOp<Type>());
Pstream::listCombineScatter(values); Pstream::listCombineScatter(values);
return tValues; return tvalues;
} }
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
Foam::probes::sampleSurfaceFields(const word& fieldName) const Foam::probes::sample(const word& fieldName) const
{ {
return sample return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
(
mesh_.lookupObject<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
fieldName
)
);
} }
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::probes::sampleSurfaceField(const word& fieldName) const
{
return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -36,46 +36,40 @@ Volume3_v_fins
probesFins probesFins
{ {
type probes; type probes;
libs (sampling); libs (sampling);
writeControl timeStep; writeControl timeStep;
writeInterval 1; writeInterval 1;
interpolationScheme cell; interpolationScheme cell;
region v_fins; region v_fins;
setFormat raw;
log true; fields ( T );
valueOutput false;
writeFields false;
probeLocations probeLocations
( (
(0.118 0.01 -0.125) (0.118 0.01 -0.125)
(0.118 0.03 -0.125) (0.118 0.03 -0.125)
); );
fields ( T );
} }
probesFluid probesFluid
{ {
type probes; type probes;
libs (sampling); libs (sampling);
writeControl timeStep; writeControl timeStep;
writeInterval 1; writeInterval 1;
interpolationScheme cell; interpolationScheme cell;
region domain0; region domain0;
setFormat raw;
log true; log true;
valueOutput false; verbose true;
writeFields false;
fields (T U);
probeLocations probeLocations
( (
(0.118 0.035 -0.125) (0.118 0.035 -0.125)
(0.118 0.07 -0.125) (0.118 0.07 -0.125)
); );
fields ( T U);
} }
#remove (_volFieldValue _surfaceFieldValue) #remove (_volFieldValue _surfaceFieldValue)