extendedEdgeMeshTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "extendedEdgeMesh.H"
27 #include "ListListOps.H"
28 #include "PackedBoolList.H"
29 #include "PatchTools.H"
30 #include "searchableBox.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<class Patch>
36 (
37  const Patch& surf,
38  const labelList& featureEdges,
39  const labelList& regionFeatureEdges,// subset of featureEdges: inter-region
40  const labelList& featurePoints
41 )
42 {
43  const pointField& sFeatLocalPts(surf.localPoints());
44  const edgeList& sFeatEds(surf.edges());
45  const labelListList edgeFaces = PatchTools::sortedEdgeFaces(surf);
46  const vectorField& faceNormals = surf.faceNormals();
48 
49  // Extract and reorder the data from surfaceFeatures
50 
51  // References to the surfaceFeatures data
52 
53  // Filling the extendedEdgeMesh with the raw geometrical data.
54 
55  label nFeatEds = featureEdges.size();
56  label nFeatPts = featurePoints.size();
57 
58  DynamicList<point> tmpPts;
59  edgeList eds(nFeatEds);
60  DynamicList<vector> norms;
61  vectorField edgeDirections(nFeatEds);
62  labelListList edgeNormals(nFeatEds);
65 
66  // Keep track of the ordered feature point feature edges
67  labelListList featurePointFeatureEdges(nFeatPts);
68  forAll(featurePointFeatureEdges, pI)
69  {
70  featurePointFeatureEdges[pI] = pointEdges[featurePoints[pI]];
71  }
72 
73  // Mapping between old and new indices, there is entry in the map for each
74  // of surf.localPoints, -1 means that this point hasn't been used (yet),
75  // >= 0 corresponds to the index
76  labelList pointMap(sFeatLocalPts.size(), -1);
77 
78  // Mapping between surface edge index and its feature edge index. -1 if it
79  // is not a feature edge
80  labelList edgeMap(sFeatEds.size(), -1);
81 
82  // Noting when the normal of a face has been used so not to duplicate
83  labelList faceMap(surf.size(), -1);
84 
85  // Collecting the status of edge for subsequent sorting
86  List<edgeStatus> edStatus(nFeatEds, NONE);
87 
88  forAll(featurePoints, i)
89  {
90  label sFPI = featurePoints[i];
91 
92  tmpPts.append(sFeatLocalPts[sFPI]);
93 
94  pointMap[sFPI] = tmpPts.size() - 1;
95  }
96 
97  // All feature points have been added
98  nonFeatureStart_ = tmpPts.size();
99 
100  PackedBoolList isRegionFeatureEdge(regionFeatureEdges);
101 
102  forAll(featureEdges, i)
103  {
104  label sFEI = featureEdges[i];
105 
106  edgeMap[sFEI] = i;
107 
108  const edge& fE = sFeatEds[sFEI];
109 
110  edgeDirections[i] = fE.vec(sFeatLocalPts);
111 
112  // Check to see if the points have been already used
113  if (pointMap[fE.start()] == -1)
114  {
115  tmpPts.append(sFeatLocalPts[fE.start()]);
116 
117  pointMap[fE.start()] = tmpPts.size() - 1;
118  }
119 
120  eds[i].start() = pointMap[fE.start()];
121 
122  if (pointMap[fE.end()] == -1)
123  {
124  tmpPts.append(sFeatLocalPts[fE.end()]);
125 
126  pointMap[fE.end()] = tmpPts.size() - 1;
127  }
128 
129  eds[i].end() = pointMap[fE.end()];
130 
131  // Pick up the faces adjacent to the feature edge
132  const labelList& eFaces = edgeFaces[sFEI];
133 
134  edgeNormals[i].setSize(eFaces.size());
135  normalDirections[i].setSize(eFaces.size());
136 
137  forAll(eFaces, j)
138  {
139  label eFI = eFaces[j];
140 
141  // Check to see if the points have been already used
142  if (faceMap[eFI] == -1)
143  {
144  norms.append(faceNormals[eFI]);
145 
146  faceMap[eFI] = norms.size() - 1;
147  }
148 
149  edgeNormals[i][j] = faceMap[eFI];
150 
151  const vector cross = (faceNormals[eFI] ^ edgeDirections[i]);
152  const vector fC0tofE0 =
153  surf[eFI].centre(surf.points())
154  - sFeatLocalPts[fE.start()];
155 
156  normalDirections[i][j] =
157  (
158  (
159  (cross/(mag(cross) + vSmall))
160  & (fC0tofE0/(mag(fC0tofE0)+ vSmall))
161  )
162  > 0.0
163  ? 1
164  : -1
165  );
166  }
167 
168  vector fC0tofC1(Zero);
169 
170  if (eFaces.size() == 2)
171  {
172  fC0tofC1 =
173  surf[eFaces[1]].centre(surf.points())
174  - surf[eFaces[0]].centre(surf.points());
175  }
176 
177  edStatus[i] = classifyEdge(norms, edgeNormals[i], fC0tofC1);
178 
179  if (isRegionFeatureEdge[i])
180  {
181  regionEdges.append(i);
182  }
183  }
184 
185  // Populate feature point feature edges
186  DynamicList<label> newFeatureEdges;
187 
188  forAll(featurePointFeatureEdges, pI)
189  {
190  const labelList& fpfe = featurePointFeatureEdges[pI];
191 
192  newFeatureEdges.setCapacity(fpfe.size());
193 
194  forAll(fpfe, eI)
195  {
196  const label oldEdgeIndex = fpfe[eI];
197 
198  const label newFeatureEdgeIndex = edgeMap[oldEdgeIndex];
199 
200  if (newFeatureEdgeIndex != -1)
201  {
202  newFeatureEdges.append(newFeatureEdgeIndex);
203  }
204  }
205 
206  featurePointFeatureEdges[pI].transfer(newFeatureEdges);
207  }
208 
209  // Reorder the edges by classification
211 
212  DynamicList<label>& externalEds(allEds[0]);
213  DynamicList<label>& internalEds(allEds[1]);
214  DynamicList<label>& flatEds(allEds[2]);
215  DynamicList<label>& openEds(allEds[3]);
216  DynamicList<label>& multipleEds(allEds[4]);
217 
218  forAll(eds, i)
219  {
220  edgeStatus eStat = edStatus[i];
221 
222  if (eStat == EXTERNAL)
223  {
224  externalEds.append(i);
225  }
226  else if (eStat == INTERNAL)
227  {
228  internalEds.append(i);
229  }
230  else if (eStat == FLAT)
231  {
232  flatEds.append(i);
233  }
234  else if (eStat == OPEN)
235  {
236  openEds.append(i);
237  }
238  else if (eStat == MULTIPLE)
239  {
240  multipleEds.append(i);
241  }
242  else if (eStat == NONE)
243  {
245  << nl << "classifyEdge returned NONE on edge "
246  << eds[i]
247  << ". There is a problem with definition of this edge."
248  << nl << abort(FatalError);
249  }
250  }
251 
252  internalStart_ = externalEds.size();
253  flatStart_ = internalStart_ + internalEds.size();
254  openStart_ = flatStart_ + flatEds.size();
255  multipleStart_ = openStart_ + openEds.size();
256 
257  labelList edMap
258  (
259  ListListOps::combine<labelList>
260  (
261  allEds,
263  )
264  );
265 
266  edMap = invert(edMap.size(), edMap);
267 
268  inplaceReorder(edMap, eds);
269  inplaceReorder(edMap, edStatus);
271  inplaceReorder(edMap, edgeNormals);
274 
275  forAll(featurePointFeatureEdges, pI)
276  {
277  inplaceRenumber(edMap, featurePointFeatureEdges[pI]);
278  }
279 
280  pointField pts(tmpPts);
281 
282  // Initialise the edgeMesh
283  edgeMesh::operator=(edgeMesh(pts, eds));
284 
285  // Initialise sorted edge related data
290 
291  // Normals are all now found and indirectly addressed, can also be stored
292  normals_ = vectorField(norms);
293 
294 
295  // Reorder the feature points by classification
296 
297  List<DynamicList<label>> allPts(3);
298 
299  DynamicList<label>& convexPts(allPts[0]);
300  DynamicList<label>& concavePts(allPts[1]);
301  DynamicList<label>& mixedPts(allPts[2]);
302 
303  for (label i = 0; i < nonFeatureStart_; i++)
304  {
305  pointStatus ptStatus = classifyFeaturePoint(i);
306 
307  if (ptStatus == CONVEX)
308  {
309  convexPts.append(i);
310  }
311  else if (ptStatus == CONCAVE)
312  {
313  concavePts.append(i);
314  }
315  else if (ptStatus == MIXED)
316  {
317  mixedPts.append(i);
318  }
319  else if (ptStatus == NONFEATURE)
320  {
322  << nl << "classifyFeaturePoint returned NONFEATURE on point at "
323  << points()[i]
324  << ". There is a problem with definition of this feature point."
325  << nl << abort(FatalError);
326  }
327  }
328 
329  concaveStart_ = convexPts.size();
330  mixedStart_ = concaveStart_ + concavePts.size();
331 
332  labelList ftPtMap
333  (
334  ListListOps::combine<labelList>
335  (
336  allPts,
338  )
339  );
340 
341  ftPtMap = invert(ftPtMap.size(), ftPtMap);
342 
343  // Creating the ptMap from the ftPtMap with identity values up to the size
344  // of pts to create an oldToNew map for inplaceReorder
345 
346  labelList ptMap(identityMap(pts.size()));
347 
348  forAll(ftPtMap, i)
349  {
350  ptMap[i] = ftPtMap[i];
351  }
352 
353  inplaceReorder(ptMap, pts);
354  inplaceReorder(ptMap, featurePointFeatureEdges);
355 
356  forAll(eds, i)
357  {
358  inplaceRenumber(ptMap, eds[i]);
359  }
360 
361  // Reinitialise the edgeMesh with sorted feature points and
362  // renumbered edges
363  reset(move(pts), move(eds));
364 
365  // Generate the featurePointNormals
366 
368 
369  for (label i = 0; i < nonFeatureStart_; i++)
370  {
371  DynamicList<label> tmpFtPtNorms;
372 
373  const labelList& ptEds = edgeMesh::pointEdges()[i];
374 
375  forAll(ptEds, j)
376  {
377  const labelList& ptEdNorms(edgeNormals[ptEds[j]]);
378 
379  forAll(ptEdNorms, k)
380  {
381  if (findIndex(tmpFtPtNorms, ptEdNorms[k]) == -1)
382  {
383  bool addNormal = true;
384 
385  // Check that the normal direction is unique at this feature
386  forAll(tmpFtPtNorms, q)
387  {
388  if
389  (
390  (normals_[ptEdNorms[k]] & normals_[tmpFtPtNorms[q]])
392  )
393  {
394  // Parallel to an existing normal, do not add
395  addNormal = false;
396 
397  break;
398  }
399  }
400 
401  if (addNormal)
402  {
403  tmpFtPtNorms.append(ptEdNorms[k]);
404  }
405  }
406  }
407  }
408 
409  featurePointNormals[i] = tmpFtPtNorms;
410  }
411 
413  featurePointEdges_ = featurePointFeatureEdges;
414 }
415 
416 
417 // ************************************************************************* //
label k
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:130
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
A bit-packed bool list.
static labelListList sortedPointEdges(const PrimitivePatch< FaceList, PointField > &)
Return point-edge addressing sorted by order around the point.
static labelListList sortedEdgeFaces(const PrimitivePatch< FaceList, PointField > &)
Return edge-face addressing sorted by angle around the edge.
iterator end()
Return an iterator to end traversing the UList.
Definition: UListI.H:224
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt >> &) const
Return *this (used for point which is a typedef to Vector<scalar>.
Definition: VectorI.H:116
void operator=(const edgeMesh &)
Definition: edgeMeshI.H:86
const labelListList & pointEdges() const
Return edges.
Definition: edgeMeshI.H:74
virtual void reset(pointField &&points, edgeList &&edges)
Reset primitive data (points, edges)
Definition: edgeMesh.C:174
edgeMesh()
Construct null.
Definition: edgeMesh.C:122
const pointField & points() const
Return points.
Definition: edgeMeshI.H:62
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
label end() const
Return end vertex label.
Definition: edgeI.H:92
vector vec(const pointField &) const
Return the vector (end - start)
Definition: edgeI.H:175
label start() const
Return start vertex label.
Definition: edgeI.H:81
labelList regionEdges_
Feature edges which are on the boundary between regions.
const labelListList & normalDirections() const
labelListList edgeNormals_
Indices of the normals that are adjacent to the feature edges.
static label nEdgeTypes
Number of possible feature edge types (i.e. number of slices)
void sortPointsAndEdges(const Patch &, const labelList &featureEdges, const labelList &regionFeatureEdges, const labelList &feaurePoints)
const vectorField & edgeDirections() const
Return the edgeDirection vectors.
pointStatus classifyFeaturePoint(label ptI) const
Classify the type of feature point. Requires valid stored member.
label nonFeatureStart_
Index of the start of the non-feature points.
const labelList & regionEdges() const
Return the feature edges which are on the boundary between.
const labelListList & edgeNormals() const
Return the indices of the normals that are adjacent to the.
vectorField edgeDirections_
Flat and open edges require the direction of the edge.
label openStart_
Index of the start of the open feature edges.
labelListList featurePointEdges_
Indices of feature edges attached to feature points. The edges are.
label flatStart_
Index of the start of the flat feature edges.
static edgeStatus classifyEdge(const List< vector > &norms, const labelList &edNorms, const vector &fC0tofC1)
Classify the type of feature edge. Requires face centre 0 to face.
label internalStart_
Index of the start of the internal feature edges.
vectorField normals_
Normals of the features, to be referred to by index by both feature.
label mixedStart_
Index of the start of the mixed type feature points.
labelListList normalDirections_
Starting directions for the edges.
const labelListList & featurePointNormals() const
Return the indices of the normals that are adjacent to the.
label multipleStart_
Index of the start of the multiply-connected feature edges.
labelListList featurePointNormals_
Indices of the normals that are adjacent to the feature points.
static scalar cosNormalAngleTol_
Angular closeness tolerance for treating normals as the same.
label concaveStart_
Index of the start of the concave feature points.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
static const zero Zero
Definition: zero.H:97
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
labelList invert(const label len, const labelUList &)
Invert one-to-one map. Unmapped elements will be -1.
Definition: ListOps.C:37
errorManip< error > abort(error &err)
Definition: errorManip.H:131
dimensioned< scalar > mag(const dimensioned< Type > &)
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
Field< vector > vectorField
Specialisation of Field<T> for vector.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
void cross(FieldField< Field1, typename crossProduct< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
static const char nl
Definition: Ostream.H:266
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.