54 bool Foam::combineFaces::convexFace
56 const scalar minConcaveCos,
66 scalar magEPrev =
mag(ePrev);
67 ePrev /= magEPrev + VSMALL;
73 scalar magE10 =
mag(e10);
74 e10 /= magE10 + VSMALL;
76 if (magEPrev > SMALL && magE10 > SMALL)
78 vector edgeNormal = ePrev ^ e10;
80 if ((edgeNormal & areaNorm) < 0)
83 if ((ePrev & e10) < minConcaveCos)
100 bool Foam::combineFaces::validFace
102 const scalar minConcaveCos,
109 if (edgeLoops.size() > 1)
114 bool isNonManifold = bigFace.checkPointManifold(
false,
nullptr);
121 face
f(getOutsideFace(bigFace));
123 return convexFace(minConcaveCos, bigFace.points(),
f);
127 void Foam::combineFaces::regioniseFaces
130 const bool mergeAcrossPatches,
133 Map<label>& faceRegion
136 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
138 for (
const label edgei : cEdges)
143 const vector&
a0 = mesh_.faceAreas()[f0];
144 const vector& a1 = mesh_.faceAreas()[f1];
167 if (!mergeAcrossPatches && (
p0 != p1))
175 if ((f0Normal & f1Normal) > minCos)
177 const label region0 = faceRegion.lookup(f0, -1);
178 const label region1 = faceRegion.lookup(f1, -1);
184 const label useRegion = faceRegion.size();
185 faceRegion.insert(f0, useRegion);
186 faceRegion.insert(f1, useRegion);
190 faceRegion.insert(f0, region1);
197 faceRegion.insert(f1, region0);
199 else if (region0 != region1)
202 const label useRegion =
min(region0, region1);
203 const label freeRegion =
max(region0, region1);
207 if (iter.val() == freeRegion)
209 iter.val() = useRegion;
220 bool Foam::combineFaces::faceNeighboursValid
223 const Map<label>& faceRegion
226 if (faceRegion.size() <= 1)
231 const cell& cFaces = mesh_.cells()[celli];
233 DynamicList<label> storage;
238 label facei = cFaces[cFacei];
240 if (!faceRegion.found(facei))
242 const labelList& fEdges = mesh_.faceEdges(facei, storage);
248 DynamicList<label> neighbourFaces(cFaces.size());
254 const label edgeI = fEdges[i];
257 const auto iter = faceRegion.cfind(nbrI);
261 neighbourRegions.insert(iter.val());
265 neighbourFaces.appendUniq(nbrI);
269 if ((neighbourFaces.size()+neighbourRegions.size()) < 3)
282 Foam::combineFaces::combineFaces
291 faceSetsVertices_(0),
292 savedPointLabels_(0),
301 const scalar featureCos,
302 const scalar minConcaveCos,
304 const bool mergeAcrossPatches
314 for (
const label celli : boundaryCells)
316 const cell& cFaces = mesh_.cells()[celli];
318 const labelList& cEdges = mesh_.cellEdges(celli,
set, storage);
337 if (faceNeighboursValid(celli, faceRegion))
344 const label facei = iter.key();
345 const label region = iter.val();
347 auto regionFnd = regionToFaces.find(region);
349 if (regionFnd.good())
352 label sz = setFaces.
size();
354 setFaces[sz] = facei;
358 regionToFaces.insert(region,
labelList(1, facei));
378 if (validFace(minConcaveCos, bigFace))
385 if (mergeAcrossPatches)
391 for (label i = 1; i < faceIDs.size(); ++i)
393 const scalar a2 =
magSqr(areas[faceIDs[i]]);
402 std::swap(faceIDs[0], faceIDs[maxIndex]);
406 allFaceSets.append(faceIDs);
412 return allFaceSets.shrink();
418 const scalar featureCos,
419 const scalar minConcaveCos,
420 const bool mergeAcrossPatches
423 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
432 if (!
patch.coupled())
436 boundaryCells.insert(mesh_.faceOwner()[
patch.start()+i]);
462 <<
"Multiple outside loops:" << fp.
edgeLoops()
470 const edge&
e = fp.
edges()[bEdgeI];
474 if (eFaces.size() != 1)
477 <<
"boundary edge:" << bEdgeI
480 <<
" on indirectPrimitivePatch has " << eFaces.
size()
494 bool edgeLoopConsistent =
false;
497 label index0 = outsideLoop.
find(
e[0]);
498 label index1 = outsideLoop.find(
e[1]);
500 if (index0 == -1 || index1 == -1)
503 <<
"Cannot find boundary edge:" <<
e 508 else if (index1 == outsideLoop.fcIndex(index0))
510 edgeLoopConsistent =
true;
512 else if (index0 == outsideLoop.fcIndex(index1))
514 edgeLoopConsistent =
false;
519 <<
"Cannot find boundary edge:" <<
e 522 <<
" on consecutive points in edgeLoop:" 529 const face& localF = fp.
localFaces()[eFaces[0]];
536 bool faceEdgeConsistent =
false;
545 <<
"Cannot find boundary edge:" <<
e 548 <<
" in face:" << eFaces[0]
549 <<
" edges:" << fp.
faceEdges()[eFaces[0]]
552 else if (localF[index] ==
e[0] && localF.nextLabel(index) ==
e[1])
554 faceEdgeConsistent =
true;
556 else if (localF[index] ==
e[1] && localF.nextLabel(index) ==
e[0])
558 faceEdgeConsistent =
false;
563 <<
"Cannot find boundary edge:" <<
e 566 <<
" in face:" << eFaces[0] <<
" verts:" << localF
574 if (faceEdgeConsistent != edgeLoopConsistent)
585 polyTopoChange& meshMod
590 masterFace_.setSize(faceSets.size());
591 faceSetsVertices_.setSize(faceSets.size());
594 const labelList& setFaces = faceSets[setI];
596 masterFace_[setI] = setFaces[0];
597 faceSetsVertices_[setI] = UIndirectList<face>
610 forAll(pointFaces, pointi)
612 nPointFaces[pointi] = pointFaces[pointi].size();
615 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
619 const labelList& setFaces = faceSets[setI];
631 <<
"Can only merge non-coupled boundary faces" 632 <<
" but found internal or coupled face:" 633 << setFaces[i] <<
" in set " << setI
653 if (edgeLoops.size() != 1)
656 <<
"Faces to-be-merged " << setFaces
657 <<
" do not form a single big face." <<
nl 667 label masterFacei = setFaces[0];
670 face outsideFace(getOutsideFace(bigFace));
672 label zoneID = mesh_.faceZones().whichZone(masterFacei);
674 bool zoneFlip =
false;
678 const faceZone& fZone = mesh_.faceZones()[zoneID];
680 zoneFlip = fZone.flipMap()[fZone.whichFace(masterFacei)];
683 label patchi = mesh_.boundaryMesh().whichPatch(masterFacei);
691 mesh_.faceOwner()[masterFacei],
705 for (label i = 1; i < setFaces.size(); i++)
707 meshMod.setAction(polyRemoveFace(setFaces[i]));
717 const face&
f = mesh_.faces()[setFaces[i]];
721 nPointFaces[
f[fp]]--;
727 nPointFaces[outsideFace[fp]]++;
744 forAll(nPointFaces, pointi)
746 if (nPointFaces[pointi] == 0)
748 meshMod.setAction(polyRemovePoint(pointi));
756 forAll(nPointFaces, pointi)
758 if (nPointFaces[pointi] == 0)
764 savedPointLabels_.setSize(
n);
765 savedPoints_.setSize(
n);
766 Map<label> meshToSaved(2*
n);
770 forAll(nPointFaces, pointi)
772 if (nPointFaces[pointi] == 0)
774 meshMod.setAction(polyRemovePoint(pointi));
776 savedPointLabels_[
n] = pointi;
777 savedPoints_[
n] = mesh_.points()[pointi];
779 meshToSaved.insert(pointi,
n);
785 forAll(faceSetsVertices_, setI)
787 faceList& setFaces = faceSetsVertices_[setI];
791 face&
f = setFaces[i];
795 label pointi =
f[fp];
797 if (nPointFaces[pointi] == 0)
799 f[fp] = -meshToSaved[pointi]-1;
817 forAll(faceSetsVertices_, setI)
819 faceList& faces = faceSetsVertices_[setI];
828 label pointi =
f[fp];
832 f[fp] = map.reversePointMap()[pointi];
837 <<
"In set " << setI <<
" at position " << i
838 <<
" with master face " 839 << masterFace_[setI] <<
nl 840 <<
"the points of the slave face " << faces[i]
841 <<
" don't exist anymore." 868 <<
"Can only call setUnrefinement if constructed with" 874 labelList addedPoints(savedPoints_.size(), -1);
881 if (masterFace_[setI] >= 0)
883 masterToSet.insert(masterFace_[setI], setI);
889 const label masterFacei = masterFaces[i];
891 const auto iter = masterToSet.cfind(masterFacei);
896 <<
"Master face " << masterFacei
897 <<
" is not the master of one of the merge sets" 898 <<
" or has already been merged" 902 const label setI = iter.val();
908 faceList& faces = faceSetsVertices_[setI];
913 <<
"Set " << setI <<
" with master face " << masterFacei
923 label pointi =
f[fp];
927 label localI = -pointi-1;
929 if (addedPoints[localI] == -1)
936 savedPoints_[localI],
945 savedPointLabels_[localI]
949 f[fp] = addedPoints[localI];
958 label own = mesh_.faceOwner()[masterFacei];
959 label zoneID = mesh_.faceZones().whichZone(masterFacei);
960 bool zoneFlip =
false;
963 const faceZone& fZone = mesh_.faceZones()[zoneID];
966 label patchi = mesh_.boundaryMesh().whichPatch(masterFacei);
968 if (mesh_.boundaryMesh()[patchi].coupled())
971 <<
"Master face " << masterFacei <<
" is on coupled patch " 972 << mesh_.boundaryMesh()[patchi].name()
995 restoredFaces.
insert(masterFacei, masterFacei);
998 for (label i = 1; i < faces.
size(); i++)
1019 restoredFaces.
insert(facei, masterFacei);
1023 faceSetsVertices_[setI].clear();
1024 masterFace_[setI] = -1;
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
void size(const label n)
Older name for setAddressableSize.
void setUnrefinement(const labelList &masterFaces, polyTopoChange &meshMod, Map< label > &restoredPoints, Map< label > &restoredFaces, Map< label > &restoredCells)
Play commands into polyTopoChange to reinsert original faces.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Class describing modification of a face.
A face is a list of labels corresponding to mesh vertices.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
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.
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
constexpr char nl
The newline '\n' character (0x0a)
bool empty() const noexcept
True if List is empty (ie, size() is zero)
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
label nInternalEdges() const
Number of internal edges.
Class containing data for point addition.
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field...
List< labelList > labelListList
List of labelList.
Type maxMagSqr(const UList< Type > &f1)
const labelListList & edgeLoops() const
Return list of closed loops of boundary vertices.
A face addition data class. A face can be inflated either from a point or from another face and can e...
const labelList & meshPoints() const
Return labelList of mesh points in patch.
#define forAll(list, i)
Loop across all elements in list.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
List< face > faceList
List of faces.
static face getOutsideFace(const indirectPrimitivePatch &)
Gets outside of patch as a face (in mesh point labels)
label size() const noexcept
The number of elements in table.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
A list of faces which address into the list of points.
vectorField pointField
pointField is a vectorField.
const dimensionedScalar e
Elementary charge.
void setSize(const label n)
Alias for resize()
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
#define forAllIters(container, iter)
Iterate across all elements in the container object.
const labelListList & edgeFaces() const
Return edge-face addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
void reverse(UList< T > &list, const label n)
Reverse the first n elements of the list.
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
errorManip< error > abort(error &err)
void setRefinement(const labelListList &, polyTopoChange &)
Play commands into polyTopoChange to combine faces. Gets.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
static bool constraintType(const word &patchType)
Return true if the given type is a constraint type.
A cell is defined as a list of faces with extra functionality.
Direct mesh changes based on v1.3 polyTopoChange syntax.
const polyBoundaryMesh & patches
const dimensionedScalar a0
Bohr radius: default SI units: [m].
const std::string patch
OpenFOAM patch number as a std::string.
const boolList & flipMap() const noexcept
Return face flip map.
const labelListList & faceEdges() const
Return face-edge addressing.
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
A subset of mesh faces organised as a primitive patch.
List< label > labelList
A List of labels.
void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
labelListList getMergeSets(const scalar featureCos, const scalar minConcaveCos, const labelHashSet &boundaryCells, const bool mergeAcrossPatches=false) const
Extract lists of all (non-coupled) boundary faces on selected.
const volScalarField & p0
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
forAllConstIters(mixture.phases(), phase)
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
static constexpr const zero Zero
Global zero (0)