starTemplates.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) 2021-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 "star.H"
27 
28 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29 
30 template<class FaceEdges>
31 void Foam::star::cross
32 (
33  const label edgei,
34  const label facei,
35  const UList<FaceEdges>& faceEdges
36 )
37 {
38  // Add the new face to the star
39  starFaceFaces_.append(facei);
40  faceStarFaces_[facei] = starFaceFaces_.size() - 1;
41 
42  // Store information about this edge, then remove it from the star
43  const label faceEdgei = findIndex(faceEdges[facei], edgei);
44  const label starEdgei = edgeStarEdges_[faceEdges[facei][faceEdgei]];
45  const label starEdgei0 = starEdgeEdges_[starEdgei].starEdgei0_;
46  const label starEdgei1 = starEdgeEdges_[starEdgei].starEdgei1_;
47  edgeStarEdges_[starEdgeEdges_[starEdgei].edgei_] = -1;
48  starEdgeEdges_[starEdgei] = {-1, -1, -1};
49 
50  // Walk backwards and forwards around the face until we find edges not
51  // already in the star. Remove edges in the star as we go.
52  label faceEdgeiR = faceEdgei, starEdgeiR1 = starEdgei1;
53  while (true)
54  {
55  const label faceEdgeiRR = faceEdges[facei].rcIndex(faceEdgeiR);
56  const label edgeiRR = faceEdges[facei][faceEdgeiRR];
57  const label starEdgeiRR = edgeStarEdges_[edgeiRR];
58  if (starEdgeiRR == -1 || starEdgeiRR != starEdgeiR1) break;
59  faceEdgeiR = faceEdgeiRR;
60  starEdgeiR1 = starEdgeEdges_[starEdgeiRR].starEdgei1_;
61  edgeStarEdges_[starEdgeEdges_[starEdgeiRR].edgei_] = -1;
62  starEdgeEdges_[starEdgeiRR] = {-1, -1, -1};
63  }
64  label faceEdgeiF = faceEdgei, starEdgeiF0 = starEdgei0;
65  while (true)
66  {
67  const label faceEdgeiFF = faceEdges[facei].fcIndex(faceEdgeiF);
68  const label edgeiFF = faceEdges[facei][faceEdgeiFF];
69  const label starEdgeiFF = edgeStarEdges_[edgeiFF];
70  if (starEdgeiFF == -1 || starEdgeiFF != starEdgeiF0) break;
71  faceEdgeiF = faceEdgeiFF;
72  starEdgeiF0 = starEdgeEdges_[starEdgeiFF].starEdgei0_;
73  edgeStarEdges_[starEdgeEdges_[starEdgeiFF].edgei_] = -1;
74  starEdgeEdges_[starEdgeiFF] = {-1, -1, -1};
75  }
76 
77  // Get the first edge after the forwards edge
78  label faceEdgej = faceEdges[facei].fcIndex(faceEdgeiF);
79 
80  // If there are no face edges not yet in the star, then all edges are
81  // to be removed. Just connect up the adjacent edges.
82  if (faceEdgej == faceEdgeiR)
83  {
84  starEdgeEdges_[starEdgeiF0].starEdgei1_ = starEdgeiR1;
85  starEdgeEdges_[starEdgeiR1].starEdgei0_ = starEdgeiF0;
86  }
87 
88  // If there are face edges not yet in the star, then loop over them and
89  // add them into the star
90  while (faceEdgej != faceEdgeiR)
91  {
92  const bool isFirst =
93  faceEdgej == faceEdges[facei].fcIndex(faceEdgeiF);
94  const bool isLast =
95  faceEdgej == faceEdges[facei].rcIndex(faceEdgeiR);
96 
97  const label starEdgej0 =
98  isFirst ? starEdgeiF0 : starEdgeEdges_.size() - 1;
99  const label starEdgej = starEdgeEdges_.size();
100  const label starEdgej1 =
101  isLast ? starEdgeiR1 : starEdgeEdges_.size() + 1;
102 
103  const label edgej = faceEdges[facei][faceEdgej];
104 
105  if (isFirst && starEdgeiF0 != -1)
106  {
107  starEdgeEdges_[starEdgeiF0].starEdgei1_ = starEdgej;
108  }
109 
110  starEdgeEdges_.append({starEdgej0, edgej, starEdgej1});
111  edgeStarEdges_[edgej] = starEdgej;
112 
113  if (isLast && starEdgeiR1 != -1)
114  {
115  starEdgeEdges_[starEdgeiR1].starEdgei0_ = starEdgej;
116  }
117 
118  faceEdgej = faceEdges[facei].fcIndex(faceEdgej);
119  }
120 }
121 
122 
123 
124 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
125 
126 template<class CanCross, class FaceEdges>
128 (
129  const label faceOrEdgei,
130  const bool isFace,
131  CanCross canCross,
132  const UList<FaceEdges>& faceEdges,
133  const UList<labelPair>& edgeFaces,
134  const label maxIterations
135 )
136 {
137  // Expand to fit supplied data
138  faceStarFaces_.resize(faceEdges.size(), -1);
139  edgeStarEdges_.resize(edgeFaces.size(), -1);
140 
141  // Initialise
142  if (isFace)
143  {
144  // Add one edge from the to the star and then cross into the face
145  const label edgei = faceEdges[faceOrEdgei][0];
146  starEdgeEdges_.append({-1, edgei, -1});
147  edgeStarEdges_[edgei] = 0;
148  cross(edgei, faceOrEdgei, faceEdges);
149 
150  // Add the edge back again as it was removed by the crossing. Reuse the
151  // first element of the starEdgeEdges array. Join up to close the star.
152  const label starEdgei0 = starEdgeEdges_.size() - 1;
153  const label starEdgei1 = 1;
154  starEdgeEdges_[0] = {starEdgei0, edgei, starEdgei1};
155  edgeStarEdges_[edgei] = 0;
156  starEdgeEdges_[starEdgei0].starEdgei1_ = 0;
157  starEdgeEdges_[starEdgei1].starEdgei0_ = 0;
158  }
159  else
160  {
161  bool first = true;
162 
163  // Loop the adjacent faces
164  forAll(edgeFaces[faceOrEdgei], edgeFacei)
165  {
166  const label facei = edgeFaces[faceOrEdgei][edgeFacei];
167  if (facei == -1) continue;
168 
169  // If the first face, add the edge to the star
170  if (first)
171  {
172  starEdgeEdges_.append({-1, faceOrEdgei, -1});
173  edgeStarEdges_[faceOrEdgei] = 0;
174  first = false;
175  }
176  // If the second face, add the edge into the star again as it was
177  // removed by the previous crossing. Reuse the first element of the
178  // starEdgeEdges array. Join up to close the star.
179  else
180  {
181  const label starEdgei0 = starEdgeEdges_.size() - 1;
182  const label starEdgei1 = 1;
183  starEdgeEdges_[0] = {starEdgei0, faceOrEdgei, starEdgei1};
184  edgeStarEdges_[faceOrEdgei] = 0;
185  starEdgeEdges_[starEdgei0].starEdgei1_ = 0;
186  starEdgeEdges_[starEdgei1].starEdgei0_ = 0;
187  }
188 
189  // Cross the edge into the face
190  cross(faceOrEdgei, facei, faceEdges);
191  }
192  }
193 
194  // Walk the star to get intersected faces and their perimeter
195  label iterations = 0;
196  forAll(starEdgeEdges_, starEdgei)
197  {
198  if (iterations == maxIterations) break;
199  ++ iterations;
200 
201  const label edgei = starEdgeEdges_[starEdgei].edgei_;
202  if (edgei == -1) continue;
203 
204  // Get the adjacent non-star face
205  label facei = -1;
206  forAll(edgeFaces[edgei], edgeFacei)
207  {
208  facei = edgeFaces[edgei][edgeFacei];
209  if (facei != -1 && faceStarFaces_[facei] == -1)
210  {
211  break;
212  }
213  facei = -1;
214  }
215 
216  // If the crossing condition is satisfied then expand the star
217  if (facei != -1 && canCross(edgei, facei))
218  {
219  cross(edgei, facei, faceEdges);
220  }
221  }
222 
223  // Remove spikes
224  forAll(starEdgeEdges_, starEdgei)
225  {
226  label starEdgei0 = starEdgei;
227  label starEdgei1 = starEdgeEdges_[starEdgei0].starEdgei1_;
228 
229  if (starEdgei1 == -1) continue;
230 
231  label edgei0 = starEdgeEdges_[starEdgei0].edgei_;
232  label edgei1 = starEdgeEdges_[starEdgei1].edgei_;
233 
234  while (edgei0 != -1 && edgei1 != -1 && edgei0 == edgei1)
235  {
236  const label starEdgei00 = starEdgeEdges_[starEdgei0].starEdgei0_;
237  const label starEdgei11 = starEdgeEdges_[starEdgei1].starEdgei1_;
238 
239  edgeStarEdges_[edgei0] = -1;
240  starEdgeEdges_[starEdgei0] = {-1, -1, -1};
241  edgeStarEdges_[edgei1] = -1;
242  starEdgeEdges_[starEdgei1] = {-1, -1, -1};
243 
244  if (starEdgei00 != -1)
245  {
246  starEdgeEdges_[starEdgei00].starEdgei1_ = starEdgei11;
247  starEdgei0 = starEdgei00;
248  edgei0 = starEdgeEdges_[starEdgei00].edgei_;
249  }
250  else
251  {
252  starEdgei0 = edgei0 = -1;
253  }
254 
255  if (starEdgei11 != -1)
256  {
257  starEdgeEdges_[starEdgei11].starEdgei0_ = starEdgei00;
258  starEdgei1 = starEdgei11;
259  edgei1 = starEdgeEdges_[starEdgei11].edgei_;
260  }
261  else
262  {
263  starEdgei1 = edgei0 = -1;
264  }
265  }
266  }
267 
268  // Allocate map storage
269  DynamicList<label>& oldStarEdgeNewStarEdges = work_;
270  oldStarEdgeNewStarEdges.resize(starEdgeEdges_.size());
271  oldStarEdgeNewStarEdges = -1;
272 
273  // Remove empty edges by shuffling up
274  label starEdgei = 0;
275  forAll(starEdgeEdges_, starEdgej)
276  {
277  if (starEdgeEdges_[starEdgej].edgei_ != -1)
278  {
279  oldStarEdgeNewStarEdges[starEdgej] = starEdgei;
280  starEdgeEdges_[starEdgei] = starEdgeEdges_[starEdgej];
281  ++ starEdgei;
282  }
283  }
284  starEdgeEdges_.resize(starEdgei);
285 
286  // Map
287  forAll(starEdgeEdges_, starEdgei)
288  {
289  label& starEdgei0 = starEdgeEdges_[starEdgei].starEdgei0_;
290  if (starEdgei0 != -1)
291  {
292  starEdgei0 = oldStarEdgeNewStarEdges[starEdgei0];
293  }
294  label& starEdgei1 = starEdgeEdges_[starEdgei].starEdgei1_;
295  if (starEdgei1 != -1)
296  {
297  starEdgei1 = oldStarEdgeNewStarEdges[starEdgei1];
298  }
299  }
300 
301  /*
302  // Randomise swapping
303  static randomGenerator rndGen(12345);
304  const label starEdgeiA = rndGen.sampleAB<label>(0, starEdgeEdges_.size());
305  const label starEdgeiB = rndGen.sampleAB<label>(0, starEdgeEdges_.size());
306  swapStarEdges(starEdgeiA, starEdgeiB);
307  */
308 
309  // If the star is open, put the first edge first, so that forAllStarEdges
310  // always starts in the right place
311  forAll(starEdgeEdges_, starEdgei)
312  {
313  if (starEdgeEdges_[starEdgei].starEdgei0_ == -1)
314  {
315  swapStarEdges(starEdgei, 0);
316  }
317  }
318 
319  return context(*this);
320 }
321 
322 
323 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
void resize(const label)
Alter the addressed list size.
Definition: DynamicListI.H:216
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:74
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
Context class. Returned by populate and resets the star when it.
Definition: star.H:66
context populate(const label faceOrEdgei, const bool isFace, CanCross canCross, const UList< FaceEdges > &faceEdges, const UList< labelPair > &edgeFaces, const label maxIterations=labelMax)
Populate the star given a seed face or edge, a function.
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 first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
void cross(FieldField< Field1, typename crossProduct< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)