autoDensity.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) 2012-2016 OpenFOAM Foundation
9 Copyright (C) 2018-2020 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
29#include "autoDensity.H"
31
32// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33
34namespace Foam
35{
36
37// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38
39defineTypeNameAndDebug(autoDensity, 0);
41(
42 initialPointsMethod,
43 autoDensity,
44 dictionary
45);
46
47
48// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49
50void Foam::autoDensity::writeOBJ
51(
52 const treeBoundBox& bb,
53 fileName name
54) const
55{
56 OFstream str(time().path()/name + ".obj");
57
58 Pout<< "Writing " << str.name() << endl;
59
60 pointField bbPoints(bb.points());
61
62 for (const point& pt : bbPoints)
63 {
64 meshTools::writeOBJ(str, pt);
65 }
66
67 for (const edge& e : treeBoundBox::edges)
68 {
69 str << "l " << e[0] + 1 << ' ' << e[1] + 1 << nl;
70 }
71}
72
73
74bool Foam::autoDensity::combinedOverlaps(const treeBoundBox& box) const
75{
76 if (Pstream::parRun())
77 {
78 return
79 decomposition().overlapsThisProcessor(box)
80 || geometryToConformTo().overlaps(box);
81 }
82
83 return geometryToConformTo().overlaps(box);
84}
85
86
87bool Foam::autoDensity::combinedInside(const point& p) const
88{
89 if (Pstream::parRun())
90 {
91 return
92 decomposition().positionOnThisProcessor(p)
93 && geometryToConformTo().inside(p);
94 }
95
96 return geometryToConformTo().inside(p);
97}
98
99
100Foam::Field<bool> Foam::autoDensity::combinedWellInside
101(
102 const pointField& pts,
103 const scalarField& sizes
104) const
105{
106 if (!Pstream::parRun())
107 {
108 return geometryToConformTo().wellInside
109 (
110 pts,
111 minimumSurfaceDistanceCoeffSqr_*sqr(sizes)
112 );
113 }
114
115 Field<bool> inside(pts.size(), true);
116
117 // Perform AND operation between testing the surfaces and the previous
118 // field, i.e the parallel result, or in serial, with true.
119
120 Field<bool> insideA
121 (
122 geometryToConformTo().wellInside
123 (
124 pts,
125 minimumSurfaceDistanceCoeffSqr_*sqr(sizes)
126 )
127 );
128
129 Field<bool> insideB
130 (
131 decomposition().positionOnThisProcessor(pts)
132 );
133
134 // inside = insideA && insideB;
135
136 // Pout<< insideA << nl << insideB << endl;
137
138 forAll(inside, i)
139 {
140 // if (inside[i] != (insideA[i] && insideB[i]))
141 // {
142 // Pout<< i << " not equal " << " "
143 // << pts[i] << " " << sizes[i] << " "
144 // << insideA[i] << " "
145 // << insideB[i] << " "
146 // << inside[i]
147 // << endl;
148 // }
149
150 inside[i] = (insideA[i] && insideB[i]);
151 }
152
153 return inside;
154}
155
156
157bool Foam::autoDensity::combinedWellInside
158(
159 const point& p,
160 scalar size
161) const
162{
163 bool inside = true;
164
165 if (Pstream::parRun())
166 {
167 inside = decomposition().positionOnThisProcessor(p);
168 }
169
170 // Perform AND operation between testing the surfaces and the previous
171 // result, i.e the parallel result, or in serial, with true.
172 inside =
173 inside
174 && geometryToConformTo().wellInside
175 (
176 p,
177 minimumSurfaceDistanceCoeffSqr_*sqr(size)
178 );
179
180 return inside;
181}
182
183
184Foam::label Foam::autoDensity::recurseAndFill
185(
186 DynamicList<Vb::Point>& initialPoints,
187 const treeBoundBox& bb,
188 label levelLimit,
189 word recursionName
190) const
191{
192 label treeDepth = 0;
193
194 for (direction i = 0; i < 8; i++)
195 {
196 treeBoundBox subBB = bb.subBbox(i);
197
198 word newName = recursionName + "_" + Foam::name(i);
199
200 conformalVoronoiMesh::timeCheck(time(), newName, debug);
201
202 if (combinedOverlaps(subBB))
203 {
204 if (levelLimit > 0)
205 {
206 treeDepth =
207 max
208 (
209 treeDepth,
210 recurseAndFill
211 (
212 initialPoints,
213 subBB,
214 levelLimit - 1,
215 newName
216 )
217 );
218 }
219 else
220 {
221 if (debug)
222 {
224 (
225 subBB,
226 word(newName + "_overlap")
227 );
228
229 Pout<< newName + "_overlap " << subBB << endl;
230 }
231
232 if (!fillBox(initialPoints, subBB, true))
233 {
234 treeDepth =
235 max
236 (
237 treeDepth,
238 recurseAndFill
239 (
240 initialPoints,
241 subBB,
242 levelLimit - 1,
243 newName
244 )
245 );
246 }
247 }
248 }
249 else if (combinedInside(subBB.centre()))
250 {
251 if (debug)
252 {
254 (
255 subBB,
256 newName + "_inside"
257 );
258
259 Pout<< newName + "_inside " << subBB << endl;
260 }
261
262 if (!fillBox(initialPoints, subBB, false))
263 {
264 treeDepth =
265 max
266 (
267 treeDepth,
268 recurseAndFill
269 (
270 initialPoints,
271 subBB,
272 levelLimit - 1,
273 newName
274 )
275 );
276 }
277 }
278 else
279 {
280 if (debug)
281 {
283 (
284 subBB,
285 newName + "_outside"
286 );
287 }
288 }
289 }
290
291 return treeDepth + 1;
292}
293
294
295bool Foam::autoDensity::fillBox
296(
297 DynamicList<Vb::Point>& initialPoints,
298 const treeBoundBox& bb,
299 bool overlapping
300) const
301{
302 const conformationSurfaces& geometry = geometryToConformTo();
303
304 label initialSize = initialPoints.size();
305
306 scalar maxCellSize = -GREAT;
307
308 scalar minCellSize = GREAT;
309
310 scalar maxDensity = 1/pow3(minCellSize);
311
312 scalar volumeAdded = 0.0;
313
314 const point& min = bb.min();
315
316 vector span = bb.span();
317
318 scalar totalVolume = bb.volume();
319
320 label trialPoints = 0;
321
322 bool wellInside = false;
323
324 if (!overlapping)
325 {
326 // Check the nearest point on the surface to the box, if it is far
327 // enough away, then the surface sampling of the box can be skipped.
328 // Checking if the nearest piece of surface is at least 1.5*bb.span away
329 // from the bb.centre()
330
331 pointIndexHit surfHit;
332 label hitSurface;
333
334 geometry.findSurfaceNearest
335 (
336 bb.centre(),
337 2.25*magSqr(span),
338 surfHit,
339 hitSurface
340 );
341
342 if (!surfHit.hit())
343 {
344 if (debug)
345 {
346 Pout<< "box wellInside, no need to sample surface." << endl;
347 }
348
349 wellInside = true;
350 }
351 }
352
353 if (!overlapping && !wellInside)
354 {
355 // If this is an inside box then it is possible to fill points very
356 // close to the boundary, to prevent this, check the corners and sides
357 // of the box so ensure that they are "wellInside". If not, set as an
358 // overlapping box.
359
360 pointField corners(bb.points());
361
362 scalarField cornerSizes = cellShapeControls().cellSize(corners);
363
364 Field<bool> insideCorners = combinedWellInside(corners, cornerSizes);
365
366 // Pout<< corners << nl << cornerSizes << nl << insideCorners << endl;
367
368 forAll(insideCorners, i)
369 {
370 // Use the sizes to improve the min/max cell size estimate
371 scalar s = cornerSizes[i];
372
373 if (s > maxCellSize)
374 {
375 maxCellSize = s;
376 }
377
378 if (s < minCellSize)
379 {
380 minCellSize = max(s, minCellSizeLimit_);
381 }
382
383 if (maxCellSize/minCellSize > maxSizeRatio_)
384 {
385 if (debug)
386 {
387 Pout<< "Abort fill at corner sample stage,"
388 << " minCellSize " << minCellSize
389 << " maxCellSize " << maxCellSize
390 << " maxSizeRatio " << maxCellSize/minCellSize
391 << endl;
392 }
393
394 return false;
395 }
396
397 if (!insideCorners[i])
398 {
399 // If one or more corners is not "wellInside", then treat this
400 // as an overlapping box.
401
402 if (debug)
403 {
404 Pout<< "Inside box found to have some non-wellInside "
405 << "corners, using overlapping fill."
406 << endl;
407 }
408
409 overlapping = true;
410
411 break;
412 }
413 }
414
415 if (!overlapping)
416 {
417 vector delta = span/(surfRes_ - 1);
418
419 label nLine = 6*(surfRes_ - 2);
420
421 pointField linePoints(nLine, Zero);
422
423 scalarField lineSizes(nLine, Zero);
424
425 for (label i = 0; i < surfRes_; i++)
426 {
427 label lPI = 0;
428
429 for (label j = 1; j < surfRes_ - 1 ; j++)
430 {
431 linePoints[lPI++] =
432 min
433 + vector(0, delta.y()*i, delta.z()*j);
434
435 linePoints[lPI++] =
436 min
437 + vector
438 (
439 delta.x()*(surfRes_ - 1),
440 delta.y()*i,
441 delta.z()*j
442 );
443
444 linePoints[lPI++] =
445 min
446 + vector(delta.x()*j, 0, delta.z()*i);
447
448 linePoints[lPI++] =
449 min
450 + vector
451 (
452 delta.x()*j,
453 delta.y()*(surfRes_ - 1),
454 delta.z()*i
455 );
456
457 linePoints[lPI++] =
458 min
459 + vector(delta.x()*i, delta.y()*j, 0);
460
461 linePoints[lPI++] =
462 min
463 + vector
464 (
465 delta.x()*i,
466 delta.y()*j,
467 delta.z()*(surfRes_ - 1)
468 );
469 }
470
471 lineSizes = cellShapeControls().cellSize(linePoints);
472
473 Field<bool> insideLines = combinedWellInside
474 (
475 linePoints,
476 lineSizes
477 );
478
479 forAll(insideLines, i)
480 {
481 // Use the sizes to improve the min/max cell size estimate
482 scalar s = lineSizes[i];
483
484 if (s > maxCellSize)
485 {
486 maxCellSize = s;
487 }
488
489 if (s < minCellSize)
490 {
491 minCellSize = max(s, minCellSizeLimit_);
492 }
493
494 if (maxCellSize/minCellSize > maxSizeRatio_)
495 {
496 if (debug)
497 {
498 Pout<< "Abort fill at surface sample stage, "
499 << " minCellSize " << minCellSize
500 << " maxCellSize " << maxCellSize
501 << " maxSizeRatio " << maxCellSize/minCellSize
502 << endl;
503 }
504
505 return false;
506 }
507
508 if (!insideLines[i])
509 {
510 // If one or more surface points is not "wellInside",
511 // then treat this as an overlapping box.
512 overlapping = true;
513
514 if (debug)
515 {
516 Pout<< "Inside box found to have some non-"
517 << "wellInside surface points, using "
518 << "overlapping fill."
519 << endl;
520 }
521
522 break;
523 }
524 }
525 }
526 }
527 }
528
529 if (overlapping)
530 {
531 // Sample the box to find an estimate of the min size, and a volume
532 // estimate when overlapping == true.
533
534 pointField samplePoints
535 (
536 volRes_*volRes_*volRes_,
537 Zero
538 );
539
540 vector delta = span/volRes_;
541
542 label pI = 0;
543
544 for (label i = 0; i < volRes_; i++)
545 {
546 for (label j = 0; j < volRes_; j++)
547 {
548 for (label k = 0; k < volRes_; k++)
549 {
550 // Perturb the points to avoid creating degenerate positions
551 // in the Delaunay tessellation.
552
553 samplePoints[pI++] =
554 min
555 + vector
556 (
557 delta.x()
558 *(i + 0.5 + 0.1*(rndGen().sample01<scalar>() - 0.5)),
559 delta.y()
560 *(j + 0.5 + 0.1*(rndGen().sample01<scalar>() - 0.5)),
561 delta.z()
562 *(k + 0.5 + 0.1*(rndGen().sample01<scalar>() - 0.5))
563 );
564 }
565 }
566 }
567
568 // Randomise the order of the points to (potentially) improve the speed
569 // of assessing the density ratio, and prevent a box being filled from a
570 // corner when only some these points are required.
571 shuffle(samplePoints);
572
573 scalarField sampleSizes = cellShapeControls().cellSize(samplePoints);
574
575 Field<bool> insidePoints = combinedWellInside
576 (
577 samplePoints,
578 sampleSizes
579 );
580
581 label nInside = 0;
582
584 {
585 if (insidePoints[i])
586 {
587 nInside++;
588
589 scalar s = sampleSizes[i];
590
591 if (s > maxCellSize)
592 {
593 maxCellSize = s;
594 }
595
596 if (s < minCellSize)
597 {
598 minCellSize = max(s, minCellSizeLimit_);
599 }
600
601 if (maxCellSize/minCellSize > maxSizeRatio_)
602 {
603 if (debug)
604 {
605 Pout<< "Abort fill at sample stage,"
606 << " minCellSize " << minCellSize
607 << " maxCellSize " << maxCellSize
608 << " maxSizeRatio " << maxCellSize/minCellSize
609 << endl;
610 }
611
612 return false;
613 }
614 }
615 }
616
617 if (nInside == 0)
618 {
619 if (debug)
620 {
621 Pout<< "No sample points found inside box" << endl;
622 }
623
624 return true;
625 }
626
627 if (debug)
628 {
629 Pout<< scalar(nInside)/scalar(samplePoints.size())
630 << " full overlapping box" << endl;
631 }
632
633 totalVolume *= scalar(nInside)/scalar(samplePoints.size());
634
635 if (debug)
636 {
637 Pout<< "Total volume to fill = " << totalVolume << endl;
638 }
639
640 // Using the sampledPoints as the first test locations as they are
641 // randomly shuffled, but uniformly sampling space and have wellInside
642 // and size data already
643
644 maxDensity = 1/pow3(max(minCellSize, SMALL));
645
647 {
648 if (insidePoints[i])
649 {
650 trialPoints++;
651
652 const point& p = samplePoints[i];
653
654 scalar localSize = sampleSizes[i];
655
656 scalar localDensity = 1/pow3(localSize);
657
658 // No need to look at max/min cell size here, already handled
659 // by sampling
660
661 // Accept possible placements proportional to the relative
662 // local density
663
664 // TODO - is there a lot of cost in the 1/density calc? Could
665 // assess on
666 // (1/maxDensity)/(1/localDensity) = minVolume/localVolume
667 if (localDensity/maxDensity > rndGen().sample01<scalar>())
668 {
669 scalar localVolume = 1/localDensity;
670
671 if (volumeAdded + localVolume > totalVolume)
672 {
673 // Add the final box with a probability of to the ratio
674 // of the remaining volume to the volume to be added,
675 // i.e. insert a box of volume 0.5 into a remaining
676 // volume of 0.1 20% of the time.
677 scalar addProbability =
678 (totalVolume - volumeAdded)/localVolume;
679
680 scalar r = rndGen().sample01<scalar>();
681
682 if (debug)
683 {
684 Pout<< "totalVolume " << totalVolume << nl
685 << "volumeAdded " << volumeAdded << nl
686 << "localVolume " << localVolume << nl
687 << "addProbability " << addProbability << nl
688 << "random " << r
689 << endl;
690 }
691
692 if (addProbability > r)
693 {
694 // Place this volume before finishing filling this
695 // box
696
697 // Pout<< "Final volume probability break accept"
698 // << endl;
699
700 initialPoints.append
701 (
702 Vb::Point(p.x(), p.y(), p.z())
703 );
704
705 volumeAdded += localVolume;
706 }
707
708 break;
709 }
710
711 initialPoints.append(Vb::Point(p.x(), p.y(), p.z()));
712
713 volumeAdded += localVolume;
714 }
715 }
716 }
717 }
718
719 if (volumeAdded < totalVolume)
720 {
721 if (debug)
722 {
723 Pout<< "Adding random points, remaining volume "
724 << totalVolume - volumeAdded
725 << endl;
726 }
727
728 maxDensity = 1/pow3(max(minCellSize, SMALL));
729
730 while (true)
731 {
732 trialPoints++;
733
734 point p = min + cmptMultiply(span, rndGen().sample01<vector>());
735
736 scalar localSize = cellShapeControls().cellSize(p);
737
738 bool insidePoint = false;
739
740 if (!overlapping)
741 {
742 insidePoint = true;
743 }
744 else
745 {
746 // Determine if the point is "wellInside" the domain
747 insidePoint = combinedWellInside(p, localSize);
748 }
749
750 if (insidePoint)
751 {
752 if (localSize > maxCellSize)
753 {
754 maxCellSize = localSize;
755 }
756
757 if (localSize < minCellSize)
758 {
759 minCellSize = max(localSize, minCellSizeLimit_);
760
761 localSize = minCellSize;
762
763 // 1/(minimum cell size)^3, gives the maximum permissible
764 // point density
765 maxDensity = 1/pow3(max(minCellSize, SMALL));
766 }
767
768 if (maxCellSize/minCellSize > maxSizeRatio_)
769 {
770 if (debug)
771 {
772 Pout<< "Abort fill at random fill stage,"
773 << " minCellSize " << minCellSize
774 << " maxCellSize " << maxCellSize
775 << " maxSizeRatio " << maxCellSize/minCellSize
776 << endl;
777 }
778
779 // Discard any points already filled into this box by
780 // setting size of initialPoints back to its starting value
781 initialPoints.resize(initialSize);
782
783 return false;
784 }
785
786 scalar localDensity = 1/pow3(max(localSize, SMALL));
787
788 // Accept possible placements proportional to the relative local
789 // density
790 if (localDensity/maxDensity > rndGen().sample01<scalar>())
791 {
792 scalar localVolume = 1/localDensity;
793
794 if (volumeAdded + localVolume > totalVolume)
795 {
796 // Add the final box with a probability of to the ratio
797 // of the remaining volume to the volume to be added,
798 // i.e. insert a box of volume 0.5 into a remaining
799 // volume of 0.1 20% of the time.
800 scalar addProbability =
801 (totalVolume - volumeAdded)/localVolume;
802
803 scalar r = rndGen().sample01<scalar>();
804
805 if (debug)
806 {
807 Pout<< "totalVolume " << totalVolume << nl
808 << "volumeAdded " << volumeAdded << nl
809 << "localVolume " << localVolume << nl
810 << "addProbability " << addProbability << nl
811 << "random " << r
812 << endl;
813 }
814
815 if (addProbability > r)
816 {
817 // Place this volume before finishing filling this
818 // box
819
820 // Pout<< "Final volume probability break accept"
821 // << endl;
822
823 initialPoints.append
824 (
825 Vb::Point(p.x(), p.y(), p.z())
826 );
827
828 volumeAdded += localVolume;
829 }
830
831 break;
832 }
833
834 initialPoints.append(Vb::Point(p.x(), p.y(), p.z()));
835
836 volumeAdded += localVolume;
837 }
838 }
839 }
840 }
841
842 globalTrialPoints_ += trialPoints;
843
844 if (debug)
845 {
846 Pout<< trialPoints
847 << " locations queried, " << initialPoints.size() - initialSize
848 << " points placed, ("
849 << scalar(initialPoints.size() - initialSize)
850 /scalar(max(trialPoints, 1))
851 << " success rate)." << nl
852 << "minCellSize " << minCellSize
853 << ", maxCellSize " << maxCellSize
854 << ", ratio " << maxCellSize/minCellSize
855 << nl << endl;
856 }
857
858 return true;
859}
860
861
862// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
863
864autoDensity::autoDensity
865(
866 const dictionary& initialPointsDict,
867 const Time& runTime,
868 Random& rndGen,
869 const conformationSurfaces& geometryToConformTo,
870 const cellShapeControl& cellShapeControls,
871 const autoPtr<backgroundMeshDecomposition>& decomposition
872)
873:
874 initialPointsMethod
875 (
876 typeName,
877 initialPointsDict,
878 runTime,
879 rndGen,
880 geometryToConformTo,
881 cellShapeControls,
882 decomposition
883 ),
884 globalTrialPoints_(0),
885 minCellSizeLimit_
886 (
887 detailsDict().getOrDefault<scalar>("minCellSizeLimit", 0)
888 ),
889 minLevels_(detailsDict().get<label>("minLevels")),
890 maxSizeRatio_(detailsDict().get<scalar>("maxSizeRatio")),
891 volRes_(detailsDict().get<label>("sampleResolution")),
892 surfRes_
893 (
894 detailsDict().getOrDefault<label>("surfaceSampleResolution", volRes_)
895 )
896{
897 if (maxSizeRatio_ <= 1.0)
898 {
899 maxSizeRatio_ = 2.0;
900
902 << "The maxSizeRatio must be greater than one to be sensible, "
903 << "setting to " << maxSizeRatio_
904 << endl;
905 }
906}
907
908
909// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
910
911List<Vb::Point> autoDensity::initialPoints() const
912{
913 treeBoundBox hierBB;
914
915 // Pick up the bounds of this processor, or the whole geometry, depending
916 // on whether this is a parallel run.
917 if (Pstream::parRun())
918 {
919 hierBB = decomposition().procBounds();
920 }
921 else
922 {
923 // Extend the global box to move it off large plane surfaces
924 hierBB = geometryToConformTo().globalBounds().extend
925 (
926 rndGen(),
927 1e-6
928 );
929 }
930
931 DynamicList<Vb::Point> initialPoints;
932
933 Info<< nl << " " << typeName << endl;
934
935 if (debug)
936 {
937 Pout<< " Filling box " << hierBB << endl;
938 }
939
940 label treeDepth = recurseAndFill
941 (
942 initialPoints,
943 hierBB,
944 minLevels_ - 1,
945 "recursionBox"
946 );
947
948 initialPoints.shrink();
949
950 label nInitialPoints = initialPoints.size();
951
952 if (Pstream::parRun())
953 {
954 reduce(nInitialPoints, sumOp<label>());
955 reduce(globalTrialPoints_, sumOp<label>());
956 }
957
959 << indent << nInitialPoints << " points placed" << nl
960 << indent << globalTrialPoints_ << " locations queried" << nl
961 << indent
962 << scalar(nInitialPoints)/scalar(max(globalTrialPoints_, 1))
963 << " success rate" << nl
964 << indent
965 << returnReduce(treeDepth, maxOp<label>())
966 << " levels of recursion (maximum)"
968 << endl;
969
970 return initialPoints;
971}
972
973
974// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
975
976} // End namespace Foam
977
978// ************************************************************************* //
label k
scalar delta
Y[inertIndex] max(0.0)
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
reduce(hasMovingMesh, orOp< bool >())
Generic templated field type.
Definition: Field.H:82
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
Type sample01()
Return a sample whose components lie in the range [0,1].
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
static void timeCheck(const Time &runTime, const string &description=string::null, const bool check=true)
Write the elapsedCpuTime and memory usage, with an optional.
static const edgeList edges
Edge to point addressing.
Definition: treeBoundBox.H:154
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
volScalarField & p
engineTime & runTime
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))
#define WarningInFunction
Report a warning using Foam::Warning.
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Namespace for OpenFOAM.
void shuffle(UList< T > &list)
Randomise the list order.
Definition: UList.C:370
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
dimensionedSymmTensor sqr(const dimensionedVector &dv)
PointIndexHit< point > pointIndexHit
A PointIndexHit for 3D points.
Definition: pointIndexHit.H:46
dimensionedScalar pow3(const dimensionedScalar &ds)
messageStream Info
Information stream (stdout output on master, null elsewhere)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
vector point
Point is a vector.
Definition: point.H:43
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:349
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:342
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
uint8_t direction
Definition: direction.H:56
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
dimensioned< Type > cmptMultiply(const dimensioned< Type > &, const dimensioned< Type > &)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Vector< scalar > vector
Definition: vector.H:61
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:356
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
insidePoints((1 2 3))
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Random rndGen
Definition: createFields.H:23