54bool 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)
100bool 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);
127void 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;
220bool 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)
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.found())
352 label sz = setFaces.
size();
354 setFaces[sz] = 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
432 if (!patch.coupled())
436 boundaryCells.
insert(mesh_.faceOwner()[patch.start()+i]);
462 <<
"Multiple outside loops:" << fp.
edgeLoops()
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:"
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)
590 masterFace_.setSize(faceSets.
size());
591 faceSetsVertices_.setSize(faceSets.
size());
594 const labelList& setFaces = faceSets[setI];
596 masterFace_[setI] = setFaces[0];
610 forAll(pointFaces, pointi)
612 nPointFaces[pointi] = pointFaces[pointi].
size();
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;
683 label patchi = mesh_.boundaryMesh().whichPatch(masterFacei);
691 mesh_.faceOwner()[masterFacei],
705 for (label i = 1; i < setFaces.
size(); 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)
756 forAll(nPointFaces, pointi)
758 if (nPointFaces[pointi] == 0)
764 savedPointLabels_.setSize(
n);
765 savedPoints_.setSize(
n);
770 forAll(nPointFaces, pointi)
772 if (nPointFaces[pointi] == 0)
776 savedPointLabels_[
n] = pointi;
777 savedPoints_[
n] = mesh_.points()[pointi];
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];
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;
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;
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
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.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
label size() const noexcept
The number of elements in table.
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
A List with indirect addressing.
void setSize(const label n)
Alias for resize()
A HashTable to objects of type <T> with a label key.
A list of faces which address into the list of points.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
label nInternalEdges() const
Number of internal edges.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const labelListList & edgeLoops() const
Return list of closed loops of boundary vertices.
const labelListList & edgeFaces() const
Return edge-face addressing.
const labelListList & faceEdges() const
Return face-edge addressing.
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
A List with indirect addressing. Like IndirectList but does not store addressing.
T & first()
Return the first element of the list.
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
void size(const label n)
Older name for setAddressableSize.
T & last()
Return the last element of the list.
label fcIndex(const label i) const noexcept
A cell is defined as a list of faces with extra functionality.
Combines boundary faces into single face. The faces get the patch of the first face ('the master')
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.
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 setRefinement(const labelListList &, polyTopoChange &)
Play commands into polyTopoChange to combine faces. Gets.
static face getOutsideFace(const indirectPrimitivePatch &)
Gets outside of patch as a face (in mesh point labels)
virtual const word & constraintType() const
Return the constraint type this pointPatch implements.
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 face is a list of labels corresponding to mesh vertices.
label nextLabel(const label i) const
Next vertex on face.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
const labelList & reversePointMap() const
Reverse point map.
const labelList & reverseFaceMap() const
Reverse face map.
void updateMesh()
Update for new mesh topology.
A face addition data class. A face can be inflated either from a point or from another face and can e...
Class containing data for point addition.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
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.
Class containing data for face removal.
Class containing data for point removal.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
const volScalarField & p0
const polyBoundaryMesh & patches
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const labelIOList & zoneID
const dimensionedScalar a0
Bohr radius: default SI units: [m].
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
List< label > labelList
A List of labels.
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
void reverse(UList< T > &list, const label n)
Reverse the first n elements of the list.
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
Type maxMagSqr(const UList< Type > &f)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< labelList > labelListList
A List of labelList.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
errorManip< error > abort(error &err)
static constexpr const zero Zero
Global zero (0)
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a)
#define forAll(list, i)
Loop across all elements in list.
#define forAllIters(container, iter)
Iterate across all elements in the container object.
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.