ENH: refactor cell selections into cellBitSet

- ensightWrite, vtkWrite, fv::cellSetOption

ENH: additional topoSet "ignore" action

- this no-op can be used to skip an action step, instead of removing
  the entire entry
This commit is contained in:
Mark Olesen 2022-05-30 19:55:47 +02:00
parent 1845c28ee4
commit 8081fc7234
15 changed files with 316 additions and 292 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2018 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -344,29 +344,39 @@ bool doCommand
topoSetSource::setAction action =
topoSetSource::actionNames[actionName];
switch (action)
{
case topoSetSource::REMOVE :
{
removeSet(mesh, setType, setName);
break;
}
IOobject::readOption r;
case topoSetSource::NEW :
case topoSetSource::CLEAR :
{
currentSetPtr = topoSet::New(setType, mesh, setName, typSize);
break;
}
if (action == topoSetSource::REMOVE)
{
removeSet(mesh, setType, setName);
}
else if
(
(action == topoSetSource::NEW)
|| (action == topoSetSource::CLEAR)
)
{
r = IOobject::NO_READ;
currentSetPtr = topoSet::New(setType, mesh, setName, typSize);
}
else
{
r = IOobject::MUST_READ;
currentSetPtr = topoSet::New(setType, mesh, setName, r);
topoSet& currentSet = currentSetPtr();
// Presize it according to current mesh data.
currentSet.resize(max(currentSet.size(), typSize));
case topoSetSource::IGNORE :
// Nothing to do
break;
default:
{
currentSetPtr = topoSet::New
(
setType,
mesh,
setName,
IOobject::MUST_READ
);
topoSet& currentSet = currentSetPtr();
// Presize it according to current mesh data.
currentSet.resize(max(currentSet.size(), typSize));
}
}
if (currentSetPtr)
@ -380,23 +390,26 @@ bool doCommand
switch (action)
{
case topoSetSource::CLEAR:
case topoSetSource::CLEAR :
{
// Already handled above by not reading
break;
}
case topoSetSource::INVERT:
case topoSetSource::INVERT :
{
currentSet.invert(currentSet.maxSize(mesh));
break;
}
case topoSetSource::LIST:
case topoSetSource::LIST :
{
currentSet.writeDebug(Pout, mesh, 100);
Pout<< endl;
break;
}
case topoSetSource::SUBSET:
case topoSetSource::SUBSET :
{
if (is >> sourceType)
{
@ -430,6 +443,7 @@ bool doCommand
}
break;
}
default:
{
if (is >> sourceType)
@ -449,7 +463,6 @@ bool doCommand
}
}
if (action != topoSetSource::LIST)
{
// Set will have been modified.

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -263,43 +263,52 @@ int main(int argc, char *argv[])
topoSetSource::actionNames.get("action", dict);
autoPtr<topoSet> currentSet;
if
(
action == topoSetSource::NEW
|| action == topoSetSource::CLEAR
)
{
currentSet = topoSet::New(setType, mesh, setName, 16384);
Info<< "Created " << currentSet().type() << ' '
<< setName << endl;
}
else if (action == topoSetSource::REMOVE)
{
//?
}
else
{
currentSet = topoSet::New
(
setType,
mesh,
setName,
IOobject::MUST_READ
);
Info<< "Read set " << currentSet().type() << ' '
<< setName << " with size "
<< returnReduce(currentSet().size(), sumOp<label>())
<< endl;
}
switch (action)
{
case topoSetSource::NEW :
case topoSetSource::CLEAR :
{
currentSet = topoSet::New(setType, mesh, setName, 16384);
Info<< "Created "
<< currentSet().type() << ' ' << setName << endl;
break;
}
case topoSetSource::IGNORE :
continue; // Nothing to do
break;
case topoSetSource::REMOVE :
// Nothing to load
break;
default:
{
// Load set
currentSet = topoSet::New
(
setType,
mesh,
setName,
IOobject::MUST_READ
);
Info<< "Read set "
<< currentSet().type() << ' ' << setName
<< " size:"
<< returnReduce(currentSet().size(), sumOp<label>())
<< endl;
}
}
// Handle special actions (clear, invert) locally,
// the other actions through sources.
switch (action)
{
case topoSetSource::NEW:
case topoSetSource::ADD:
case topoSetSource::SUBTRACT:
case topoSetSource::NEW :
case topoSetSource::ADD :
case topoSetSource::SUBTRACT :
{
const word sourceType(dict.get<word>("source"));
@ -321,10 +330,10 @@ int main(int argc, char *argv[])
<< currentSet().objectPath() << endl;
}
fileHandler().flush();
break;
}
break;
case topoSetSource::SUBSET:
case topoSetSource::SUBSET :
{
const word sourceType(dict.get<word>("source"));
@ -362,10 +371,12 @@ int main(int argc, char *argv[])
<< currentSet().objectPath() << endl;
}
fileHandler().flush();
}
break;
case topoSetSource::CLEAR:
break;
}
case topoSetSource::CLEAR :
{
Info<< " Clearing " << currentSet().type() << endl;
currentSet().clear();
if (!currentSet().write())
@ -375,9 +386,12 @@ int main(int argc, char *argv[])
<< currentSet().objectPath() << endl;
}
fileHandler().flush();
break;
case topoSetSource::INVERT:
break;
}
case topoSetSource::INVERT :
{
Info<< " Inverting " << currentSet().type() << endl;
currentSet().invert(currentSet().maxSize(mesh));
if (!currentSet().write())
@ -387,17 +401,22 @@ int main(int argc, char *argv[])
<< currentSet().objectPath() << endl;
}
fileHandler().flush();
break;
case topoSetSource::REMOVE:
break;
}
case topoSetSource::REMOVE :
{
Info<< " Removing set" << endl;
removeSet(mesh, setType, setName);
break;
break;
}
default:
WarningInFunction
<< "Unhandled action " << action << endl;
break;
<< "Unhandled action: "
<< topoSetSource::actionNames[action] << endl;
}
if (currentSet)

