82 const label patchi =
bMesh.findPatchID(
name);
87 <<
"Known patches: " <<
bMesh.names() <<
endl;
92 if (bMesh[patchi].empty())
94 Info<<
"Patch " <<
name <<
" has zero size" <<
nl;
103int main(
int argc,
char *argv[])
107 "Merge the faces on specified patches (if geometrically possible)"
109 "faces become internal.\n"
110 "This utility can be called without arguments (uses stitchMeshDict)"
112 "two arguments (master/slave patch names)."
115 argList::noParallel();
116 argList::noFunctionObjects();
121 argList::addOption(
"dict",
"file",
"Alternative stitchMeshDict");
123 argList::addBoolOption
126 "Couple integral master/slave patches (2 argument mode: default)"
128 argList::addBoolOption
131 "Couple partially overlapping master/slave patches (2 argument mode)"
133 argList::addBoolOption
136 "Couple perfectly aligned master/slave patches (2 argument mode)"
138 argList::addBoolOption
141 "Write intermediate stages, not just the final result"
147 "Dictionary file with tolerances"
151 argList::noMandatoryArgs();
155 "The master patch name (non-dictionary mode)"
160 "The slave patch name (non-dictionary mode)"
166 const bool useCommandArgs = (
args.size() > 1);
170 if (
args.found(
"dict"))
173 <<
"Cannot specify both dictionary and command-line arguments"
179 if (!
args.check(
true,
false))
188 if (
args.found(
"integral"))
191 <<
"Only specify -integral with command-line arguments"
195 if (
args.found(
"partial"))
198 <<
"Only specify -partial with command-line arguments"
202 if (
args.found(
"perfect"))
205 <<
"Only specify -perfect with command-line arguments"
213 const word oldInstance =
mesh.pointsInstance();
215 const bool intermediate =
args.found(
"intermediate");
216 const bool overwrite =
args.found(
"overwrite");
218 const word
dictName(
"stitchMeshDict");
226 const int integralCover =
args.found(
"integral");
227 const int partialCover =
args.found(
"partial");
228 const int perfectCover =
args.found(
"perfect");
230 if ((integralCover + partialCover + perfectCover) > 1)
233 <<
"Can only specify one of -integral | -partial | -perfect."
235 <<
"Use perfect match option if the patches perfectly align"
236 <<
" (both vertex positions and face centres)" <<
endl
241 const word masterPatchName(
args[1]);
242 const word slavePatchName(
args[2]);
245 Info<<
" " << masterPatchName
246 <<
" / " << slavePatchName <<
nl;
267 dict.add(
"match", word(
"perfect"));
269 else if (partialCover)
274 slidingInterface::typeOfMatchNames[slidingInterface::PARTIAL]
282 slidingInterface::typeOfMatchNames[slidingInterface::INTEGRAL]
287 dict.add(
"master", masterPatchName);
288 dict.add(
"slave", slavePatchName);
290 validatedDict.add(
"stitchMesh",
dict);
300 IOdictionary stitchDict(
dictIO);
302 Info<<
" with " << stitchDict.size() <<
" entries" <<
nl;
307 for (
const entry& dEntry : stitchDict)
309 if (!dEntry.isDict())
311 Info<<
"Ignoring non-dictionary entry: "
312 << dEntry.keyword() <<
nl;
316 const keyType&
key = dEntry.keyword();
321 if (
dict.readIfPresent(
"match", matchName))
325 matchName !=
"perfect"
326 && !slidingInterface::typeOfMatchNames.
found(matchName)
329 Info<<
"Error: unknown match type - " << matchName
330 <<
" should be one of "
331 << slidingInterface::typeOfMatchNames.toc() <<
nl;
337 const word masterPatchName(
dict.get<word>(
"master"));
338 const word slavePatchName(
dict.get<word>(
"slave"));
341 Info<<
" " << masterPatchName
342 <<
" / " << slavePatchName <<
nl;
344 if (!requestedPatches.insert(masterPatchName))
346 Info<<
"Error: patch specified multiple times - "
347 << masterPatchName <<
nl;
351 if (!requestedPatches.insert(slavePatchName))
353 Info<<
"Error: patch specified multiple times - "
354 << slavePatchName <<
nl;
356 requestedPatches.erase(masterPatchName);
367 requestedPatches.erase(masterPatchName);
368 requestedPatches.erase(slavePatchName);
374 validatedDict.add(key,
dict);
378 const label nActions = validatedDict.size();
380 Info<<
nl << nActions <<
" validated actions" <<
endl;
394 if (
args.found(
"toleranceDict"))
396 IOdictionary toleranceFile
400 args[
"toleranceDict"],
403 IOobject::MUST_READ_IF_MODIFIED,
407 slidingTolerances += toleranceFile;
415 Info<<
"Reading all current volfields" <<
endl;
416 PtrList<volScalarField> volScalarFields;
419 PtrList<volVectorField> volVectorFields;
422 PtrList<volSphericalTensorField> volSphericalTensorFields;
425 PtrList<volSymmTensorField> volSymmTensorFields;
428 PtrList<volTensorField> volTensorFields;
443 IOstream::minPrecision(10);
445 polyTopoChanger stitcher(
mesh, IOobject::NO_READ);
449 for (
const entry& dEntry : validatedDict)
454 bool perfect =
false;
455 slidingInterface::typeOfMatch matchType = slidingInterface::PARTIAL;
458 if (
dict.readIfPresent(
"match", matchName))
460 if (matchName ==
"perfect")
466 matchType = slidingInterface::typeOfMatchNames[matchName];
471 const word masterPatchName(
dict.get<word>(
"master"));
472 const word slavePatchName(
dict.get<word>(
"slave"));
475 const word mergePatchName(masterPatchName + slavePatchName);
476 const word cutZoneName(mergePatchName +
"CutFaceZone");
478 Info<<
nl <<
"========================================" <<
nl;
483 Info<<
"Coupling PERFECTLY aligned patches "
484 << masterPatchName <<
" / " << slavePatchName <<
nl <<
nl
485 <<
"Resulting (internal) faces in faceZone "
486 << cutZoneName <<
nl <<
nl
487 <<
"The patch vertices and face centres must align within a"
488 <<
" tolerance relative to the minimum edge length on the patch"
491 else if (matchType == slidingInterface::INTEGRAL)
493 Info<<
"Coupling INTEGRALLY matching of patches "
494 << masterPatchName <<
" / " << slavePatchName <<
nl <<
nl
495 <<
"Resulting (internal) faces in faceZone "
496 << cutZoneName <<
nl <<
nl
497 <<
"The overall area covered by both patches should be"
498 <<
" identical!" <<
endl
499 <<
"If this is not the case use partial"
504 Info<<
"Coupling PARTIALLY overlapping patches "
505 << masterPatchName <<
" / " << slavePatchName <<
nl
506 <<
"Resulting internal faces in faceZone "
508 <<
"Uncovered faces remain in their patch"
514 const polyPatch& masterPatch =
mesh.boundaryMesh()[masterPatchName];
515 const polyPatch& slavePatch =
mesh.boundaryMesh()[slavePatchName];
517 mesh.pointZones().clearAddressing();
518 mesh.faceZones().clearAddressing();
519 mesh.cellZones().clearAddressing();
538 ).resetAddressing(std::move(faceIds),
false);
560 mergePatchName +
"CutPointZone",
566 mergePatchName +
"Side0Zone",
568 ).resetAddressing(std::move(faceIds),
false);
571 faceIds.resize_nocopy(slavePatch.size());
576 mergePatchName +
"Side1Zone",
578 ).resetAddressing(std::move(faceIds),
false);
597 mergePatchName +
"Side0Zone",
598 mergePatchName +
"Side1Zone",
599 mergePatchName +
"CutPointZone",
608 static_cast<slidingInterface&
>(stitcher[0]).setTolerances
618 if (!overwrite && (intermediate || actioni == nActions))
624 autoPtr<mapPolyMesh> morphMap = stitcher.changeMesh(
true);
626 mesh.movePoints(morphMap->preMotionPoints());
631 mesh.setInstance(oldInstance);
632 stitcher.instance() = oldInstance;
635 if (intermediate || actioni == nActions)
637 Info<<
nl <<
"Writing polyMesh to time "
643 !
runTime.objectRegistry::writeObject
655 <<
"Failed writing polyMesh."
659 mesh.faceZones().write();
660 mesh.pointZones().write();
661 mesh.cellZones().write();
Field reading functions for post-processing utilities.
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const word dictName("faMeshDefinition")
constexpr auto key(const Type &t) noexcept
Helper function to return the enum value.
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.
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
List< label > labelList
A List of labels.
messageStream Info
Information stream (stdout output on master, null elsewhere).
Ostream & endl(Ostream &os)
Add newline and flush stream.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
PrimitivePatch< List< face >, const pointField > bMesh
Holder of faceList and points. (v.s. e.g. primitivePatch which references points).
errorManipArg< error, int > exit(error &err, const int errNo=1)
Ostream & flush(Ostream &os)
Flush stream.
constexpr char nl
The newline '\n' character (0x0a).
bool checkPatch(const bool allGeometry, const std::string &name, const polyMesh &mesh, const PatchType &pp, const labelUList &meshEdges, labelHashSet *pointSetPtr=nullptr, labelHashSet *badEdgesPtr=nullptr)
Foam::argList args(argc, argv)