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.push_uniq(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 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 within a list.
constexpr char nl
The newline '\n' character (0x0a)
bool empty() const noexcept
True if List is empty (ie, size() is zero)
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)
label find(const T &val) const
Find index of the first occurrence of the value.
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 within 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)