View File

@ -144,15 +144,6 @@ namespace Foam
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Detail::parcelSelection::parcelSelection()
:
parcelSelect_(),
parcelAddr_()
{}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::Detail::parcelSelection::calculateFilter

View File

@ -179,7 +179,7 @@ public:
protected:
// Protected data
// Protected Data
//- The filtered parcel addressing. Eg, for the current cloud.
dictionary parcelSelect_;
@ -202,13 +202,12 @@ public:
// Constructors
//- Construct null
parcelSelection();
//- Default construct
parcelSelection() = default;
//- Destructor
virtual ~parcelSelection() = default;
};

View File

@ -123,6 +123,7 @@ See also
Foam::functionObjects::vtkWrite
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::timeControl
Foam::cellBitSet::select
SourceFiles
ensightWrite.C
@ -148,7 +149,7 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class dictionary;
namespace functionObjects

View File

@ -28,23 +28,6 @@ License
#include "ensightWrite.H"
#include "dictionary.H"
#include "cellBitSet.H"
#include "topoSetCellSource.H"
// * * * * * * * * * * * * * * Local Data Members * * * * * * * * * * * * * //
namespace Foam
{
// A limited selection of actions
const Enum<topoSetSource::setAction> actionNames
({
{ topoSetSource::NEW, "use" }, // Reuse NEW for "use" action name
{ topoSetSource::ADD, "add" },
{ topoSetSource::SUBTRACT, "subtract" },
{ topoSetSource::SUBSET, "subset" },
{ topoSetSource::INVERT, "invert" },
});
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -58,74 +41,12 @@ bool Foam::functionObjects::ensightWrite::updateSubset
return false;
}
const fvMesh& mesh = subsetter.baseMesh();
bitSet selectedCells
(
cellBitSet::select(subsetter.baseMesh(), selection_)
);
// Start with all cells unselected
cellBitSet cellsToSelect(mesh, false);
// Execute all actions
for (const entry& dEntry : selection_)
{
if (!dEntry.isDict())
{
WarningInFunction
<< "Ignoring non-dictionary entry "
<< dEntry << endl;
continue;
}
const dictionary& dict = dEntry.dict();
const auto action = actionNames.get("action", dict);
// Handle manually
if (action == topoSetSource::INVERT)
{
cellsToSelect.invert(mesh.nCells());
continue;
}
auto source = topoSetCellSource::New
(
dict.get<word>("source"),
mesh,
dict.optionalSubDict("sourceInfo")
);
source->verbose(false);
switch (action)
{
case topoSetSource::NEW: // "use"
case topoSetSource::ADD:
case topoSetSource::SUBTRACT:
if (topoSetSource::NEW == action)
{
// "use": only use this selection (clear + ADD)
// NEW is handled like ADD in applyToSet()
cellsToSelect.reset();
}
source->applyToSet(action, cellsToSelect);
break;
case topoSetSource::SUBSET:
{
cellBitSet other(mesh, false);
source->applyToSet(topoSetSource::NEW, other);
cellsToSelect.subset(other);
}
break;
default:
// Should already have been caught
WarningInFunction
<< "Ignoring unhandled action '"
<< actionNames[action] << "'" << endl;
break;
}
}
subsetter.reset(cellsToSelect.addressing());
subsetter.reset(selectedCells);
return true;
}

