2014-11-09 00:10:28 +00:00
|
|
|
/*---------------------------------------------------------------------------*\
|
|
|
|
========= |
|
2015-05-17 13:32:07 +00:00
|
|
|
\\ / F ield | foam-extend: Open Source CFD
|
|
|
|
\\ / O peration | Version: 3.2
|
|
|
|
\\ / A nd | Web: http://www.foam-extend.org
|
|
|
|
\\/ M anipulation | For copyright notice see file Copyright
|
2014-11-09 00:10:28 +00:00
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
License
|
2015-05-17 13:32:07 +00:00
|
|
|
This file is part of foam-extend.
|
2014-11-09 00:10:28 +00:00
|
|
|
|
2015-05-17 13:32:07 +00:00
|
|
|
foam-extend is free software: you can redistribute it and/or modify it
|
2014-11-09 00:10:28 +00:00
|
|
|
under the terms of the GNU General Public License as published by the
|
2015-05-17 13:32:07 +00:00
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
2014-11-09 00:10:28 +00:00
|
|
|
option) any later version.
|
|
|
|
|
2015-05-17 13:32:07 +00:00
|
|
|
foam-extend 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.
|
2014-11-09 00:10:28 +00:00
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2015-05-17 13:32:07 +00:00
|
|
|
along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
|
2014-11-09 00:10:28 +00:00
|
|
|
|
|
|
|
Description
|
|
|
|
cfMesh utility to merge the supplied list of patches onto a single
|
|
|
|
patch.
|
|
|
|
|
|
|
|
Author
|
|
|
|
Ivor Clifford <ivor.clifford@psi.ch>
|
|
|
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
#include "argList.H"
|
|
|
|
#include "autoPtr.H"
|
|
|
|
#include "Time.H"
|
|
|
|
#include "triSurf.H"
|
|
|
|
#include "triSurfModifier.H"
|
|
|
|
#include "demandDrivenData.H"
|
|
|
|
#include "Pair.H"
|
|
|
|
|
|
|
|
using namespace Foam;
|
|
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
|
|
|
|
// Find the supplied list of patch names and return a list of patch Ids
|
|
|
|
void getPatchIds
|
|
|
|
(
|
|
|
|
const triSurf& origSurf,
|
|
|
|
const wordList& patchNames,
|
|
|
|
DynamicList<label>& patchIds
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const geometricSurfacePatchList& origPatches = origSurf.patches();
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Create patch name map
|
|
|
|
HashSet<word> patchNameHash(patchNames);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Find selected patches
|
|
|
|
label nFound = 0;
|
|
|
|
forAll(origPatches, patchI)
|
|
|
|
{
|
|
|
|
if (patchNameHash.found(origPatches[patchI].name()))
|
|
|
|
{
|
|
|
|
patchIds.append(patchI);
|
|
|
|
nFound++;
|
|
|
|
}
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if (nFound != patchNames.size())
|
|
|
|
{
|
|
|
|
WarningIn("getPatchIds")
|
|
|
|
<< "Not all supplied patch names were found on the surface mesh" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Copy all face subsets from one triSurf to another
|
|
|
|
void copyFaceSubsets
|
|
|
|
(
|
|
|
|
const triSurf& origSurf,
|
|
|
|
triSurf& newSurf
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DynList<label> subsetIds;
|
|
|
|
origSurf.facetSubsetIndices(subsetIds);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(subsetIds, subsetI)
|
|
|
|
{
|
|
|
|
label newSubsetId = newSurf.addFacetSubset
|
|
|
|
(
|
|
|
|
origSurf.facetSubsetName(subsetI)
|
|
|
|
);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
|
|
|
labelList origFaces;
|
2014-11-09 00:10:28 +00:00
|
|
|
origSurf.facetsInSubset(subsetI, origFaces);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(origFaces, faceI)
|
|
|
|
{
|
|
|
|
newSurf.addFacetToSubset
|
|
|
|
(
|
|
|
|
newSubsetId,
|
|
|
|
origFaces[faceI]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Copy all edge subsets from one triSurf to another
|
|
|
|
void copyEdgeSubsets
|
|
|
|
(
|
|
|
|
const triSurf& origSurf,
|
|
|
|
triSurf& newSurf
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DynList<label> subsetIds;
|
|
|
|
origSurf.edgeSubsetIndices(subsetIds);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(subsetIds, subsetI)
|
|
|
|
{
|
|
|
|
label newSubsetId = newSurf.addEdgeSubset
|
|
|
|
(
|
|
|
|
origSurf.edgeSubsetName(subsetI)
|
|
|
|
);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
|
|
|
labelList origEdges;
|
2014-11-09 00:10:28 +00:00
|
|
|
origSurf.edgesInSubset(subsetI, origEdges);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(origEdges, faceI)
|
|
|
|
{
|
|
|
|
newSurf.addEdgeToSubset
|
|
|
|
(
|
|
|
|
newSubsetId,
|
|
|
|
origEdges[faceI]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Copy all point subsets from one triSurf to another
|
|
|
|
void copyPointSubsets
|
|
|
|
(
|
|
|
|
const triSurf& origSurf,
|
|
|
|
triSurf& newSurf
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DynList<label> subsetIds;
|
|
|
|
origSurf.pointSubsetIndices(subsetIds);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(subsetIds, subsetI)
|
|
|
|
{
|
|
|
|
label newSubsetId = newSurf.addPointSubset
|
|
|
|
(
|
|
|
|
origSurf.pointSubsetName(subsetI)
|
|
|
|
);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
|
|
|
labelList origPoints;
|
2014-11-09 00:10:28 +00:00
|
|
|
origSurf.pointsInSubset(subsetI, origPoints);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(origPoints, faceI)
|
|
|
|
{
|
|
|
|
newSurf.addPointToSubset
|
|
|
|
(
|
|
|
|
newSubsetId,
|
|
|
|
origPoints[faceI]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Merge the supplied list of patchIds onto a new patch
|
|
|
|
autoPtr<triSurf> mergeSurfacePatches
|
|
|
|
(
|
|
|
|
const triSurf& origSurf, // Surface
|
|
|
|
const UList<label>& patchIds, // Ids of patches to merge
|
|
|
|
const word& newPatchName, // Name of new (merged) patch
|
|
|
|
bool keepPatches // Keep the original patches - they will be emptied
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const geometricSurfacePatchList& origPatches = origSurf.patches();
|
|
|
|
const LongList<labelledTri>& origFacets = origSurf.facets();
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
label newPatchId = origPatches.size();
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Determine new patch type
|
|
|
|
word newPatchType = origPatches[patchIds[0]].geometricType();
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Create patch addressing
|
|
|
|
List<DynamicList<label> > patchAddr(origPatches.size()+1);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
forAll(origFacets, faceI)
|
|
|
|
{
|
|
|
|
patchAddr[origFacets[faceI].region()].append(faceI);
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Move selected patches to new patch
|
|
|
|
forAll(patchIds, patchI)
|
|
|
|
{
|
|
|
|
patchAddr[newPatchId].append(patchAddr[patchIds[patchI]]);
|
|
|
|
patchAddr[patchIds[patchI]].clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new facets list
|
|
|
|
LongList<labelledTri> newFacets(origFacets.size());
|
|
|
|
labelList newFaceAddr(origFacets.size(), -1);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
label patchCount = 0;
|
|
|
|
label faceI = 0;
|
|
|
|
forAll(patchAddr, patchI)
|
|
|
|
{
|
|
|
|
const unallocLabelList& addr = patchAddr[patchI];
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if(addr.size())
|
|
|
|
{
|
|
|
|
forAll(addr, i)
|
|
|
|
{
|
|
|
|
newFacets[faceI] = origFacets[addr[i]];
|
|
|
|
newFacets[faceI].region() = patchCount;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
newFaceAddr[addr[i]] = faceI;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
faceI++;
|
|
|
|
}
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if(addr.size() || keepPatches)
|
|
|
|
{
|
|
|
|
patchCount++;
|
|
|
|
}
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Create new patch list
|
|
|
|
geometricSurfacePatchList newPatches(patchCount);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
patchCount = 0;
|
|
|
|
forAll(origPatches, patchI)
|
|
|
|
{
|
|
|
|
// Only add patches if they contain faces
|
|
|
|
if(patchAddr[patchI].size())
|
|
|
|
{
|
|
|
|
newPatches[patchCount] = origPatches[patchI];
|
|
|
|
newPatches[patchCount].index() = patchCount;
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if(patchAddr[patchI].size() || keepPatches)
|
|
|
|
{
|
|
|
|
patchCount++;
|
|
|
|
}
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Add new patch if it contains faces
|
|
|
|
if(patchAddr[patchAddr.size()-1].size())
|
|
|
|
{
|
|
|
|
newPatches[patchCount] = geometricSurfacePatch
|
|
|
|
(
|
|
|
|
newPatchType,
|
|
|
|
newPatchName,
|
|
|
|
patchCount
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if(patchAddr[patchAddr.size()-1].size() || keepPatches)
|
|
|
|
{
|
|
|
|
patchCount++;
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Create new surface
|
|
|
|
autoPtr<triSurf> newSurf
|
|
|
|
(
|
|
|
|
new triSurf
|
|
|
|
(
|
|
|
|
newFacets,
|
|
|
|
newPatches,
|
|
|
|
origSurf.featureEdges(),
|
|
|
|
origSurf.points()
|
|
|
|
)
|
|
|
|
);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Transfer face subsets
|
|
|
|
copyFaceSubsets(origSurf, newSurf());
|
|
|
|
newSurf->updateFacetsSubsets(newFaceAddr);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Transfer feature edge subsets
|
|
|
|
copyEdgeSubsets(origSurf, newSurf());
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Transfer point subsets
|
|
|
|
copyPointSubsets(origSurf, newSurf());
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Done
|
|
|
|
return newSurf;
|
|
|
|
}
|
|
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
argList::noParallel();
|
|
|
|
argList::validArgs.clear();
|
|
|
|
|
|
|
|
argList::validArgs.append("input surface file");
|
|
|
|
argList::validArgs.append("new patch");
|
|
|
|
argList::validOptions.insert("patchNames", "list of names");
|
|
|
|
argList::validOptions.insert("patchIds", "list of patchIds");
|
|
|
|
argList::validOptions.insert("patchIdRange", "( start end )");
|
|
|
|
argList::validOptions.insert("output", "file name (default overwrite)");
|
|
|
|
argList::validOptions.insert("keep", "");
|
|
|
|
argList args(argc, argv);
|
|
|
|
|
|
|
|
// Process commandline arguments
|
|
|
|
fileName inFileName(args.args()[1]);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
word newPatchName(args.args()[2]);
|
|
|
|
|
|
|
|
fileName outFileName(inFileName);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if( args.options().found("output") )
|
|
|
|
{
|
|
|
|
outFileName = args.options()["output"];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool keepPatches = false;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if( args.options().found("keep") )
|
|
|
|
{
|
|
|
|
keepPatches = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read original surface
|
|
|
|
triSurf origSurf(inFileName);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Get patch ids
|
|
|
|
DynamicList<label> patchIds;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
if (args.options().found("patchNames"))
|
|
|
|
{
|
|
|
|
if (args.options().found("patchIds"))
|
|
|
|
{
|
|
|
|
FatalError() << "Cannot specify both patch names and ids"
|
|
|
|
<< Foam::abort(FatalError);
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
IStringStream is(args.options()["patchNames"]);
|
|
|
|
wordList patchNames(is);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
getPatchIds
|
|
|
|
(
|
|
|
|
origSurf,
|
|
|
|
patchNames,
|
|
|
|
patchIds
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (args.options().found("patchIds"))
|
|
|
|
{
|
|
|
|
IStringStream is(args.options()["patchIds"]);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
patchIds = labelList(is);
|
|
|
|
}
|
|
|
|
if (args.options().found("patchIds"))
|
|
|
|
{
|
|
|
|
IStringStream is(args.options()["patchIds"]);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
patchIds.append(labelList(is));
|
|
|
|
}
|
|
|
|
if (args.options().found("patchIdRange"))
|
|
|
|
{
|
|
|
|
IStringStream is(args.options()["patchIdRange"]);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
Pair<label> idRange(is);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
for(label id = idRange.first(); id <= idRange.second(); id++)
|
|
|
|
{
|
|
|
|
patchIds.append(id);
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
}
|
2014-11-09 00:10:28 +00:00
|
|
|
if (!patchIds.size())
|
|
|
|
{
|
|
|
|
FatalError() << "No patches specified"
|
|
|
|
<< Foam::abort(FatalError);
|
|
|
|
}
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Merge patches
|
|
|
|
autoPtr<triSurf> newSurf = mergeSurfacePatches
|
|
|
|
(
|
|
|
|
origSurf,
|
|
|
|
patchIds,
|
|
|
|
newPatchName,
|
|
|
|
keepPatches
|
|
|
|
);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
// Write new surface mesh
|
|
|
|
newSurf->writeSurface(outFileName);
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
Info << "Original surface patches: " << origSurf.patches().size() << endl;
|
|
|
|
Info << "Final surface patches: " << newSurf->patches().size() << endl;
|
|
|
|
Info << "Surface written to " << outFileName << endl;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
Info << "End\n" << endl;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2014-11-09 00:10:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ************************************************************************* //
|