45 #include "surfaceInterpolate.H"
53 template<
class FaceList,
class Po
intField>
62 p.meshPoints()[
p.edges()[edgei][0]],
63 p.meshPoints()[
p.edges()[edgei][1]]
96 void Foam::fvMeshStitcher::regionNames(
const fvMesh& mesh,
wordHashSet& names)
104 if (!isA<nonConformalMappedWallFvPatch>(fvp))
continue;
106 const nonConformalMappedWallFvPatch& ncmwFvp =
107 refCast<const nonConformalMappedWallFvPatch>(fvp);
109 if (!names.found(ncmwFvp.nbrRegionName()))
111 regionNames(ncmwFvp.nbrMesh(), names);
129 UPtrList<fvMesh> result(names.size());
135 &mesh_.time().lookupObjectRef<fvMesh>(names[i])
147 UPtrList<const fvMesh> result(names.size());
153 &mesh_.time().lookupObject<fvMesh>(names[i])
161 Foam::IOobject Foam::fvMeshStitcher::polyFacesBfIO(
const fvMesh& mesh)
166 mesh.time().findInstance
168 mesh.dbDir()/fvMesh::typeName,
181 bool Foam::fvMeshStitcher::loadPolyFacesBf
183 IOobject& polyFacesBfIO,
184 SurfaceFieldBoundary<label>& polyFacesBf
192 auto polyFacesBfIOIter = regionPolyFacesBfIOs_.find(mesh_.name());
193 auto polyFacesBfIter = regionPolyFacesBfs_.find(mesh_.name());
194 if (polyFacesBfIOIter != regionPolyFacesBfIOs_.end())
199 regionPolyFacesBfIOs_.remove(polyFacesBfIOIter)
204 tmp<SurfaceFieldBoundary<label>>
206 regionPolyFacesBfs_.remove(polyFacesBfIter)
216 typeIOobject<surfaceLabelField> io
218 fvMeshStitcher::polyFacesBfIO(mesh_)
235 if (!loaded)
return false;
241 const fvPatch& fvp = mesh_.boundary()[
patchi];
243 if (!isA<nonConformalMappedWallFvPatch>(fvp))
continue;
245 const nonConformalMappedWallFvPatch& ncmwFvp =
246 refCast<const nonConformalMappedWallFvPatch>(fvp);
248 if (!ncmwFvp.haveNbr())
continue;
250 if (regionPolyFacesBfs_.found(ncmwFvp.nbrMesh().name()))
continue;
252 IOobject io = fvMeshStitcher::polyFacesBfIO(ncmwFvp.nbrMesh());
254 regionPolyFacesBfIOs_.insert
256 ncmwFvp.nbrMesh().name(),
260 regionPolyFacesBfs_.insert
262 ncmwFvp.nbrMesh().name(),
286 return mesh_.time().lookupObject<fvMesh>(
regionName).polyFacesBf();
291 void Foam::fvMeshStitcher::getOrigNbrBfs
293 const SurfaceFieldBoundary<label>& polyFacesBf,
294 const SurfaceFieldBoundary<vector>& SfBf,
295 const SurfaceFieldBoundary<vector>& CfBf,
296 tmp<SurfaceFieldBoundary<label>>& tOrigFacesNbrBf,
297 tmp<SurfaceFieldBoundary<vector>>& tOrigSfNbrBf,
298 tmp<SurfaceFieldBoundary<point>>& tOrigCfNbrBf
308 dimensioned<label>(
dimless, -1)
333 const fvPatch& fvp = mesh_.boundary()[
patchi];
335 if (isA<nonConformalCoupledFvPatch>(fvp))
337 const nonConformalCoupledFvPatch& nccFvp =
338 refCast<const nonConformalCoupledFvPatch>(fvp);
340 origFaces.boundaryFieldRef()[
patchi] =
341 polyFacesBf[
patchi] - nccFvp.origPatch().start();
346 if (isA<coupledFvPatch>(fvp))
348 origSf.boundaryFieldRef()[
patchi] =
350 origCf.boundaryFieldRef()[
patchi] =
354 origFaces.boundaryFieldRef() =
355 origFaces.boundaryField().boundaryNeighbourField();
356 origSf.boundaryFieldRef() =
357 origSf.boundaryField().boundaryNeighbourField();
358 origCf.boundaryFieldRef() =
359 origCf.boundaryField().boundaryNeighbourField();
364 const fvPatch& fvp = mesh_.boundary()[
patchi];
366 if (!isA<nonConformalMappedWallFvPatch>(fvp))
continue;
368 const nonConformalMappedWallFvPatch& ncmwFvp =
369 refCast<const nonConformalMappedWallFvPatch>(fvp);
371 if (!ncmwFvp.haveNbr())
continue;
373 const fvMesh& nbrMesh = ncmwFvp.nbrMesh();
374 const nonConformalMappedWallFvPatch& nbrPatch = ncmwFvp.nbrPatch();
377 getPolyFacesBf(nbrMesh.name())[nbrPatch.index()];
379 origFaces.boundaryFieldRef()[
patchi] =
383 nbrPolyFacesPf - nbrPatch.origPatch().start(),
386 origSf.boundaryFieldRef()[
patchi] =
393 origCf.boundaryFieldRef()[
patchi] =
397 vectorField(nbrMesh.faceCentres(), nbrPolyFacesPf),
406 const fvPatch& fvp = mesh_.boundary()[
patchi];
410 if (isA<nonConformalCoupledFvPatch>(fvp))
412 const nonConformalCoupledFvPatch& nccFvp =
413 refCast<const nonConformalCoupledFvPatch>(fvp);
415 nccFvp.transform().invTransform(Cfp, Cfp);
416 nccFvp.transform().transformPosition(Cfp, Cfp);
419 if (isA<nonConformalMappedWallFvPatch>(fvp))
421 const nonConformalMappedWallFvPatch& ncmwFvp =
422 refCast<const nonConformalMappedWallFvPatch>(fvp);
424 if (ncmwFvp.haveNbr())
426 ncmwFvp.transform().invTransform(Cfp, Cfp);
427 ncmwFvp.transform().transformPosition(Cfp, Cfp);
437 origFaces.boundaryField()
443 origSf.boundaryField()
449 origCf.boundaryField()
455 Foam::fvMeshStitcher::procFacesToIndices
457 const List<List<remote>>& faceOtherProcFaces,
463 forAll(faceOtherProcFaces, facei)
465 forAll(faceOtherProcFaces[facei], i)
467 const remote& otherProcFacei = faceOtherProcFaces[facei][i];
469 is[otherProcFacei.proci] ++;
477 indices[proci].resize(is[proci]);
482 forAll(faceOtherProcFaces, facei)
484 forAll(faceOtherProcFaces[facei], i)
486 const remote& otherProcFacei = faceOtherProcFaces[facei][i];
488 FixedList<label, 3>& index =
489 indices[otherProcFacei.proci][is[otherProcFacei.proci] ++];
491 index = {facei, otherProcFacei.elementi, i};
493 if (!owner)
Swap(index[0], index[1]);
500 sort(indices[proci]);
507 void Foam::fvMeshStitcher::matchIndices
511 List<List<FixedList<label, 3>>>& indices,
512 const fvPatch& ncFvp,
513 const polyPatch& origPp,
521 List<List<FixedList<label, 3>>> indicesRef(indices.size());
528 indicesRef[proci].resize(patchSizes[proci]);
530 for (
label indexi = 0; indexi < patchSizes[proci]; ++ indexi)
532 FixedList<label, 3>& indexRef = indicesRef[proci][indexi];
534 const label patchFacei = indexi + patchOffsets[proci];
538 polyFacesBf[
patchi][patchFacei] - origPp.start(),
539 origFacesNbrBf[
patchi][patchFacei],
543 if (!owner)
Swap(indexRef[0], indexRef[1]);
549 label nCouplesRemoved = 0, nCouplesAdded = 0;
556 label refi = 0, i = 0;
560 refi < indicesRef[proci].size()
561 && i < indices[proci].size()
564 const FixedList<label, 3> index
566 indices[proci][i][0],
567 indices[proci][i][1],
571 FixedList<label, 3>& indexRef = indicesRef[proci][refi];
573 if (index < indexRef)
578 else if (index == indexRef)
580 indexRef[2] = indices[proci][i][2];
591 nCouplesRemoved +=
min(indices[proci].size() - i, 0);
592 nCouplesAdded +=
min(indicesRef[proci].size() - refi, 0);
597 reduce(nCouplesRemoved, sumOp<label>());
598 reduce(nCouplesAdded, sumOp<label>());
599 if ((nCouplesRemoved || nCouplesAdded) && owner)
601 Info<<
indent << nCouplesRemoved <<
'/' << nCouplesAdded
602 <<
" small couplings removed/added to " << ncFvp.
name()
607 Swap(indices, indicesRef);
611 void Foam::fvMeshStitcher::createCouplings
616 const tmp<surfaceVectorField::Boundary>& tOrigSfNbrBf,
617 const tmp<surfaceVectorField::Boundary>& tOrigCfNbrBf,
618 const List<List<FixedList<label, 3>>>& indices,
619 const List<DynamicList<couple>>& couples,
620 const polyPatch& origPp,
630 const label patchOffset = patchOffsets[proci];
634 forAll(indices[proci], indexi)
636 const label patchFacei = indexi + patchOffset;
638 const label origFacei = indices[proci][indexi][!owner];
639 const label i = indices[proci][indexi][2];
641 polyFacesBf[
patchi][patchFacei] = origFacei + origPp.start();
646 c = couples[origFacei][i];
655 small*origPp.faceAreas()[origFacei],
656 origPp.faceCentres()[origFacei]
660 small*tOrigSfNbrBf()[
patchi][patchFacei],
661 tOrigCfNbrBf()[
patchi][patchFacei]
671 SfBf[
patchi][patchFacei] =
c.nbr.area;
672 CfBf[
patchi][patchFacei] =
c.nbr.centre;
678 SfBf[origPp.index()][origFacei],
679 CfBf[origPp.index()][origFacei]
683 SfBf[origPp.index()][origFacei] = origP.area;
684 CfBf[origPp.index()][origFacei] = origP.centre;
692 void Foam::fvMeshStitcher::createErrorAndEdgeParts
696 List<part>& origEdgeParts,
697 const patchToPatches::intersection& intersection,
698 const polyPatch& origPp
702 forAll(intersection.srcErrorParts(), origFacei)
706 SfBf[origPp.index()][origFacei],
707 CfBf[origPp.index()][origFacei]
709 origP += intersection.srcErrorParts()[origFacei];
711 SfBf[origPp.index()][origFacei] = origP.area;
712 CfBf[origPp.index()][origFacei] = origP.centre;
716 forAll(intersection.srcEdgeParts(), origEdgei)
718 origEdgeParts[origEdgei] += intersection.srcEdgeParts()[origEdgei];
723 void Foam::fvMeshStitcher::intersectNonConformalCyclic
725 const nonConformalCyclicFvPatch& nccFvp,
729 const tmp<surfaceLabelField::Boundary>& tOrigFacesNbrBf,
730 const tmp<surfaceVectorField::Boundary>& tOrigSfNbrBf,
731 const tmp<surfaceVectorField::Boundary>& tOrigCfNbrBf,
732 List<part>& origEdgeParts
736 const polyPatch& origPp = nccFvp.origPatch().patch();
742 forAll(mesh_.boundary(), patchj)
744 const fvPatch& fvp = mesh_.boundary()[patchj];
746 if (isA<nonConformalProcessorCyclicFvPatch>(fvp))
748 const nonConformalProcessorCyclicFvPatch& ncpcFvp =
749 refCast<const nonConformalProcessorCyclicFvPatch>(fvp);
751 if (ncpcFvp.referPatchIndex() == nccFvp.index())
753 patchis[ncpcFvp.neighbProcNo()] = patchj;
759 const patchToPatches::intersection& intersection =
761 ? nccFvp.nonConformalCyclicPatch().intersection()
762 : nccFvp.nbrPatch().nonConformalCyclicPatch().intersection();
765 List<List<FixedList<label, 3>>> indices =
769 ? intersection.srcTgtProcFaces()
770 : intersection.tgtSrcProcFaces(),
775 if (tOrigFacesNbrBf.valid())
780 if (patchis[proci] != -1)
782 patchSizes[proci] = polyFacesBf[patchis[proci]].size();
805 const label patchSize = indices[proci].size();
807 if (
patchi == -1 && patchSize)
810 <<
"Intersection generated coupling through "
811 << nccFvp.name() <<
" between processes "
813 <<
" but a corresponding processor interface was not found"
819 polyFacesBf[
patchi].resize(patchSize);
820 SfBf[
patchi].resize(patchSize);
821 CfBf[
patchi].resize(patchSize);
835 nccFvp.owner() ? intersection.srcCouples() : intersection.tgtCouples(),
845 createErrorAndEdgeParts
857 void Foam::fvMeshStitcher::intersectNonConformalMappedWall
859 const nonConformalMappedWallFvPatch& ncmwFvp,
863 const tmp<surfaceLabelField::Boundary>& tOrigFacesNbrBf,
864 const tmp<surfaceVectorField::Boundary>& tOrigSfNbrBf,
865 const tmp<surfaceVectorField::Boundary>& tOrigCfNbrBf,
866 List<part>& origEdgeParts
870 const polyPatch& origPp = ncmwFvp.origPatch().patch();
873 const patchToPatches::intersection& intersection =
875 ? ncmwFvp.nonConformalMappedWallPatch().intersection()
876 : ncmwFvp.nbrPatch().nonConformalMappedWallPatch().intersection();
879 List<List<FixedList<label, 3>>> indices =
883 ? intersection.srcTgtProcFaces()
884 : intersection.tgtSrcProcFaces(),
889 nonConformalMappedPolyFacesFvsPatchLabelField& polyFacesPf =
890 refCast<nonConformalMappedPolyFacesFvsPatchLabelField>
892 polyFacesBf[ncmwFvp.index()]
896 if (tOrigFacesNbrBf.valid())
906 polyFacesPf.procOffsets(),
907 polyFacesPf.procSizes(),
918 polyFacesPf.procOffsets()[proci] =
count;
920 count += indices[proci].size();
923 polyFacesPf.resize(
count);
924 SfBf[polyFacesPf.patch().index()].resize(
count);
925 CfBf[polyFacesPf.patch().index()].resize(
count);
938 ncmwFvp.owner() ? intersection.srcCouples() : intersection.tgtCouples(),
941 polyFacesPf.procOffsets(),
948 createErrorAndEdgeParts
961 Foam::fvMeshStitcher::calculateOwnerOrigBoundaryEdgeParts
963 const List<List<part>>& patchEdgeParts
966 const polyBoundaryMesh& pbMesh = mesh_.boundaryMesh();
969 const labelList& ownerOrigBoundaryPointMeshPoint =
970 ncb.ownerOrigBoundaryPointMeshPoint();
971 const labelList& ownerOrigBoundaryEdgeMeshEdge =
972 ncb.ownerOrigBoundaryEdgeMeshEdge();
973 const edgeList& ownerOrigBoundaryEdges = ncb.ownerOrigBoundaryEdges();
974 const edgeList& ownerOrigBoundaryMeshEdges =
975 ncb.ownerOrigBoundaryMeshEdges();
978 labelList ownerOrigBoundaryEdgeNParts(ownerOrigBoundaryEdges.size(), 0);
979 List<part> ownerOrigBoundaryEdgeParts(ownerOrigBoundaryEdges.size());
982 if (patchEdgeParts[
patchi].empty())
continue;
984 const polyPatch& patch = pbMesh[
patchi];
986 const labelList& patchEdgeOwnerOrigBoundaryEdges =
987 ncb.patchEdgeOwnerOrigBoundaryEdges(
patchi);
991 const label ownerOrigBoundaryEdgei =
992 patchEdgeOwnerOrigBoundaryEdges[patchEdgei];
998 ownerOrigBoundaryMeshEdges[ownerOrigBoundaryEdgei]
1001 const part& pU = patchEdgeParts[
patchi][patchEdgei];
1002 const part
p =
sign > 0 ? pU : -pU;
1004 ownerOrigBoundaryEdgeNParts[ownerOrigBoundaryEdgei] ++;
1005 ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei] +=
p;
1010 const globalIndex globalOwnerOrigBoundaryPoints
1012 ownerOrigBoundaryPointMeshPoint.size()
1016 ownerOrigBoundaryPointMeshPoint.size()
1018 forAll(ownerOrigBoundaryPointIndices, ownerOrigBoundaryPointi)
1020 ownerOrigBoundaryPointIndices[ownerOrigBoundaryPointi] =
1021 globalOwnerOrigBoundaryPoints.toGlobal(ownerOrigBoundaryPointi);
1026 ownerOrigBoundaryPointMeshPoint,
1027 ownerOrigBoundaryPointIndices,
1035 forAll(ownerOrigBoundaryEdgeParts, ownerOrigBoundaryEdgei)
1037 const edge&
e = ownerOrigBoundaryEdges[ownerOrigBoundaryEdgei];
1041 ownerOrigBoundaryPointIndices[
e.start()]
1042 > ownerOrigBoundaryPointIndices[
e.end()])
1044 ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei] =
1045 - ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei];
1053 ownerOrigBoundaryEdgeMeshEdge,
1054 ownerOrigBoundaryEdgeNParts,
1061 ownerOrigBoundaryEdgeMeshEdge,
1062 ownerOrigBoundaryEdgeParts,
1067 const transformer& vt,
1078 fld[i].area = vt.transform(
fld[i].area);
1079 fld[i].centre = vt.transformPosition(
fld[i].centre);
1089 fld[i].area = vt.invTransform(
fld[i].area);
1090 fld[i].centre = vt.invTransformPosition(
fld[i].centre);
1096 forAll(ownerOrigBoundaryEdgeParts, ownerOrigBoundaryEdgei)
1098 if (ownerOrigBoundaryEdgeNParts[ownerOrigBoundaryEdgei] != 0)
1100 ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei].area /=
1101 ownerOrigBoundaryEdgeNParts[ownerOrigBoundaryEdgei];
1106 forAll(ownerOrigBoundaryEdgeParts, ownerOrigBoundaryEdgei)
1108 const edge&
e = ownerOrigBoundaryEdges[ownerOrigBoundaryEdgei];
1112 ownerOrigBoundaryPointIndices[
e.start()]
1113 > ownerOrigBoundaryPointIndices[
e.end()]
1116 ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei] =
1117 - ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei];
1121 return ownerOrigBoundaryEdgeParts;
1126 void Foam::fvMeshStitcher::applyOwnerOrigBoundaryEdgeParts
1130 const List<part>& ownerOrigBoundaryEdgeParts
1133 const polyBoundaryMesh& pbMesh = mesh_.boundaryMesh();
1136 const labelList ownerOrigPatchIndices = ncb.ownerOrigPatchIndices();
1137 const labelList& ownerOrigBoundaryEdgeMeshEdge =
1138 ncb.ownerOrigBoundaryEdgeMeshEdge();
1139 const edgeList& ownerOrigBoundaryMeshEdges =
1140 ncb.ownerOrigBoundaryMeshEdges();
1142 boolList patchIsOwnerOrig(pbMesh.size(),
false);
1143 UIndirectList<bool>(patchIsOwnerOrig, ownerOrigPatchIndices) =
true;
1146 labelList ownerOrigBoundaryEdgeNOrigFaces
1148 ownerOrigBoundaryEdgeMeshEdge.size(),
1151 forAll(ownerOrigBoundaryEdgeMeshEdge, ownerOrigBoundaryEdgei)
1153 const label meshEdgei =
1154 ownerOrigBoundaryEdgeMeshEdge[ownerOrigBoundaryEdgei];
1156 forAll(mesh_.edgeFaces()[meshEdgei], edgeFacei)
1158 const label facei = mesh_.edgeFaces()[meshEdgei][edgeFacei];
1161 mesh_.isInternalFace(facei)
1162 ? -1 : pbMesh.patchIndices()[facei - mesh_.nInternalFaces()];
1166 ownerOrigBoundaryEdgeNOrigFaces[ownerOrigBoundaryEdgei] ++;
1175 ownerOrigBoundaryEdgeMeshEdge,
1176 ownerOrigBoundaryEdgeNOrigFaces,
1182 tmp<surfaceLabelField> tChanged =
1188 forAll(ownerOrigBoundaryEdgeMeshEdge, ownerOrigBoundaryEdgei)
1190 const label meshEdgei =
1191 ownerOrigBoundaryEdgeMeshEdge[ownerOrigBoundaryEdgei];
1193 const part& ownerOrigBoundaryEdgeP =
1194 ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei];
1196 switch (ownerOrigBoundaryEdgeNOrigFaces[ownerOrigBoundaryEdgei])
1207 label origFacei = -1, origPatchi = -1, origPatchFacei = -1;
1208 forAll(mesh_.edgeFaces()[meshEdgei], edgeFacei)
1210 const label facei = mesh_.edgeFaces()[meshEdgei][edgeFacei];
1213 mesh_.isInternalFace(facei)
1215 : pbMesh.patchIndices()[facei - mesh_.nInternalFaces()];
1221 origPatchFacei = facei - pbMesh[
patchi].start();
1226 if (origFacei != -1)
1229 SfSf.boundaryFieldRef()[origPatchi][origPatchFacei];
1231 CfSf.boundaryFieldRef()[origPatchi][origPatchFacei];
1234 mesh_.faces()[origFacei].edgeDirection
1236 ownerOrigBoundaryMeshEdges[ownerOrigBoundaryEdgei]
1239 part
p(area, centre);
1242 ? ownerOrigBoundaryEdgeP
1243 : -ownerOrigBoundaryEdgeP;
1251 [origPatchi][origPatchFacei] =
label(1);
1262 forAll(mesh_.edgeFaces()[meshEdgei], edgeFacei)
1264 const label facei = mesh_.edgeFaces()[meshEdgei][edgeFacei];
1267 mesh_.isInternalFace(facei)
1269 : pbMesh.patchIndices()[facei - mesh_.nInternalFaces()];
1276 const label patchFacei =
1282 : SfSf.boundaryFieldRef()[
patchi][patchFacei];
1286 : CfSf.boundaryFieldRef()[
patchi][patchFacei];
1289 mesh_.faces()[facei].edgeDirection
1291 ownerOrigBoundaryMeshEdges[ownerOrigBoundaryEdgei]
1294 part
p(area, centre);
1297 ? ownerOrigBoundaryEdgeP
1298 : -ownerOrigBoundaryEdgeP;
1303 if (debug &&
patchi != -1)
1316 <<
"Boundary is not manifold"
1326 tChanged->boundaryField();
1331 changedBf.boundaryNeighbourField()
1334 bool synchronised =
true;
1341 if (!isA<processorFvPatch>(changedPf.patch()))
continue;
1343 forAll(changedPf, patchFacei)
1345 if (changedPf[patchFacei] != changedNbrPf[patchFacei])
1348 changedPf.patch().start() + patchFacei;
1351 <<
"Face not synchronised with centre at "
1352 << mesh_.faceCentres()[facei] <<
endl;
1354 synchronised =
false;
1368 void Foam::fvMeshStitcher::stabiliseOrigPatchFaces
1375 const labelList allOrigPatchIndices = ncb.allOrigPatchIndices();
1377 forAll(allOrigPatchIndices, i)
1379 const label origPatchi = allOrigPatchIndices[i];
1380 const polyPatch& origPp = mesh_.boundaryMesh()[origPatchi];
1382 forAll(origPp, origPatchFacei)
1384 const vector& a = origPp.faceAreas()[origPatchFacei];
1385 const point&
c = origPp.faceCentres()[origPatchFacei];
1387 vector& Sf = SfBf[origPatchi][origPatchFacei];
1388 point& Cf = CfBf[origPatchi][origPatchFacei];
1402 dSfHat = (Sf & Sf)*a - (Sf & a)*Sf;
1407 part SAndCf(Sf, Cf);
1409 SAndCf += part(small*
mag(a)*dSfHat,
c);
1418 void Foam::fvMeshStitcher::intersect
1424 const bool matchTopology
1427 const polyBoundaryMesh& pbMesh = mesh_.boundaryMesh();
1430 const labelList ownerOrigPatchIndices = ncb.ownerOrigPatchIndices();
1437 List<List<part>> patchEdgeParts(mesh_.boundary().size());
1438 forAll(ownerOrigPatchIndices, i)
1440 const label origPatchi = ownerOrigPatchIndices[i];
1442 patchEdgeParts[origPatchi].resize
1444 mesh_.boundaryMesh()[origPatchi].nEdges(),
1452 tmp<surfaceLabelField::Boundary> tOrigFacesNbrBf;
1453 tmp<surfaceVectorField::Boundary> tOrigSfNbrBf;
1454 tmp<surfaceVectorField::Boundary> tOrigCfNbrBf;
1471 if (!patchCoupleds[
patchi])
continue;
1473 const fvPatch& fvp = mesh_.boundary()[
patchi];
1475 if (isA<nonConformalCyclicFvPatch>(fvp))
1477 const nonConformalCyclicFvPatch& nccFvp =
1478 refCast<const nonConformalCyclicFvPatch>(fvp);
1480 intersectNonConformalCyclic
1489 patchEdgeParts[nccFvp.origPatchIndex()]
1492 else if (isA<nonConformalProcessorCyclicFvPatch>(fvp))
1494 else if (isA<nonConformalMappedWallFvPatch>(fvp))
1496 const nonConformalMappedWallFvPatch& ncmwFvp =
1497 refCast<const nonConformalMappedWallFvPatch>(fvp);
1499 intersectNonConformalMappedWall
1508 patchEdgeParts[ncmwFvp.origPatchIndex()]
1514 <<
"Coupled patch type not recognised"
1523 if (patchCoupleds[
patchi])
continue;
1525 const fvPatch& fvp = mesh_.boundary()[
patchi];
1527 if (!isA<nonConformalFvPatch>(fvp))
continue;
1529 const polyPatch& origPp =
1530 refCast<const nonConformalFvPatch>(fvp).origPatch().patch();
1535 small*origPp.faceAreas(),
1536 polyFacesBf[
patchi] - origPp.start()
1541 origPp.faceCentres(),
1542 polyFacesBf[
patchi] - origPp.start()
1547 List<part> ownerOrigBoundaryEdgeParts =
1548 calculateOwnerOrigBoundaryEdgeParts(patchEdgeParts);
1552 forAll(ownerOrigPatchIndices, i)
1554 const label origPatchi = ownerOrigPatchIndices[i];
1555 const polyPatch& origPatch = pbMesh[origPatchi];
1557 const labelList& origPatchEdgeOwnerOrigBoundaryEdges =
1558 ncb.patchEdgeOwnerOrigBoundaryEdges(origPatchi);
1560 forAll(patchEdgeParts[origPatchi], origPatchEdgei)
1562 const label ownerOrigBoundaryEdgei =
1563 origPatchEdgeOwnerOrigBoundaryEdges[origPatchEdgei];
1566 patchEdgeParts[origPatchi][origPatchEdgei];
1567 errorP -= ownerOrigBoundaryEdgeParts[ownerOrigBoundaryEdgei];
1569 forAll(origPatch.edgeFaces()[origPatchEdgei], patchEdgeFacei)
1571 const label patchFacei =
1572 origPatch.edgeFaces()[origPatchEdgei][patchEdgeFacei];
1576 SfBf[origPatchi][patchFacei],
1577 CfBf[origPatchi][patchFacei]
1581 SfBf[origPatchi][patchFacei] =
p.area;
1582 CfBf[origPatchi][patchFacei] =
p.centre;
1588 applyOwnerOrigBoundaryEdgeParts(SfSf, CfSf, ownerOrigBoundaryEdgeParts);
1591 stabiliseOrigPatchFaces(SfBf, CfBf);
1595 bool Foam::fvMeshStitcher::disconnectThis
1597 const bool changing,
1598 const bool geometric
1601 if (!stitches() || (changing && !dynamic()))
1609 ? this->patchCoupleds()
1612 if (
any(patchCoupleds))
1621 preConformVolFields();
1622 preConformSurfaceFields();
1629 for (
label i = 1; i < mesh_.phi().nOldTimes(
false); ++ i)
1631 phi.oldTimeRef(i) == mesh_.phi().oldTime(i);
1633 conformCorrectMeshPhi(phi);
1642 resizePatchFields<VolField>();
1643 resizePatchFields<SurfaceField>();
1646 mesh_.deltaCoeffs();
1648 if (
any(patchCoupleds) && geometric)
1651 Info<<
indent <<
"Cell min/avg/max openness = "
1656 for (
label i = 0; i <= mesh_.phi().nOldTimes(
false); ++ i)
1660 for (
label j = 0; j < i; ++ j)
Info<<
"old-";
1661 Info<< (i ?
"time " :
"") <<
"volume conservation error = "
1668 if (
any(patchCoupleds))
1674 const polyTopoChangeMap map(mesh_);
1676 meshObjects::topoChange<fvMesh>(mesh_, map);
1677 meshObjects::topoChange<lduMesh>(mesh_, map);
1679 const_cast<Time&
>(mesh_.time()).functionObjects().topoChange(map);
1685 bool Foam::fvMeshStitcher::connectThis
1687 const bool changing,
1688 const bool geometric,
1692 if (!stitches() || (changing && !dynamic()))
1698 IOobject polyFacesBfIO(
word::null, mesh_.pointsInstance(), mesh_);
1706 const bool matchTopology =
1707 load && loadPolyFacesBf(polyFacesBfIO, polyFacesBf);
1711 (geometric || !matchTopology)
1712 ? this->patchCoupleds()
1713 :
boolList(mesh_.boundary().size(),
false);
1718 if (!patchCoupleds[
patchi])
continue;
1720 const fvPatch& fvp = mesh_.boundary()[
patchi];
1722 if (isA<nonConformalCyclicFvPatch>(fvp))
1724 const nonConformalCyclicFvPatch& nccFvp =
1725 refCast<const nonConformalCyclicFvPatch>(fvp);
1729 nccFvp.nonConformalCyclicPatch().intersection();
1732 else if (isA<nonConformalProcessorCyclicFvPatch>(fvp))
1734 else if (isA<nonConformalMappedWallFvPatch>(fvp))
1736 const nonConformalMappedWallFvPatch& ncmwFvp =
1737 refCast<const nonConformalMappedWallFvPatch>(fvp);
1739 const nonConformalMappedWallFvPatch& ownerNcmwFvp =
1740 ncmwFvp.owner() ? ncmwFvp : ncmwFvp.nbrPatch();
1742 ownerNcmwFvp.nonConformalMappedWallPatch().intersection();
1747 <<
"Coupled patch type not recognised"
1752 if (
any(patchCoupleds))
1762 intersect(polyFacesBf, Sf, Cf, patchCoupleds, matchTopology);
1768 createNonConformalCorrectMeshPhiGeometry(polyFacesBf, Sf, Cf);
1775 for (
label i = 1; i <= mesh_.phi().nOldTimes(
false); ++ i)
1777 phi.oldTimeRef(i) == mesh_.phi().oldTime(i);
1779 unconformCorrectMeshPhi(polyFacesBf, Sf, Cf, phi);
1780 mesh_.unconform(polyFacesBf, Sf, Cf, phi);
1784 mesh_.unconform(polyFacesBf, Sf, Cf);
1790 mesh_.setPolyFacesBfInstance(polyFacesBfIO.instance());
1794 resizePatchFields<VolField>();
1795 resizePatchFields<SurfaceField>();
1801 postUnconformVolFields();
1802 postUnconformSurfaceFields();
1806 mesh_.deltaCoeffs();
1808 if (
any(patchCoupleds) && geometric)
1811 Info<<
indent <<
"Cell min/avg/max openness = "
1816 for (
label i = 0; i <= mesh_.phi().nOldTimes(
false); ++ i)
1820 for (
label j = 0; j < i; ++ j)
Info<<
"old-";
1821 Info<< (i ?
"time " :
"") <<
"volume conservation error = "
1834 mesh_.phi().boundaryField()
1836 mfe += mesh_.phi().boundaryField().boundaryNeighbourField();
1839 label nNonProcPatches = 0;
1842 const fvPatch& fvp = mesh_.boundary()[
patchi];
1844 if (!isA<processorFvPatch>(fvp))
1846 if (nNonProcPatches !=
patchi)
1849 <<
"Processor patches do not follow non-processor "
1860 scalarField sumMfe(nNonProcPatches, 0), nSumMfe(nNonProcPatches, 0);
1864 const fvPatch& fvp = mesh_.boundary()[
patchi];
1866 const label nccPatchi =
1867 isA<nonConformalCyclicFvPatch>(fvp)
1868 ? refCast<const nonConformalCyclicFvPatch>(fvp)
1870 : isA<nonConformalProcessorCyclicFvPatch>(fvp)
1871 ? refCast<const nonConformalProcessorCyclicFvPatch>(fvp)
1875 if (nccPatchi != -1)
1880 nSumMfe[nccPatchi] += mfe[
patchi].size();
1885 reduce(minMfe, ListOp<minOp<scalar>>());
1886 reduce(sumMfe, ListOp<minOp<scalar>>());
1887 reduce(nSumMfe, ListOp<minOp<scalar>>());
1888 reduce(maxMfe, ListOp<maxOp<scalar>>());
1893 const fvPatch& fvp = mesh_.boundary()[
patchi];
1897 isA<nonConformalCyclicFvPatch>(fvp)
1898 && refCast<const nonConformalCyclicFvPatch>(fvp).owner()
1903 <<
" min/avg/max mesh flux error = " << minMfe[
patchi]
1911 if (
any(patchCoupleds))
1917 const polyTopoChangeMap map(mesh_);
1919 meshObjects::topoChange<fvMesh>(mesh_, map);
1920 meshObjects::topoChange<lduMesh>(mesh_, map);
1922 const_cast<Time&
>(mesh_.time()).functionObjects().topoChange(map);
1928 void Foam::fvMeshStitcher::preConformVolFields()
1930 #define PreConformVolFields(Type, nullArg) \
1931 preConformVolFields<Type>();
1933 #undef PreConformVolFields
1937 void Foam::fvMeshStitcher::preConformSurfaceFields()
1939 #define PreConformSurfaceFields(Type, nullArg) \
1940 preConformSurfaceFields<Type>();
1942 #undef PreConformSurfaceFields
1946 void Foam::fvMeshStitcher::postUnconformVolFields()
1948 #define PostUnconformVolFields(Type, nullArg) \
1949 postUnconformVolFields<Type>();
1951 #undef PostUnconformVolFields
1954 const labelList origPatchIndices = ncb.allOrigPatchIndices();
1955 const labelList errorPatchIndices = ncb.allErrorPatchIndices();
1960 UPtrList<volVectorField> Us(mesh().fields<volVectorField>());
1965 forAll(errorPatchIndices, i)
1967 const label errorPatchi = errorPatchIndices[i];
1968 const label origPatchi = origPatchIndices[i];
1971 boundaryFieldRefNoUpdate(
U)[origPatchi];
1975 isA<movingWallVelocityFvPatchVectorField>(origUp)
1976 || isA<movingWallSlipVelocityFvPatchVectorField>(origUp)
1979 boundaryFieldRefNoUpdate(
U).set
1982 new movingWallSlipVelocityFvPatchVectorField
1992 #define PostUnconformEvaluateVolFields(Type, nullArg) \
1993 postUnconformEvaluateVolFields<Type>();
1995 #undef PostUnconformEvaluateVolFields
1999 void Foam::fvMeshStitcher::postUnconformSurfaceFields()
2001 #define PostUnconformSurfaceFields(Type, nullArg) \
2002 postUnconformSurfaceFields<Type>();
2004 #undef PostUnconformSurfaceFields
2021 if (isA<nonConformalFvPatch>(mesh_.boundary()[
patchi]))
2023 boundaryFieldRefNoUpdate(Uf)[
patchi] ==
2024 UfInterpolated.boundaryField()[
patchi];
2035 boolList result(mesh_.boundary().size(),
false);
2042 if (isA<nonConformalCyclicFvPatch>(fvp))
2051 if (isA<nonConformalProcessorCyclicFvPatch>(fvp))
2054 refCast<const nonConformalProcessorCyclicFvPatch>(fvp);
2063 if (isA<nonConformalMappedWallFvPatch>(fvp))
2066 refCast<const nonConformalMappedWallFvPatch>(fvp);
2087 bool result =
false;
2093 if (!isA<nonConformalFvPatch>(fvp))
continue;
2096 mesh_.magSf().boundaryField()[
patchi];
2099 refCast<const nonConformalFvPatch>(fvp).origPatch().patch();
2107 if (
max(magSfp/origMagSfp) > rootSmall)
2127 (small*
sqr(
cbrt(mesh_.V())))()
2138 <<
"Can only compute volume conservation error for this time, or "
2145 n == 0 ? mesh_.time().deltaT() : mesh_.time().deltaT0();
2160 regionPolyFacesBfIOs_(),
2161 regionPolyFacesBfs_()
2177 if (isA<nonConformalFvPatch>(mesh_.boundary()[
patchi]))
2193 if (regionMeshes[i].dynamic())
2205 const bool changing,
2206 const bool geometric
2212 return disconnectThis(changing, geometric);
2218 const bool changing,
2219 const bool geometric,
2225 return connectThis(changing, geometric, load);
2241 if (!regionMeshes[i]().stitcher().ready_)
2248 bool result =
false;
2251 if (regionMeshes[i]().stitcher().connectThis(changing, geometric, load))
2260 regionMeshes[i]().stitcher().ready_ =
false;
2269 if (mesh_.conformal() || geometric == this->geometric())
2287 ? this->patchCoupleds()
2288 :
boolList(mesh_.boundary().size(),
false);
2295 intersect(polyFacesBf, Sf, Cf, patchCoupleds,
true);
2298 mesh_.unconform(polyFacesBf, Sf, Cf);
2301 mesh_.deltaCoeffs();
2306 meshObjects::topoChange<fvMesh>(mesh_, map);
2307 meshObjects::topoChange<lduMesh>(mesh_, map);
2309 const_cast<Time&
>(mesh_.time()).functionObjects().topoChange(map);
#define forAll(list, i)
Loop across all elements in list.
static nonConformalBoundary & New(const word &name, const polyMesh &mesh)
Construct and return the named DemandDrivenMeshObject.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static const DimensionedField< Type, GeoMesh > & null()
Return a null DimensionedField.
Generic GeometricBoundaryField class.
Generic GeometricField class.
DimensionedField< Type, GeoMesh > Internal
Type of the internal field from which this GeometricField is derived.
GeometricBoundaryField< Type, PatchField, GeoMesh > Boundary
Type of the boundary field.
PatchField< Type > Patch
Type of the patch field of which the Boundary is composed.
static const GeometricField< Type, PatchField, GeoMesh > & null()
Return a null geometric field.
Boundary & boundaryFieldRef()
Return a reference to the boundary field.
static tmp< GeometricField< Type, PatchField, GeoMesh > > New(const word &name, const Internal &, const PtrList< PatchField< Type >> &, const HashPtrTable< Source > &=HashPtrTable< Source >())
Return a temporary field constructed from name,.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
virtual const fileName & name() const
Return the name of the stream.
const FieldType & oldTime() const
Return the old time field.
A list of faces which address into the list of points.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
static bool & parRun()
Is this a parallel run?
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
static Form uniform(const Cmpt &s)
Return a VectorSpace with all elements = s.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
static int compare(const edge &, const edge &)
Compare edges.
Mesh manipulator that uses the intersection provided by the cyclic non-conformal poly patches to crea...
bool disconnect(const bool changing, const bool geometric)
Disconnect the mesh by removing faces from the nonConformalCyclics.
bool connect(const bool changing, const bool geometric, const bool load)
Connect the mesh by adding faces into the nonConformalCyclics.
void reconnect(const bool geometric) const
Re-compute the connection. Topology is preserved. Permits a change.
bool geometric() const
Is the connection "geometric", or has the topology just been.
fvMeshStitcher(fvMesh &)
Construct from fvMesh.
virtual void topoChange(const polyTopoChangeMap &)
Update corresponding to the given map.
virtual void distribute(const polyDistributionMap &)
Update corresponding to the given distribution map.
bool stitches() const
Does this stitcher do anything?
fvMesh & mesh()
Return the fvMesh.
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
tmp< DimensionedField< scalar, volMesh > > openness() const
Return the non-dimensional cell openness for debugging/checking.
tmp< DimensionedField< scalar, volMesh > > volumeConservationError(const label n) const
Return the non-dimensional old-time volume conservation error.
bool dynamic() const
Is the set of connected region meshes dynamic?
boolList patchCoupleds() const
Determine which patches are coupled; i.e., for which.
virtual ~fvMeshStitcher()
Destructor.
Mesh data needed to do the Finite Volume discretisation.
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
const word & name() const
Return reference to name.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
virtual label size() const
Return size.
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
bool haveNbr() const
Is the neighbour available?
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
Class containing mesh-to-mesh mapping information.
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.
const scalarField::subField magFaceAreas() const
Return face area magnitudes.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
label referPatchIndex() const
Return the referring patch ID.
A class for managing temporary objects.
static const word null
An empty word.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
#define PreConformVolFields(Type, nullArg)
#define PostUnconformEvaluateVolFields(Type, nullArg)
#define PreConformSurfaceFields(Type, nullArg)
#define PostUnconformVolFields(Type, nullArg)
#define PostUnconformSurfaceFields(Type, nullArg)
Surface integrate surfaceField creating a volField. Surface sum a surfaceField creating a volField.
gmvFile<< "tracers "<< particles.size()<< nl;{ pointField positions(particles.size());label particlei=0;forAllConstIter(Cloud< passiveParticle >, particles, iter) { positions[particlei++]=iter().position(mesh);} for(i=0;i< pTraits< point >::nComponents;i++) { forAll(positions, particlei) { gmvFile<< component(positions[particlei], i)<< ' ';} gmvFile<< nl;}}forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const dimensionedScalar c
Speed of light in a vacuum.
tmp< VolField< Type > > surfaceSum(const SurfaceField< Type > &ssf)
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
void surfaceIntegrate(Field< Type > &ivf, const SurfaceField< Type > &ssf)
errorManipArg< error, int > exit(error &err, const int errNo=1)
List< word > wordList
A List of words.
VolField< vector > volVectorField
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
List< label > labelList
A List of labels.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
dimensionedScalar sign(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
const dimensionSet dimless
const word & regionName(const solver ®ion)
SurfaceField< scalar > surfaceScalarField
SurfaceField< label > surfaceLabelField
const dimensionSet dimLength
vectorField pointField
pointField is a vectorField.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
List< bool > boolList
Bool container classes.
List< scalar > scalarList
A List of scalars.
vector point
Point is a vector.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
Vector< scalar > vector
A scalar version of the templated Vector.
fvsPatchField< label > fvsPatchLabelField
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
edge meshEdge(const PrimitivePatch< FaceList, PointField > &p, const label edgei)
dimensionSet normalised(const dimensionSet &)
dimensioned< scalar > mag(const dimensioned< Type > &)
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Field< vector > vectorField
Specialisation of Field<T> for vector.
dimensionSet cmptMag(const dimensionSet &)
bool any(const boolList &l)
Type gAverage(const FieldField< Field, Type > &f)
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
HashSet wordHashSet
A HashSet with word keys.
FOR_ALL_FIELD_TYPES(makeFieldSourceTypedef)
const dimensionSet dimArea
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
dimensionedScalar cbrt(const dimensionedScalar &ds)
Type gMin(const FieldField< Field, Type > &f)
static const label labelMax
SurfaceField< vector > surfaceVectorField
dimensionSet perpendicular(const dimensionSet &)
Ostream & indent(Ostream &os)
Indent stream.
fvsPatchField< vector > fvsPatchVectorField
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Type gMax(const FieldField< Field, Type > &f)
const volVectorField & surfaceToVolVelocity(const surfaceVectorField &Uf)
Get the cell velocity field corresponding to a given face velocity, or a.
faceListList boundary(nPatches)
const Foam::wordList regionNames(args.optionFound("allRegions") ? runTime .controlDict().subDict("regionSolvers").toc() :wordList(1, args.optionFound("region") ? args.optionRead< word >("region") :polyMesh::defaultRegion))
Return the vol-field velocity corresponding to a given surface-field velocity.