ENH: support patch group selection

- vtkWrite, foamToVTK, surfaceMeshExtract
This commit is contained in:
Mark Olesen
2025-06-12 10:38:41 +02:00
parent e8dce32b0a
commit 93f980834b
6 changed files with 104 additions and 126 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2023 OpenCFD Ltd.
Copyright (C) 2021-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -44,10 +44,10 @@ forAll(meshes, regioni)
IOobjectOption::NO_REGISTER
);
if (fieldSelector && !fieldSelector().empty())
if (fieldSelector)
{
objects.filterObjects(fieldSelector());
faObjects.filterObjects(fieldSelector());
objects.filterObjects(fieldSelector);
faObjects.filterObjects(fieldSelector);
}
// Remove "*_0" restart fields

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2022 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -406,34 +406,27 @@ int main(int argc, char *argv[])
// Field selection/deselection
wordRes includedFields, excludedFields;
autoPtr<wordRes::filter> fieldSelector(nullptr);
const bool doConvertFields = !args.found("no-fields");
if (doConvertFields)
{
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("fields", includedFields))
{
resetFilter = true;
Info<< "Including fields "
<< flatOutput(includedFields) << nl << endl;
}
if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
{
resetFilter = true;
Info<< "Excluding fields "
<< flatOutput(excludedFields) << nl << endl;
}
if (resetFilter)
{
fieldSelector =
autoPtr<wordRes::filter>::New(includedFields, excludedFields);
}
}
else if (doConvertFields)
else
{
Info<< "Field conversion disabled with the '-no-fields' option" << nl;
}
const wordRes::filter fieldSelector(includedFields, excludedFields);
// ------------------------------------------------------------------------
#include "createTime.H"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -136,7 +136,7 @@ Description
labelList patchIds;
if (doBoundary)
{
patchIds = getSelectedPatches(patches, patchSelector);
patchIds = patchSelector.indices(patches);
}
if (oneBoundary && patchIds.size())

View File

