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

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

View File

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

View File

@ -166,56 +166,54 @@ Note
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
labelList getSelectedPatches namespace Foam
(
const polyBoundaryMesh& patches,
const autoPtr<wordRes::filter>& patchSelector
)
{ {
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 allow_.clear();
indices = deny_.clear();
(
stringListOps::findMatching
(
patches,
patchSelector(),
nameOp<polyPatch>()
)
);
}
else
{
indices = identity(patches.size());
} }
// 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; 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)) if (isType<emptyPolyPatch>(pp))
{ {
continue; continue;
} }
else if (UPstream::parRun() && bool(isA<processorPolyPatch>(pp))) else if (excludeProcPatches && bool(isA<processorPolyPatch>(pp)))
{ {
break; // No processor patches for parallel output break; // No processor patches for parallel output
} }
indices[count] = patchi; ids[count] = patchi;
++count; ++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 // Patch selection/deselection
wordRes includedPatches, excludedPatches; polyBoundaryPatchSelector patchSelector;
autoPtr<wordRes::filter> patchSelector(nullptr);
if (doBoundary) if (doBoundary)
{ {
bool resetFilter = false; if
if (args.readListIfPresent<wordRe>("patches", includedPatches)) (
auto& slot = patchSelector.allow_;
args.readListIfPresent<wordRe>("patches", slot)
)
{ {
resetFilter = true; Info<< "Including patches " << flatOutput(slot) << nl << endl;
Info<< "Including patches "
<< flatOutput(includedPatches) << 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(slot) << nl << endl;
Info<< "Excluding patches "
<< flatOutput(excludedPatches) << nl << endl;
}
if (resetFilter)
{
patchSelector =
autoPtr<wordRes::filter>::New(includedPatches, excludedPatches);
} }
} }
// Field selection/deselection // Field selection/deselection
wordRes includedFields, excludedFields; wordRes includedFields, excludedFields;
autoPtr<wordRes::filter> fieldSelector(nullptr);
bool doConvertFields = !args.found("no-fields"); bool doConvertFields = !args.found("no-fields");
if (doConvertFields) if (doConvertFields)
{ {
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("fields", includedFields)) if (args.readListIfPresent<wordRe>("fields", includedFields))
{ {
Info<< "Including fields " Info<< "Including fields "
<< flatOutput(includedFields) << nl << endl; << flatOutput(includedFields) << nl << endl;
resetFilter = !includedFields.empty();
if (includedFields.empty()) if (includedFields.empty())
{ {
// Compat: Can be specified as empty (ie, no fields) // 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)) if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
{ {
resetFilter = true;
Info<< "Excluding fields " Info<< "Excluding fields "
<< flatOutput(excludedFields) << nl << endl; << flatOutput(excludedFields) << nl << endl;
} }
if (resetFilter && doConvertFields) if (!doConvertFields)
{ {
fieldSelector = includedFields.clear();
autoPtr<wordRes::filter>::New(includedFields, excludedFields); excludedFields.clear();
} }
} }
else if (doConvertFields) else
{ {
Info<< "Field conversion disabled with the '-no-fields' option" << nl; Info<< "Field conversion disabled with the '-no-fields' option" << nl;
} }
const wordRes::filter fieldSelector(includedFields, excludedFields);
// Non-mandatory // Non-mandatory
const wordRes selectedFaceZones(args.getList<wordRe>("faceZones", false)); const wordRes selectedFaceZones(args.getList<wordRe>("faceZones", false));
@ -799,10 +790,10 @@ int main(int argc, char *argv[])
IOobjectOption::NO_REGISTER IOobjectOption::NO_REGISTER
); );
if (fieldSelector && !fieldSelector().empty()) if (fieldSelector)
{ {
objects.filterObjects(fieldSelector()); objects.filterObjects(fieldSelector);
faObjects.filterObjects(fieldSelector()); faObjects.filterObjects(fieldSelector);
} }
// Remove "*_0" restart fields // Remove "*_0" restart fields

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

View File

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