extendedEdgeMeshTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2018 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "extendedEdgeMesh.H"
30 #include "ListListOps.H"
31 #include "unitConversion.H"
32 #include "bitSet.H"
33 #include "PatchTools.H"
34 #include "searchableBox.H"
35 
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 
38 template<class Patch>
40 (
41  const Patch& surf,
42  const labelUList& featureEdges,
43  const labelUList& regionFeatureEdges,// subset of featureEdges: inter-region
44  const labelUList& featurePoints
45 )
46 {
47  const pointField& sFeatLocalPts(surf.localPoints());
48  const edgeList& sFeatEds(surf.edges());
49  const labelListList edgeFaces = PatchTools::sortedEdgeFaces(surf);
50  const vectorField& faceNormals = surf.faceNormals();
51  const labelListList pointEdges = PatchTools::sortedPointEdges(surf);
52 
53  // Extract and reorder the data from surfaceFeatures
54 
55  // References to the surfaceFeatures data
56 
57  // Filling the extendedEdgeMesh with the raw geometrical data.
58 
59  label nFeatEds = featureEdges.size();
60  label nFeatPts = featurePoints.size();
61 
62  DynamicList<point> tmpPts;
63  edgeList eds(nFeatEds);
64  DynamicList<vector> norms;
65  vectorField edgeDirections(nFeatEds);
66  labelListList edgeNormals(nFeatEds);
67  labelListList normalDirections(nFeatEds);
68  DynamicList<label> regionEdges;
69 
70  // Keep track of the ordered feature point feature edges
71  labelListList featurePointFeatureEdges(nFeatPts);
72  forAll(featurePointFeatureEdges, pI)
73  {
74  featurePointFeatureEdges[pI] = pointEdges[featurePoints[pI]];
75  }
76 
77  // Mapping between old and new indices, there is entry in the map for each
78  // of surf.localPoints, -1 means that this point hasn't been used (yet),
79  // >= 0 corresponds to the index
80  labelList pointMap(sFeatLocalPts.size(), -1);
81 
82  // Mapping between surface edge index and its feature edge index. -1 if it
83  // is not a feature edge
84  labelList edgeMap(sFeatEds.size(), -1);
85 
86  // Noting when the normal of a face has been used so not to duplicate
87  labelList faceMap(surf.size(), -1);
88 
89  // Collecting the status of edge for subsequent sorting
90  List<edgeStatus> edStatus(nFeatEds, NONE);
91 
92  forAll(featurePoints, i)
93  {
94  label sFPI = featurePoints[i];
95 
96  tmpPts.append(sFeatLocalPts[sFPI]);
97 
98  pointMap[sFPI] = tmpPts.size() - 1;
99  }
100 
101  // All feature points have been added
102  nonFeatureStart_ = tmpPts.size();
103 
104  bitSet isRegionFeatureEdge(regionFeatureEdges);
105 
106  forAll(featureEdges, i)
107  {
108  label sFEI = featureEdges[i];
109 
110  edgeMap[sFEI] = i;
111 
112  const edge& fE = sFeatEds[sFEI];
113 
114  edgeDirections[i] = fE.vec(sFeatLocalPts);
115 
116  // Check to see if the points have been already used
117  if (pointMap[fE.start()] == -1)
118  {
119  tmpPts.append(sFeatLocalPts[fE.start()]);
120 
121  pointMap[fE.start()] = tmpPts.size() - 1;
122  }
123 
124  eds[i].start() = pointMap[fE.start()];
125 
126  if (pointMap[fE.end()] == -1)
127  {
128  tmpPts.append(sFeatLocalPts[fE.end()]);
129 
130  pointMap[fE.end()] = tmpPts.size() - 1;
131  }
132 
133  eds[i].end() = pointMap[fE.end()];
134 
135  // Pick up the faces adjacent to the feature edge
136  const labelList& eFaces = edgeFaces[sFEI];
137 
138  edgeNormals[i].setSize(eFaces.size());
139  normalDirections[i].setSize(eFaces.size());
140 
141  forAll(eFaces, j)
142  {
143  label eFI = eFaces[j];
144 
145  // Check to see if the points have been already used
146  if (faceMap[eFI] == -1)
147  {
148  norms.append(faceNormals[eFI]);
149 
150  faceMap[eFI] = norms.size() - 1;
151  }
152 
153  edgeNormals[i][j] = faceMap[eFI];
154 
155  const vector cross = (faceNormals[eFI] ^ edgeDirections[i]);
156  const vector fC0tofE0 =
157  surf[eFI].centre(surf.points())
158  - sFeatLocalPts[fE.start()];
159 
160  normalDirections[i][j] =
161  (
162  (
163  (cross/(mag(cross) + VSMALL))
164  & (fC0tofE0/(mag(fC0tofE0)+ VSMALL))
165  )
166  > 0.0
167  ? 1
168  : -1
169  );
170  }
171 
172  vector fC0tofC1(Zero);
173 
174  if (eFaces.size() == 2)
175  {
176  fC0tofC1 =
177  surf[eFaces[1]].centre(surf.points())
178  - surf[eFaces[0]].centre(surf.points());
179  }
180 
181  edStatus[i] = classifyEdge(norms, edgeNormals[i], fC0tofC1);
182 
183  if (isRegionFeatureEdge.test(i))
184  {
185  regionEdges.append(i);
186  }
187  }
188 
189  // Populate feature point feature edges
190  DynamicList<label> newFeatureEdges;
191 
192  forAll(featurePointFeatureEdges, pI)
193  {
194  const labelList& fpfe = featurePointFeatureEdges[pI];
195 
196  newFeatureEdges.setCapacity(fpfe.size());
197 
198  forAll(fpfe, eI)
199  {
200  const label oldEdgeIndex = fpfe[eI];
201 
202  const label newFeatureEdgeIndex = edgeMap[oldEdgeIndex];
203 
204  if (newFeatureEdgeIndex != -1)
205  {
206  newFeatureEdges.append(newFeatureEdgeIndex);
207  }
208  }
209 
210  featurePointFeatureEdges[pI].transfer(newFeatureEdges);
211  }
212 
213  // Reorder the edges by classification
214  List<DynamicList<label>> allEds(nEdgeTypes);
215 
216  DynamicList<label>& externalEds(allEds[0]);
217  DynamicList<label>& internalEds(allEds[1]);
218  DynamicList<label>& flatEds(allEds[2]);
219  DynamicList<label>& openEds(allEds[3]);
220  DynamicList<label>& multipleEds(allEds[4]);
221 
222  forAll(eds, i)
223  {
224  edgeStatus eStat = edStatus[i];
225 
226  if (eStat == EXTERNAL)
227  {
228  externalEds.append(i);
229  }
230  else if (eStat == INTERNAL)
231  {
232  internalEds.append(i);
233  }
234  else if (eStat == FLAT)
235  {
236  flatEds.append(i);
237  }
238  else if (eStat == OPEN)
239  {
240  openEds.append(i);
241  }
242  else if (eStat == MULTIPLE)
243  {
244  multipleEds.append(i);
245  }
246  else if (eStat == NONE)
247  {
249  << nl << "classifyEdge returned NONE on edge "
250  << eds[i]
251  << ". There is a problem with definition of this edge."
252  << nl << abort(FatalError);
253  }
254  }
255 
256  internalStart_ = externalEds.size();
257  flatStart_ = internalStart_ + internalEds.size();
258  openStart_ = flatStart_ + flatEds.size();
259  multipleStart_ = openStart_ + openEds.size();
260 
261  labelList edMap
262  (
263  ListListOps::combine<labelList>
264  (
265  allEds,
267  )
268  );
269 
270  edMap = invert(edMap.size(), edMap);
271 
272  inplaceReorder(edMap, eds);
273  inplaceReorder(edMap, edStatus);
274  inplaceReorder(edMap, edgeDirections);
275  inplaceReorder(edMap, edgeNormals);
276  inplaceReorder(edMap, normalDirections);
277  inplaceRenumber(edMap, regionEdges);
278 
279  forAll(featurePointFeatureEdges, pI)
280  {
281  inplaceRenumber(edMap, featurePointFeatureEdges[pI]);
282  }
283 
284  pointField pts(tmpPts);
285 
286  // Initialise the edgeMesh
287  edgeMesh::operator=(edgeMesh(pts, eds));
288 
289  // Initialise sorted edge related data
290  edgeDirections_ = edgeDirections/(mag(edgeDirections) + VSMALL);
291  edgeNormals_ = edgeNormals;
292  normalDirections_ = normalDirections;
293  regionEdges_ = regionEdges;
294 
295  // Normals are all now found and indirectly addressed, can also be stored
296  normals_ = vectorField(norms);
297 
298 
299  // Reorder the feature points by classification
300 
301  List<DynamicList<label>> allPts(3);
302 
303  DynamicList<label>& convexPts(allPts[0]);
304  DynamicList<label>& concavePts(allPts[1]);
305  DynamicList<label>& mixedPts(allPts[2]);
306 
307  for (label i = 0; i < nonFeatureStart_; i++)
308  {
309  pointStatus ptStatus = classifyFeaturePoint(i);
310 
311  if (ptStatus == CONVEX)
312  {
313  convexPts.append(i);
314  }
315  else if (ptStatus == CONCAVE)
316  {
317  concavePts.append(i);
318  }
319  else if (ptStatus == MIXED)
320  {
321  mixedPts.append(i);
322  }
323  else if (ptStatus == NONFEATURE)
324  {
326  << nl << "classifyFeaturePoint returned NONFEATURE on point at "
327  << points()[i]
328  << ". There is a problem with definition of this feature point."
329  << nl << abort(FatalError);
330  }
331  }
332 
333  concaveStart_ = convexPts.size();
334  mixedStart_ = concaveStart_ + concavePts.size();
335 
336  labelList ftPtMap
337  (
338  ListListOps::combine<labelList>
339  (
340  allPts,
342  )
343  );
344 
345  ftPtMap = invert(ftPtMap.size(), ftPtMap);
346 
347  // Creating the ptMap from the ftPtMap with identity values up to the size
348  // of pts to create an oldToNew map for inplaceReorder
349 
350  labelList ptMap(identity(pts.size()));
351 
352  forAll(ftPtMap, i)
353  {
354  ptMap[i] = ftPtMap[i];
355  }
356 
357  inplaceReorder(ptMap, pts);
358  inplaceReorder(ptMap, featurePointFeatureEdges);
359 
360  forAll(eds, i)
361  {
362  inplaceRenumber(ptMap, eds[i]);
363  }
364 
365  // Reinitialise the edgeMesh with sorted feature points and
366  // renumbered edges
367  {
368  edgeMesh newmesh(std::move(pts), std::move(eds));
369  edgeMesh::transfer(newmesh);
370  }
371 
372  // Generate the featurePointNormals
373 
374  labelListList featurePointNormals(nonFeatureStart_);
375 
376  for (label i = 0; i < nonFeatureStart_; i++)
377  {
378  DynamicList<label> tmpFtPtNorms;
379 
380  const labelList& ptEds = edgeMesh::pointEdges()[i];
381 
382  forAll(ptEds, j)
383  {
384  const labelList& ptEdNorms(edgeNormals[ptEds[j]]);
385 
386  forAll(ptEdNorms, k)
387  {
388  if (!tmpFtPtNorms.found(ptEdNorms[k]))
389  {
390  bool addNormal = true;
391 
392  // Check that the normal direction is unique at this feature
393  forAll(tmpFtPtNorms, q)
394  {
395  if
396  (
397  (normals_[ptEdNorms[k]] & normals_[tmpFtPtNorms[q]])
398  > cosNormalAngleTol_
399  )
400  {
401  // Parallel to an existing normal, do not add
402  addNormal = false;
403 
404  break;
405  }
406  }
407 
408  if (addNormal)
409  {
410  tmpFtPtNorms.append(ptEdNorms[k]);
411  }
412  }
413  }
414  }
415 
416  featurePointNormals[i] = tmpFtPtNorms;
417  }
418 
419  featurePointNormals_ = featurePointNormals;
420  featurePointEdges_ = featurePointFeatureEdges;
421 }
422 
423 
424 // ************************************************************************* //
Foam::extendedEdgeMesh::edgeStatus
edgeStatus
Definition: extendedEdgeMesh.H:104
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::accessOp
Definition: UList.H:668
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
PatchTools.H
Foam::DynamicList< point >
ListListOps.H
searchableBox.H
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
unitConversion.H
Unit conversion functions.
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:520
bitSet.H
Foam::invert
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition: ListOps.C:36
Foam::DynamicList::setCapacity
void setCapacity(const label len)
Alter the size of the underlying storage.
Definition: DynamicListI.H:303
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::edge::start
label start() const
Return start (first) vertex label.
Definition: edgeI.H:95
faceNormals
surfaceVectorField faceNormals(mesh.Sf()/mesh.magSf())
Foam::Field< vector >
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:456
Foam::Vector::centre
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:114
Foam::edge::end
label end() const
Return end (last/second) vertex label.
Definition: edgeI.H:106
extendedEdgeMesh.H
Foam::ListListOps::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &lists)
Inplace renumber the values (not the indices) of a list of lists.
Definition: ensightOutput.H:89
Foam::FatalError
error FatalError
Foam::extendedEdgeMesh::pointStatus
pointStatus
Definition: extendedEdgeMesh.H:94
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::edge::vec
vector vec(const UList< point > &pts) const
Return the vector (end - start)
Definition: edgeI.H:417
Foam::Vector< scalar >
Foam::List< edge >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::UList< label >
points
const pointField & points
Definition: gmvOutputHeader.H:1
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::extendedEdgeMesh::sortPointsAndEdges
void sortPointsAndEdges(const Patch &, const labelUList &featureEdges, const labelUList &regionFeatureEdges, const labelUList &feaurePoints)
Definition: extendedEdgeMeshTemplates.C:40
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::cross
void cross(FieldField< Field1, typename crossProduct< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:943
Foam::edgeMesh
Mesh data needed to do the Finite Area discretisation.
Definition: edgeFaMesh.H:53