OpenFOAM: v1912 released! - For more information see https://www.openfoam.com/releases/openfoam-v1912

Commit 9b856995 authored by Mark Olesen's avatar Mark Olesen

ENH: add a patches filter for volMesh conversion (issue #2)

- allows restriction of the output patches to specific names and hiding
  others.
parent 79639bce
......@@ -62,13 +62,17 @@ void Foam::catalyst::faMeshInput::update()
forAllConstIters(meshes_, iter)
{
if (!backends_.found(iter.key()))
const word& areaName(iter.key());
if (!backends_.found(areaName))
{
backends_.set
(
iter.key(),
new Foam::vtk::faMeshAdaptor(*(iter.object()))
);
auto backend =
autoPtr<Foam::vtk::faMeshAdaptor>::New(*(iter.object()));
// Apply any configuration options
// ...
backends_.set(areaName, backend);
}
}
}
......@@ -215,7 +219,6 @@ bool Foam::catalyst::faMeshInput::convert
{
auto dataset = backends_[areaName]->output(selectFields_);
// Existing or new
vtkSmartPointer<vtkMultiBlockDataSet> block =
outputs.lookup
......
......@@ -38,6 +38,9 @@ catalyst
// Emit internal mesh/fields
internal true;
// Restrict boundary conversion to specific patches
patches (walls "*.top");
// Selected fields (words or regex)
fields (T U p);
}
......
......@@ -139,7 +139,6 @@ bool Foam::catalyst::cloudInput::convert
auto dataset =
vtk::cloudAdaptor(fvm).getCloud(cloudName, selectFields_);
// Existing or new
vtkSmartPointer<vtkMultiBlockDataSet> block =
outputs.lookup
......
......@@ -60,13 +60,22 @@ void Foam::catalyst::fvMeshInput::update()
forAllConstIters(meshes_, iter)
{
if (!backends_.found(iter.key()))
const word& regionName = iter.key();
if (!backends_.found(regionName))
{
backends_.set
(
iter.key(),
new Foam::vtk::fvMeshAdaptor(*(iter.object()), decomposeOpt_)
);
auto backend =
autoPtr<Foam::vtk::fvMeshAdaptor>::New
(
*(iter.object()),
channelOpt_,
selectPatches_
);
// Special polyhedral treatment?
backend->setDecompose(decomposeOpt_);
backends_.set(regionName, backend);
}
}
}
......@@ -86,6 +95,7 @@ Foam::catalyst::fvMeshInput::fvMeshInput
channelOpt_(channelType::DEFAULT),
decomposeOpt_(false),
selectRegions_(),
selectPatches_(),
selectFields_(),
meshes_(),
backends_()
......@@ -102,8 +112,9 @@ bool Foam::catalyst::fvMeshInput::read(const dictionary& dict)
meshes_.clear();
backends_.clear();
selectFields_.clear();
selectRegions_.clear();
selectPatches_.clear();
selectFields_.clear();
decomposeOpt_ = dict.lookupOrDefault("decompose", false);
unsigned selected(channelType::NONE);
......@@ -132,6 +143,7 @@ bool Foam::catalyst::fvMeshInput::read(const dictionary& dict)
// All possible meshes
meshes_ = time_.lookupClass<fvMesh>();
dict.readIfPresent("patches", selectPatches_);
dict.readIfPresent("regions", selectRegions_);
if (selectRegions_.empty())
......@@ -226,12 +238,8 @@ bool Foam::catalyst::fvMeshInput::convert
for (const word& regionName : regionNames)
{
// Define/redefine output channels (caching)
backends_[regionName]->channels(channelOpt_);
auto dataset = backends_[regionName]->output(selectFields_);
// Existing or new
vtkSmartPointer<vtkMultiBlockDataSet> block =
outputs.lookup
......
......@@ -50,6 +50,7 @@ Usage
type | input type: \c default | no | default
region | name for a single region | no | region0
regions | wordRe list of regions | no |
patches | explicit wordRe list of patches | no |
fields | wordRe list of fields | yes |
boundary | convert boundary fields | no | true
internal | convert internal fields | no | true
......@@ -83,6 +84,10 @@ Usage
Note
The channel name is that of the defining dictionary.
If the \c patches entry is missing or an empty list,
all non-processor patches will be used for the boundary.
When it is non-empty, only the explicitly specified (non-processor)
patch names will be used.
See also
Foam::vtk::fvMeshAdaptor
......@@ -135,6 +140,9 @@ protected:
//- Requested names of regions to process
wordRes selectRegions_;
//- Requested names of patches to process
wordRes selectPatches_;
//- Names of fields to process
wordRes selectFields_;
......
......@@ -59,26 +59,69 @@ Foam::vtk::fvMeshAdaptor::channelNames
};
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::fvMeshAdaptor::definePatchIds()
{
// Generate or update the list of patchIds
patchIds_.clear();
if (!usingBoundary())
{
return;
}
// General patch information
// Restrict to non-processor patches.
// This value is invariant across all processors.
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const label nNonProcessor = patches.nNonProcessor();
if (patchPatterns_.empty())
{
patchIds_ = identity(nNonProcessor);
}
else
{
labelHashSet ids(patches.patchSet(patchPatterns_, false, false));
// Restricted to non-processor patches
ids.filterKeys
(
[nNonProcessor](const label i){ return i < nNonProcessor; }
);
// MUST be sorted. Other internal logic relies upon this!
patchIds_ = ids.sortedToc();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::fvMeshAdaptor::fvMeshAdaptor
(
const fvMesh& mesh,
const bool decompose
const channelType channelsOpt,
const wordRes& patchSelection
)
:
mesh_(mesh),
channels_(ALL),
patchPatterns_(patchSelection),
patchIds_(),
channels_(channelsOpt),
interpFields_(true),
extrapPatches_(false),
decomposePoly_(decompose),
decomposePoly_(false),
meshState_(polyMesh::TOPO_CHANGE)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::fvMeshAdaptor::channels(const wordList& chanNames)
void Foam::vtk::fvMeshAdaptor::setChannels(const wordList& chanNames)
{
unsigned chanIds = 0;
for (const word& chan : chanNames)
......@@ -89,11 +132,11 @@ void Foam::vtk::fvMeshAdaptor::channels(const wordList& chanNames)
}
}
channels(chanIds);
setChannels(chanIds);
}
void Foam::vtk::fvMeshAdaptor::channels(enum channelType chanIds)
void Foam::vtk::fvMeshAdaptor::setChannels(enum channelType chanIds)
{
channels_ = chanIds;
......@@ -105,11 +148,12 @@ void Foam::vtk::fvMeshAdaptor::channels(enum channelType chanIds)
if (!usingBoundary())
{
cachedVtp_.clear();
patchIds_.clear();
}
}
void Foam::vtk::fvMeshAdaptor::channels(unsigned chanIds)
void Foam::vtk::fvMeshAdaptor::setChannels(unsigned chanIds)
{
channels_ = (chanIds & 0x3);
......@@ -121,6 +165,17 @@ void Foam::vtk::fvMeshAdaptor::channels(unsigned chanIds)
if (!usingBoundary())
{
cachedVtp_.clear();
patchIds_.clear();
}
}
void Foam::vtk::fvMeshAdaptor::setDecompose(const bool val)
{
if (usingInternal() && val != decomposePoly_)
{
cachedVtu_.clear();
decomposePoly_ = val;
}
}
......@@ -143,17 +198,9 @@ bool Foam::vtk::fvMeshAdaptor::usingBoundary() const
}
Foam::label Foam::vtk::fvMeshAdaptor::nPatches() const
const Foam::labelList& Foam::vtk::fvMeshAdaptor::patchIds() const
{
// Restrict to non-processor patches.
// This value is invariant across all processors.
if (usingBoundary())
{
return mesh_.boundaryMesh().nNonProcessor();
}
return 0;
return patchIds_;
}
......@@ -161,6 +208,14 @@ void Foam::vtk::fvMeshAdaptor::updateContent(const wordRes& selectFields)
{
const bool oldDecomp = decomposePoly_;
// General patch information
// Restrict to non-processor patches.
// This value is invariant across all processors.
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const label nNonProcessor = patches.nNonProcessor();
// Update cached, saved, unneed values.
HashSet<string> nowActive;
......@@ -171,18 +226,15 @@ void Foam::vtk::fvMeshAdaptor::updateContent(const wordRes& selectFields)
nowActive.insert(internalName());
}
// BOUNDARY
// Restrict to non-processor patches.
// This value is invariant across all processors.
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const label npatches = this->nPatches();
for (label patchId=0; patchId < npatches; ++patchId)
// BOUNDARY
if (usingBoundary())
{
const polyPatch& pp = patches[patchId];
nowActive.insert(pp.name());
for (label patchId=0; patchId < nNonProcessor; ++patchId)
{
const polyPatch& pp = patches[patchId];
nowActive.insert(pp.name());
}
}
// Dispose of unneeded components
......@@ -206,6 +258,8 @@ void Foam::vtk::fvMeshAdaptor::updateContent(const wordRes& selectFields)
iter.object().clearGeom();
iter.object().clear();
}
definePatchIds();
}
else if (oldDecomp != decomposePoly_)
{
......@@ -281,8 +335,7 @@ Foam::vtk::fvMeshAdaptor::output(const wordRes& select)
}
// BOUNDARY
const label npatches = this->nPatches();
if (npatches)
if (!patchIds_.empty())
{
unsigned int subBlockNo = 0;
......@@ -290,7 +343,7 @@ Foam::vtk::fvMeshAdaptor::output(const wordRes& select)
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
for (label patchId=0; patchId < npatches; ++patchId)
for (const label patchId : patchIds_)
{
const polyPatch& pp = patches[patchId];
const word& longName = pp.name();
......
......@@ -170,6 +170,12 @@ private:
//- OpenFOAM mesh
const fvMesh& mesh_;
//- In non-empty, restrict to these selected patches only
wordRes patchPatterns_;
//- Cached values for selected patches. *Always* in sorted order.
labelList patchIds_;
//- Selected output channels
unsigned channels_;
......@@ -195,6 +201,9 @@ private:
// Mesh Conversion
//- Define patch ids
void definePatchIds();
//- Convert internal
void convertGeometryInternal();
......@@ -293,7 +302,12 @@ public:
// Constructors
//- Construct from components
fvMeshAdaptor(const fvMesh& mesh, const bool decompose=false);
fvMeshAdaptor
(
const fvMesh& mesh,
const channelType channelsOpt = channelType::DEFAULT,
const wordRes& patchSelection = wordRes()
);
//- Destructor
......@@ -303,13 +317,17 @@ public:
// Member Functions
//- Define the output channels by name
void channels(const wordList& chanNames);
void setChannels(const wordList& chanNames);
//- Define the output channels by enum
void channels(enum channelType chanIds);
void setChannels(enum channelType chanIds);
//- Define the output channels by value
void channels(unsigned chanIds);
void setChannels(unsigned chanIds);
//- Define polyhedral decomposition treatment
void setDecompose(const bool on);
//- Return the selected output channel ids
label channels() const;
......@@ -320,9 +338,9 @@ public:
//- True if BOUNDARY channel is being used
bool usingBoundary() const;
//- Number of non-processor patches, when the BOUNDARY channel is being
//- used - otherwise 0.
label nPatches() const;
//- Selected (non-processor) patch ids, when the BOUNDARY channel
//- is being used. Empty otherwise.
const labelList& patchIds() const;
//- Return the names of known (supported) fields
wordHashSet knownFields(const wordRes& selectFields) const;
......
......@@ -69,9 +69,7 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
convertVolFieldInternal(fld, ptfPtr);
// BOUNDARY
const label npatches = this->nPatches();
for (label patchId=0; patchId < npatches; ++patchId)
for (const label patchId : patchIds_)
{
const polyPatch& pp = patches[patchId];
const word& longName = pp.name();
......@@ -125,7 +123,11 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
transcribeFloatData(cdata, tpptf());
if (interpFields_ && patchId < patchInterpList.size())
if
(
patchId < patchInterpList.size()
&& patchInterpList.set(patchId)
)
{
pdata = vtk::Tools::convertFieldToVTK
(
......@@ -138,7 +140,11 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
{
transcribeFloatData(cdata, ptf);
if (interpFields_ && patchId < patchInterpList.size())
if
(
patchId < patchInterpList.size()
&& patchInterpList.set(patchId)
)
{
pdata = vtk::Tools::convertFieldToVTK
(
......
......@@ -105,21 +105,23 @@ void Foam::vtk::fvMeshAdaptor::convertVolFields
PtrList<patchInterpolator> interpLst;
if (interpFields_)
if (interpFields_ && patchIds_.size())
{
// NOTE: this will be broken with processor patches, but
// for the catalyst adaptor we explicitly restrict ourselves
// to non-processor patches
interpLst.setSize(this->nPatches());
// NOTE: this would be broken with processor patches,
// but we don't allow them for the catalyst adaptor anyhow
forAll(interpLst, i)
// patchIds_ are sorted, so the last one is also the max
interpLst.setSize(patchIds_.last() + 1);
for (const label patchId : patchIds_)
{
interpLst.set
(
i,
patchId,
new PrimitivePatchInterpolation<primitivePatch>
(
mesh_.boundaryMesh()[i]
mesh_.boundaryMesh()[patchId]
)
);
}
......
......@@ -90,9 +90,8 @@ void Foam::vtk::fvMeshAdaptor::convertGeometryBoundary()
// BOUNDARY
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const label npatches = this->nPatches();
for (label patchId=0; patchId < npatches; ++patchId)
for (const label patchId : patchIds_)
{
const polyPatch& pp = patches[patchId];
const word& longName = pp.name();
......@@ -233,9 +232,8 @@ void Foam::vtk::fvMeshAdaptor::applyGhostingBoundary(const labelUList& types)
}
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const label npatches = this->nPatches();
for (label patchId=0; patchId < npatches; ++patchId)
for (const label patchId : patchIds_)
{
const polyPatch& pp = patches[patchId];
const word& longName = pp.name();
......
......@@ -7,6 +7,7 @@ catalyst
scripts
(
"<system>/scripts/slice1.py"
// "<system>/scripts/showT.py"
// "<etc>/caseDicts/insitu/catalyst/writeAll.py"
);
......@@ -21,7 +22,19 @@ catalyst
boundary false;
// Selected fields (words or regex)
fields (T U p);
fields (T U p);
}
// Solid walls only
walls
{
internal false;
regions ( heater "(?i).*solid" );
patches ( "(?i).*solid_to.*" "heater.*(Air|Water)" );
fields (T);
}
}
}
......
......@@ -9,17 +9,21 @@ def CreateCoProcessor():
def _CreatePipeline(coprocessor, datadescription):
class Pipeline:
region = coprocessor.CreateProducer(datadescription, 'region')
walls = coprocessor.CreateProducer(datadescription, 'walls')
slice1 = Slice(Input=region, guiName="Slice1", SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane")
slice1.SliceType.Offset = 0.0
slice1.SliceType.Origin = [0, 0, 0]
slice1 = Slice(Input=region)
slice1.SliceType = 'Plane'
slice1.SliceOffsetValues = [0.0]
slice1.SliceType.Normal = [0, 0, 1]
sliceWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=slice1)
coprocessor.RegisterWriter(sliceWriter, filename='slice_%t.vtm', freq=10, paddingamount=fileNamePadding)
meshWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=region)
coprocessor.RegisterWriter(meshWriter, filename='region_%t.vtm', freq=100, paddingamount=fileNamePadding)
regionWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=region)
coprocessor.RegisterWriter(regionWriter, filename='region_%t.vtm', freq=100, paddingamount=fileNamePadding)
wallsWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=walls)
coprocessor.RegisterWriter(wallsWriter, filename='walls_%t.vtm', freq=25, paddingamount=fileNamePadding)
return Pipeline()
......@@ -28,7 +32,7 @@ def CreateCoProcessor():
self.Pipeline = _CreatePipeline(self, datadescription)
coprocessor = CoProcessor()
freqs = {'region': [10, 100]}
freqs = {'region': [10, 100], 'walls': [25]}
coprocessor.SetUpdateFrequencies(freqs)
return coprocessor
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment