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;
103 int 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);
173 <<
"Cannot specify both dictionary and command-line arguments" 191 <<
"Only specify -integral with command-line arguments" 198 <<
"Only specify -partial with command-line arguments" 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);
378 const label nActions = validatedDict.size();
380 Info<<
nl << nActions <<
" validated actions" <<
endl;
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();
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.
errorManipArg< error, int > exit(error &err, const int errNo=1)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
constexpr char nl
The newline '\n' character (0x0a)
const word dictName("faMeshDefinition")
Ostream & endl(Ostream &os)
Add newline and flush stream.
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Field reading functions for post-processing utilities.
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
void clear()
Clear the list, i.e. set size to zero.
label size() const noexcept
The number of arguments.
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
constexpr auto key(const Type &t) noexcept
Helper function to return the enum value.
Ostream & flush(Ostream &os)
Flush stream.
messageStream Info
Information stream (stdout output on master, null elsewhere)
List< label > labelList
A List of labels.
Foam::argList args(argc, argv)
PrimitivePatch< List< face >, const pointField > bMesh
Holder of faceList and points. (v.s. e.g. primitivePatch which references points) ...
bool checkPatch(const bool allGeometry, const std::string &name, const polyMesh &mesh, const PatchType &pp, const labelUList &meshEdges, labelHashSet *pointSetPtr=nullptr, labelHashSet *badEdgesPtr=nullptr)
bool check(bool checkArgs=argList::argsMandatory(), bool checkOpts=true) const
Check the parsed command-line for mandatory arguments and that all the options are correct...
bool found(const word &optName) const
Return true if the named option is found.
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...