76 pName += mesh0.
name();
78 pName += mesh1.
name();
85 const word& entryName,
86 const word& AMIMethod,
121 const auto& ppi =
meshes[meshi].boundaryMesh()[patchesi[i]];
125 const auto& ppj =
meshes[meshj].boundaryMesh()[patchesj[j]];
128 auto AMPtr(AMIInterpolation::New(AMIMethod, AMIDict));
130 AMPtr->calculate(ppi, ppj,
nullptr);
133 gAverage(AMPtr->tgtWeightsSum()) > SMALL
134 ||
gAverage(AMPtr->srcWeightsSum()) > SMALL
137 const label inti = interfaceMesh0.
size();
139 Info<<
"Introducing interface " << inti <<
" between"
140 <<
" mesh " <<
meshes[meshi].name()
142 <<
" patch " << ppi.name()
143 <<
" and mesh " <<
meshes[meshj].name()
145 <<
" patch " << ppj.name()
152 auto& intMesh0 = interfaceMesh0.
last();
153 intMesh0.setSize(nSourcei, -1);
154 intMesh0[sourcei] = meshi;
156 interfaceSource0.
append(sourcei);
159 auto& intPatch0 = interfacePatch0.
last();
160 intPatch0.setSize(nSourcei, -1);
161 intPatch0[sourcei] = ppi.index();
164 auto& intNames0 = interfaceNames0.
last();
165 intNames0.setSize(nSourcei);
174 auto& intMesh1 = interfaceMesh1.
last();
175 intMesh1.setSize(nSourcej, -1);
176 intMesh1[sourcej] = meshj;
178 interfaceSource1.
append(sourcej);
181 auto& intPatch1 = interfacePatch1.
last();
182 intPatch1.setSize(nSourcej, -1);
183 intPatch1[sourcej] = ppj.index();
186 auto& intNames1 = interfaceNames1.
last();
187 intNames1.setSize(nSourcej);
192 auto& intFaces0 = interfaceFaces0.
last();
193 intFaces0.setSize(nSourcei);
198 auto& intFaces1 = interfaceFaces1.
last();
199 intFaces1.setSize(nSourcej);
214 const scalarField& weights = AMPtr->srcWeightsSum();
218 const scalar
sum = weights[facei];
226 targetMask = AMPtr->interpolateToTarget(mask);
231 const scalarField& weights = AMPtr->tgtWeightsSum();
235 const scalar
sum = weights[facei];
243 sourceMask = AMPtr->interpolateToSource(mask);
247 const scalarField& weights = AMPtr->srcWeightsSum();
250 if (weights[facei] > 0.5 || sourceMask[facei] > SMALL)
252 faces0.
append(ppi.start()+facei);
257 const scalarField& weights = AMPtr->tgtWeightsSum();
260 if (weights[facei] > 0.5 || targetMask[facei] > SMALL)
262 faces1.
append(ppj.start()+facei);
277 const bool includeOwn,
303 const label meshjStart(includeOwn ? meshi : meshi+1);
305 for (label meshj = meshjStart; meshj <
meshes.
size(); meshj++)
309 for (
const label sourcei : interRegionSources[meshi])
311 const labelList& patchesi = allPatchesi[sourcei];
313 for (
const label sourcej : interRegionSources[meshj])
315 const labelList& patchesj = allPatchesj[sourcej];
325 AMIMethods[meshi][sourcei].size()
326 ? AMIMethods[meshi][sourcei]
327 : faceAreaWeightAMI2D::typeName
329 patchInfoDicts[meshi][sourcei],
369 const label
zoneID =
mesh.faceZones().whichZone(faceID);
371 bool zoneFlip =
false;
384 mesh.faces()[faceID],
386 mesh.faceOwner()[faceID],
403 bitSet& isRepatchedBoundary,
407 for (
const label facei : faceLabels)
409 if (
mesh.isInternalFace(facei))
413 <<
" is not an external face of the mesh." <<
endl
414 <<
"This application can only repatch"
415 <<
" existing boundary faces." <<
exit(FatalError);
418 if (!isRepatchedBoundary.
set(facei-
mesh.nInternalFaces()))
420 static label nWarnings = 0;
423 const label newPatchi = meshMod.
region()[facei];
427 <<
" at " <<
mesh.faceCentres()[facei]
428 <<
" marked for patch " <<
patchID
430 <<
" is already marked for patch " << newPatchi
431 <<
" name " <<
mesh.boundaryMesh()[newPatchi].name()
432 <<
". Suppressing further warnings"
451 if (cpp && cpp->
owner())
453 const auto& cycPatch = *cpp;
458 OFstream str(prefix+cycPatch.name()+
".obj");
459 Pout<<
"Dumping " << cycPatch.
name()
460 <<
" faces to " << str.
name() <<
endl;
470 OFstream str(prefix+nbrPatch.name()+
".obj");
471 Pout<<
"Dumping " << nbrPatch.
name()
472 <<
" faces to " << str.
name() <<
endl;
483 OFstream str(prefix+cycPatch.name()+nbrPatch.name()+
"_match.obj");
486 Pout<<
"Dumping cyclic match as lines between face centres to "
491 const point& fc0 =
mesh.faceCentres()[cycPatch.start()+facei];
492 meshTools::writeOBJ(str, fc0);
494 const point& fc1 =
mesh.faceCentres()[nbrPatch.start()+facei];
495 meshTools::writeOBJ(str, fc1);
498 str<<
"l " << vertI-1 <<
' ' << vertI <<
nl;
511 if (separation.
size() == 1)
517 field[i] += separation[0];
520 else if (separation.
size() ==
field.size())
524 field[i] += separation[i];
530 <<
"Sizes of field and transformation not equal. field:"
531 <<
field.size() <<
" transformation:" << separation.
size()
532 <<
abort(FatalError);
538template<
class CombineOp>
543 const CombineOp& cop,
544 const point& nullValue
550 <<
"Number of values " <<
points.size()
551 <<
" is not equal to the number of points in the mesh "
558 bool hasTransformation =
false;
560 if (Pstream::parRun())
562 const labelList& procPatches =
mesh.globalData().processorPatches();
565 for (
const label patchi : procPatches)
568 const auto& procPatch = refCast<const processorPolyPatch>(pp);
570 if (pp.
nPoints() && procPatch.owner())
573 pointField patchInfo(procPatch.nPoints(), nullValue);
575 const labelList& meshPts = procPatch.meshPoints();
576 const labelList& nbrPts = procPatch.neighbPoints();
580 label nbrPointi = nbrPts[pointi];
581 if (nbrPointi >= 0 && nbrPointi < patchInfo.size())
583 patchInfo[nbrPointi] =
points[meshPts[pointi]];
589 Pstream::commsTypes::blocking,
590 procPatch.neighbProcNo()
599 for (
const label patchi : procPatches)
602 const auto& procPatch = refCast<const processorPolyPatch>(pp);
604 if (pp.
nPoints() && !procPatch.owner())
612 Pstream::commsTypes::blocking,
613 procPatch.neighbProcNo()
615 fromNbr >> nbrPatchInfo;
618 nbrPatchInfo.setSize(procPatch.nPoints(), nullValue);
620 if (!procPatch.parallel())
622 hasTransformation =
true;
625 else if (procPatch.separated())
627 hasTransformation =
true;
628 separateList(-procPatch.separation(), nbrPatchInfo);
631 const labelList& meshPts = procPatch.meshPoints();
635 label meshPointi = meshPts[pointi];
636 points[meshPointi] = nbrPatchInfo[pointi];
647 if (cpp && cpp->
owner())
651 const auto& cycPatch = *cpp;
654 const edgeList& coupledPoints = cycPatch.coupledPoints();
655 const labelList& meshPts = cycPatch.meshPoints();
656 const labelList& nbrMeshPts = nbrPatch.meshPoints();
662 const edge&
e = coupledPoints[i];
663 label point0 = meshPts[
e[0]];
664 half0Values[i] =
points[point0];
667 if (!cycPatch.parallel())
669 hasTransformation =
true;
672 else if (cycPatch.separated())
674 hasTransformation =
true;
675 separateList(cycPatch.separation(), half0Values);
680 const edge&
e = coupledPoints[i];
681 label point1 = nbrMeshPts[
e[1]];
682 points[point1] = half0Values[i];
696 if (hasTransformation)
699 <<
"There are decomposed cyclics in this mesh with"
700 <<
" transformations." <<
endl
701 <<
"This is not supported. The result will be incorrect"
717 Pstream::listCombineAllGather(sharedPts, cop);
731int main(
int argc,
char *argv[])
735 "Create patches out of selected boundary faces, which are either"
736 " from existing patches or from a faceSet"
742 argList::addOption(
"dict",
"file",
"Alternative createPatchDict");
743 argList::addBoolOption
746 "Write obj files showing the cyclic matching process"
749 argList::noFunctionObjects();
755 const bool overwrite =
args.
found(
"overwrite");
759 const bool writeObj =
args.
found(
"writeObj");
777 patches.checkParallelSync(
true);
779 oldInstances[meshi] =
mesh.pointsInstance();
787 const auto&
dict = dicts[meshi];
789 patchNames[meshi].setSize(patchSources.size());
790 matchPatchIDs[meshi].
setSize(patchSources.size());
791 matchMethods[meshi].setSize(patchSources.size());
792 patchInfoDicts[meshi].setSize(patchSources.size());
795 forAll(patchSources, sourcei)
797 const auto& pDict = patchSources[sourcei];
805 patchInfoDicts[meshi].set
810 dictionary& patchDict = patchInfoDicts[meshi][sourcei];
811 if (patchDict.
found(
"AMIMethod"))
813 matchMethods[meshi][sourcei] = patchDict.
get<
word>(
"AMIMethod");
816 patchDict.
add(
"requireMatch",
false);
820 if (pDict.readIfPresent(
"patches", matchNames, keyType::LITERAL))
822 matchPatchIDs[meshi][sourcei] =
823 patches.patchSet(matchNames).sortedToc();
826 if (pDict.get<
word>(
"constructFrom") ==
"autoPatch")
828 interRegionSources[meshi].append(sourcei);
908 bool noFields =
true;
909 for (
const auto& d : patchInfoDicts[meshi])
911 if (d.found(
"patchFields"))
947 Info<<
"\n\nAdding patches to mesh " <<
mesh.name() <<
nl <<
endl;
954 dumpCyclicMatch(
"initial_",
mesh);
964 forAll(patchSources, sourcei)
978 dictionary patchDict(patchInfoDicts[meshi][sourcei]);
979 patchDict.
set(
"nFaces", 0);
980 patchDict.
set(
"startFace", 0);
983 if (sourceType ==
"autoPatch")
988 forAll(interfaceMesh0, inti)
990 const labelList& allMeshes0 = interfaceMesh0[inti];
991 const wordList& allNames0 = interfaceNames0[inti];
992 const labelList& allMeshes1 = interfaceMesh1[inti];
993 const wordList& allNames1 = interfaceNames1[inti];
997 interfaceSource0[inti] == sourcei
998 && allMeshes0[sourcei] == meshi
1002 const label sourcej = interfaceSource1[inti];
1003 const word& patchName = allNames0[sourcei];
1004 if (
patches.findPatchID(patchName) == -1)
1007 const auto& mesh1 =
meshes[allMeshes1[sourcej]];
1008 allDict.
set(
"sampleRegion", mesh1.
name());
1009 const auto& destPatch = allNames1[sourcej];
1010 allDict.
set(
"samplePatch", destPatch);
1011 allDict.set(
"neighbourPatch", destPatch);
1013 Info<<
"Adding new patch " << patchName
1014 <<
" from " << allDict <<
endl;
1026 fvMeshTools::addPatch
1031 calculatedFvPatchScalarField::typeName,
1038 forAll(interfaceMesh1, inti)
1040 const labelList& allMeshes0 = interfaceMesh0[inti];
1041 const wordList& allNames0 = interfaceNames0[inti];
1042 const labelList& allMeshes1 = interfaceMesh1[inti];
1043 const wordList& allNames1 = interfaceNames1[inti];
1047 interfaceSource1[inti] == sourcei
1048 && allMeshes1[sourcei] == meshi
1053 const label sourcej = interfaceSource0[inti];
1054 const word& patchName = allNames1[sourcei];
1055 if (
patches.findPatchID(patchName) == -1)
1058 const auto& destPatch = allNames0[sourcej];
1059 const auto& mesh0 =
meshes[allMeshes0[sourcej]];
1060 allDict.
set(
"sampleRegion", mesh0.
name());
1061 allDict.
set(
"samplePatch", destPatch);
1062 allDict.set(
"neighbourPatch", destPatch);
1064 Info<<
"Adding new patch " << patchName
1065 <<
" from " << allDict <<
endl;
1077 fvMeshTools::addPatch
1082 calculatedFvPatchScalarField::typeName,
1091 if (
patches.findPatchID(patchName) == -1)
1093 Info<<
"Adding new patch " << patchName
1094 <<
" from " << patchDict <<
endl;
1106 fvMeshTools::addPatch
1111 calculatedFvPatchScalarField::typeName,
1136 const bool pointSync(
dict.get<
bool>(
"pointSync"));
1146 bitSet isRepatchedBoundary(
mesh.nBoundaryFaces());
1148 forAll(patchSources, sourcei)
1151 const word patchName
1160 const word sourceType(
dict.get<
word>(
"constructFrom"));
1162 if (sourceType ==
"autoPatch")
1164 forAll(interfaceMesh0, inti)
1166 const labelList& allMeshes0 = interfaceMesh0[inti];
1167 const wordList& allNames0 = interfaceNames0[inti];
1168 const auto& allFaces0 = interfaceFaces0[inti];
1170 const labelList& allMeshes1 = interfaceMesh1[inti];
1171 const wordList& allNames1 = interfaceNames1[inti];
1172 const auto& allFaces1 = interfaceFaces1[inti];
1176 interfaceSource0[inti] == sourcei
1177 && allMeshes0[sourcei] == meshi
1182 const label destPatchi =
1183 patches.findPatchID(allNames0[sourcei],
false);
1196 isRepatchedBoundary,
1202 interfaceSource1[inti] == sourcei
1203 && allMeshes1[sourcei] == meshi
1208 const label destPatchi =
1209 patches.findPatchID(allNames1[sourcei],
false);
1222 isRepatchedBoundary,
1228 else if (sourceType ==
"patches")
1230 const label destPatchi =
patches.findPatchID(patchName,
false);
1237 for (
const label patchi : patchSources)
1241 Info<<
"Moving faces from patch " << pp.
name()
1242 <<
" to patch " << destPatchi <<
endl;
1249 isRepatchedBoundary,
1254 else if (sourceType ==
"set")
1256 const label destPatchi =
patches.findPatchID(patchName,
false);
1262 <<
" faces from faceSet " <<
set.name() <<
endl;
1272 isRepatchedBoundary,
1279 <<
"Invalid source type " << sourceType <<
endl
1280 <<
"Valid source types are 'patches' 'set'"
1281 <<
exit(FatalError);
1288 Info<<
"Doing topology modification to order faces." <<
nl <<
endl;
1291 if (map().hasMotionPoints())
1293 mesh.movePoints(map().preMotionPoints());
1303 mesh.updateMesh(map());
1307 const auto& oldToNew = map().reverseFaceMap();
1308 forAll(interfaceMesh0, inti)
1310 const labelList& allMeshes0 = interfaceMesh0[inti];
1311 forAll(allMeshes0, sourcei)
1313 if (allMeshes0[sourcei] == meshi)
1319 forAll(interfaceMesh1, inti)
1321 const labelList& allMeshes1 = interfaceMesh1[inti];
1322 forAll(allMeshes1, sourcei)
1324 if (allMeshes1[sourcei] == meshi)
1334 dumpCyclicMatch(
"coupled_",
mesh);
1340 Info<<
"Not synchronising points." <<
nl <<
endl;
1344 Info<<
"Synchronising points." <<
nl <<
endl;
1357 if (pp.size() && isA<coupledPolyPatch>(pp))
1360 refCast<const coupledPolyPatch>(pp);
1364 Info<<
"On coupled patch " << pp.
name()
1365 <<
" separation[0] was "
1368 if (isA<cyclicPolyPatch>(pp) && pp.size())
1371 refCast<const cyclicPolyPatch>(pp);
1376 == cyclicPolyPatch::TRANSLATIONAL
1380 Info<<
"On cyclic translation patch "
1382 <<
" forcing uniform separation of "
1383 << cycpp.separationVector() <<
endl;
1389 const auto& nbr = cycpp.neighbPatch();
1394 nbr[0].centre(
mesh.points())
1395 - cycpp[0].centre(
mesh.points())
1399 Info<<
"On coupled patch " << pp.
name()
1400 <<
" forcing uniform separation of "
1405 Info<<
"On coupled patch " << pp.
name()
1406 <<
" forcing uniform rotation of "
1418 Info<<
"On coupled patch " << pp.
name()
1419 <<
" forcing uniform rotation of "
1425 Info<<
"Synchronising points." <<
endl;
1434 point(GREAT, GREAT, GREAT)
1441 mesh.movePoints(newPoints);
1448 Info<<
"Removing patches with no faces in them." <<
nl <<
endl;
1449 const wordList oldPatchNames(
mesh.boundaryMesh().names());
1450 const wordList oldPatchTypes(
mesh.boundaryMesh().types());
1451 fvMeshTools::removeEmptyPatches(
mesh,
true);
1452 forAll(oldPatchNames, patchi)
1454 const word& pName = oldPatchNames[patchi];
1455 if (
mesh.boundaryMesh().findPatchID(pName) == -1)
1457 Info<<
"Removed zero-sized patch " << pName
1458 <<
" type " << oldPatchTypes[patchi]
1459 <<
" at position " << patchi <<
endl;
1466 dumpCyclicMatch(
"final_",
mesh);
1480 mesh.setInstance(oldInstances[meshi]);
1485 IOstream::defaultPrecision(
max(10u, IOstream::defaultPrecision()));
1491 Info<<
"\n\nWriting repatched mesh " <<
mesh.name()
1495 topoSet::removeFiles(
mesh);
1496 processorMeshes::removeFiles(
mesh);
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 clear() noexcept
Clear the addressed list, i.e. set the size to zero.
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
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.
bool set(const Key &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
A PtrList of objects of type <T> with automated input and output.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
List of IOobjects with searching and retrieving facilities.
Input inter-processor communications stream.
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
void setSize(const label n)
Alias for resize()
Output to file stream, using an OSstream.
Output inter-processor communications stream.
virtual const fileName & name() const
Get the name of the stream.
label nPoints() const
Number of points supporting patch faces.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
const T * set(const label i) const
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
void size(const label n)
Older name for setAddressableSize.
T & last()
Return the last element of the list.
label size() const noexcept
The number of elements in the list.
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...
void set(const bitSet &bitset)
Set specified bits from another bitset.
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
virtual const tensorField & reverseT() const
Return neighbour-cell transformation tensor.
virtual bool separated() const
Are the planes separated.
virtual bool parallel() const
Are the cyclic planes parallel.
virtual const vectorField & separation() const
If the planes are separated the separation vector.
virtual const tensorField & forwardT() const
Return face transformation tensor.
virtual bool owner() const
Does this side own the patch ?
const cyclicPolyPatch & neighbPatch() const
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
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.
A class for handling file names.
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Mesh data needed to do the Finite Volume discretisation.
const word & name() const
Return reference to name.
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
label nGlobalPoints() const
Return number of globally shared points.
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
const word & name() const noexcept
The patch name.
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.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
const DynamicList< label > & region() const
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.
A List of wordRe with additional matching capabilities.
A class for handling words, derived from Foam::string.
#define defineTemplateTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information for templates, useful.
const polyBoundaryMesh & patches
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const word dictName("faMeshDefinition")
const labelIOList & zoneID
#define WarningInFunction
Report a warning using Foam::Warning.
void set(List< bool > &bools, const labelUList &locations)
Set the listed locations (assign 'true').
void inplaceRenumber(const labelUList &oldToNew, IntListType &lists)
Inplace renumber the values (not the indices) of a list of lists.
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)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
errorManip< error > abort(error &err)
Type gAverage(const FieldField< Field, Type > &f)
void transformList(const tensor &rotTensor, UList< T > &field)
Inplace transform a list of elements.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Type gMax(const FieldField< Field, Type > &f)
constexpr char nl
The newline '\n' character (0x0a)
wordList patchNames(nPatches)
points setSize(newPointi)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.