Loading...
Searching...
No Matches
PairSpringSliderDashpot.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) 2018-2019 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
31// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32
33template<class CloudType>
34void Foam::PairSpringSliderDashpot<CloudType>::findMinMaxProperties
35(
36 scalar& RMin,
37 scalar& rhoMax,
38 scalar& UMagMax
39) const
40{
41 RMin = VGREAT;
42 rhoMax = -VGREAT;
43 UMagMax = -VGREAT;
44
45 for (const typename CloudType::parcelType& p : this->owner())
46 {
47 // Finding minimum diameter to avoid excessive arithmetic
48
49 scalar dEff = p.d();
50
51 if (useEquivalentSize_)
52 {
53 dEff *= cbrt(p.nParticle()*volumeFactor_);
54 }
55
56 RMin = min(dEff, RMin);
57
58 rhoMax = max(p.rho(), rhoMax);
59
60 UMagMax = max
61 (
62 mag(p.U()) + mag(p.omega())*dEff/2,
63 UMagMax
64 );
65 }
66
67 // Transform the minimum diameter into minimum radius
68 // rMin = dMin/2
69 // then rMin into minimum R,
70 // 1/RMin = 1/rMin + 1/rMin,
71 // RMin = rMin/2 = dMin/4
72
73 RMin /= 4.0;
74
75 // Multiply by two to create the worst-case relative velocity
76
77 UMagMax = 2*UMagMax;
78}
79
80
81// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
82
83template<class CloudType>
85(
86 const dictionary& dict,
88)
89:
91 Estar_(),
92 Gstar_(),
93 alpha_(this->coeffDict().getScalar("alpha")),
94 b_(this->coeffDict().getScalar("b")),
95 mu_(this->coeffDict().getScalar("mu")),
96 cohesionEnergyDensity_
97 (
98 this->coeffDict().getScalar("cohesionEnergyDensity")
99 ),
100 cohesion_(false),
101 collisionResolutionSteps_
102 (
103 this->coeffDict().getScalar("collisionResolutionSteps")
104 ),
105 volumeFactor_(1.0),
106 useEquivalentSize_(Switch(this->coeffDict().lookup("useEquivalentSize")))
107{
108 if (useEquivalentSize_)
109 {
110 this->coeffDict().readEntry("volumeFactor", volumeFactor_);
111 }
112
113 scalar nu = this->owner().constProps().poissonsRatio();
114
115 scalar E = this->owner().constProps().youngsModulus();
116
117 Estar_ = E/(2.0*(1.0 - sqr(nu)));
118
119 scalar G = E/(2.0*(1.0 + nu));
120
121 Gstar_ = G/(2.0*(2.0 - nu));
122
123 cohesion_ = (mag(cohesionEnergyDensity_) > VSMALL);
124}
125
126
127// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
128
129template<class CloudType>
131{
132 return true;
133}
134
135
136template<class CloudType>
138{
139 if (!(this->owner().size()))
140 {
141 return 1;
142 }
143
144 scalar RMin;
145 scalar rhoMax;
146 scalar UMagMax;
147
148 findMinMaxProperties(RMin, rhoMax, UMagMax);
149
150 // Note: pi^(7/5)*(5/4)^(2/5) = 5.429675
151 scalar minCollisionDeltaT =
152 5.429675
153 *RMin
154 *pow(rhoMax/(Estar_*sqrt(UMagMax) + VSMALL), 0.4)
155 /collisionResolutionSteps_;
156
157 return ceil(this->owner().time().deltaTValue()/minCollisionDeltaT);
158}
159
160
161template<class CloudType>
163(
164 typename CloudType::parcelType& pA,
165 typename CloudType::parcelType& pB
166) const
167{
168 vector r_AB = (pA.position() - pB.position());
169
170 scalar dAEff = pA.d();
171
172 if (useEquivalentSize_)
173 {
174 dAEff *= cbrt(pA.nParticle()*volumeFactor_);
175 }
176
177 scalar dBEff = pB.d();
178
179 if (useEquivalentSize_)
180 {
181 dBEff *= cbrt(pB.nParticle()*volumeFactor_);
182 }
183
184 scalar r_AB_mag = mag(r_AB);
185
186 scalar normalOverlapMag = 0.5*(dAEff + dBEff) - r_AB_mag;
187
188 if (normalOverlapMag > 0)
189 {
190 // Particles in collision
191
192 // Force coefficient
193 scalar forceCoeff = this->forceCoeff(pA, pB);
194
195 vector rHat_AB = r_AB/(r_AB_mag + VSMALL);
196
197 vector U_AB = pA.U() - pB.U();
198
199 // Effective radius
200 scalar R = 0.5*dAEff*dBEff/(dAEff + dBEff);
201
202 // Effective mass
203 scalar M = pA.mass()*pB.mass()/(pA.mass() + pB.mass());
204
205 scalar kN = (4.0/3.0)*sqrt(R)*Estar_;
206
207 scalar etaN = alpha_*sqrt(M*kN)*pow025(normalOverlapMag);
208
209 // Normal force
210 vector fN_AB =
211 rHat_AB
212 *(kN*pow(normalOverlapMag, b_) - etaN*(U_AB & rHat_AB));
213
214 // Cohesion force, energy density multiplied by the area of
215 // particle-particle overlap
216 if (cohesion_)
217 {
218 fN_AB +=
219 -cohesionEnergyDensity_
220 *overlapArea(dAEff/2.0, dBEff/2.0, r_AB_mag)
221 *rHat_AB;
222 }
223
224 fN_AB *= forceCoeff;
225
226 pA.f() += fN_AB;
227 pB.f() += -fN_AB;
228
229 vector USlip_AB =
230 U_AB - (U_AB & rHat_AB)*rHat_AB
231 - ((dAEff/2*pA.omega() + dBEff/2*pB.omega()) ^ rHat_AB);
232
233 scalar deltaT = this->owner().mesh().time().deltaTValue();
234
235 vector& tangentialOverlap_AB =
236 pA.collisionRecords().matchPairRecord
237 (
238 pB.origProc(),
239 pB.origId()
240 ).collisionData();
241
242 vector& tangentialOverlap_BA =
243 pB.collisionRecords().matchPairRecord
244 (
245 pA.origProc(),
246 pA.origId()
247 ).collisionData();
248
249 vector deltaTangentialOverlap_AB = USlip_AB*deltaT;
250
251 tangentialOverlap_AB += deltaTangentialOverlap_AB;
252 tangentialOverlap_BA += -deltaTangentialOverlap_AB;
253
254 scalar tangentialOverlapMag = mag(tangentialOverlap_AB);
255
256 if (tangentialOverlapMag > VSMALL)
257 {
258 scalar kT = 8.0*sqrt(R*normalOverlapMag)*Gstar_;
259
260 scalar etaT = etaN;
261
262 // Tangential force
263 vector fT_AB;
264
265 if (kT*tangentialOverlapMag > mu_*mag(fN_AB))
266 {
267 // Tangential force greater than sliding friction,
268 // particle slips
269
270 fT_AB = -mu_*mag(fN_AB)*USlip_AB/mag(USlip_AB);
271
272 tangentialOverlap_AB = Zero;
273 tangentialOverlap_BA = Zero;
274 }
275 else
276 {
277 fT_AB = - kT*tangentialOverlap_AB - etaT*USlip_AB;
278 }
279
280 fT_AB *= forceCoeff;
281
282 pA.f() += fT_AB;
283 pB.f() += -fT_AB;
284
285 pA.torque() += (dAEff/2*-rHat_AB) ^ fT_AB;
286 pB.torque() += (dBEff/2*rHat_AB) ^ -fT_AB;
287 }
288 }
289}
290
291
292// ************************************************************************* //
#define R(A, B, C, D, E, F, K, M)
#define M(I)
const List< typename ParcelType::constantProperties > & constProps() const
Return all of the constant properties.
Definition DSMCCloudI.H:91
const vector & U() const
Return const access to velocity.
Templated pair interaction class.
Definition PairModel.H:52
const dictionary & coeffDict() const
Return the coefficients dictionary.
Definition PairModel.C:82
const dictionary & dict() const
Return the dictionary.
Definition PairModel.C:75
scalar forceCoeff(typename CloudType::parcelType &pA, typename CloudType::parcelType &pB) const
Return the force coefficient based on the forceRampTime_.
Definition PairModel.C:90
const CloudType & owner() const
Return the owner cloud object.
Definition PairModel.C:68
PairModel(CloudType &owner)
Construct null from cloud owner.
Definition PairModel.C:28
virtual label nSubCycles() const
For PairModels that control the timestep, calculate the.
scalar overlapArea(scalar rA, scalar rB, scalar rAB) const
Return the area of overlap between two spheres of radii rA and rB,.
PairSpringSliderDashpot(const dictionary &dict, CloudType &cloud)
Construct from dictionary.
virtual void evaluatePair(typename CloudType::parcelType &pA, typename CloudType::parcelType &pB) const
Calculate the pair interaction between parcels.
virtual bool controlsTimestep() const
Whether the PairModel has a timestep limit that will.
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition Switch.H:81
A cloud is a registry collection of lagrangian particles.
Definition cloud.H:56
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect,...
vector position() const
Return current particle position.
Definition particleI.H:283
label origId() const noexcept
Return the particle ID on the originating processor.
Definition particleI.H:194
label origProc() const noexcept
Return the originating processor ID.
Definition particleI.H:182
Lookup type of boundary radiation properties.
Definition lookup.H:60
volScalarField & p
const dimensionedScalar rhoMax
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
DSMCCloud< dsmcParcel > CloudType
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
dimensionedScalar cbrt(const dimensionedScalar &ds)
Vector< scalar > vector
Definition vector.H:57
dimensionedScalar pow025(const dimensionedScalar &ds)
volScalarField & nu
dictionary dict