@ -166,56 +166,54 @@ Note
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
labelList getSelectedPatches
(
const polyBoundaryMesh& patches,
const autoPtr<wordRes::filter>& patchSelector
)
namespace Foam
{
labelList indices;
if (patchSelector && !patchSelector().empty())
// Simple wrapper for polyBoundaryMesh::indices() with some additional logic
struct polyBoundaryPatchSelector
{
wordRes allow_;
wordRes deny_;
void clear()
{
// Name-based selection
indices =
(
stringListOps::findMatching
(
patches,
patchSelector(),
nameOp<polyPatch>()
)
);
}
else
{
indices = identity(patches.size());
allow_.clear();
deny_.clear();
}
// Remove undesirable patches
//- Forward to polyBoundaryMesh::indices() with additional handling.
// Prune emptyPolyPatch (always) and processorPolyPatch (in parallel)
labelList indices(const polyBoundaryMesh& pbm) const
{
labelList ids = pbm.indices(allow_, deny_);
const bool excludeProcPatches = UPstream::parRun();
// Prune undesirable patches
label count = 0;
for (const label patchi : indices)
for (const label patchi : ids)
{
const polyPatch& pp = patches[patchi];
const auto& pp = pbm[patchi];
if (isType<emptyPolyPatch>(pp))
{
continue;
}
else if (UPstream::parRun() && bool(isA<processorPolyPatch>(pp)))
else if (excludeProcPatches && bool(isA<processorPolyPatch>(pp)))
{
break; // No processor patches for parallel output
}
indices[count] = patchi;
ids[count] = patchi;
++count;
}
indices.resize(count);
ids.resize(count);
return ids;
}
};
return indices;
}
} // End namespace Foam
//
@ -552,45 +550,38 @@ int main(int argc, char *argv[])
}
// Patch selection/deselection
wordRes includedPatches, excludedPatches;
autoPtr<wordRes::filter> patchSelector(nullptr);
polyBoundaryPatchSelector patchSelector;
if (doBoundary)
{
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("patches", includedPatches))
if
(
auto& slot = patchSelector.allow_;
args.readListIfPresent<wordRe>("patches", slot)
)
{
resetFilter = true;
Info<< "Including patches "
<< flatOutput(includedPatches) << nl << endl;
Info<< "Including patches " << flatOutput(slot) << nl << endl;
}
if (args.readListIfPresent<wordRe>("exclude-patches", excludedPatches))
if
(
auto& slot = patchSelector.deny_;
args.readListIfPresent<wordRe>("exclude-patches", slot)
)
{
resetFilter = true;
Info<< "Excluding patches "
<< flatOutput(excludedPatches) << nl << endl;
}
if (resetFilter)
{
patchSelector =
autoPtr<wordRes::filter>::New(includedPatches, excludedPatches);
Info<< "Excluding patches " << flatOutput(slot) << nl << endl;
}
}
// Field selection/deselection
wordRes includedFields, excludedFields;
autoPtr<wordRes::filter> fieldSelector(nullptr);
bool doConvertFields = !args.found("no-fields");
if (doConvertFields)
{
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("fields", includedFields))
{
Info<< "Including fields "
<< flatOutput(includedFields) << nl << endl;
resetFilter = !includedFields.empty();
if (includedFields.empty())
{
// Compat: Can be specified as empty (ie, no fields)
@ -603,22 +594,22 @@ int main(int argc, char *argv[])
}
if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
{
resetFilter = true;
Info<< "Excluding fields "
<< flatOutput(excludedFields) << nl << endl;
}
if (resetFilter && doConvertFields)
if (!doConvertFields)
{
fieldSelector =
autoPtr<wordRes::filter>::New(includedFields, excludedFields);
includedFields.clear();
excludedFields.clear();
}
}
else if (doConvertFields)
else
{
Info<< "Field conversion disabled with the '-no-fields' option" << nl;
}
const wordRes::filter fieldSelector(includedFields, excludedFields);
// Non-mandatory
const wordRes selectedFaceZones(args.getList<wordRe>("faceZones", false));
@ -799,10 +790,10 @@ int main(int argc, char *argv[])
IOobjectOption::NO_REGISTER
);
if (fieldSelector && !fieldSelector().empty())
if (fieldSelector)
{
objects.filterObjects(fieldSelector());
faObjects.filterObjects(fieldSelector());
objects.filterObjects(fieldSelector);
faObjects.filterObjects(fieldSelector);
}
// Remove "*_0" restart fields

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2024 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -155,50 +155,39 @@ void writeOBJ
}
}
// Simple wrapper for polyBoundaryMesh::indices() with some additional logic
// - prune emptyPolyPatch (always) and (maybe) processorPolyPatch
labelList getSelectedPatches
(
const polyBoundaryMesh& patches,
const polyBoundaryMesh& pbm,
const wordRes& allow,
const wordRes& deny
const wordRes& deny,
const bool excludeProcPatches
)
{
// Name-based selection
labelList indices
(
stringListOps::findMatching
(
patches,
allow,
deny,
nameOp<polyPatch>()
)
);
labelList ids = pbm.indices(allow, deny);
// Remove undesirable patches
label count = 0;
for (const label patchi : indices)
for (const label patchi : ids)
{
const polyPatch& pp = patches[patchi];
const polyPatch& pp = pbm[patchi];
if (isType<emptyPolyPatch>(pp))
{
continue;
}
else if (Pstream::parRun() && bool(isA<processorPolyPatch>(pp)))
else if (excludeProcPatches && bool(isA<processorPolyPatch>(pp)))
{
break; // No processor patches for parallel output
}
indices[count] = patchi;
ids[count] = patchi;
++count;
}
indices.resize(count);
return indices;
ids.resize(count);
return ids;
}
@ -668,11 +657,14 @@ int main(int argc, char *argv[])
const labelList patchIds =
(
(includePatches.size() || excludePatches.size())
? getSelectedPatches(bMesh, includePatches, excludePatches)
: includeProcPatches
? identity(bMesh.size())
: identity(bMesh.nNonProcessor())
getSelectedPatches
(
bMesh,
includePatches,
excludePatches,
// No processor patches? (parallel output or excluded)
(UPstream::parRun() || !includeProcPatches)
)
);
labelList faceZoneIds;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,7 @@ License
#include "vtkWrite.H"
#include "cellBitSet.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -54,15 +55,17 @@ bool Foam::functionObjects::vtkWrite::updateSubset
Foam::labelList Foam::functionObjects::vtkWrite::getSelectedPatches
(
const polyBoundaryMesh& patches
const polyBoundaryMesh& pbm
) const
{
DynamicList<label> patchIDs(patches.size());
labelList ids = pbm.indices(selectPatches_, blockPatches_);
wordRes::filter patchFilter(selectPatches_, blockPatches_);
for (const polyPatch& pp : patches)
// Prune undesirable patches
label count = 0;
for (const label patchi : ids)
{
const auto& pp = pbm[patchi];
if (isType<emptyPolyPatch>(pp))
{
continue;
@ -72,13 +75,12 @@ Foam::labelList Foam::functionObjects::vtkWrite::getSelectedPatches
break; // No processor patches
}
if (patchFilter(pp.name()))
{
patchIDs.append(pp.index());
}
ids[count] = patchi;
++count;
}
return labelList(std::move(patchIDs));
ids.resize(count);
return ids;
}