Commit 8c08ad66 authored by mattijs's avatar mattijs
Browse files

ENH: mergeOrSplitBaffles: allow operation on selected patches. Fixes #314.

parent d29a8afb
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -28,15 +28,31 @@ Group
grpMeshManipulationUtilities
Description
Detects faces that share points (baffles). Either merge them or
Detects boundary faces that share points (baffles). Either merges them or
duplicate the points.
Notes:
Usage
\b mergeOrSplitBaffles [OPTION]
Options:
- \par -detect
Detect baffles and write to faceSet duplicateFaces.
- \par -merge
Detect baffles and convert to internal faces.
- \par -split
Detect baffles and duplicate the points (used so the two sides
can move independently)
- \par -dict \<dictionary\>
Specify a dictionary to read actions from.
Note
- can only handle pairwise boundary faces. So three faces using
the same points is not handled (is illegal mesh anyway)
- there is no option to only split/merge some baffles.
- surfaces consisting of duplicate faces can be topologically split
if the points on the interior of the surface cannot walk to all the
cells that use them in one go.
......@@ -71,6 +87,7 @@ using namespace Foam;
void insertDuplicateMerge
(
const polyMesh& mesh,
const labelList& boundaryFaces,
const labelList& duplicates,
polyTopoChange& meshMod
)
......@@ -87,8 +104,8 @@ void insertDuplicateMerge
{
// Two duplicate faces. Merge.
label face0 = mesh.nInternalFaces() + bFacei;
label face1 = mesh.nInternalFaces() + otherFacei;
label face0 = boundaryFaces[bFacei];
label face1 = boundaryFaces[otherFacei];
label own0 = faceOwner[face0];
label own1 = faceOwner[face1];
......@@ -156,6 +173,45 @@ void insertDuplicateMerge
}
label patchSize(const polyMesh& mesh, const labelList& patchIDs)
{
const polyBoundaryMesh& patches = mesh.boundaryMesh();
label sz = 0;
forAll(patchIDs, i)
{
const polyPatch& pp = patches[patchIDs[i]];
sz += pp.size();
}
return sz;
}
labelList patchFaces(const polyMesh& mesh, const labelList& patchIDs)
{
const polyBoundaryMesh& patches = mesh.boundaryMesh();
labelList faceIDs(patchSize(mesh, patchIDs));
label sz = 0;
forAll(patchIDs, i)
{
const polyPatch& pp = patches[patchIDs[i]];
forAll(pp, ppi)
{
faceIDs[sz++] = pp.start()+ppi;
}
}
if (faceIDs.size() != sz)
{
FatalErrorInFunction << exit(FatalError);
}
return faceIDs;
}
labelList findBaffles(const polyMesh& mesh, const labelList& boundaryFaces)
{
// Get all duplicate face labels (in boundaryFaces indices!).
......@@ -173,7 +229,7 @@ labelList findBaffles(const polyMesh& mesh, const labelList& boundaryFaces)
{
if (duplicates[bFacei] != -1)
{
label facei = mesh.nInternalFaces() + bFacei;
label facei = boundaryFaces[bFacei];
label patchi = patches.whichPatch(facei);
if (isA<processorPolyPatch>(patches[patchi]))
......@@ -205,12 +261,12 @@ labelList findBaffles(const polyMesh& mesh, const labelList& boundaryFaces)
if (otherFacei != -1 && otherFacei > bFacei)
{
duplicateSet.insert(mesh.nInternalFaces() + bFacei);
duplicateSet.insert(mesh.nInternalFaces() + otherFacei);
duplicateSet.insert(boundaryFaces[bFacei]);
duplicateSet.insert(boundaryFaces[otherFacei]);
}
}
Pout<< "Writing " << duplicateSet.size()
Info<< "Writing " << returnReduce(duplicateSet.size(), sumOp<label>())
<< " duplicate faces to faceSet " << duplicateSet.objectPath()
<< nl << endl;
duplicateSet.write();
......@@ -220,8 +276,6 @@ labelList findBaffles(const polyMesh& mesh, const labelList& boundaryFaces)
}
int main(int argc, char *argv[])
{
argList::addNote
......@@ -232,6 +286,7 @@ int main(int argc, char *argv[])
#include "addOverwriteOption.H"
#include "addRegionOption.H"
#include "addDictOption.H"
argList::addBoolOption
(
"detectOnly",
......@@ -249,27 +304,91 @@ int main(int argc, char *argv[])
#include "createNamedMesh.H"
const word oldInstance = mesh.pointsInstance();
const polyBoundaryMesh& patches = mesh.boundaryMesh();
const bool readDict = args.optionFound("dict");
const bool split = args.optionFound("split");
const bool overwrite = args.optionFound("overwrite");
const bool detectOnly = args.optionFound("detectOnly");
// Collect all boundary faces
labelList boundaryFaces(mesh.nFaces() - mesh.nInternalFaces());
if (readDict && (split || detectOnly))
{
FatalErrorInFunction
<< "Use of dictionary for settings not compatible with"
<< " using command line arguments for \"split\""
<< " or \"detectOnly\"" << exit(FatalError);
}
labelList detectPatchIDs;
labelList splitPatchIDs;
labelList mergePatchIDs;
forAll(boundaryFaces, i)
if (readDict)
{
boundaryFaces[i] = i+mesh.nInternalFaces();
const word dictName;
#include "setSystemMeshDictionaryIO.H"
Info<< "Reading " << dictName << "\n" << endl;
IOdictionary dict(dictIO);
if (dict.found("detect"))
{
wordReList patchNames(dict.subDict("detect").lookup("patches"));
detectPatchIDs = patches.patchSet(patchNames).sortedToc();
Info<< "Detecting baffles on " << detectPatchIDs.size()
<< " patches with "
<< returnReduce(patchSize(mesh, detectPatchIDs), sumOp<label>())
<< " faces" << endl;
}
if (dict.found("merge"))
{
wordReList patchNames(dict.subDict("merge").lookup("patches"));
mergePatchIDs = patches.patchSet(patchNames).sortedToc();
Info<< "Detecting baffles on " << mergePatchIDs.size()
<< " patches with "
<< returnReduce(patchSize(mesh, mergePatchIDs), sumOp<label>())
<< " faces" << endl;
}
if (dict.found("split"))
{
wordReList patchNames(dict.subDict("split").lookup("patches"));
splitPatchIDs = patches.patchSet(patchNames).sortedToc();
Info<< "Detecting baffles on " << splitPatchIDs.size()
<< " patches with "
<< returnReduce(patchSize(mesh, splitPatchIDs), sumOp<label>())
<< " faces" << endl;
}
}
else
{
if (detectOnly)
{
detectPatchIDs = identity(patches.size());
}
else if (split)
{
splitPatchIDs = identity(patches.size());
}
else
{
mergePatchIDs = identity(patches.size());
}
}
if (detectOnly)
if (detectPatchIDs.size())
{
findBaffles(mesh, boundaryFaces);
return 0;
findBaffles(mesh, patchFaces(mesh, detectPatchIDs));
if (detectOnly)
{
return 0;
}
}
// Read objects in time directory
IOobjectList objects(mesh, runTime.timeName());
......@@ -308,64 +427,118 @@ int main(int argc, char *argv[])
ReadFields(mesh, objects, stFlds);
// Mesh change engine
polyTopoChange meshMod(mesh);
if (mergePatchIDs.size())
{
Info<< "Merging duplicate faces" << nl << endl;
// Mesh change engine
polyTopoChange meshMod(mesh);
const labelList boundaryFaces(patchFaces(mesh, mergePatchIDs));
// Get all duplicate face pairs (in boundaryFaces indices!).
labelList duplicates(findBaffles(mesh, boundaryFaces));
// Merge into internal faces.
insertDuplicateMerge(mesh, boundaryFaces, duplicates, meshMod);
if (!overwrite)
{
runTime++;
}
if (split)
// Change the mesh. No inflation.
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
// Update fields
mesh.updateMesh(map);
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
if (overwrite)
{
mesh.setInstance(oldInstance);
}
Info<< "Writing mesh to time " << runTime.timeName() << endl;
mesh.write();
}
if (splitPatchIDs.size())
{
Pout<< "Topologically splitting duplicate surfaces"
<< ", i.e. duplicating points internal to duplicate surfaces."
Info<< "Topologically splitting duplicate surfaces"
<< ", i.e. duplicating points internal to duplicate surfaces"
<< nl << endl;
// Determine points on split patches
DynamicList<label> candidates;
{
label sz = 0;
forAll(splitPatchIDs, i)
{
sz += patches[splitPatchIDs[i]].nPoints();
}
candidates.setCapacity(sz);
PackedBoolList isCandidate(mesh.nPoints());
forAll(splitPatchIDs, i)
{
const labelList& mp = patches[splitPatchIDs[i]].meshPoints();
forAll(mp, mpi)
{
label pointi = mp[mpi];
if (isCandidate.set(pointi))
{
candidates.append(pointi);
}
}
}
}
// Analyse which points need to be duplicated
localPointRegion regionSide(mesh);
localPointRegion regionSide(mesh, candidates);
// Point duplication engine
duplicatePoints pointDuplicator(mesh);
// Mesh change engine
polyTopoChange meshMod(mesh);
// Insert topo changes
pointDuplicator.setRefinement(regionSide, meshMod);
}
else
{
Pout<< "Merging duplicate faces."
<< nl << endl;
// Get all duplicate face labels (in boundaryFaces indices!).
labelList duplicates(findBaffles(mesh, boundaryFaces));
// Merge into internal faces.
insertDuplicateMerge(mesh, duplicates, meshMod);
}
if (!overwrite)
{
runTime++;
}
if (!overwrite)
{
runTime++;
}
// Change the mesh. No inflation.
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
// Change the mesh. No inflation.
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
// Update fields
mesh.updateMesh(map);
// Update fields
mesh.updateMesh(map);
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
if (overwrite)
{
mesh.setInstance(oldInstance);
}
Info<< "Writing mesh to time " << runTime.timeName() << endl;
mesh.write();
if (overwrite)
{
mesh.setInstance(oldInstance);
}
Pout<< "Writing mesh to time " << runTime.timeName() << endl;
mesh.write();
// Dump duplicated points (if any)
if (split)
{
// Dump duplicated points (if any)
const labelList& pointMap = map().pointMap();
labelList nDupPerPoint(map().nOldPoints(), 0);
......@@ -385,7 +558,7 @@ int main(int argc, char *argv[])
}
}
Pout<< "Writing " << dupPoints.size()
Info<< "Writing " << returnReduce(dupPoints.size(), sumOp<label>())
<< " duplicated points to pointSet "
<< dupPoints.objectPath() << nl << endl;
......
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object mergeOrSplitBafflesDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Detect baffles (boundary faces sharing points) on selected set of patches
// and write to a faceSet.
detect
{
patches (".*Wall");
}
// Detect baffles (on selected patches) and merge these into internal faces.
merge
{
patches ("mergePatch");
}
// Detect baffles (on selected patches) and duplicate the points. This is
// used if e.g. the two sides need to move separately. Note that since the
// points are duplicated the two faces are no longer baffles.
split
{
patches ("split.*Patches");
}
// ************************************************************************* //
Supports Markdown
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