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-2022 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 {
40  defineTypeNameAndDebug(lineFace, 0);
41  addToRunTimeSelectionTable(sampledSet, lineFace, word);
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 bool 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, rootGreat);
171 
172  segmentT[i] =
174  (
175  particles.size()
176  ? mag(particles.first()->position() - 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(start - p, 0);
211  trackFwd.trackToFace(end - p, 0);
212  if (trackBwd.onFace() && trackFwd.onFace())
213  {
214  samplingPositions.append
215  (
216  (trackBwd.position() + trackFwd.position())/2
217  );
218  samplingSegments.append(segmenti);
219  samplingCells.append(celli);
220  samplingFaces.append(-1);
221  }
222  }
223  }
224 
225  // Disable all candidates that fall within the bounds of the
226  // computed segment
227  forAll(procCandidateCells, procj)
228  {
229  forAll(procCandidateCells[procj], candidatej)
230  {
231  const label cellj = procCandidateCells[procj][candidatej];
232 
233  if (cellj == -1) continue;
234 
235  const scalar t = procCandidateTs[procj][candidatej];
236 
237  if
238  (
239  t > segmentT.first() - rootSmall
240  && t < segmentT.second() + rootSmall
241  )
242  {
243  procCandidateCells[procj][candidatej] = -1;
244  procCandidateTs[procj][candidatej] = NaN;
245  }
246  }
247  }
248 
249  // Move onto the next segment
250  segmenti ++;
251  }
252  }
253 
254  // Set the distances
255  samplingDistances.resize(samplingPositions.size());
256  forAll(samplingPositions, i)
257  {
258  samplingDistances[i] = mag(samplingPositions[i] - start);
259  }
260 }
261 
262 
263 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
264 
265 void Foam::sampledSets::lineFace::calcSamples
266 (
267  DynamicList<point>& samplingPositions,
268  DynamicList<scalar>& samplingDistances,
269  DynamicList<label>& samplingSegments,
270  DynamicList<label>& samplingCells,
271  DynamicList<label>& samplingFaces
272 ) const
273 {
274  calcSamples
275  (
276  mesh(),
277  searchEngine(),
278  start_,
279  end_,
280  true,
281  false,
282  samplingPositions,
283  samplingDistances,
284  samplingSegments,
285  samplingCells,
286  samplingFaces
287  );
288 }
289 
290 
291 void Foam::sampledSets::lineFace::genSamples()
292 {
293  DynamicList<point> samplingPositions;
294  DynamicList<scalar> samplingDistances;
295  DynamicList<label> samplingSegments;
296  DynamicList<label> samplingCells;
297  DynamicList<label> samplingFaces;
298 
299  calcSamples
300  (
301  samplingPositions,
302  samplingDistances,
303  samplingSegments,
304  samplingCells,
305  samplingFaces
306  );
307 
308  samplingPositions.shrink();
309  samplingDistances.shrink();
310  samplingSegments.shrink();
311  samplingCells.shrink();
312  samplingFaces.shrink();
313 
314  setSamples
315  (
316  samplingPositions,
317  samplingDistances,
318  samplingSegments,
319  samplingCells,
320  samplingFaces
321  );
322 }
323 
324 
325 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
326 
328 (
329  const word& name,
330  const polyMesh& mesh,
331  const meshSearch& searchEngine,
332  const dictionary& dict
333 )
334 :
335  sampledSet(name, mesh, searchEngine, dict),
336  start_(dict.lookup("start")),
337  end_(dict.lookup("end"))
338 {
339  genSamples();
340 }
341 
342 
343 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
344 
346 {}
347 
348 
349 // ************************************************************************* //
Template class for intrusive linked lists.
Definition: ILList.H:50
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search...
Definition: meshSearch.H:57
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Particle for generating line-type sampled sets.
#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
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
scalar trackToFace(const vector &displacement, const scalar fraction)
As particle::track, but stops when a face is hit.
Definition: particle.C:606
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
const dimensionedScalar b
Wien displacement law constant: default SI units: [m K].
Definition: createFields.H:27
virtual ~lineFace()
Destructor.
Definition: lineFace.C:345
label size() const
Return the number of particles in the cloud.
Definition: Cloud.H:190
fvMesh & mesh
Macros for easy insertion into run-time selection tables.
Base particle class.
Definition: particle.H:81
void addParticle(ParticleType *pPtr)
Transfer particle to cloud.
Definition: Cloud.C:220
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
Holds list of sampling points which is filled at construction time. Various implementations of this b...
Definition: sampledSet.H:61
label findCell(const point &location, const label seedCelli=-1, const bool useTreeSearch=true) const
Find cell containing location.
Definition: meshSearch.C:750
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:125
A class for handling words, derived from string.
Definition: word.H:59
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
A Cloud of sampledSet particles.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
List< label > labelList
A List of labels.
Definition: labelList.H:56
addToRunTimeSelectionTable(sampledSet, arcUniform, word)
void reverse(UList< T > &, const label n)
Definition: UListI.H:334
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:252
void clear()
Definition: Cloud.H:231
bool onFace() const
Is the particle on a face?
Definition: particleI.H:254
const Type & second() const
Return second.
Definition: Pair.H:110
void move(TrackCloudType &cloud, typename ParticleType::trackingData &td, const scalar trackTime)
Move the particles.
Definition: Cloud.C:265
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
dimensioned< scalar > mag(const dimensioned< Type > &)
label n
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:76
volScalarField & p
List< pointIndexHit > intersections(const point &pStart, const point &pEnd) const
Find all intersections of boundary within segment pStart .. pEnd.
Definition: meshSearch.C:861
T * first()
Return the first entry.
Definition: UILList.H:109
defineTypeNameAndDebug(arcUniform, 0)
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:236
lineFace(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const dictionary &dict)
Construct from dictionary.
Definition: lineFace.C:328
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
const Type & first() const
Return first.
Definition: Pair.H:98
vector position() const
Return current particle position.
Definition: particleI.H:278
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:864