SprayCloudI.H
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 "SortableList.H"
27 
28 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
29 
30 template<class CloudType>
31 inline const Foam::SprayCloud<CloudType>&
33 {
34  return cloudCopyPtr_();
35 }
36 
37 
38 template<class CloudType>
41 {
42  return atomisationModel_;
43 }
44 
45 
46 template<class CloudType>
49 {
50  return atomisationModel_();
51 }
52 
53 
54 template<class CloudType>
57 {
58  return breakupModel_;
59 }
60 
61 
62 template<class CloudType>
65 {
66  return breakupModel_();
67 }
68 
69 
70 template<class CloudType>
72 (
73  const scalar fraction
74 ) const
75 {
76  if ((fraction < 0) || (fraction > 1))
77  {
79  << "fraction should be in the range 0 < fraction < 1"
80  << exit(FatalError);
81  }
82 
83  const polyMesh& mesh = this->mesh();
84 
85  scalar distance = 0.0;
86 
87  const label nParcel = this->size();
88  globalIndex globalParcels(nParcel);
89  const label nParcelSum = globalParcels.size();
90 
91  if (nParcelSum == 0)
92  {
93  return distance;
94  }
95 
96  // lists of parcels mass and distance from initial injection point
97  List<List<scalar>> procMass(Pstream::nProcs());
98  List<List<scalar>> procDist(Pstream::nProcs());
99 
100  List<scalar>& mass = procMass[Pstream::myProcNo()];
101  List<scalar>& dist = procDist[Pstream::myProcNo()];
102 
103  mass.setSize(nParcel);
104  dist.setSize(nParcel);
105 
106  label i = 0;
107  scalar mSum = 0.0;
108  forAllConstIter(typename SprayCloud<CloudType>, *this, iter)
109  {
110  const parcelType& p = iter();
111  scalar m = p.nParticle()*p.mass();
112  scalar d = mag(p.position(mesh) - p.position0());
113  mSum += m;
114 
115  mass[i] = m;
116  dist[i] = d;
117 
118  i++;
119  }
120 
121  // calculate total mass across all processors
122  reduce(mSum, sumOp<scalar>());
123  Pstream::gatherList(procMass);
124  Pstream::gatherList(procDist);
125 
126  if (Pstream::master())
127  {
128  // flatten the mass lists
129  List<scalar> allMass(nParcelSum, 0.0);
130  SortableList<scalar> allDist(nParcelSum, 0.0);
131  for (label proci = 0; proci < Pstream::nProcs(); proci++)
132  {
134  (
135  allMass,
136  globalParcels.localSize(proci),
137  globalParcels.offset(proci)
138  ) = procMass[proci];
139 
140  // flatten the distance list
142  (
143  allDist,
144  globalParcels.localSize(proci),
145  globalParcels.offset(proci)
146  ) = procDist[proci];
147  }
148 
149  // sort allDist distances into ascending order
150  // note: allMass masses are left unsorted
151  allDist.sort();
152 
153  if (nParcelSum > 1)
154  {
155  const scalar mLimit = fraction*mSum;
156  const labelList& indices = allDist.indices();
157 
158  if (mLimit > (mSum - allMass[indices.last()]))
159  {
160  distance = allDist.last();
161  }
162  else
163  {
164  // assuming that 'fraction' is generally closer to 1 than 0,
165  // loop through in reverse distance order
166  const scalar mThreshold = (1.0 - fraction)*mSum;
167  scalar mCurrent = 0.0;
168  label i0 = 0;
169 
170  forAllReverse(indices, i)
171  {
172  label indI = indices[i];
173 
174  mCurrent += allMass[indI];
175 
176  if (mCurrent > mThreshold)
177  {
178  i0 = i;
179  break;
180  }
181  }
182 
183  if (i0 == indices.size() - 1)
184  {
185  distance = allDist.last();
186  }
187  else
188  {
189  // linearly interpolate to determine distance
190  scalar alpha = (mCurrent - mThreshold)/allMass[indices[i0]];
191  distance =
192  allDist[i0] + alpha*(allDist[i0+1] - allDist[i0]);
193  }
194  }
195  }
196  else
197  {
198  distance = allDist.first();
199  }
200  }
201 
202  Pstream::scatter(distance);
203 
204  return distance;
205 }
206 
207 
208 // ************************************************************************* //
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:446
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
Templated atomisation model class.
Templated break-up model class.
Definition: BreakupModel.H:55
ParcelType parcelType
Type of parcel the cloud was instantiated for.
Definition: DSMCCloud.H:221
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 size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
A list that is sorted upon construction or when explicitly requested with the sort() method.
Definition: SortableList.H:55
const labelList & indices() const
Return the list of sorted indices. Updated every sort.
Definition: SortableList.H:96
void sort()
(stable) sort the list (if changed after construction time)
Definition: SortableList.C:112
Templated base class for spray cloud.
Definition: SprayCloud.H:75
const BreakupModel< SprayCloud< CloudType > > & breakup() const
Return const-access to the breakup model.
Definition: SprayCloudI.H:56
const SprayCloud & cloudCopy() const
Return a reference to the cloud copy.
Definition: SprayCloudI.H:32
scalar penetration(const scalar fraction) const
Penetration for fraction [0-1] of the current total mass.
Definition: SprayCloudI.H:72
const AtomisationModel< SprayCloud< CloudType > > & atomisation() const
Return const-access to the atomisation model.
Definition: SprayCloudI.H:40
A List obtained as a section of another List.
Definition: SubList.H:56
T & first()
Return the first element of the list.
Definition: UListI.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:128
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
label localSize() const
My local size.
Definition: globalIndexI.H:60
label size() const
Global sum of localSizes.
Definition: globalIndexI.H:66
label offset(const label proci) const
Start of proci data.
Definition: globalIndexI.H:48
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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 reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensioned< scalar > mag(const dimensioned< Type > &)
error FatalError
volScalarField & p