51 bool Foam::combineFaces::convexFace
53 const scalar minConcaveCos,
59 const vector n = f.normal(points);
62 vector ePrev(points[f.first()] - points[f.last()]);
63 scalar magEPrev =
mag(ePrev);
64 ePrev /= magEPrev + vSmall;
69 label fp1 = f.fcIndex(fp0);
72 vector e10(points[f[fp1]] - points[f[fp0]]);
73 scalar magE10 =
mag(e10);
74 e10 /= magE10 + vSmall;
76 if (magEPrev > small && magE10 > small)
78 vector edgeNormal = ePrev ^ e10;
80 if ((edgeNormal & n) < 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
133 Map<label>& faceRegion
136 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
140 label edgeI = cEdges[i];
145 label p0 = patches.whichPatch(f0);
146 label p1 = patches.whichPatch(f1);
155 && !patches[p0].coupled()
156 && patchIDs.found(p0)
159 vector f0Normal = mesh_.faceAreas()[f0];
160 f0Normal /=
mag(f0Normal);
161 vector f1Normal = mesh_.faceAreas()[
f1];
162 f1Normal /=
mag(f1Normal);
164 if ((f0Normal&f1Normal) > minCos)
169 if (f0Fnd != faceRegion.end())
177 if (f1Fnd != faceRegion.end())
186 label useRegion = faceRegion.size();
187 faceRegion.insert(f0, useRegion);
188 faceRegion.insert(f1, useRegion);
192 faceRegion.insert(f0, region1);
199 faceRegion.insert(f1, region0);
201 else if (region0 != region1)
204 label useRegion =
min(region0, region1);
205 label freeRegion =
max(region0, region1);
209 if (iter() == freeRegion)
222 bool Foam::combineFaces::faceNeighboursValid
225 const Map<label>& faceRegion
228 if (faceRegion.size() <= 1)
233 const cell& cFaces = mesh_.cells()[celli];
235 DynamicList<label> storage;
240 label facei = cFaces[cFacei];
242 if (!faceRegion.found(facei))
244 const labelList& fEdges = mesh_.faceEdges(facei, storage);
250 DynamicList<label> neighbourFaces(cFaces.size());
256 label edgeI = fEdges[i];
261 if (iter == faceRegion.end())
263 if (
findIndex(neighbourFaces, nbrI) == -1)
265 neighbourFaces.append(nbrI);
270 neighbourRegions.insert(iter());
274 if ((neighbourFaces.size()+neighbourRegions.size()) < 3)
296 faceSetsVertices_(0),
297 savedPointLabels_(0),
306 const scalar featureCos,
307 const scalar minConcaveCos,
320 label celli = iter.key();
322 const cell& cFaces = mesh_.cells()[celli];
324 const labelList& cEdges = mesh_.cellEdges(celli, storage);
328 regioniseFaces(featureCos, patchIDs, celli, cEdges, faceRegion);
336 if (faceNeighboursValid(celli, faceRegion))
343 label facei = iter.key();
344 label region = iter();
348 if (regionFnd != regionToFaces.end())
353 setFaces[sz] = facei;
357 regionToFaces.insert(region,
labelList(1, facei));
377 if (validFace(minConcaveCos, bigFace))
379 allFaceSets.append(iter());
385 return allFaceSets.shrink();
391 const scalar featureCos,
392 const scalar minConcaveCos,
399 labelHashSet boundaryCells(mesh_.nFaces()-mesh_.nInternalFaces());
403 const polyPatch& patch = patches[iter.key()];
409 boundaryCells.
insert(mesh_.faceOwner()[patch.
start()+i]);
414 return getMergeSets(featureCos, minConcaveCos, patchIDs, boundaryCells);
421 const scalar featureCos,
422 const scalar minConcaveCos
427 return getMergeSets(featureCos, minConcaveCos, patchIDs);
442 <<
"Multiple outside loops:" << fp.
edgeLoops()
454 if (eFaces.
size() != 1)
457 <<
"boundary edge:" << bEdgeI
460 <<
" on indirectPrimitivePatch has " << eFaces.
size()
474 bool edgeLoopConsistent =
false;
480 if (index0 == -1 || index1 == -1)
483 <<
"Cannot find boundary edge:" << e
488 else if (index1 == outsideLoop.
fcIndex(index0))
490 edgeLoopConsistent =
true;
492 else if (index0 == outsideLoop.
fcIndex(index1))
494 edgeLoopConsistent =
false;
499 <<
"Cannot find boundary edge:" << e
502 <<
" on consecutive points in edgeLoop:" 516 bool faceEdgeConsistent =
false;
525 <<
"Cannot find boundary edge:" << e
528 <<
" in face:" << eFaces[0]
529 <<
" edges:" << fp.
faceEdges()[eFaces[0]]
532 else if (localF[index] == e[0] && localF.
nextLabel(index) == e[1])
534 faceEdgeConsistent =
true;
536 else if (localF[index] == e[1] && localF.
nextLabel(index) == e[0])
538 faceEdgeConsistent =
false;
543 <<
"Cannot find boundary edge:" << e
546 <<
" in face:" << eFaces[0] <<
" verts:" << localF
554 if (faceEdgeConsistent != edgeLoopConsistent)
570 masterFace_.setSize(faceSets.
size());
571 faceSetsVertices_.setSize(faceSets.
size());
574 const labelList& setFaces = faceSets[setI];
576 masterFace_[setI] = setFaces[0];
586 labelList nPointFaces(mesh_.nPoints(), 0);
590 forAll(pointFaces, pointi)
592 nPointFaces[pointi] = pointFaces[pointi].
size();
599 const labelList& setFaces = faceSets[setI];
608 if (patchi == -1 || patches[patchi].coupled())
611 <<
"Can only merge non-coupled boundary faces" 612 <<
" but found internal or coupled face:" 613 << setFaces[i] <<
" in set " << setI
633 if (edgeLoops.size() != 1)
636 <<
"Faces to-be-merged " << setFaces
637 <<
" do not form a single big face." <<
nl 647 label masterFacei = setFaces[0];
650 face outsideFace(getOutsideFace(bigFace));
652 label zoneID = mesh_.faceZones().whichZone(masterFacei);
654 bool zoneFlip =
false;
658 const faceZone& fZone = mesh_.faceZones()[zoneID];
663 label patchi = mesh_.boundaryMesh().whichPatch(masterFacei);
671 mesh_.faceOwner()[masterFacei],
685 for (
label i = 1; i < setFaces.
size(); i++)
697 const face& f = mesh_.faces()[setFaces[i]];
701 nPointFaces[f[fp]]--;
707 nPointFaces[outsideFace[fp]]++;
724 forAll(nPointFaces, pointi)
726 if (nPointFaces[pointi] == 0)
736 forAll(nPointFaces, pointi)
738 if (nPointFaces[pointi] == 0)
744 savedPointLabels_.setSize(n);
745 savedPoints_.setSize(n);
750 forAll(nPointFaces, pointi)
752 if (nPointFaces[pointi] == 0)
756 savedPointLabels_[
n] = pointi;
757 savedPoints_[
n] = mesh_.points()[pointi];
759 meshToSaved.
insert(pointi, n);
765 forAll(faceSetsVertices_, setI)
767 faceList& setFaces = faceSetsVertices_[setI];
771 face& f = setFaces[i];
775 label pointi = f[fp];
777 if (nPointFaces[pointi] == 0)
779 f[fp] = -meshToSaved[pointi]-1;
797 forAll(faceSetsVertices_, setI)
799 faceList& faces = faceSetsVertices_[setI];
808 label pointi = f[fp];
817 <<
"In set " << setI <<
" at position " << i
818 <<
" with master face " 819 << masterFace_[setI] <<
nl 820 <<
"the points of the slave face " << faces[i]
821 <<
" don't exist anymore." 848 <<
"Can only call setUnrefinement if constructed with" 854 labelList addedPoints(savedPoints_.size(), -1);
861 if (masterFace_[setI] >= 0)
863 masterToSet.insert(masterFace_[setI], setI);
869 label masterFacei = masterFaces[i];
873 if (iter == masterToSet.
end())
876 <<
"Master face " << masterFacei
877 <<
" is not the master of one of the merge sets" 878 <<
" or has already been merged" 888 faceList& faces = faceSetsVertices_[setI];
893 <<
"Set " << setI <<
" with master face " << masterFacei
903 label pointi = f[fp];
907 label localI = -pointi-1;
909 if (addedPoints[localI] == -1)
916 savedPoints_[localI],
925 savedPointLabels_[localI]
929 f[fp] = addedPoints[localI];
938 label own = mesh_.faceOwner()[masterFacei];
939 label zoneID = mesh_.faceZones().whichZone(masterFacei);
940 bool zoneFlip =
false;
943 const faceZone& fZone = mesh_.faceZones()[zoneID];
946 label patchi = mesh_.boundaryMesh().whichPatch(masterFacei);
948 if (mesh_.boundaryMesh()[
patchi].coupled())
951 <<
"Master face " << masterFacei <<
" is on coupled patch " 952 << mesh_.boundaryMesh()[
patchi].name()
975 restoredFaces.
insert(masterFacei, masterFacei);
999 restoredFaces.
insert(facei, masterFacei);
1003 faceSetsVertices_[setI].clear();
1004 masterFace_[setI] = -1;
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
Class containing data for face removal.
List< labelList > labelListList
A List of labelList.
#define forAll(list, i)
Loop across all elements in list.
bool empty() const
Return true if the UList is empty (ie, size() is zero)
const labelList & reversePointMap() const
Reverse point map.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
void setUnrefinement(const labelList &masterFaces, polyTopoChange &meshMod, Map< label > &restoredPoints, Map< label > &restoredFaces, Map< label > &restoredCells)
Play commands into polyTopoChange to reinsert original faces.
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Class describing modification of a face.
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
A face is a list of labels corresponding to mesh vertices.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
void size(const label)
Override size to be inconsistent with allocated storage.
const boolList & flipMap() const
Return face flip map.
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
label nextLabel(const label i) const
Next vertex on face.
label nInternalEdges() const
Number of internal edges.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
HashTable< label, label, Hash< label > >::const_iterator const_iterator
Class containing data for point addition.
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Vector< scalar > vector
A scalar version of the templated Vector.
combineFaces(const polyMesh &mesh, const bool undoable=false)
Construct from mesh.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
bool insert(const Key &key)
Insert a new entry.
const labelListList & edgeLoops() const
Return list of closed loops of boundary vertices.
label size() const
Return number of elements in table.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
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. They are constructed.
labelListList getMergeSets(const scalar featureCos, const scalar minConcaveCos, const labelHashSet &patchIDs, const labelHashSet &boundaryCells) const
Extract lists of all (non-coupled) boundary faces on selected.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
An STL-conforming iterator.
static face getOutsideFace(const indirectPrimitivePatch &)
Gets outside of patch as a face (in mesh point labels)
A list of faces which address into the list of points.
vectorField pointField
pointField is a vectorField.
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
label size() const
Return the number of elements in the list.
const labelListList & edgeFaces() const
Return edge-face addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
List< label > labelList
A List of labels.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
errorManip< error > abort(error &err)
void setRefinement(const labelListList &, polyTopoChange &)
Play commands into polyTopoChange to combine faces. Gets.
void reverse(UList< T > &, const label n)
defineTypeNameAndDebug(combustionModel, 0)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
void setSize(const label)
Reset size of List.
A cell is defined as a list of faces with extra functionality.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
A List with indirect addressing.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label start() const
Return start label of this patch in the polyMesh face list.
const labelListList & faceEdges() const
Return face-edge addressing.
dimensioned< scalar > mag(const dimensioned< Type > &)
const doubleScalar e
Elementary charge.
Mesh consisting of general polyhedral cells.
A subset of mesh faces organised as a primitive patch.
A patch is a list of labels that address the faces in the global face list.
void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
A List with indirect addressing.
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Class containing data for point removal.
const labelList & reverseFaceMap() const
Reverse face map.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.