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 | Copyright (C) 2011-2013 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 "unitConversion.H"
29 #include "PackedBoolList.H"
30 #include "PatchTools.H"
31 #include "searchableBox.H"
32 
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 
35 template<class Patch>
37 (
38  const Patch& surf,
39  const labelList& featureEdges,
40  const labelList& regionFeatureEdges,// subset of featureEdges: inter-region
41  const labelList& featurePoints
42 )
43 {
44  const pointField& sFeatLocalPts(surf.localPoints());
45  const edgeList& sFeatEds(surf.edges());
46  const labelListList edgeFaces = PatchTools::sortedEdgeFaces(surf);
47  const vectorField& faceNormals = surf.faceNormals();
48  const labelListList pointEdges = PatchTools::sortedPointEdges(surf);
49 
50  // Extract and reorder the data from surfaceFeatures
51 
52  // References to the surfaceFeatures data
53 
54  // Filling the extendedEdgeMesh with the raw geometrical data.
55 
56  label nFeatEds = featureEdges.size();
57  label nFeatPts = featurePoints.size();
58 
59  DynamicList<point> tmpPts;
60  edgeList eds(nFeatEds);
61  DynamicList<vector> norms;
62  vectorField edgeDirections(nFeatEds);
63  labelListList edgeNormals(nFeatEds);
64  labelListList normalDirections(nFeatEds);
65  DynamicList<label> regionEdges;
66 
67  // Keep track of the ordered feature point feature edges
68  labelListList featurePointFeatureEdges(nFeatPts);
69  forAll(featurePointFeatureEdges, pI)
70  {
71  featurePointFeatureEdges[pI] = pointEdges[featurePoints[pI]];
72  }
73 
74  // Mapping between old and new indices, there is entry in the map for each
75  // of surf.localPoints, -1 means that this point hasn't been used (yet),
76  // >= 0 corresponds to the index
77  labelList pointMap(sFeatLocalPts.size(), -1);
78 
79  // Mapping between surface edge index and its feature edge index. -1 if it
80  // is not a feature edge
81  labelList edgeMap(sFeatEds.size(), -1);
82 
83  // Noting when the normal of a face has been used so not to duplicate
84  labelList faceMap(surf.size(), -1);
85 
86  // Collecting the status of edge for subsequent sorting
87  List<edgeStatus> edStatus(nFeatEds, NONE);
88 
89  forAll(featurePoints, i)
90  {
91  label sFPI = featurePoints[i];
92 
93  tmpPts.append(sFeatLocalPts[sFPI]);
94 
95  pointMap[sFPI] = tmpPts.size() - 1;
96  }
97 
98  // All feature points have been added
99  nonFeatureStart_ = tmpPts.size();
100 
101  PackedBoolList isRegionFeatureEdge(regionFeatureEdges);
102 
103  forAll(featureEdges, i)
104  {
105  label sFEI = featureEdges[i];
106 
107  edgeMap[sFEI] = i;
108 
109  const edge& fE = sFeatEds[sFEI];
110 
111  edgeDirections[i] = fE.vec(sFeatLocalPts);
112 
113  // Check to see if the points have been already used
114  if (pointMap[fE.start()] == -1)
115  {
116  tmpPts.append(sFeatLocalPts[fE.start()]);
117 
118  pointMap[fE.start()] = tmpPts.size() - 1;
119  }
120 
121  eds[i].start() = pointMap[fE.start()];
122 
123  if (pointMap[fE.end()] == -1)
124  {
125  tmpPts.append(sFeatLocalPts[fE.end()]);
126 
127  pointMap[fE.end()] = tmpPts.size() - 1;
128  }
129 
130  eds[i].end() = pointMap[fE.end()];
131 
132  // Pick up the faces adjacent to the feature edge
133  const labelList& eFaces = edgeFaces[sFEI];
134 
135  edgeNormals[i].setSize(eFaces.size());
136  normalDirections[i].setSize(eFaces.size());
137 
138  forAll(eFaces, j)
139  {
140  label eFI = eFaces[j];
141 
142  // Check to see if the points have been already used
143  if (faceMap[eFI] == -1)
144  {
145  norms.append(faceNormals[eFI]);
146 
147  faceMap[eFI] = norms.size() - 1;
148  }
149 
150  edgeNormals[i][j] = faceMap[eFI];
151 
152  const vector cross = (faceNormals[eFI] ^ edgeDirections[i]);
153  const vector fC0tofE0 =
154  surf[eFI].centre(surf.points())
155  - sFeatLocalPts[fE.start()];
156 
157  normalDirections[i][j] =
158  (
159  (
160  (cross/(mag(cross) + VSMALL))
161  & (fC0tofE0/(mag(fC0tofE0)+ VSMALL))
162  )
163  > 0.0
164  ? 1
165  : -1
166  );
167  }
168 
169  vector fC0tofC1(vector::zero);
170 
171  if (eFaces.size() == 2)
172  {
173  fC0tofC1 =
174  surf[eFaces[1]].centre(surf.points())
175  - surf[eFaces[0]].centre(surf.points());
176  }
177 
178  edStatus[i] = classifyEdge(norms, edgeNormals[i], fC0tofC1);
179 
180  if (isRegionFeatureEdge[i])
181  {
182  regionEdges.append(i);
183  }
184  }
185 
186  // Populate feature point feature edges
187  DynamicList<label> newFeatureEdges;
188 
189  forAll(featurePointFeatureEdges, pI)
190  {
191  const labelList& fpfe = featurePointFeatureEdges[pI];
192 
193  newFeatureEdges.setCapacity(fpfe.size());
194 
195  forAll(fpfe, eI)
196  {
197  const label oldEdgeIndex = fpfe[eI];
198 
199  const label newFeatureEdgeIndex = edgeMap[oldEdgeIndex];
200 
201  if (newFeatureEdgeIndex != -1)
202  {
203  newFeatureEdges.append(newFeatureEdgeIndex);
204  }
205  }
206 
207  featurePointFeatureEdges[pI].transfer(newFeatureEdges);
208  }
209 
210  // Reorder the edges by classification
211  List<DynamicList<label> > allEds(nEdgeTypes);
212 
213  DynamicList<label>& externalEds(allEds[0]);
214  DynamicList<label>& internalEds(allEds[1]);
215  DynamicList<label>& flatEds(allEds[2]);
216  DynamicList<label>& openEds(allEds[3]);
217  DynamicList<label>& multipleEds(allEds[4]);
218 
219  forAll(eds, i)
220  {
221  edgeStatus eStat = edStatus[i];
222 
223  if (eStat == EXTERNAL)
224  {
225  externalEds.append(i);
226  }
227  else if (eStat == INTERNAL)
228  {
229  internalEds.append(i);
230  }
231  else if (eStat == FLAT)
232  {
233  flatEds.append(i);
234  }
235  else if (eStat == OPEN)
236  {
237  openEds.append(i);
238  }
239  else if (eStat == MULTIPLE)
240  {
241  multipleEds.append(i);
242  }
243  else if (eStat == NONE)
244  {
246  (
247  ":extendedEdgeMesh::sortPointsAndEdges"
248  "("
249  " const Patch&,"
250  " const labelList& featureEdges,"
251  " const labelList& feaurePoints"
252  ")"
253  ) << nl << "classifyEdge returned NONE on edge "
254  << eds[i]
255  << ". There is a problem with definition of this edge."
256  << nl << abort(FatalError);
257  }
258  }
259 
260  internalStart_ = externalEds.size();
261  flatStart_ = internalStart_ + internalEds.size();
262  openStart_ = flatStart_ + flatEds.size();
263  multipleStart_ = openStart_ + openEds.size();
264 
265  labelList edMap
266  (
267  ListListOps::combine<labelList>
268  (
269  allEds,
271  )
272  );
273 
274  edMap = invert(edMap.size(), edMap);
275 
276  inplaceReorder(edMap, eds);
277  inplaceReorder(edMap, edStatus);
278  inplaceReorder(edMap, edgeDirections);
279  inplaceReorder(edMap, edgeNormals);
280  inplaceReorder(edMap, normalDirections);
281  inplaceRenumber(edMap, regionEdges);
282 
283  forAll(featurePointFeatureEdges, pI)
284  {
285  inplaceRenumber(edMap, featurePointFeatureEdges[pI]);
286  }
287 
288  pointField pts(tmpPts);
289 
290  // Initialise the edgeMesh
291  edgeMesh::operator=(edgeMesh(pts, eds));
292 
293  // Initialise sorted edge related data
294  edgeDirections_ = edgeDirections/(mag(edgeDirections) + VSMALL);
295  edgeNormals_ = edgeNormals;
296  normalDirections_ = normalDirections;
297  regionEdges_ = regionEdges;
298 
299  // Normals are all now found and indirectly addressed, can also be stored
300  normals_ = vectorField(norms);
301 
302 
303  // Reorder the feature points by classification
304 
305  List<DynamicList<label> > allPts(3);
306 
307  DynamicList<label>& convexPts(allPts[0]);
308  DynamicList<label>& concavePts(allPts[1]);
309  DynamicList<label>& mixedPts(allPts[2]);
310 
311  for (label i = 0; i < nonFeatureStart_; i++)
312  {
313  pointStatus ptStatus = classifyFeaturePoint(i);
314 
315  if (ptStatus == CONVEX)
316  {
317  convexPts.append(i);
318  }
319  else if (ptStatus == CONCAVE)
320  {
321  concavePts.append(i);
322  }
323  else if (ptStatus == MIXED)
324  {
325  mixedPts.append(i);
326  }
327  else if (ptStatus == NONFEATURE)
328  {
330  (
331  ":extendedEdgeMesh::sortPointsAndEdges"
332  "("
333  " const Patch&,"
334  " const labelList& featureEdges,"
335  " const labelList& feaurePoints"
336  ")"
337  ) << nl << "classifyFeaturePoint returned NONFEATURE on point at "
338  << points()[i]
339  << ". There is a problem with definition of this feature point."
340  << nl << abort(FatalError);
341  }
342  }
343 
344  concaveStart_ = convexPts.size();
345  mixedStart_ = concaveStart_ + concavePts.size();
346 
347  labelList ftPtMap
348  (
349  ListListOps::combine<labelList>
350  (
351  allPts,
353  )
354  );
355 
356  ftPtMap = invert(ftPtMap.size(), ftPtMap);
357 
358  // Creating the ptMap from the ftPtMap with identity values up to the size
359  // of pts to create an oldToNew map for inplaceReorder
360 
361  labelList ptMap(identity(pts.size()));
362 
363  forAll(ftPtMap, i)
364  {
365  ptMap[i] = ftPtMap[i];
366  }
367 
368  inplaceReorder(ptMap, pts);
369  inplaceReorder(ptMap, featurePointFeatureEdges);
370 
371  forAll(eds, i)
372  {
373  inplaceRenumber(ptMap, eds[i]);
374  }
375 
376  // Reinitialise the edgeMesh with sorted feature points and
377  // renumbered edges
378  reset(xferMove(pts), xferMove(eds));
379 
380  // Generate the featurePointNormals
381 
382  labelListList featurePointNormals(nonFeatureStart_);
383 
384  for (label i = 0; i < nonFeatureStart_; i++)
385  {
386  DynamicList<label> tmpFtPtNorms;
387 
388  const labelList& ptEds = edgeMesh::pointEdges()[i];
389 
390  forAll(ptEds, j)
391  {
392  const labelList& ptEdNorms(edgeNormals[ptEds[j]]);
393 
394  forAll(ptEdNorms, k)
395  {
396  if (findIndex(tmpFtPtNorms, ptEdNorms[k]) == -1)
397  {
398  bool addNormal = true;
399 
400  // Check that the normal direction is unique at this feature
401  forAll(tmpFtPtNorms, q)
402  {
403  if
404  (
405  (normals_[ptEdNorms[k]] & normals_[tmpFtPtNorms[q]])
406  > cosNormalAngleTol_
407  )
408  {
409  // Parallel to an existing normal, do not add
410  addNormal = false;
411 
412  break;
413  }
414  }
415 
416  if (addNormal)
417  {
418  tmpFtPtNorms.append(ptEdNorms[k]);
419  }
420  }
421  }
422  }
423 
424  featurePointNormals[i] = tmpFtPtNorms;
425  }
426 
427  featurePointNormals_ = featurePointNormals;
428  featurePointEdges_ = featurePointFeatureEdges;
429 }
430 
431 
432 // ************************************************************************* //
iterator end()
Return an iterator to end traversing the UList.
Definition: UListI.H:237
const pointField & points
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:109
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:390
dimensioned< scalar > mag(const dimensioned< Type > &)
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
A bit-packed bool list.
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
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:310
Xfer< T > xferMove(T &)
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
static const char nl
Definition: Ostream.H:260
void setSize(const label)
Reset size of List.
Definition: List.C:318
volVectorField vectorField(fieldObject, mesh)
#define forAll(list, i)
Definition: UList.H:421
label k
Boltzmann constant.
Unit conversion functions.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
vector vec(const pointField &) const
Return the vector (end - start)
Definition: edgeI.H:157
errorManip< error > abort(error &err)
Definition: errorManip.H:131
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:106
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
labelList invert(const label len, const labelUList &)
Invert one-to-one map. Unmapped elements will be -1.
Definition: ListOps.C:37
Points connected by edges.
Definition: edgeMesh.H:69
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
error FatalError
label end() const
Return end vertex label.
Definition: edgeI.H:92
label start() const
Return start vertex label.
Definition: edgeI.H:81
void cross(FieldField< Field1, typename crossProduct< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
void sortPointsAndEdges(const Patch &, const labelList &featureEdges, const labelList &regionFeatureEdges, const labelList &feaurePoints)
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.