View File

@ -124,6 +124,7 @@ See also
Foam::functionObjects::ensightWrite
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::timeControl
Foam::cellBitSet::select
SourceFiles
vtkWrite.C

View File

@ -27,25 +27,8 @@ License
#include "vtkWrite.H"
#include "cellBitSet.H"
#include "topoSetCellSource.H"
#include "processorPolyPatch.H"
// * * * * * * * * * * * * * * Local Data Members * * * * * * * * * * * * * //
namespace Foam
{
// A limited selection of actions
const Enum<topoSetSource::setAction> actionNames
({
{ topoSetSource::NEW, "use" }, // Reuse NEW for "use" action name
{ topoSetSource::ADD, "add" },
{ topoSetSource::SUBTRACT, "subtract" },
{ topoSetSource::SUBSET, "subset" },
{ topoSetSource::INVERT, "invert" },
});
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::functionObjects::vtkWrite::updateSubset
@ -58,73 +41,12 @@ bool Foam::functionObjects::vtkWrite::updateSubset
return false;
}
const fvMesh& mesh = subsetter.baseMesh();
bitSet selectedCells
(
cellBitSet::select(subsetter.baseMesh(), selection_)
);
// Start with all cells unselected
cellBitSet cellsToSelect(mesh, false);
for (const entry& dEntry : selection_)
{
if (!dEntry.isDict())
{
WarningInFunction
<< "Ignoring non-dictionary entry "
<< dEntry << endl;
continue;
}
const dictionary& dict = dEntry.dict();
const auto action = actionNames.get("action", dict);
// Handle manually
if (action == topoSetSource::INVERT)
{
cellsToSelect.invert(mesh.nCells());
continue;
}
auto source = topoSetCellSource::New
(
dict.get<word>("source"),
mesh,
dict.optionalSubDict("sourceInfo")
);
source->verbose(false);
switch (action)
{
case topoSetSource::NEW: // "use"
case topoSetSource::ADD:
case topoSetSource::SUBTRACT:
if (topoSetSource::NEW == action)
{
// "use": only use this selection (clear + ADD)
// NEW is handled like ADD in applyToSet()
cellsToSelect.reset();
}
source->applyToSet(action, cellsToSelect);
break;
case topoSetSource::SUBSET:
{
cellBitSet other(mesh, false);
source->applyToSet(topoSetSource::NEW, other);
cellsToSelect.subset(other);
}
break;
default:
// Should already have been caught
WarningInFunction
<< "Ignoring unhandled action '"
<< actionNames[action] << "'" << endl;
break;
}
}
subsetter.reset(cellsToSelect.addressing());
subsetter.reset(selectedCells);
return true;
}

View File

