mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: output filtering of vtkCloud by user selection (#1056)
- can filter by stride or field information.
For example,
selection
{
stride
{
// every 10th parcelId
action add;
source stride;
stride 10;
}
Umin
{
// Remove slow parcels
action subtract;
source field;
field U;
accept (less 1e-3);
}
diam
{
// Only particular diameter ranges
action subset;
source field;
field d;
accept (greater 1e-3) and (less 1e-3);
}
}
This commit is contained in:
@ -4,5 +4,6 @@ icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.C
|
|||||||
dsmcFields/dsmcFields.C
|
dsmcFields/dsmcFields.C
|
||||||
|
|
||||||
vtkCloud/vtkCloud.C
|
vtkCloud/vtkCloud.C
|
||||||
|
vtkCloud/parcelSelectionDetail.C
|
||||||
|
|
||||||
LIB = $(FOAM_LIBBIN)/liblagrangianFunctionObjects
|
LIB = $(FOAM_LIBBIN)/liblagrangianFunctionObjects
|
||||||
|
|||||||
416
src/functionObjects/lagrangian/vtkCloud/parcelSelectionDetail.C
Normal file
416
src/functionObjects/lagrangian/vtkCloud/parcelSelectionDetail.C
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "parcelSelectionDetail.H"
|
||||||
|
#include "scalarPredicates.H"
|
||||||
|
#include "labelField.H"
|
||||||
|
#include "scalarField.H"
|
||||||
|
#include "pointField.H"
|
||||||
|
#include "ListListOps.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::Enum
|
||||||
|
<
|
||||||
|
Foam::Detail::parcelSelection::actionType
|
||||||
|
>
|
||||||
|
Foam::Detail::parcelSelection::actionNames
|
||||||
|
({
|
||||||
|
{ actionType::ALL, "all" },
|
||||||
|
{ actionType::CLEAR, "clear" },
|
||||||
|
{ actionType::INVERT, "invert" },
|
||||||
|
{ actionType::ADD, "add" },
|
||||||
|
{ actionType::SUBTRACT, "subtract" },
|
||||||
|
{ actionType::SUBSET, "subset" },
|
||||||
|
{ actionType::IGNORE, "ignore" },
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::Enum
|
||||||
|
<
|
||||||
|
Foam::Detail::parcelSelection::sourceType
|
||||||
|
>
|
||||||
|
Foam::Detail::parcelSelection::sourceNames
|
||||||
|
({
|
||||||
|
{ sourceType::FIELD, "field" },
|
||||||
|
{ sourceType::STRIDE, "stride" },
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::Enum
|
||||||
|
<
|
||||||
|
Foam::Detail::parcelSelection::logicType
|
||||||
|
> Foam::Detail::parcelSelection::logicNames
|
||||||
|
({
|
||||||
|
{ logicType::AND, "and" },
|
||||||
|
{ logicType::OR, "or" },
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
template<class Type, class Predicate, class AccessOp>
|
||||||
|
static void apply
|
||||||
|
(
|
||||||
|
bitSet& selection,
|
||||||
|
const Detail::parcelSelection::actionType action,
|
||||||
|
const Predicate& accept,
|
||||||
|
const UList<Type>& list,
|
||||||
|
const AccessOp& aop
|
||||||
|
)
|
||||||
|
{
|
||||||
|
using actionType = Detail::parcelSelection::actionType;
|
||||||
|
|
||||||
|
const label len = selection.size();
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case actionType::ADD:
|
||||||
|
{
|
||||||
|
for (label parceli = 0; parceli < len; ++parceli)
|
||||||
|
{
|
||||||
|
if (accept(aop(list[parceli])))
|
||||||
|
{
|
||||||
|
selection.set(parceli);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case actionType::SUBTRACT:
|
||||||
|
{
|
||||||
|
for (label parceli = 0; parceli < len; ++parceli)
|
||||||
|
{
|
||||||
|
if (accept(aop(list[parceli])))
|
||||||
|
{
|
||||||
|
selection.unset(parceli);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case actionType::SUBSET:
|
||||||
|
{
|
||||||
|
for (const label parceli : selection)
|
||||||
|
{
|
||||||
|
if (!accept(aop(list[parceli])))
|
||||||
|
{
|
||||||
|
selection.unset(parceli);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::Detail::parcelSelection::parcelSelection()
|
||||||
|
:
|
||||||
|
parcelSelect_(),
|
||||||
|
parcelAddr_()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::Detail::parcelSelection::calculateFilter
|
||||||
|
(
|
||||||
|
const objectRegistry& obrTmp,
|
||||||
|
const bool log
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (parcelSelect_.empty())
|
||||||
|
{
|
||||||
|
parcelAddr_.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with all parcels unselected
|
||||||
|
|
||||||
|
// Number of parcels (locally)
|
||||||
|
const auto* pointsPtr = obrTmp.findObject<vectorField>("position");
|
||||||
|
label nParcels = pointsPtr->size();
|
||||||
|
|
||||||
|
parcelAddr_.reset();
|
||||||
|
parcelAddr_.resize(nParcels);
|
||||||
|
|
||||||
|
reduce(nParcels, sumOp<label>());
|
||||||
|
|
||||||
|
Log << "Applying parcel filtering to " << nParcels << " parcels" << nl;
|
||||||
|
|
||||||
|
if (!nParcels)
|
||||||
|
{
|
||||||
|
parcelAddr_.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The unary function type(s) for testing a scalar.
|
||||||
|
// Allocate 3 slots.
|
||||||
|
// 0 is the test
|
||||||
|
// 1,2 are for storage of composite tests (eg, and/or logic)
|
||||||
|
predicates::scalars tests(3);
|
||||||
|
|
||||||
|
for (const entry& dEntry : parcelSelect_)
|
||||||
|
{
|
||||||
|
if (!dEntry.isDict())
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< "Ignoring non-dictionary entry "
|
||||||
|
<< dEntry << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dictionary& dict = dEntry.dict();
|
||||||
|
|
||||||
|
// A very limited number of sources (stride, field)
|
||||||
|
// and actions (all add subtract subset) so handle manually
|
||||||
|
|
||||||
|
auto action = actionNames.get("action", dict);
|
||||||
|
|
||||||
|
// These ones we do directly
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case actionType::ALL:
|
||||||
|
Log << "- select all" << nl;
|
||||||
|
parcelAddr_ = true;
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case actionType::CLEAR:
|
||||||
|
Log << "- clear" << nl;
|
||||||
|
parcelAddr_ = false;
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case actionType::INVERT:
|
||||||
|
Log << "- invert" << nl;
|
||||||
|
parcelAddr_.flip();
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case actionType::IGNORE:
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The others need a source
|
||||||
|
// Need a source
|
||||||
|
const auto source = sourceNames.get("source", dict);
|
||||||
|
|
||||||
|
switch (source)
|
||||||
|
{
|
||||||
|
case sourceType::STRIDE:
|
||||||
|
{
|
||||||
|
const label stride = dict.get<label>("stride");
|
||||||
|
|
||||||
|
const labelField& ids =
|
||||||
|
obrTmp.lookupObject<labelField>("origId");
|
||||||
|
|
||||||
|
Log << "- " << actionNames[action]
|
||||||
|
<< " stride " << stride << nl;
|
||||||
|
|
||||||
|
if (stride <= 0)
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< nl
|
||||||
|
<< "Ignoring bad value for stride=" << stride << nl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
else if (stride == 1)
|
||||||
|
{
|
||||||
|
// More efficient handling of stride 1, but should
|
||||||
|
// not really be using stride == 1.
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case actionType::ADD:
|
||||||
|
parcelAddr_ = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case actionType::SUBTRACT:
|
||||||
|
parcelAddr_ = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Using stride > 1
|
||||||
|
apply
|
||||||
|
(
|
||||||
|
parcelAddr_,
|
||||||
|
action,
|
||||||
|
[=](const label id) -> bool { return !(id % stride); },
|
||||||
|
ids,
|
||||||
|
accessOp<label>() // pass-through
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sourceType::FIELD:
|
||||||
|
{
|
||||||
|
const word fieldName(dict.get<word>("field"));
|
||||||
|
|
||||||
|
const auto* labelFld =
|
||||||
|
obrTmp.findObject<labelField>(fieldName);
|
||||||
|
|
||||||
|
const auto* scalarFld =
|
||||||
|
obrTmp.findObject<scalarField>(fieldName);
|
||||||
|
|
||||||
|
const auto* vectorFld =
|
||||||
|
obrTmp.findObject<vectorField>(fieldName);
|
||||||
|
|
||||||
|
|
||||||
|
Log << "- " << actionNames[action] << " field " << fieldName;
|
||||||
|
|
||||||
|
if (!labelFld && !scalarFld && !vectorFld)
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< nl
|
||||||
|
<< "No scalar/vector parcel field: " << fieldName
|
||||||
|
<< " ignoring selection" << nl
|
||||||
|
<< endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry& e = dict.lookupEntry("accept", keyType::LITERAL);
|
||||||
|
|
||||||
|
ITstream& is = e.stream();
|
||||||
|
|
||||||
|
if (4 == is.size())
|
||||||
|
{
|
||||||
|
// 4 tokens:
|
||||||
|
// -> (op val)
|
||||||
|
|
||||||
|
Tuple2<word,scalar> expr1(is);
|
||||||
|
e.checkITstream(is);
|
||||||
|
|
||||||
|
tests.first() = predicates::scalars::operation(expr1);
|
||||||
|
|
||||||
|
Log << " : " << expr1;
|
||||||
|
}
|
||||||
|
else if (9 == is.size())
|
||||||
|
{
|
||||||
|
// 9 tokens:
|
||||||
|
// -> (op val) and (op val)
|
||||||
|
// -> (op val) or (op val)
|
||||||
|
|
||||||
|
Tuple2<word,scalar> expr1(is);
|
||||||
|
word logicName(is);
|
||||||
|
Tuple2<word,scalar> expr2(is);
|
||||||
|
e.checkITstream(is);
|
||||||
|
|
||||||
|
logicType logic = logicNames[logicName];
|
||||||
|
tests[1] = predicates::scalars::operation(expr1);
|
||||||
|
tests[2] = predicates::scalars::operation(expr2);
|
||||||
|
|
||||||
|
switch (logic)
|
||||||
|
{
|
||||||
|
case logicType::AND:
|
||||||
|
tests.first() =
|
||||||
|
predicates::scalars::andOp(tests[1], tests[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case logicType::OR:
|
||||||
|
tests.first() =
|
||||||
|
predicates::scalars::orOp(tests[1], tests[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log << " : " << expr1 << ' ' << logicName << ' ' << expr2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
action = actionType::IGNORE;
|
||||||
|
|
||||||
|
// Use the following to always provoke an error.
|
||||||
|
e.checkITstream(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labelFld)
|
||||||
|
{
|
||||||
|
apply
|
||||||
|
(
|
||||||
|
parcelAddr_,
|
||||||
|
action,
|
||||||
|
tests.first(),
|
||||||
|
*labelFld,
|
||||||
|
accessOp<label>() // pass-through
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (scalarFld)
|
||||||
|
{
|
||||||
|
apply
|
||||||
|
(
|
||||||
|
parcelAddr_,
|
||||||
|
action,
|
||||||
|
tests.first(),
|
||||||
|
*scalarFld,
|
||||||
|
accessOp<scalar>() // pass-through
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (vectorFld)
|
||||||
|
{
|
||||||
|
apply
|
||||||
|
(
|
||||||
|
parcelAddr_,
|
||||||
|
action,
|
||||||
|
tests.first(),
|
||||||
|
*vectorFld,
|
||||||
|
[](const vector& val) -> scalar
|
||||||
|
{
|
||||||
|
return Foam::mag(val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log << endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
221
src/functionObjects/lagrangian/vtkCloud/parcelSelectionDetail.H
Normal file
221
src/functionObjects/lagrangian/vtkCloud/parcelSelectionDetail.H
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::Detail::parcelSelection
|
||||||
|
|
||||||
|
Description
|
||||||
|
Selection of parcels based on their objectRegistry entries.
|
||||||
|
Normally accessed via a dictionary entry.
|
||||||
|
|
||||||
|
Example sub-dictionary entry
|
||||||
|
\verbatim
|
||||||
|
selection
|
||||||
|
{
|
||||||
|
stride
|
||||||
|
{
|
||||||
|
// every 10th parcelId
|
||||||
|
action add;
|
||||||
|
source stride;
|
||||||
|
stride 10;
|
||||||
|
}
|
||||||
|
injector
|
||||||
|
{
|
||||||
|
// Only output from injectorID == 1
|
||||||
|
action subset;
|
||||||
|
source field;
|
||||||
|
field typeId;
|
||||||
|
accept (equal 1);
|
||||||
|
}
|
||||||
|
Umin
|
||||||
|
{
|
||||||
|
// Remove slow parcels
|
||||||
|
action subtract;
|
||||||
|
source field;
|
||||||
|
field U;
|
||||||
|
accept (less 1e-3);
|
||||||
|
}
|
||||||
|
diam
|
||||||
|
{
|
||||||
|
// Only particular diameter ranges
|
||||||
|
action subset;
|
||||||
|
source field;
|
||||||
|
field d;
|
||||||
|
accept (greater 1e-3) and (less 1e-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
\heading Entry type
|
||||||
|
\table
|
||||||
|
Property | Description | Required | Default
|
||||||
|
action | all/clear/invert add/subtract/subset/ignore | yes |
|
||||||
|
source | field/stride | mostly |
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
\heading Stride source
|
||||||
|
\table
|
||||||
|
Property | Description | Required | Default
|
||||||
|
stride | The stride for the parcel id | yes |
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
\heading Field source
|
||||||
|
\table
|
||||||
|
Property | Description | Required | Default
|
||||||
|
field | The label/scalar/vector field name | yes |
|
||||||
|
accept | Acceptance or test criterion | yes |
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
The \c accept criterion has two forms:
|
||||||
|
-# single expression
|
||||||
|
- (expr)
|
||||||
|
-# composite expression
|
||||||
|
- (expr) or (expr)
|
||||||
|
- (expr) and (expr)
|
||||||
|
|
||||||
|
The expressions are a (op scalar) pair that form a unary scalar
|
||||||
|
predicate. The \a op is one of the following:
|
||||||
|
- lt, less
|
||||||
|
- le, lessEq
|
||||||
|
- gt, greater
|
||||||
|
- ge, greaterEq
|
||||||
|
- eq, equal
|
||||||
|
- neq, notEqual
|
||||||
|
|
||||||
|
For example,
|
||||||
|
\verbatim
|
||||||
|
accept (less 10);
|
||||||
|
accept (less 10) or (greater 100);
|
||||||
|
accept (ge 10) and (le 20);
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
See also
|
||||||
|
Foam::predicates::scalars
|
||||||
|
Foam::functionObjects::vtkCloud
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
parcelSelectionDetail.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef parcelSelectionDetail_H
|
||||||
|
#define parcelSelectionDetail_H
|
||||||
|
|
||||||
|
#include "bitSet.H"
|
||||||
|
#include "Enum.H"
|
||||||
|
#include "objectRegistry.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace Detail
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class Detail::parcelSelection Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class parcelSelection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Enumeration defining the valid selection actions
|
||||||
|
enum actionType
|
||||||
|
{
|
||||||
|
ALL, //!< "all" - select all parcels
|
||||||
|
CLEAR, //!< "clear" - clear the selection
|
||||||
|
INVERT, //!< "invert" - invert the selection
|
||||||
|
ADD, //!< "add" - parcel selection
|
||||||
|
SUBTRACT, //!< "subtract" - remove parcel selection
|
||||||
|
SUBSET, //!< "subset" - subset parcel selection
|
||||||
|
IGNORE, //!< "ignore" - dummy no-op
|
||||||
|
};
|
||||||
|
|
||||||
|
//- Names for the actionType
|
||||||
|
static const Enum<actionType> actionNames;
|
||||||
|
|
||||||
|
|
||||||
|
//- Enumeration defining the valid sources
|
||||||
|
enum sourceType
|
||||||
|
{
|
||||||
|
FIELD, //!< "field" - select based on field value
|
||||||
|
STRIDE //!< "stride" - select based on stride (parcel id)
|
||||||
|
};
|
||||||
|
|
||||||
|
//- Names for the sourceType
|
||||||
|
static const Enum<sourceType> sourceNames;
|
||||||
|
|
||||||
|
|
||||||
|
//- Enumeration defining and/or logic
|
||||||
|
enum logicType { AND, OR };
|
||||||
|
|
||||||
|
//- Names for the logicType
|
||||||
|
static const Enum<logicType> logicNames;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- The filtered parcel addressing. Eg, for the current cloud.
|
||||||
|
dictionary parcelSelect_;
|
||||||
|
|
||||||
|
//- The filtered parcel addressing. Eg, for the current cloud.
|
||||||
|
bitSet parcelAddr_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Calculate parcel selection filter.
|
||||||
|
// \return True if the filter is applicable
|
||||||
|
bool calculateFilter
|
||||||
|
(
|
||||||
|
const objectRegistry& obrTmp,
|
||||||
|
const bool log = true
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct null
|
||||||
|
parcelSelection();
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~parcelSelection() = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Detail
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -132,9 +132,23 @@ bool Foam::functionObjects::vtkCloud::writeCloud
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyFilter_ = calculateFilter(obrTmp, log);
|
||||||
|
reduce(applyFilter_, orOp<bool>());
|
||||||
|
|
||||||
|
|
||||||
|
// Number of parcels (locally)
|
||||||
|
label nParcels = (applyFilter_ ? parcelAddr_.count() : pointsPtr->size());
|
||||||
|
|
||||||
// Total number of parcels on all processes
|
// Total number of parcels on all processes
|
||||||
const label nTotParcels =
|
const label nTotParcels = returnReduce(nParcels, sumOp<label>());
|
||||||
returnReduce(pointsPtr->size(), sumOp<label>());
|
|
||||||
|
if (applyFilter_ && log)
|
||||||
|
{
|
||||||
|
// Report filtered/unfiltered count
|
||||||
|
Log << "After filtering using " << nTotParcels << '/'
|
||||||
|
<< (returnReduce(pointsPtr->size(), sumOp<label>()))
|
||||||
|
<< " parcels" << nl;
|
||||||
|
}
|
||||||
|
|
||||||
if (pruneEmpty_ && !nTotParcels)
|
if (pruneEmpty_ && !nTotParcels)
|
||||||
{
|
{
|
||||||
@ -216,7 +230,14 @@ bool Foam::functionObjects::vtkCloud::writeCloud
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (applyFilter_)
|
||||||
|
{
|
||||||
|
vtk::writeListParallel(format.ref(), *pointsPtr, parcelAddr_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vtk::writeListParallel(format.ref(), *pointsPtr);
|
vtk::writeListParallel(format.ref(), *pointsPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Pstream::master())
|
if (Pstream::master())
|
||||||
@ -333,6 +354,7 @@ Foam::functionObjects::vtkCloud::vtkCloud
|
|||||||
printf_(),
|
printf_(),
|
||||||
useVerts_(false),
|
useVerts_(false),
|
||||||
pruneEmpty_(false),
|
pruneEmpty_(false),
|
||||||
|
applyFilter_(false),
|
||||||
selectClouds_(),
|
selectClouds_(),
|
||||||
selectFields_(),
|
selectFields_(),
|
||||||
directory_(),
|
directory_(),
|
||||||
@ -404,7 +426,6 @@ bool Foam::functionObjects::vtkCloud::read(const dictionary& dict)
|
|||||||
useVerts_ = dict.lookupOrDefault<bool>("cellData", false);
|
useVerts_ = dict.lookupOrDefault<bool>("cellData", false);
|
||||||
pruneEmpty_ = dict.lookupOrDefault<bool>("prune", false);
|
pruneEmpty_ = dict.lookupOrDefault<bool>("prune", false);
|
||||||
|
|
||||||
|
|
||||||
selectClouds_.clear();
|
selectClouds_.clear();
|
||||||
dict.readIfPresent("clouds", selectClouds_);
|
dict.readIfPresent("clouds", selectClouds_);
|
||||||
|
|
||||||
@ -417,7 +438,10 @@ bool Foam::functionObjects::vtkCloud::read(const dictionary& dict)
|
|||||||
|
|
||||||
selectFields_.clear();
|
selectFields_.clear();
|
||||||
dict.readIfPresent("fields", selectFields_);
|
dict.readIfPresent("fields", selectFields_);
|
||||||
|
selectFields_.uniq();
|
||||||
|
|
||||||
|
// Actions to define selection
|
||||||
|
parcelSelect_ = dict.subOrEmptyDict("selection");
|
||||||
|
|
||||||
// Output directory
|
// Output directory
|
||||||
|
|
||||||
|
|||||||
@ -44,23 +44,56 @@ Description
|
|||||||
cloud myCloud;
|
cloud myCloud;
|
||||||
fields (T U rho);
|
fields (T U rho);
|
||||||
width 4; // file-padding
|
width 4; // file-padding
|
||||||
|
|
||||||
|
selection
|
||||||
|
{
|
||||||
|
stride
|
||||||
|
{
|
||||||
|
// every 10th parcelId
|
||||||
|
action add;
|
||||||
|
source stride;
|
||||||
|
stride 10;
|
||||||
|
}
|
||||||
|
Umin
|
||||||
|
{
|
||||||
|
// Remove slow parcels
|
||||||
|
action subtract;
|
||||||
|
source field;
|
||||||
|
field U;
|
||||||
|
accept (less 1e-3);
|
||||||
|
}
|
||||||
|
diam
|
||||||
|
{
|
||||||
|
// Only particular diameter ranges
|
||||||
|
action subset;
|
||||||
|
source field;
|
||||||
|
field d;
|
||||||
|
accept (greater 1e-3) and (less 1e-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
Usage
|
\heading Basic Usage
|
||||||
\table
|
\table
|
||||||
Property | Description | Required | Default
|
Property | Description | Required | Default
|
||||||
type | Type name: vtkCloud | yes |
|
type | Type name: vtkCloud | yes |
|
||||||
writeControl | Output control | recommended | timeStep
|
clouds | List of clouds (name or regex) | no |
|
||||||
cloud | | no | defaultCloud
|
cloud | Cloud name | no | defaultCloud
|
||||||
clouds | wordRe list of clouds | no |
|
fields | List of fields (name or regex) | no |
|
||||||
fields | wordRe list of fields | no |
|
selection | Parcel selection control | no | empty-dict
|
||||||
prune | Suppress writing of empty clouds | no | false
|
\endtable
|
||||||
cellData | Emit cellData instead of pointData | no | false
|
|
||||||
directory | The output directory name | no | postProcessing/NAME
|
\heading Output Options
|
||||||
width | Padding width for file name | no | 8
|
\table
|
||||||
|
Property | Description | Required | Default
|
||||||
format | Format as ascii or binary | no | binary
|
format | Format as ascii or binary | no | binary
|
||||||
precision | Write precision in ascii | no | same as IOstream
|
precision | Write precision in ascii | no | same as IOstream
|
||||||
|
directory | The output directory name | no | postProcessing/NAME
|
||||||
|
width | Padding width for file name | no | 8
|
||||||
|
cellData | Emit cellData instead of pointData | no | false
|
||||||
|
prune | Suppress writing of empty clouds | no | false
|
||||||
|
writeControl | Output control | recommended | timeStep
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
The output filename and fields are added to the functionObjectProperties
|
The output filename and fields are added to the functionObjectProperties
|
||||||
@ -77,7 +110,17 @@ Usage
|
|||||||
}
|
}
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
|
Note
|
||||||
|
The selection dictionary can be used for finer control of the parcel
|
||||||
|
output. It contains a set of (add,subtract,subset,clear,invert)
|
||||||
|
selection actions and sources.
|
||||||
|
Omitting the selection dictionary is the same as specifying the
|
||||||
|
conversion of all parcels (in the selected clouds).
|
||||||
|
More syntax details are to be found in the corresponding
|
||||||
|
Foam::Detail::parcelSelection class.
|
||||||
|
|
||||||
See also
|
See also
|
||||||
|
Foam::Detail::parcelSelection
|
||||||
Foam::functionObjects::ensightWrite
|
Foam::functionObjects::ensightWrite
|
||||||
Foam::functionObjects::vtkWrite
|
Foam::functionObjects::vtkWrite
|
||||||
Foam::functionObjects::fvMeshFunctionObject
|
Foam::functionObjects::fvMeshFunctionObject
|
||||||
@ -93,6 +136,7 @@ SourceFiles
|
|||||||
#define functionObjects_vtkCloud_H
|
#define functionObjects_vtkCloud_H
|
||||||
|
|
||||||
#include "fvMeshFunctionObject.H"
|
#include "fvMeshFunctionObject.H"
|
||||||
|
#include "parcelSelectionDetail.H"
|
||||||
#include "foamVtkOutputOptions.H"
|
#include "foamVtkOutputOptions.H"
|
||||||
#include "foamVtkSeriesWriter.H"
|
#include "foamVtkSeriesWriter.H"
|
||||||
#include "wordRes.H"
|
#include "wordRes.H"
|
||||||
@ -111,7 +155,8 @@ namespace functionObjects
|
|||||||
|
|
||||||
class vtkCloud
|
class vtkCloud
|
||||||
:
|
:
|
||||||
public fvMeshFunctionObject
|
public fvMeshFunctionObject,
|
||||||
|
public Foam::Detail::parcelSelection
|
||||||
{
|
{
|
||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
@ -127,6 +172,9 @@ class vtkCloud
|
|||||||
//- Suppress writing of empty clouds
|
//- Suppress writing of empty clouds
|
||||||
bool pruneEmpty_;
|
bool pruneEmpty_;
|
||||||
|
|
||||||
|
//- Apply output filter (for the current cloud)
|
||||||
|
bool applyFilter_;
|
||||||
|
|
||||||
//- Requested names of clouds to process
|
//- Requested names of clouds to process
|
||||||
wordRes selectClouds_;
|
wordRes selectClouds_;
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,14 @@ Foam::wordList Foam::functionObjects::vtkCloud::writeFields
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (applyFilter_)
|
||||||
|
{
|
||||||
|
vtk::writeListParallel(format.ref(), values, parcelAddr_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vtk::writeListParallel(format.ref(), values);
|
vtk::writeListParallel(format.ref(), values);
|
||||||
|
}
|
||||||
|
|
||||||
if (Pstream::master())
|
if (Pstream::master())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -54,6 +54,7 @@ maxDeltaT 1;
|
|||||||
functions
|
functions
|
||||||
{
|
{
|
||||||
#include "vtkCloud"
|
#include "vtkCloud"
|
||||||
|
#include "vtkWrite"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -6,6 +6,9 @@ cloudWrite
|
|||||||
libs ("liblagrangianFunctionObjects.so");
|
libs ("liblagrangianFunctionObjects.so");
|
||||||
log true;
|
log true;
|
||||||
|
|
||||||
|
// Nothing happens before this anyhow
|
||||||
|
timeStart 0.5;
|
||||||
|
|
||||||
writeControl writeTime;
|
writeControl writeTime;
|
||||||
|
|
||||||
// cloud reactingCloud1;
|
// cloud reactingCloud1;
|
||||||
@ -15,16 +18,68 @@ cloudWrite
|
|||||||
fields ( U T d "Y.*" );
|
fields ( U T d "Y.*" );
|
||||||
|
|
||||||
//- Output format (ascii | binary) - default = binary
|
//- Output format (ascii | binary) - default = binary
|
||||||
// format binary;
|
|
||||||
|
|
||||||
// format ascii;
|
// format ascii;
|
||||||
// writePrecision 12;
|
|
||||||
|
|
||||||
//- Suppress writing of empty clouds - default = false
|
// precision 12;
|
||||||
// prune true;
|
|
||||||
|
|
||||||
//- Output directory name - default = "VTK"
|
// Suppress writing of empty clouds - default = false
|
||||||
|
prune true;
|
||||||
|
|
||||||
|
//- Output directory name - Default postProcessing
|
||||||
// directory "VTK";
|
// directory "VTK";
|
||||||
|
|
||||||
|
selection
|
||||||
|
{
|
||||||
|
all
|
||||||
|
{
|
||||||
|
action all;
|
||||||
|
}
|
||||||
|
|
||||||
|
none
|
||||||
|
{
|
||||||
|
action clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduced number of output parcels
|
||||||
|
stride
|
||||||
|
{
|
||||||
|
action add;
|
||||||
|
source stride;
|
||||||
|
stride 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
T
|
||||||
|
{
|
||||||
|
action subset;
|
||||||
|
source field;
|
||||||
|
field T;
|
||||||
|
accept (greater 280) and (less 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
YH2O
|
||||||
|
{
|
||||||
|
action subset;
|
||||||
|
source field;
|
||||||
|
field YH2O(l);
|
||||||
|
accept (greater 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
diameter
|
||||||
|
{
|
||||||
|
action subset;
|
||||||
|
source field;
|
||||||
|
field d;
|
||||||
|
accept (greater 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
Umin
|
||||||
|
{
|
||||||
|
action subtract;
|
||||||
|
source field;
|
||||||
|
field U;
|
||||||
|
accept (less 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
// Minimal example of using the vtkWrite function object.
|
||||||
|
vtkWrite
|
||||||
|
{
|
||||||
|
type vtkWrite;
|
||||||
|
libs ("libutilityFunctionObjects.so");
|
||||||
|
log true;
|
||||||
|
|
||||||
|
// Nothing happens before this anyhow
|
||||||
|
timeStart 0.4;
|
||||||
|
writeControl writeTime;
|
||||||
|
|
||||||
|
boundary false;
|
||||||
|
|
||||||
|
interpolate true;
|
||||||
|
|
||||||
|
fields (U);
|
||||||
|
// format ascii;
|
||||||
|
|
||||||
|
// Region of interest
|
||||||
|
selection
|
||||||
|
{
|
||||||
|
inletRegion
|
||||||
|
{
|
||||||
|
action add;
|
||||||
|
source zone;
|
||||||
|
zones (leftFluid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write cell ids as field - Default=true
|
||||||
|
writeIds false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user