lineFace.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-2023 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 "lineFace.H"
27 #include "meshSearch.H"
28 #include "DynamicList.H"
29 #include "polyMesh.H"
30 #include "treeDataCell.H"
31 #include "sampledSetCloud.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace sampledSets
39 {
42 }
43 }
44 
45 
46 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
47 
48 void Foam::sampledSets::lineFace::calcSamples
49 (
50  const polyMesh& mesh,
51  const meshSearch& searchEngine,
52  const vector& start,
53  const vector& end,
54  const label storeFaces,
55  const bool storeCells,
56  DynamicList<point>& samplingPositions,
57  DynamicList<scalar>& samplingDistances,
58  DynamicList<label>& samplingSegments,
59  DynamicList<label>& samplingCells,
60  DynamicList<label>& samplingFaces
61 )
62 {
63  // Get all candidates for starting the tracks
64  List<DynamicList<label>> procCandidateCells(Pstream::nProcs());
65  List<DynamicList<scalar>> procCandidateTs(Pstream::nProcs());
66  {
67  const label startCelli = searchEngine.findCell(start);
68  if (startCelli != -1)
69  {
70  procCandidateCells[Pstream::myProcNo()].append(startCelli);
71  procCandidateTs[Pstream::myProcNo()].append(0);
72  }
73 
74  const label endCelli = searchEngine.findCell(end);
75  if (endCelli != -1)
76  {
77  procCandidateCells[Pstream::myProcNo()].append(endCelli);
78  procCandidateTs[Pstream::myProcNo()].append(1);
79  }
80 
81  const List<pointIndexHit> bHits =
82  searchEngine.intersections(start, end);
83  forAll(bHits, bHiti)
84  {
85  for (label bHitj = bHiti + 1; bHitj < bHits.size(); ++ bHitj)
86  {
87  const point midP =
88  (bHits[bHiti].hitPoint() + bHits[bHitj].hitPoint())/2;
89 
90  const label midCelli = searchEngine.findCell(midP);
91  const scalar midT = mag(midP - start)/mag(end - start);
92 
93  if (midCelli != -1)
94  {
95  procCandidateCells[Pstream::myProcNo()].append(midCelli);
96  procCandidateTs[Pstream::myProcNo()].append(midT);
97  }
98  }
99  }
100  }
101  Pstream::gatherList(procCandidateCells);
102  Pstream::scatterList(procCandidateCells);
103  Pstream::gatherList(procCandidateTs);
104  Pstream::scatterList(procCandidateTs);
105 
106  // Tracking data
107  const List<point> startEnd({start, end});
108  const List<point> endStart({end, start});
109  DynamicList<point> halfSegmentPositions;
110  DynamicList<scalar> halfSegmentDistances;
111  DynamicList<label> halfSegmentCells;
112  DynamicList<label> halfSegmentFaces;
113 
114  // Create a cloud with which to track segments
115  sampledSetCloud particles
116  (
117  mesh,
118  lineFace::typeName,
120  );
121 
122  // Create each segment in turn
123  label segmenti = 0;
124  forAll(procCandidateCells, proci)
125  {
126  forAll(procCandidateCells[proci], candidatei)
127  {
128  const label celli = procCandidateCells[proci][candidatei];
129 
130  if (celli == -1) continue;
131 
132  const scalar t = procCandidateTs[proci][candidatei];
133  const point p = (1 - t)*start + t*end;
134 
135  // Track in both directions to form parts of the segment either
136  // side of the candidate
137  Pair<scalar> segmentT;
138  forAll(segmentT, i)
139  {
141  (
142  particles,
143  i == 0 ? endStart : startEnd,
144  false,
145  storeFaces,
146  storeCells,
147  halfSegmentPositions,
148  halfSegmentDistances,
149  halfSegmentCells,
150  halfSegmentFaces
151  );
152 
153  particles.clear();
154  if (proci == Pstream::myProcNo())
155  {
156  particles.addParticle
157  (
159  (
160  mesh,
161  p,
162  celli,
163  0,
164  i == 0 ? t : 1 - t,
165  0
166  )
167  );
168  }
169 
170  particles.move(particles, tdBwd);
171 
172  segmentT[i] =
174  (
175  particles.size()
176  ? mag(particles.first()->position(mesh) - start)
177  /mag(end - start)
178  : i == 0 ? vGreat : -vGreat,
179  [i](const scalar a, const scalar b)
180  {
181  return (i == 0) == (a < b) ? a : b;
182  }
183  );
184 
185  if (i == 0)
186  {
187  reverse(halfSegmentPositions);
188  reverse(halfSegmentDistances);
189  reverse(halfSegmentCells);
190  reverse(halfSegmentFaces);
191  }
192 
193  const label n = halfSegmentPositions.size();
194 
195  samplingPositions.append(halfSegmentPositions);
196  samplingSegments.append(labelList(n, segmenti));
197  samplingCells.append(halfSegmentCells);
198  samplingFaces.append(halfSegmentFaces);
199 
200  halfSegmentPositions.clear();
201  halfSegmentDistances.clear();
202  halfSegmentCells.clear();
203  halfSegmentFaces.clear();
204 
205  // If storing cells we need to store the starting cells between
206  // the tracks
207  if (proci == Pstream::myProcNo() && i == 0 && storeCells)
208  {
209  particle trackBwd(mesh, p, celli), trackFwd(trackBwd);
210  trackBwd.trackToFace(mesh, start - p, 0);
211  trackFwd.trackToFace(mesh, end - p, 0);
212  if (trackBwd.onFace() && trackFwd.onFace())
213  {
214  samplingPositions.append
215  (
216  (
217  trackBwd.position(mesh)
218  + trackFwd.position(mesh)
219  )/2
220  );
221  samplingSegments.append(segmenti);
222  samplingCells.append(celli);
223  samplingFaces.append(-1);
224  }
225  }
226  }
227 
228  // Disable all candidates that fall within the bounds of the
229  // computed segment
230  forAll(procCandidateCells, procj)
231  {
232  forAll(procCandidateCells[procj], candidatej)
233  {
234  const label cellj = procCandidateCells[procj][candidatej];
235 
236  if (cellj == -1) continue;
237 
238  const scalar t = procCandidateTs[procj][candidatej];
239 
240  if
241  (
242  t > segmentT.first() - rootSmall
243  && t < segmentT.second() + rootSmall
244  )
245  {
246  procCandidateCells[procj][candidatej] = -1;
247  procCandidateTs[procj][candidatej] = NaN;
248  }
249  }
250  }
251 
252  // Move onto the next segment
253  segmenti ++;
254  }
255  }
256 
257  // Set the distances
258  samplingDistances.resize(samplingPositions.size());
259  forAll(samplingPositions, i)
260  {
261  samplingDistances[i] = mag(samplingPositions[i] - start);
262  }
263 }
264 
265 
266 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
267 
268 void Foam::sampledSets::lineFace::calcSamples
269 (
270  DynamicList<point>& samplingPositions,
271  DynamicList<scalar>& samplingDistances,
272  DynamicList<label>& samplingSegments,
273  DynamicList<label>& samplingCells,
274  DynamicList<label>& samplingFaces
275 ) const
276 {
277  calcSamples
278  (
279  mesh(),
280  searchEngine(),
281  start_,
282  end_,
283  1,
284  false,
285  samplingPositions,
286  samplingDistances,
287  samplingSegments,
288  samplingCells,
289  samplingFaces
290  );
291 }
292 
293 
294 void Foam::sampledSets::lineFace::genSamples()
295 {
296  DynamicList<point> samplingPositions;
297  DynamicList<scalar> samplingDistances;
298  DynamicList<label> samplingSegments;
299  DynamicList<label> samplingCells;
300  DynamicList<label> samplingFaces;
301 
302  calcSamples
303  (
304  samplingPositions,
305  samplingDistances,
306  samplingSegments,
307  samplingCells,
308  samplingFaces
309  );
310 
311  samplingPositions.shrink();
312  samplingDistances.shrink();
313  samplingSegments.shrink();
314  samplingCells.shrink();
315  samplingFaces.shrink();
316 
317  setSamples
318  (
319  samplingPositions,
320  samplingDistances,
321  samplingSegments,
322  samplingCells,
323  samplingFaces
324  );
325 }
326 
327 
328 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
329 
331 (
332  const word& name,
333  const polyMesh& mesh,
334  const meshSearch& searchEngine,
335  const dictionary& dict
336 )
337 :
338  sampledSet(name, mesh, searchEngine, dict),
339  start_(dict.lookup("start")),
340  end_(dict.lookup("end"))
341 {
342  genSamples();
343 }
344 
345 
346 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
347 
349 {}
350 
351 
352 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Macros for easy insertion into run-time selection tables.
label size() const
Return the number of particles in the cloud.
Definition: Cloud.H:190
void clear()
Definition: Cloud.H:231
void addParticle(ParticleType *pPtr)
Transfer particle to cloud.
Definition: Cloud.C:218
void move(TrackCloudType &cloud, typename ParticleType::trackingData &td)
Move the particles.
Definition: Cloud.C:275
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
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
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:252
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:236
Template class for intrusive linked lists.
Definition: ILList.H:67
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
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 clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:125
const Type & second() const
Return second.
Definition: Pair.H:110
const Type & first() const
Return first.
Definition: Pair.H:98
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
T * first()
Return the first entry.
Definition: UILList.H:109
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
Definition: meshSearch.H:58
List< pointIndexHit > intersections(const point &pStart, const point &pEnd) const
Find all intersections of boundary within segment pStart .. pEnd.
Definition: meshSearch.C:861
label findCell(const point &location, const label seedCelli=-1, const bool useTreeSearch=true) const
Find cell containing location.
Definition: meshSearch.C:750
Base particle class.
Definition: particle.H:83
scalar trackToFace(const polyMesh &mesh, const vector &displacement, const scalar fraction)
As particle::track, but stops when a face is hit.
Definition: particle.C:595
bool onFace() const
Is the particle on a face?
Definition: particleI.H:231
vector position(const polyMesh &mesh) const
Return current particle position.
Definition: particleI.H:255
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
A Cloud of sampledSet particles.
Particle for generating line-type sampled sets.
Holds list of sampling points which is filled at construction time. Various implementations of this b...
Definition: sampledSet.H:64
const meshSearch & searchEngine() const
Access the search engine.
Definition: sampledSet.H:216
const polyMesh & mesh() const
Access the mesh.
Definition: sampledSet.H:210
Face-intersections along a line.
Definition: lineFace.H:93
virtual ~lineFace()
Destructor.
Definition: lineFace.C:348
lineFace(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const dictionary &dict)
Construct from dictionary.
Definition: lineFace.C:331
Set of sets to sample. Call sampledSets.write() to sample&write files.
A class for handling words, derived from string.
Definition: word.H:62
volScalarField & b
Definition: createFields.H:27
static Type NaN()
Return a primitive with all components set to NaN.
defineTypeNameAndDebug(arcUniform, 0)
addToRunTimeSelectionTable(sampledSet, arcUniform, word)
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: labelList.H:56
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 reverse(UList< T > &, const label n)
Definition: UListI.H:334
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< scalar > mag(const dimensioned< Type > &)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
dictionary dict
volScalarField & p