Loading...
Searching...
No Matches
searchableSurfacesQueries.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) 2015-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
30#include "ListOps.H"
31#include "OFstream.H"
32#include "meshTools.H"
33#include "DynamicField.H"
35#include "plane.H"
36
37// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38
39namespace Foam
40{
42}
43
44
45// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46
47void Foam::searchableSurfacesQueries::mergeHits
48(
49 const point& start,
50
51 const label testI, // index of surface
52 const List<pointIndexHit>& surfHits, // hits on surface
53
54 labelList& allSurfaces,
55 List<pointIndexHit>& allInfo,
56 scalarList& allDistSqr
57)
58{
59 // Given current set of hits (allSurfaces, allInfo) merge in those coming
60 // from surface surfI.
61
62 // Precalculate distances
63 scalarList surfDistSqr(surfHits.size());
64 forAll(surfHits, i)
65 {
66 surfDistSqr[i] = surfHits[i].hitPoint().distSqr(start);
67 }
68
69 forAll(surfDistSqr, i)
70 {
71 label index = findLower(allDistSqr, surfDistSqr[i]);
72
73 // Check if equal to lower.
74 if (index >= 0)
75 {
76 // Same. Do not count.
77 //Pout<< "point:" << surfHits[i].point()
78 // << " considered same as:" << allInfo[index].point()
79 // << " within tol:" << mergeDist
80 // << endl;
81 }
82 else
83 {
84 // Check if equal to higher
85 label next = index + 1;
86
87 if (next < allDistSqr.size())
88 {
89 //Pout<< "point:" << surfHits[i].point()
90 // << " considered same as:" << allInfo[next].point()
91 // << " within tol:" << mergeDist
92 // << endl;
93 }
94 else
95 {
96 // Insert after index
97 label sz = allSurfaces.size();
98 allSurfaces.setSize(sz+1);
99 allInfo.setSize(allSurfaces.size());
100 allDistSqr.setSize(allSurfaces.size());
101 // Make space.
102 for (label j = sz-1; j > index; --j)
103 {
104 allSurfaces[j+1] = allSurfaces[j];
105 allInfo[j+1] = allInfo[j];
106 allDistSqr[j+1] = allDistSqr[j];
107 }
108 // Insert new value
109 allSurfaces[index+1] = testI;
110 allInfo[index+1] = surfHits[i];
111 allDistSqr[index+1] = surfDistSqr[i];
112 }
113 }
115}
116
117
118// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
119
120// Find any intersection
122(
123 const PtrList<searchableSurface>& allSurfaces,
124 const labelList& surfacesToTest,
125 const pointField& start,
126 const pointField& end,
127 labelList& hitSurfaces,
128 List<pointIndexHit>& hitInfo
129)
130{
131 hitSurfaces.setSize(start.size());
132 hitSurfaces = -1;
133 hitInfo.setSize(start.size());
134
135 // Work arrays
136 labelList hitMap(identity(start.size()));
137 pointField p0(start);
138 pointField p1(end);
139 List<pointIndexHit> intersectInfo(start.size());
140
141 forAll(surfacesToTest, testI)
142 {
143 // Do synchronised call to all surfaces.
144 allSurfaces[surfacesToTest[testI]].findLineAny(p0, p1, intersectInfo);
145
146 // Copy all hits into arguments, continue with misses
147 label newI = 0;
148 forAll(intersectInfo, i)
149 {
150 if (intersectInfo[i].hit())
151 {
152 hitInfo[hitMap[i]] = intersectInfo[i];
153 hitSurfaces[hitMap[i]] = testI;
154 }
155 else
156 {
157 if (i != newI)
158 {
159 hitMap[newI] = hitMap[i];
160 p0[newI] = p0[i];
161 p1[newI] = p1[i];
162 }
163 newI++;
164 }
165 }
166
167 // All done? Note that this decision should be synchronised
168 if (newI == 0)
169 {
170 break;
171 }
172
173 // Trim and continue
174 hitMap.setSize(newI);
175 p0.setSize(newI);
176 p1.setSize(newI);
177 intersectInfo.setSize(newI);
178 }
179}
180
181
183(
184 const PtrList<searchableSurface>& allSurfaces,
185 const labelList& surfacesToTest,
186 const pointField& start,
187 const pointField& end,
188 labelListList& hitSurfaces,
189 List<List<pointIndexHit>>& hitInfo
190)
191{
192 // Note: maybe move the single-surface all intersections test into
193 // searchable surface? Some of the tolerance issues might be
194 // lessened.
195
196 // 2. Currently calling searchableSurface::findLine with start==end
197 // is expected to find no intersection. Problem if it does.
198
199 hitSurfaces.setSize(start.size());
200 hitInfo.setSize(start.size());
201
202 if (surfacesToTest.empty())
203 {
204 return;
205 }
206
207 // Test first surface
208 allSurfaces[surfacesToTest[0]].findLineAll(start, end, hitInfo);
209
210 // Set hitSurfaces and distance
211 List<scalarList> hitDistSqr(hitInfo.size());
212 forAll(hitInfo, pointi)
213 {
214 const List<pointIndexHit>& pHits = hitInfo[pointi];
215
216 labelList& pSurfaces = hitSurfaces[pointi];
217 pSurfaces.setSize(pHits.size());
218 pSurfaces = 0;
219
220 scalarList& pDistSqr = hitDistSqr[pointi];
221 pDistSqr.setSize(pHits.size());
222 forAll(pHits, i)
223 {
224 pDistSqr[i] = pHits[i].hitPoint().distSqr(start[pointi]);
225 }
226 }
227
228
229 if (surfacesToTest.size() > 1)
230 {
231 // Test the other surfaces and merge (according to distance from start).
232 for (label testI = 1; testI < surfacesToTest.size(); testI++)
233 {
234 List<List<pointIndexHit>> surfHits;
235 allSurfaces[surfacesToTest[testI]].findLineAll
236 (
237 start,
238 end,
239 surfHits
240 );
241
242 forAll(surfHits, pointi)
243 {
244 mergeHits
245 (
246 start[pointi], // Current segment
247
248 testI, // Surface and its hits
249 surfHits[pointi],
250
251 hitSurfaces[pointi], // Merge into overall hit info
252 hitInfo[pointi],
253 hitDistSqr[pointi]
254 );
255 }
256 }
257 }
258}
259
260
262(
263 const PtrList<searchableSurface>& allSurfaces,
264 const labelList& surfacesToTest,
265 const pointField& start,
266 const pointField& end,
267 labelList& surface1,
269 labelList& surface2,
271)
272{
273 // 1. intersection from start to end
274 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
275
276 // Initialize arguments
277 surface1.setSize(start.size());
278 surface1 = -1;
279 hit1.setSize(start.size());
280
281 // Current end of segment to test.
282 pointField nearest(end);
283 // Work array
284 List<pointIndexHit> nearestInfo(start.size());
285
286 forAll(surfacesToTest, testI)
287 {
288 // See if any intersection between start and current nearest
289 allSurfaces[surfacesToTest[testI]].findLine
290 (
291 start,
292 nearest,
293 nearestInfo
294 );
295
296 forAll(nearestInfo, pointi)
297 {
298 if (nearestInfo[pointi].hit())
299 {
300 hit1[pointi] = nearestInfo[pointi];
301 surface1[pointi] = testI;
302 nearest[pointi] = hit1[pointi].point();
303 }
304 }
305 }
306
307
308 // 2. intersection from end to last intersection
309 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
310
311 // Find the nearest intersection from end to start. Note that we
312 // initialize to the first intersection (if any).
313 surface2 = surface1;
314 hit2 = hit1;
315
316 // Set current end of segment to test.
317 forAll(nearest, pointi)
318 {
319 if (hit1[pointi].hit())
320 {
321 nearest[pointi] = hit1[pointi].point();
322 }
323 else
324 {
325 // Disable testing by setting to end.
326 nearest[pointi] = end[pointi];
327 }
328 }
329
330 forAll(surfacesToTest, testI)
331 {
332 // See if any intersection between end and current nearest
333 allSurfaces[surfacesToTest[testI]].findLine(end, nearest, nearestInfo);
334
335 forAll(nearestInfo, pointi)
336 {
337 if (nearestInfo[pointi].hit())
338 {
339 hit2[pointi] = nearestInfo[pointi];
340 surface2[pointi] = testI;
341 nearest[pointi] = hit2[pointi].point();
342 }
343 }
344 }
345}
346
347
349(
350 const PtrList<searchableSurface>& allSurfaces,
351 const labelList& surfacesToTest,
352 const pointField& samples,
353 const scalarField& nearestDistSqr,
354 labelList& nearestSurfaces,
355 List<pointIndexHit>& nearestInfo
356)
357{
358 // Find nearest. Return -1 or nearest point
359
360 if (samples.size() != nearestDistSqr.size())
361 {
362 FatalErrorInFunction << "Inconsistent sizes. samples:" << samples.size()
363 << " search-radius:" << nearestDistSqr.size()
364 << exit(FatalError);
365 }
366
367 // Initialise
368 nearestSurfaces.setSize(samples.size());
369 nearestSurfaces = -1;
370 nearestInfo.setSize(samples.size());
371
372 // Work arrays
373 scalarField minDistSqr(nearestDistSqr);
375
376 forAll(surfacesToTest, testI)
377 {
378 allSurfaces[surfacesToTest[testI]].findNearest
379 (
380 samples,
381 minDistSqr,
382 hitInfo
383 );
384
385 // Update minDistSqr and arguments
386 forAll(hitInfo, pointi)
387 {
388 if (hitInfo[pointi].hit())
389 {
390 minDistSqr[pointi] =
391 hitInfo[pointi].point().distSqr(samples[pointi]);
392
393 nearestInfo[pointi] = hitInfo[pointi];
394 nearestSurfaces[pointi] = testI;
395 }
396 }
397 }
398}
399
400
402(
403 const PtrList<searchableSurface>& allSurfaces,
404 const labelList& surfacesToTest,
405 const labelListList& regionIndices,
406
407 const pointField& samples,
408 const scalarField& nearestDistSqr,
409
410 labelList& nearestSurfaces,
411 List<pointIndexHit>& nearestInfo
412)
413{
414 // Find nearest. Return -1 or nearest point
415
416 if (samples.size() != nearestDistSqr.size())
417 {
418 FatalErrorInFunction << "Inconsistent sizes. samples:" << samples.size()
419 << " search-radius:" << nearestDistSqr.size()
420 << exit(FatalError);
421 }
422
423
424 if (regionIndices.empty())
425 {
426 findNearest
427 (
428 allSurfaces,
429 surfacesToTest,
430 samples,
431 nearestDistSqr,
432 nearestSurfaces,
433 nearestInfo
434 );
435 }
436
437 // Initialise
438 nearestSurfaces.setSize(samples.size());
439 nearestSurfaces = -1;
440 nearestInfo.setSize(samples.size());
441
442 // Work arrays
443 scalarField minDistSqr(nearestDistSqr);
445
446 forAll(surfacesToTest, testI)
447 {
448 allSurfaces[surfacesToTest[testI]].findNearest
449 (
450 samples,
451 minDistSqr,
452 regionIndices[testI],
453 hitInfo
454 );
455
456 // Update minDistSqr and arguments
457 forAll(hitInfo, pointi)
458 {
459 if (hitInfo[pointi].hit())
460 {
461 minDistSqr[pointi] =
462 hitInfo[pointi].point().distSqr(samples[pointi]);
463
464 nearestInfo[pointi] = hitInfo[pointi];
465 nearestSurfaces[pointi] = testI;
466 }
467 }
468 }
469}
470
471
473(
474 const PtrList<searchableSurface>& allSurfaces,
475 const labelList& surfacesToTest,
476 const pointField& start,
477 const scalarField& distSqr,
478 pointField& near,
479 List<pointConstraint>& constraint,
480 const label nIter
481)
482{
483 // Multi-surface findNearest
484
485
486 if (start.size() != distSqr.size())
487 {
488 FatalErrorInFunction << "Inconsistent sizes. samples:" << start.size()
489 << " search-radius:" << distSqr.size()
490 << exit(FatalError);
491 }
492
493
494 vectorField normal;
496
497 allSurfaces[surfacesToTest[0]].findNearest(start, distSqr, info);
498 allSurfaces[surfacesToTest[0]].getNormal(info, normal);
499
500 // Extract useful info from initial start point
501 near = start;
502 forAll(info, i)
503 {
504 if (info[i].hit())
505 {
506 near[i] = info[i].point();
507 }
508 }
509
510 // Store normal as constraint
511 constraint.setSize(near.size());
512 constraint = pointConstraint();
513 forAll(constraint, i)
514 {
515 if (info[i].hit())
516 {
517 constraint[i].applyConstraint(normal[i]);
518 }
519 }
520
521 if (surfacesToTest.size() >= 2)
522 {
523 // Work space
524 //pointField near1;
525 vectorField normal1;
526
527 label surfi = 1;
528 for (label iter = 0; iter < nIter; iter++)
529 {
530 // Find nearest on next surface
531 const searchableSurface& s = allSurfaces[surfacesToTest[surfi]];
532
533 // Update: info, normal1
534 s.findNearest(near, distSqr, info);
535 s.getNormal(info, normal1);
536
537 // Move to intersection of
538 // - previous surface(s) : near+normal
539 // - current surface : info+normal1
540 forAll(near, i)
541 {
542 if (info[i].hit())
543 {
544 if (normal[i] != vector::zero)
545 {
546 // Have previous hit. Find intersection
547 if (mag(normal[i]&normal1[i]) < 1.0-1e-6)
548 {
549 plane pl0(near[i], normal[i], false);
550 plane pl1(info[i].point(), normal1[i], false);
551
552 plane::ray r(pl0.planeIntersect(pl1));
553 vector n = r.dir() / mag(r.dir());
554
555 // Calculate vector to move onto intersection line
556 vector d(r.refPoint()-near[i]);
557 d.removeCollinear(n);
558
559 // Trim the max distance
560 scalar magD = mag(d);
561 if (magD > SMALL)
562 {
563 scalar maxDist = Foam::sqrt(distSqr[i]);
564 if (magD > maxDist)
565 {
566 // Clip
567 d /= magD;
568 d *= maxDist;
569 }
570
571 near[i] += d;
572 normal[i] = normal1[i];
573 constraint[i].applyConstraint(normal1[i]);
574 }
575 }
576 }
577 else
578 {
579 // First hit
580 near[i] = info[i].point();
581 normal[i] = normal1[i];
582 constraint[i].applyConstraint(normal1[i]);
583 }
584 }
585 }
586
587 // Step to next surface
588 surfi = surfacesToTest.fcIndex(surfi);
589 }
590 }
591}
592
593
595(
596 const PtrList<searchableSurface>& allSurfaces,
597 const labelList& surfacesToTest,
598 const pointField& samples,
599 const scalarField& nearestDistSqr,
600 const volumeType illegalHandling,
601 labelList& nearestSurfaces,
603)
604{
605 // Initialise
606 distance.setSize(samples.size());
607 distance = -GREAT;
608
609 // Find nearest
610 List<pointIndexHit> nearestInfo;
611 findNearest
612 (
613 allSurfaces,
614 surfacesToTest,
615 samples,
616 nearestDistSqr,
617 nearestSurfaces,
618 nearestInfo
619 );
620
621 // Determine sign of nearest. Sort by surface to do this.
622 DynamicField<point> surfPoints(samples.size());
623 DynamicList<label> surfIndices(samples.size());
624
625 forAll(surfacesToTest, testI)
626 {
627 // Extract samples on this surface
628 surfPoints.clear();
629 surfIndices.clear();
630 forAll(nearestSurfaces, i)
631 {
632 if (nearestSurfaces[i] == testI)
633 {
634 surfPoints.append(samples[i]);
635 surfIndices.append(i);
636 }
637 }
638
639 // Calculate sideness of these surface points
640 List<volumeType> volType;
641 allSurfaces[surfacesToTest[testI]].getVolumeType(surfPoints, volType);
642
643 // Push back to original
644 forAll(volType, i)
645 {
646 label pointi = surfIndices[i];
647 scalar dist = samples[pointi].dist(nearestInfo[pointi].hitPoint());
648
649 volumeType vT = volType[i];
650
651 if (vT == volumeType::OUTSIDE)
652 {
653 distance[pointi] = dist;
654 }
655 else if (vT == volumeType::INSIDE)
656 {
657 distance[i] = -dist;
658 }
659 else
660 {
661 switch (illegalHandling)
662 {
664 {
665 distance[pointi] = dist;
666 break;
667 }
669 {
670 distance[pointi] = -dist;
671 break;
672 }
673 default:
674 {
676 << "getVolumeType failure,"
677 << " neither INSIDE or OUTSIDE."
678 << " point:" << surfPoints[i]
679 << " surface:"
680 << allSurfaces[surfacesToTest[testI]].name()
681 << " volType:" << vT.str()
682 << exit(FatalError);
683 break;
684 }
686 }
687 }
688 }
689}
690
691
693(
694 const PtrList<searchableSurface>& allSurfaces,
695 const labelUList& surfacesToTest
696)
697{
698 boundBox bb;
699
700 for (const label surfi : surfacesToTest)
701 {
702 bb.add(allSurfaces[surfi].bounds());
703 }
704
705 return bb;
706}
707
708
709// ************************************************************************* //
Various functions to operate on Lists.
label n
Dynamically sized Field. Similar to DynamicList, but inheriting from a Field instead of a List.
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void append(const T &val)
Append an element at the end of the list.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void append(const T &val)
Copy append an element to the end of this list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void setSize(label n)
Alias for resize().
Definition List.H:536
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition PtrList.H:67
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static const Form zero
Vector< Cmpt > & removeCollinear(const Vector< Cmpt > &unitVec)
Inplace removal of components that are collinear to the given unit vector.
Definition VectorI.H:136
A bounding box defined in terms of min/max extrema points.
Definition boundBox.H:71
void add(const boundBox &bb)
Extend to include the second box.
Definition boundBoxI.H:323
A reference point and direction.
Definition plane.H:114
const point & refPoint() const noexcept
Return the reference point.
Definition plane.H:132
const vector & dir() const noexcept
Return the direction.
Definition plane.H:137
Geometric class that creates a 3D plane and can return the intersection point between a line and the ...
Definition plane.H:91
ray planeIntersect(const plane &plane2) const
Return the cutting line between this plane and another.
Definition plane.C:304
Accumulates point constraints through successive applications of the applyConstraint function.
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const =0
A collection of tools for searchableSurfaces.
static void findNearestIntersection(const PtrList< searchableSurface > &allSurfaces, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &surface2, List< pointIndexHit > &hit2)
Find intersections of edge nearest to both endpoints.
static void signedDistance(const PtrList< searchableSurface > &allSurfaces, const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, const volumeType illegalHandling, labelList &nearestSurfaces, scalarField &distance)
Find signed distance to nearest surface. Outside is positive.
static void findAnyIntersection(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &)
Find any intersection. Return hit point information and.
static void findAllIntersections(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelListList &surfaces, List< List< pointIndexHit > > &surfaceHits)
Find all intersections in order from start to end. Returns for.
static void findNearest(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &)
Find nearest. Return -1 (and a miss()) or surface and nearest.
static boundBox bounds(const PtrList< searchableSurface > &allSurfaces, const labelUList &surfacesToTest)
Find the boundBox of the selected surfaces.
An enumeration wrapper for classification of a location as being inside/outside of a volume.
Definition volumeType.H:56
const word & str() const
The string representation of the volume type enumeration.
Definition volumeType.C:55
@ OUTSIDE
A location outside the volume.
Definition volumeType.H:66
@ INSIDE
A location inside the volume.
Definition volumeType.H:65
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
const volScalarField & p0
Definition EEqn.H:36
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const char * end
Definition SVGTools.H:223
Namespace for bounding specifications. At the moment, mostly for tables.
Namespace for OpenFOAM.
scalar distance(const vector &p1, const vector &p2)
Definition curveTools.C:12
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Binary search to find the index of the last element in a sorted list that is less than value.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
Definition point.H:37
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
Vector< scalar > vector
Definition vector.H:57
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
List< scalar > scalarList
List of scalar.
Definition scalarList.H:32
volScalarField & e
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
scalarField samples(nIntervals, Zero)