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,
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
226 if (faceRegion.size() <= 1)
231 const cell& cFaces = mesh_.cells()[celli];
238 label facei = cFaces[cFacei];
240 if (!faceRegion.found(facei))
242 const labelList& fEdges = mesh_.faceEdges(facei, storage);
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)
282Foam::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);
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()
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:"
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();
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++)
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];
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);
877 Map<label> masterToSet(masterFace_.size());
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];
964 zoneFlip = fZone.flipMap()[fZone.whichFace(masterFacei)];
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.
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.
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
label size() const noexcept
The number of elements in table.
A List with indirect addressing.
void setSize(label n)
Alias for resize().
A HashTable to objects of type <T> with a label key.
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.
bool empty() const noexcept
True if List is empty (ie, size() is zero).
void size(const label n)
Older name for setAddressableSize.
label find(const T &val) const
Find index of the first occurrence of the value.
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
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.
void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
static face getOutsideFace(const indirectPrimitivePatch &)
Gets outside of patch as a face (in mesh point labels).
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
A subset of mesh faces organised as a primitive patch.
label whichFace(const label meshFaceID) const
The local index of the given mesh face, -1 if not in the zone.
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 & reverseFaceMap() const noexcept
Reverse face map.
const labelList & reversePointMap() const noexcept
Reverse point map.
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 registered IO, a reference to the associated polyMesh,...
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
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.
static bool constraintType(const word &patchType)
Return true if the given type is a constraint type.
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
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const dimensionedScalar a0
Bohr radius: default SI units: [m].
Namespace for handling debugging switches.
const std::string patch
OpenFOAM patch number as a std::string.
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 within a list.
List< labelList > labelListList
List of labelList.
List< label > labelList
A List of labels.
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
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 within a list.
List< face > faceList
List of faces.
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)
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
errorManip< error > abort(error &err)
Field< vector > vectorField
Specialisation of Field<T> for vector.
static constexpr const zero Zero
Global zero (0).
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
Type maxMagSqr(const UList< Type > &f1)
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.