Files
OpenFOAM-12/applications/utilities/surface/surfaceToPatch/surfaceToPatch.C
Henry Weller 69da8f3d7b stitchMesh: Replacement utility based on the new patchIntersection algorithm
The mergePatchPairs functionality in blockMesh also now uses patchIntersection.

The new mergePatchPairs and patchIntersection replaces the old, fragile and
practically unusable polyTopoChanger::slidingInterface functionality the removal
of which has allowed the deletion of a lot of other ancient and otherwise unused
clutter including polyTopoChanger, polyMeshModifier, polyTopoChange::setAction
and associated addObject/*, modifyObject/* and removeObject/*.  This
rationalisation paves the way for the completion of the update of zone handling
allowing mesh points, faces and cells to exist in multiple zones which is
currently not supported with mesh topology change.

Application
    stitchMesh

Description
    Utility to stitch or conform pairs of patches,
    converting the patch faces either into internal faces
    or conformal faces or another patch.

Usage
    \b stitchMesh (\<list of patch pairs\>)

    E.g. to stitch patches \c top1 to \c top2 and \c bottom1 to \c bottom2
        stitchMesh "((top1 top2) (bottom1 bottom2))"

    Options:
      - \par -overwrite \n
        Replace the old mesh with the new one, rather than writing the new one
        into a separate time directory

      - \par -region \<name\>
        Specify an alternative mesh region.

      - \par -fields
        Update vol and point fields

      - \par -tol
        Merge tolerance relative to local edge length (default 1e-4)

See also
    Foam::mergePatchPairs
2023-12-25 13:32:39 +00:00

335 lines
8.6 KiB
C++

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
surfaceToPatch
Description
Reads surface and applies surface regioning to a mesh. Uses repatchMesh
to do the hard work.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "repatchMesh.H"
#include "polyMesh.H"
#include "faceSet.H"
#include "polyTopoChange.H"
#include "globalMeshData.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Adds empty patch if not yet there. Returns patchID.
label addPatch(polyMesh& mesh, const word& patchName)
{
label patchi = mesh.boundaryMesh().findIndex(patchName);
if (patchi == -1)
{
const polyBoundaryMesh& patches = mesh.boundaryMesh();
List<polyPatch*> newPatches(patches.size() + 1);
patchi = 0;
// Copy all old patches
forAll(patches, i)
{
const polyPatch& pp = patches[i];
newPatches[patchi] =
pp.clone
(
patches,
patchi,
pp.size(),
pp.start()
).ptr();
patchi++;
}
// Add zero-sized patch
newPatches[patchi] =
new polyPatch
(
patchName,
0,
mesh.nFaces(),
patchi,
patches,
polyPatch::typeName
);
mesh.removeBoundary();
mesh.addPatches(newPatches);
Pout<< "Created patch " << patchName << " at " << patchi << endl;
}
else
{
Pout<< "Reusing patch " << patchName << " at " << patchi << endl;
}
return patchi;
}
// Repatch single face. Return true if patch changed.
bool repatchFace
(
const polyMesh& mesh,
const repatchMesh& rMesh,
const labelList& nearest,
const labelList& surfToMeshPatch,
const label facei,
polyTopoChange& meshMod
)
{
bool changed = false;
label bFacei = facei - mesh.nInternalFaces();
if (nearest[bFacei] != -1)
{
// Use boundary mesh one.
label rMeshPatchID = rMesh.whichPatch(nearest[bFacei]);
label patchID = surfToMeshPatch[rMeshPatchID];
if (patchID != mesh.boundaryMesh().whichPatch(facei))
{
label own = mesh.faceOwner()[facei];
label zoneID = mesh.faceZones().whichZone(facei);
bool zoneFlip = false;
if (zoneID >= 0)
{
const faceZone& fZone = mesh.faceZones()[zoneID];
zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
}
meshMod.modifyFace
(
mesh.faces()[facei],// modified face
facei, // label of face being modified
own, // owner
-1, // neighbour
false, // face flip
patchID, // patch for face
zoneID, // zone for face
zoneFlip // face flip in zone
);
changed = true;
}
}
else
{
changed = false;
}
return changed;
}
int main(int argc, char *argv[])
{
argList::addNote
(
"reads surface and applies surface regioning to a mesh"
);
argList::noParallel();
argList::validArgs.append("surface file");
argList::addOption
(
"faceSet",
"name",
"only repatch the faces in specified faceSet"
);
argList::addOption
(
"tol",
"scalar",
"search tolerance as fraction of mesh size (default 1e-3)"
);
#include "setRootCase.H"
#include "createTime.H"
#include "createPolyMesh.H"
const fileName surfName = args[1];
Info<< "Reading surface from " << surfName << " ..." << endl;
word setName;
const bool readSet = args.optionReadIfPresent("faceSet", setName);
if (readSet)
{
Info<< "Repatching only the faces in faceSet " << setName
<< " according to nearest surface triangle ..." << endl;
}
else
{
Info<< "Patching all boundary faces according to nearest surface"
<< " triangle ..." << endl;
}
const scalar searchTol = args.optionLookupOrDefault("tol", 1e-3);
// Get search box. Anything not within this box will not be considered.
const boundBox& meshBb = mesh.bounds();
const vector searchSpan = searchTol * meshBb.span();
Info<< "All boundary faces further away than " << searchTol
<< " of mesh bounding box " << meshBb
<< " will keep their patch label ..." << endl;
Info<< "Before patching:" << nl
<< " patch\tsize" << endl;
forAll(mesh.boundaryMesh(), patchi)
{
Info<< " " << mesh.boundaryMesh()[patchi].name() << '\t'
<< mesh.boundaryMesh()[patchi].size() << nl;
}
Info<< endl;
repatchMesh rMesh;
// Load in the surface.
rMesh.readTriSurface(surfName);
// Add all the boundaryMesh patches to the mesh.
const PtrList<repatchPatch>& bPatches = rMesh.patches();
// Map from surface patch ( = boundaryMesh patch) to polyMesh patch
labelList patchMap(bPatches.size());
forAll(bPatches, i)
{
patchMap[i] = addPatch(mesh, bPatches[i].name());
}
// Obtain nearest face in rMesh for each boundary face in mesh that
// is within search span.
// Note: should only determine for faceSet if working with that.
labelList nearest(rMesh.getNearest(mesh, searchSpan));
{
// Dump unmatched faces to faceSet for debugging.
faceSet unmatchedFaces(mesh, "unmatchedFaces", nearest.size()/100);
forAll(nearest, bFacei)
{
if (nearest[bFacei] == -1)
{
unmatchedFaces.insert(mesh.nInternalFaces() + bFacei);
}
}
Pout<< "Writing all " << unmatchedFaces.size()
<< " unmatched faces to faceSet "
<< unmatchedFaces.name()
<< endl;
unmatchedFaces.write();
}
polyTopoChange meshMod(mesh);
label nChanged = 0;
if (readSet)
{
faceSet faceLabels(mesh, setName);
Info<< "Read " << faceLabels.size() << " faces to repatch ..." << endl;
forAllConstIter(faceSet, faceLabels, iter)
{
label facei = iter.key();
if (repatchFace(mesh, rMesh, nearest, patchMap, facei, meshMod))
{
nChanged++;
}
}
}
else
{
forAll(nearest, bFacei)
{
label facei = mesh.nInternalFaces() + bFacei;
if (repatchFace(mesh, rMesh, nearest, patchMap, facei, meshMod))
{
nChanged++;
}
}
}
Pout<< "Changed " << nChanged << " boundary faces." << nl << endl;
if (nChanged > 0)
{
meshMod.changeMesh(mesh, false);
Info<< "After patching:" << nl
<< " patch\tsize" << endl;
forAll(mesh.boundaryMesh(), patchi)
{
Info<< " " << mesh.boundaryMesh()[patchi].name() << '\t'
<< mesh.boundaryMesh()[patchi].size() << endl;
}
Info<< endl;
runTime++;
// Write resulting mesh
Info<< "Writing modified mesh to time "
<< runTime.userTimeName() << endl;
mesh.write();
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //