33template<
class CloudType>
34void Foam::WallLocalSpringSliderDashpot<CloudType>::findMinMaxProperties
45 for (
const typename CloudType::parcelType&
p : this->owner())
51 if (useEquivalentSize_)
53 dEff *=
cbrt(
p.nParticle()*volumeFactor_);
56 rMin =
min(dEff, rMin);
74template<
class CloudType>
75void Foam::WallLocalSpringSliderDashpot<CloudType>::evaluateWall
77 typename CloudType::parcelType&
p,
79 const WallSiteData<vector>& data,
85 label wPI = patchMap_[data.patchIndex()];
88 scalar Estar = Estar_[wPI];
89 scalar Gstar = Gstar_[wPI];
90 scalar
alpha = alpha_[wPI];
93 scalar cohesionEnergyDensity = cohesionEnergyDensity_[wPI];
94 cohesion = cohesion && cohesion_[wPI];
96 vector r_PW =
p.position() - site;
98 vector U_PW =
p.U() - data.wallData();
100 scalar r_PW_mag =
mag(r_PW);
102 scalar normalOverlapMag =
max(pREff - r_PW_mag, 0.0);
104 vector rHat_PW = r_PW/(r_PW_mag + VSMALL);
106 scalar kN = (4.0/3.0)*
sqrt(pREff)*Estar;
112 *(kN*
pow(normalOverlapMag,
b) - etaN*(U_PW & rHat_PW));
119 -cohesionEnergyDensity
120 *mathematical::pi*(
sqr(pREff) -
sqr(r_PW_mag))
127 U_PW - (U_PW & rHat_PW)*rHat_PW
128 + (
p.omega() ^ (pREff*-rHat_PW));
130 scalar deltaT = this->owner().mesh().time().deltaTValue();
132 vector& tangentialOverlap_PW =
133 p.collisionRecords().matchWallRecord(-r_PW, pREff).collisionData();
135 tangentialOverlap_PW += USlip_PW*deltaT;
137 scalar tangentialOverlapMag =
mag(tangentialOverlap_PW);
139 if (tangentialOverlapMag > VSMALL)
141 scalar kT = 8.0*
sqrt(pREff*normalOverlapMag)*Gstar;
148 if (kT*tangentialOverlapMag >
mu*
mag(fN_PW))
153 fT_PW = -
mu*
mag(fN_PW)*USlip_PW/
mag(USlip_PW);
155 tangentialOverlap_PW = Zero;
160 -kT*tangentialOverlapMag
161 *tangentialOverlap_PW/tangentialOverlapMag
167 p.torque() += (pREff*-rHat_PW) ^ fT_PW;
174template<
class CloudType>
181 WallModel<CloudType>(
dict, cloud, typeName),
187 cohesionEnergyDensity_(),
191 collisionResolutionSteps_
193 this->coeffDict().getScalar(
"collisionResolutionSteps")
196 useEquivalentSize_(Switch(this->coeffDict().lookup(
"useEquivalentSize")))
198 if (useEquivalentSize_)
207 const polyMesh&
mesh = cloud.mesh();
209 const polyBoundaryMesh&
bMesh =
mesh.boundaryMesh();
213 DynamicList<label> wallPatchIndices;
215 for (
const polyPatch&
pp :
bMesh)
219 wallPatchIndices.append(
pp.index());
223 label nWallPatches = wallPatchIndices.size();
225 Estar_.setSize(nWallPatches);
226 Gstar_.setSize(nWallPatches);
227 alpha_.setSize(nWallPatches);
228 b_.setSize(nWallPatches);
229 mu_.setSize(nWallPatches);
230 cohesionEnergyDensity_.setSize(nWallPatches);
231 cohesion_.setSize(nWallPatches);
233 scalar maxEstar = -GREAT;
235 forAll(wallPatchIndices, wPI)
242 patchMap_[wallPatchIndices[wPI]] = wPI;
244 scalar
nu = patchCoeffDict.get<scalar>(
"poissonsRatio");
246 scalar E = patchCoeffDict.get<scalar>(
"youngsModulus");
248 Estar_[wPI] = 1/((1 -
sqr(pNu))/pE + (1 -
sqr(
nu))/E);
250 Gstar_[wPI] = 1/(2*((2 + pNu -
sqr(pNu))/pE + (2 +
nu -
sqr(
nu))/E));
252 alpha_[wPI] = patchCoeffDict.get<scalar>(
"alpha");
254 b_[wPI] = patchCoeffDict.get<scalar>(
"b");
256 mu_[wPI] = patchCoeffDict.get<scalar>(
"mu");
258 cohesionEnergyDensity_[wPI] =
259 patchCoeffDict.get<scalar>(
"cohesionEnergyDensity");
261 cohesion_[wPI] = (
mag(cohesionEnergyDensity_[wPI]) > VSMALL);
263 if (Estar_[wPI] > maxEstar)
265 maxEstarIndex_ = wPI;
267 maxEstar = Estar_[wPI];
275template<
class CloudType>
281 if (useEquivalentSize_)
283 return p.d()/2*
cbrt(
p.nParticle()*volumeFactor_);
290template<
class CloudType>
297template<
class CloudType>
300 if (!(this->owner().size()))
309 findMinMaxProperties(rMin,
rhoMax, UMagMax);
312 scalar minCollisionDeltaT =
315 *
pow(
rhoMax/(Estar_[maxEstarIndex_]*
sqrt(UMagMax) + VSMALL), 0.4)
316 /collisionResolutionSteps_;
318 return ceil(this->
owner().time().deltaTValue()/minCollisionDeltaT);
322template<
class CloudType>
323void Foam::WallLocalSpringSliderDashpot<CloudType>::evaluateWall
332 scalar pREff = this->pREff(
p);
334 forAll(flatSitePoints, siteI)
339 flatSitePoints[siteI],
346 forAll(sharpSitePoints, siteI)
353 sharpSitePoints[siteI],
354 sharpSiteData[siteI],
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const List< typename ParcelType::constantProperties > & constProps() const
Return all of the constant properties.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
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...
void setSize(label n)
Alias for resize().
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
void size(const label n)
Older name for setAddressableSize.
virtual label nSubCycles() const
For WallModels that control the timestep, calculate the.
WallLocalSpringSliderDashpot(const dictionary &dict, CloudType &cloud)
Construct from dictionary.
virtual scalar pREff(const typename CloudType::parcelType &p) const
Return the effective radius for a particle for the model.
virtual bool controlsTimestep() const
Whether the WallModel has a timestep limit that will.
WallModel(const dictionary &dict, CloudType &owner, const word &type)
Construct from components.
const dictionary & coeffDict() const
Return the coefficients dictionary.
const dictionary & dict() const
Return the dictionary.
const CloudType & owner() const
Return the owner cloud object.
Stores the patch ID and templated data to represent a collision with a wall to be passed to the wall ...
A cloud is a registry collection of lagrangian particles.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
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,...
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Mesh consisting of general polyhedral cells.
A patch is a list of labels that address the faces in the global face list.
Lookup type of boundary radiation properties.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const dimensionedScalar rhoMax
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
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)
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
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.
dimensionedScalar cbrt(const dimensionedScalar &ds)
PrimitivePatch< List< face >, const pointField > bMesh
Holder of faceList and points. (v.s. e.g. primitivePatch which references points).
dimensionedScalar pow025(const dimensionedScalar &ds)
#define forAll(list, i)
Loop across all elements in list.