@ -29,7 +29,6 @@ License
#include "cellSetOption.H"
#include "cellSet.H"
#include "cellBitSet.H"
#include "topoSetCellSource.H"
#include "volFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -133,36 +132,16 @@ void Foam::fv::cellSetOption::setCellSelection()
{
case smGeometric:
{
// Modify bitSet via topoSetCellSource
cellBitSet selectedCells(mesh_);
Info<< indent << "- selecting cells geometrically" << endl;
for (const entry& dEntry : geometricSelection_)
{
if (!dEntry.isDict())
{
WarningInFunction
<< "Ignoring non-dictionary entry "
<< dEntry << endl;
continue;
}
bitSet selectedCells
(
// verbosity = true
cellBitSet::select(mesh_, geometricSelection_, true)
);
const dictionary& spec = dEntry.dict();
auto source = topoSetCellSource::New
(
spec.get<word>("source"),
mesh_,
spec.optionalSubDict("sourceInfo")
);
// source->verbose(false);
source->applyToSet(topoSetSource::ADD, selectedCells);
}
// Retrieve bitSet
cells_ = selectedCells.addressing().sortedToc();
// From bitSet -> labels
cells_ = selectedCells.sortedToc();
break;
}
case smPoints:

View File

@ -64,12 +64,14 @@ Usage
{
box1
{
action use;
source box;
min (-0.1 -0.01 -0.1);
max (0.1 0.30 0.1);
}
ball
{
action add;
source sphere;
origin (-0.1 -0.01 -0.1);
radius 0.25;
@ -102,20 +104,22 @@ Usage
cellZone | Use specified cellZone
cellSet | Use specified cellSet
points | Use cells containing a given set of points
geometric | Select cells based on topoSetCellSource
geometric | Select cells based on topoSetCellSource actions
\endverbatim
The inherited entries are elaborated in:
- \link fvOption.H \endlink
The geometric selection uses topoSetCellSource to select cells.
The combined cell selections are treated as an OR operation.
Any searchableSurface selections must describe a closed volume.
Ie, its hasVolumeType() method must be true.
Note
- Source/sink options are to be added to the right-hand side of equations.
See also
Foam::cellBitSet::select
SourceFiles
cellSetOption.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -53,16 +53,32 @@ Foam::topoSetSource::actionNames
({
{ setAction::ADD, "add" },
{ setAction::SUBTRACT, "subtract" },
{ setAction::NEW, "new" },
{ setAction::SUBSET, "subset" },
{ setAction::INVERT, "invert" },
{ setAction::CLEAR, "clear" },
{ setAction::NEW, "new" },
{ setAction::REMOVE, "remove" },
{ setAction::LIST, "list" },
{ setAction::IGNORE, "ignore" },
{ setAction::SUBTRACT, "delete" }, // Compat (1806)
});
const Foam::Enum
<
Foam::topoSetSource::setAction
>
Foam::topoSetSource::combineNames
({
{ setAction::NEW, "use" }, // "use" specified selection
{ setAction::ADD, "add" },
{ setAction::SUBTRACT, "subtract" },
{ setAction::SUBSET, "subset" },
{ setAction::INVERT, "invert" },
{ setAction::IGNORE, "ignore" },
});
const Foam::string Foam::topoSetSource::illegalSource_
(
"Illegal topoSetSource name"

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,8 +38,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef topoSetSource_H
#define topoSetSource_H
#ifndef Foam_topoSetSource_H
#define Foam_topoSetSource_H
#include "pointField.H"
#include "labelList.H"
@ -97,13 +97,13 @@ public:
POINTZONESOURCE = POINTZONE_SOURCE, // Compat (2019-11)
};
//- Enumeration defining the valid actions
//- Enumeration defining various actions
enum setAction
{
// Fundamental actions
ADD, //!< Add elements to current set
NEW, //!< Create a new set and ADD elements to it
SUBTRACT, //!< Subtract elements from current set
NEW, //!< Create a new set and ADD elements to it
// Derived/intrinsic actions
SUBSET, //!< Union of elements with current set
@ -112,12 +112,21 @@ public:
REMOVE, //!< Remove the set (from the file system)
LIST, //!< Print contents of the set
IGNORE, //!< "ignore" no-op action
DELETE = SUBTRACT, //!< \deprecated(2018-10) Alias for SUBTRACT
};
//- The setActions text representations
//- The setActions enum text.
//- Names: "new", add", "subtract", "subset", "invert",
//- "clear", "remove", "list", "ignore"
static const Enum<setAction> actionNames;
//- The setAction enum text when combining selections.
//- Names: "use", "add", "subtract", "subset", "invert", "ignore"
//
// \note The "use" is like "new" (start from empty + ADD)
static const Enum<setAction> combineNames;
protected:

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,7 +26,9 @@ License
\*---------------------------------------------------------------------------*/
#include "cellBitSet.H"
#include "dictionary.H"
#include "polyMesh.H"
#include "topoSetCellSource.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -89,4 +91,98 @@ void Foam::cellBitSet::writeDebug
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::bitSet Foam::cellBitSet::select
(
const polyMesh& mesh,
const dictionary& dict,
const bool verbosity
)
{
// Start with all cells unselected
cellBitSet result(mesh);
// Execute all actions
for (const entry& dEntry : dict)
{
if (!dEntry.isDict())
{
WarningInFunction
<< "Ignoring non-dictionary entry "
<< dEntry << endl;
continue;
}
const dictionary& dict = dEntry.dict();
const auto action = topoSetSource::combineNames.get("action", dict);
// These ones we do directly
switch (action)
{
case topoSetSource::INVERT :
{
result.invert(mesh.nCells());
continue; // Handled
break;
}
case topoSetSource::IGNORE :
continue; // Nothing to do
break;
default:
break;
}
auto source = topoSetCellSource::New
(
dict.get<word>("source"),
mesh,
dict.optionalSubDict("sourceInfo")
);
source->verbose(verbosity);
switch (action)
{
case topoSetSource::NEW : // ie, "use"
case topoSetSource::ADD :
case topoSetSource::SUBTRACT :
{
if (topoSetSource::NEW == action)
{
// "use": only use this selection (CLEAR + ADD)
// NEW is handled like ADD in applyToSet()
result.reset();
}
source->applyToSet(action, result);
break;
}
case topoSetSource::SUBSET :
{
cellBitSet other(mesh);
source->applyToSet(topoSetSource::NEW, other);
result.subset(other);
break;
}
default:
// Should already have been caught
WarningInFunction
<< "Ignoring unhandled action: "
<< topoSetSource::combineNames[action] << endl;
}
}
bitSet addr(std::move(result.addressing()));
return addr;
}
// ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,6 +30,43 @@ Description
A special purpose topoSet with the cell labels stored as a bitSet.
It does not correspond to a cellSet either (no associated IOobject).
The cellBitSet::select method is embedded in function objects
such as Foam::functionObjects::ensightWrite with actions like the
following:
\verbatim
selection
{
box
{
action use;
source box;
box (-0.1 -0.01 -0.1) (0.1 0.30 0.1);
}
dome
{
action add;
shape sphere;
origin (-0.1 -0.01 -0.1);
radius 0.25;
}
centre
{
action subtract;
source sphere;
origin (-0.1 -0.01 -0.1);
radius 0.1;
}
blob
{
action add;
source surface;
surface triSurfaceMesh;
name blob.stl;
}
}
\endverbatim
SourceFiles
cellBitSet.C
@ -45,6 +82,9 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class dictionary;
/*---------------------------------------------------------------------------*\
Class cellBitSet Declaration
\*---------------------------------------------------------------------------*/
@ -78,6 +118,18 @@ public:
virtual ~cellBitSet() = default;
// Static Functions
//- Return a cell selection according to the dictionary
//- specification of actions.
static bitSet select
(
const polyMesh& mesh,
const dictionary& dict,
const bool verbosity = false
);
// Member Functions
//- Sync cellBitSet across coupled patches.

View File

@ -26,6 +26,7 @@ tracer0
{
cylinder
{
action use;
source cylinder;
point1 (0.050 0 -1);
point2 (0.050 0 1);