87void insertDuplicateMerge
101 label otherFacei = duplicates[bFacei];
103 if (otherFacei != -1 && otherFacei > bFacei)
107 label face0 = boundaryFaces[bFacei];
108 label face1 = boundaryFaces[otherFacei];
110 label own0 = faceOwner[face0];
111 label own1 = faceOwner[face1];
117 bool zoneFlip =
false;
146 bool zoneFlip =
false;
202 faceIDs[sz++] = pp.
start()+ppi;
206 if (faceIDs.size() != sz)
218 labelList duplicates = localPointRegion::findDuplicateFaces
228 forAll(duplicates, bFacei)
230 if (duplicates[bFacei] != -1)
232 label facei = boundaryFaces[bFacei];
233 label patchi =
patches.whichPatch(facei);
235 if (isA<processorPolyPatch>(
patches[patchi]))
238 <<
"Duplicate face " << facei
239 <<
" is on a processorPolyPatch."
240 <<
"This is not allowed." <<
nl
242 <<
" is on patch:" <<
patches[patchi].name()
243 <<
abort(FatalError);
255 mesh.nBoundaryFaces()/256
258 forAll(duplicates, bFacei)
260 label otherFacei = duplicates[bFacei];
262 if (otherFacei != -1 && otherFacei > bFacei)
264 duplicateSet.insert(boundaryFaces[bFacei]);
265 duplicateSet.insert(boundaryFaces[otherFacei]);
270 <<
" duplicate faces to faceSet " << duplicateSet.objectPath()
272 duplicateSet.
write();
279int main(
int argc,
char *argv[])
283 "Detect faces that share points (baffles).\n"
284 "Merge them or duplicate the points."
293 "Specify a dictionary to read actions from"
295 argList::addBoolOption
298 "Find baffles only, but do not merge or split them"
300 argList::addBoolOption
303 "Topologically split duplicate surfaces"
306 argList::noFunctionObjects();
312 const word oldInstance =
mesh.pointsInstance();
315 const bool readDict =
args.
found(
"dict");
317 const bool overwrite =
args.
found(
"overwrite");
318 const bool detectOnly =
args.
found(
"detectOnly");
320 if (readDict && (
split || detectOnly))
323 <<
"Use of dictionary for settings not compatible with"
324 <<
" using command line arguments for \"split\""
325 <<
" or \"detectOnly\"" <<
exit(FatalError);
341 if (
dict.found(
"detect"))
343 detectPatchIDs =
patches.patchSet
348 Info<<
"Detecting baffles on " << detectPatchIDs.
size()
353 if (
dict.found(
"merge"))
355 mergePatchIDs =
patches.patchSet
360 Info<<
"Detecting baffles on " << mergePatchIDs.
size()
365 if (
dict.found(
"split"))
367 splitPatchIDs =
patches.patchSet
372 Info<<
"Detecting baffles on " << splitPatchIDs.
size()
395 if (detectPatchIDs.
size())
397 findBaffles(
mesh, patchFaces(
mesh, detectPatchIDs));
446 if (mergePatchIDs.
size())
448 Info<<
"Merging duplicate faces" <<
nl <<
endl;
453 const labelList boundaryFaces(patchFaces(
mesh, mergePatchIDs));
459 insertDuplicateMerge(
mesh, boundaryFaces, duplicates, meshMod);
470 mesh.updateMesh(map());
473 if (map().hasMotionPoints())
475 mesh.movePoints(map().preMotionPoints());
480 mesh.setInstance(oldInstance);
487 if (splitPatchIDs.
size())
489 Info<<
"Topologically splitting duplicate surfaces"
490 <<
", i.e. duplicating points internal to duplicate surfaces"
499 sz +=
patches[splitPatchIDs[i]].nPoints();
509 label pointi =
mp[mpi];
510 if (isCandidate.set(pointi))
512 candidates.
append(pointi);
529 pointDuplicator.setRefinement(
regionSide, meshMod);
540 mesh.updateMesh(map());
543 if (map().hasMotionPoints())
545 mesh.movePoints(map().preMotionPoints());
550 mesh.setInstance(oldInstance);
555 topoSet::removeFiles(
mesh);
556 processorMeshes::removeFiles(
mesh);
559 const labelList& pointMap = map().pointMap();
561 labelList nDupPerPoint(map().nOldPoints(), Zero);
567 label oldPointi = pointMap[pointi];
569 nDupPerPoint[oldPointi]++;
571 if (nDupPerPoint[oldPointi] > 1)
573 dupPoints.insert(map().reversePointMap()[oldPointi]);
574 dupPoints.insert(pointi);
579 <<
" duplicated points to pointSet "
580 << dupPoints.objectPath() <<
nl <<
endl;
static bool split(const std::string &line, std::string &key, std::string &val)
Field reading functions for post-processing utilities.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
void append(const T &val)
Copy append an element to the end of this list.
void setCapacity(const label len)
Alter the size of the underlying storage.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
List of IOobjects with searching and retrieving facilities.
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
void size(const label n)
Older name for setAddressableSize.
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
bool found(const word &optName) const
Return true if the named option is found.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
A subset of mesh faces organised as a primitive patch.
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
const boolList & flipMap() const noexcept
Return face flip map.
Takes mesh with 'baffles' (= boundary faces sharing points). Determines for selected points on bounda...
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Mesh consisting of general polyhedral cells.
Class describing modification of a face.
A patch is a list of labels that address the faces in the global face list.
label start() const
Return start label of this patch in the polyMesh face list.
Class containing data for face removal.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const labelUList &patchMap, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
Determines the 'side' for every face and connected to a singly-connected (through edges) region of fa...
A List of wordRe with additional matching capabilities.
A class for handling words, derived from Foam::string.
const polyBoundaryMesh & patches
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const word dictName("faMeshDefinition")
const labelIOList & zoneID
const dimensionedScalar mp
Proton mass.
wordList ReadFields(const typename GeoMesh::Mesh &mesh, const IOobjectList &objects, PtrList< GeometricField< Type, PatchField, GeoMesh > > &fields, const bool syncPar=true, const bool readOldTime=false)
Read Geometric fields of templated type.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
errorManip< error > abort(error &err)
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.