49
41
Real Mass = b2->state->mass;
50
42
if (Mass == 0) Mass = b->state->mass;
52
const Real SmoothDist = -geom.penetrationDepth + phys.h;
44
const Real SmoothDist = (b2->state->pos - b->state->pos).norm();
55
rho += b2->state->mass*kernelFunctionCurDensity(SmoothDist, phys.h);
46
// [Monaghan1992], (2.7) (3.8)
47
rho += b2->state->mass*kernelFunctionCurDensity(SmoothDist, h);
57
// [Mueller2003], (3), we need to consider the density of the current body (?)
58
rho += b->state->mass*kernelFunctionCurDensity(0.0, s->radius);
50
// Self mass contribution
51
rho += b->state->mass*kernelFunctionCurDensity(0.0, h);
63
void SPHEngine::calculateSPHCs(const shared_ptr<Body>& b) {
69
// Pointer to kernel function
70
KernelFunction kernelFunctionCurDensity = returnKernelFunction (KernFunctionDensity, KernFunctionDensity, Norm);
72
// Calculate Cs for every particle
73
for(Body::MapId2IntrT::iterator it=b->intrs.begin(),end=b->intrs.end(); it!=end; ++it) {
74
const shared_ptr<Body> b2 = Body::byId((*it).first,scene);
75
Sphere* s=dynamic_cast<Sphere*>(b->shape.get());
78
if (((*it).second)->geom and ((*it).second)->phys) {
79
const ScGeom geom = *(YADE_PTR_CAST<ScGeom>(((*it).second)->geom));
80
const ViscElPhys phys=*(YADE_PTR_CAST<ViscElPhys>(((*it).second)->phys));
82
if((b2->groupMask & mask)==0) continue;
84
Real Mass = b2->state->mass;
85
if (Mass == 0) Mass = b->state->mass;
87
const Real SmoothDist = -geom.penetrationDepth + phys.h;
89
// [Mueller2003], (15)
90
Cs += b2->state->mass/b2->rho*kernelFunctionCurDensity(SmoothDist, phys.h);
96
Real smoothkernelPoly6(const double & rr, const double & hh) {
98
const Real h = 1; const Real r = rr/hh;
99
//return 315/(64*M_PI*pow(h,9))*pow((h*h - r*r), 3);
100
return 315/(64*M_PI)*pow((h - r*r), 3);
106
Real smoothkernelPoly6Grad(const double & rr, const double & hh) {
108
const Real h = 1; const Real r = rr/hh;
109
//return -315/(64*M_PI*pow(h,9))*(-6*r*pow((h*h-r*r), 2));
110
return -315/(64*M_PI)*(-6*r*pow((h-r*r), 2));
116
Real smoothkernelPoly6Lapl(const double & rr, const double & hh) {
118
const Real h = 1; const Real r = rr/hh;
119
//return 315/(64*M_PI*pow(h,9))*(-6*(h*h-r*r)*(h*h - 5*r*r));
120
return 315/(64*M_PI)*(-6*(h*h-r*r)*(h*h - 5*r*r));
126
Real smoothkernelSpiky(const double & rr, const double & hh) {
128
const Real h = 1; const Real r = rr/hh;
129
//return 15/(M_PI*pow(h,6))*(pow((h-r), 3)); // [Mueller2003], (21)
130
return 15/(M_PI)*(pow((h-r), 3)); // [Mueller2003], (21)
136
Real smoothkernelSpikyGrad(const double & rr, const double & hh) {
138
const Real h = 1; const Real r = rr/hh;
139
//return -15/(M_PI*pow(h,6))*(-3*pow((h-r),2));
140
return -15/(M_PI)*(-3*pow((h-r),2));
146
Real smoothkernelSpikyLapl(const double & rr, const double & hh) {
148
const Real h = 1; const Real r = rr/hh;
149
//return 15/(M_PI*pow(h,6))*(6*(h-r));
150
return 15/(M_PI)*(6*(h-r));
156
Real smoothkernelVisco(const double & rr, const double & hh) {
157
if (rr<=hh and rr!=0 and hh!=0) {
158
const Real h = 1; const Real r = rr/hh;
159
//return 15/(2*M_PI*pow(h,3))*(-r*r*r/(2*h*h*h) + r*r/(h*h) + h/(2*r) -1); // [Mueller2003], (21)
160
return 15/(2*M_PI)*(-r*r*r/(2) + r*r + h/(2*r) -1); // [Mueller2003], (21)
166
Real smoothkernelViscoGrad(const double & rr, const double & hh) {
167
if (rr<=hh and rr!=0 and hh!=0) {
168
const Real h = 1; const Real r = rr/hh;
169
//return -15/(2*M_PI*pow(h,3))*(-3*r*r/(2*h*h*h) + 2*r/(h*h) - h/(2*r*r));
170
return -15/(2*M_PI)*(-3*r*r/(2) + 2*r - h/(2*r*r));
176
Real smoothkernelViscoLapl(const double & rr, const double & hh) {
177
if (rr<=hh and rr!=0 and hh!=0) {
178
const Real h = 1; const Real r = rr/hh;
179
//return 45/(M_PI*pow(h,6))*(h - rrj); // [Mueller2003], (22+)
180
//return 15/(2*M_PI*pow(h,3))*(-3*r*r/(2*h*h*h) + 2*r/(h*h) - h/(2*r*r));
181
return 15/(2*M_PI)*(-3*r*r/(2) + 2*r - h/(2*r*r));
187
Real smoothkernelLucy(const double & rr, const double & hh) {
188
if (rr<=hh and rr!=0 and hh!=0) {
190
//return 5/(9*M_PI*pow(h,2))*(1+3*r/h)*pow((1-r/h),3);
191
const Real r = rr/hh;
192
return 5/(9*M_PI)*(1+3*r)*pow((1-r),3);
198
Real smoothkernelLucyGrad(const double & rr, const double & hh) {
199
if (rr<=hh and rr!=0 and hh!=0) {
201
//return -5/(9*M_PI*pow(h,2))*(-12*r/(h*h))*pow((1-r/h),2);
202
const Real r = rr/hh;
203
return -5/(9*M_PI)*(-12*r)*pow((1-r),2);
209
Real smoothkernelLucyLapl(const double & rr, const double & hh) {
210
if (rr<=hh and rr!=0 and hh!=0) {
212
//return 5/(9*M_PI*pow(h,2))*(-12/(h*h))*(1-r/h)*(1-3*r/h);
213
const Real r = rr/hh;
214
return 5/(9*M_PI)*(-12)*(1-r)*(1-3*r);
220
Real smoothkernelMonaghan(const double & rr, const double & hh) {
224
const Real r = rr/hh;
226
//ret = 40/(7*M_PI*h*h)*(1 - 6*pow((r/h),2) + 6*pow((r/h),3));
227
ret = 40/(7*M_PI)*(1 - 6*pow((r),2) + 6*pow((r),3));
229
//ret = 80/(7*M_PI*h*h)*pow((1 - (r/h)), 3);
230
ret = 80/(7*M_PI)*pow((1 - (r)), 3);
236
Real smoothkernelMonaghanGrad(const double & rr, const double & hh) {
239
const Real h = 1; const Real r = rr/hh;
241
//ret = -40/(7*M_PI*h*h)*( - 6*r/(h*h))*(2 - 3 * r/(h*h*h));
242
ret = -40/(7*M_PI)*( - 6*r)*(2 - 3 * r);
244
//ret = -80/(7*M_PI*h*h)*( -3/h)*pow((1 -r/h), 2);
245
ret = -80/(7*M_PI)*( -3/h)*pow((1 -r), 2);
251
Real smoothkernelMonaghanLapl(const double & rr, const double & hh) {
255
const Real r = rr/hh;
257
//ret = 40/(7*M_PI*h*h)*( - 12/(h*h))*(1 - 3 * r/(h*h*h*h*h));
258
ret = 40/(7*M_PI)*( - 12)*(1 - 3 * r);
260
//ret = 80/(7*M_PI*h*h)*( 6/(h*h))*(1 -r/h);
261
ret = 80/(7*M_PI)*( 6)*(1 -r);
55
Real smoothkernelLucy(const double & r, const double & h) {
57
// Lucy Kernel function,
58
return 105./(16.*M_PI*h*h*h) * (1 + 3 * r / h) * pow((1.0 - r / h), 3);
64
Real smoothkernelLucyGrad(const double & r, const double & h) {
66
// 1st derivative of Lucy Kernel function,
67
return 105./(16.*M_PI*h*h*h) * (-12 * r) * (1/( h * h ) - 2 * r / (h * h * h ) + r * r / (h * h * h * h));
73
Real smoothkernelLucyLapl(const double & r, const double & h) {
75
// 2nd derivative of Lucy Kernel function,
76
return 105./(16.*M_PI*h*h*h) * (-12) / (h * h * h * h) * (h * h - 2 * r * h + 3 * r * r);
82
KernelFunction returnKernelFunction(const int a, const typeKernFunctions typeF) {
83
return returnKernelFunction(a, a, typeF);
267
86
KernelFunction returnKernelFunction(const int a, const int b, const typeKernFunctions typeF) {
269
88
throw runtime_error("Kernel types should be equal!");
273
return smoothkernelPoly6;
274
} else if (typeF==Grad) {
275
return smoothkernelPoly6Grad;
276
} else if (typeF==Lapl) {
277
return smoothkernelPoly6Lapl;
281
} else if (a==Spiky) {
283
return smoothkernelSpiky;
284
} else if (typeF==Grad) {
285
return smoothkernelSpikyGrad;
286
} else if (typeF==Lapl) {
287
return smoothkernelSpikyLapl;
291
} else if (a==Visco) {
293
return smoothkernelVisco;
294
} else if (typeF==Grad) {
295
return smoothkernelViscoGrad;
296
} else if (typeF==Lapl) {
297
return smoothkernelViscoLapl;
300
} else if (a==Lucy) {
301
91
if (typeF==Norm) {
302
92
return smoothkernelLucy;
303
93
} else if (typeF==Grad) {
336
115
//////////////////////////////////////////////////////////////////
117
// Handle periodicity.
118
const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(I->cellDist): Vector3r::Zero();
119
const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(I->cellDist): Vector3r::Zero();
339
121
const State& de1 = *static_cast<State*>(bodies[id1]->state.get());
340
122
const State& de2 = *static_cast<State*>(bodies[id2]->state.get());
342
// Handle periodicity.
343
const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(I->cellDist): Vector3r::Zero();
344
const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(I->cellDist): Vector3r::Zero();
346
124
const Vector3r c1x = (geom.contactPoint - de1.pos);
347
125
const Vector3r c2x = (geom.contactPoint - de2.pos - shift2);
349
127
const Vector3r relativeVelocity = (de1.vel+de1.angVel.cross(c1x)) - (de2.vel+de2.angVel.cross(c2x)) + shiftVel;
350
128
const Real normalVelocity = geom.normal.dot(relativeVelocity);
351
//const Vector3r shearVelocity = relativeVelocity-normalVelocity*geom.normal;
354
131
//////////////////////////////////////////////////////////////////
357
Sphere* s1=dynamic_cast<Sphere*>(bodies[id1]->shape.get());
358
Sphere* s2=dynamic_cast<Sphere*>(bodies[id2]->shape.get());
360
phys.h = s1->radius + s2->radius;
361
} else if (s1 and not(s2)) {
368
Real Mass = bodies[id2]->state->mass;
369
if (Mass==0.0 and bodies[id1]->state->mass!= 0.0) {
370
Mass = bodies[id1]->state->mass;
373
Real Rho = bodies[id2]->rho;
374
if (Rho==0.0 and bodies[id1]->rho!=0.0) {
375
Rho = bodies[id1]->rho;
378
const Vector3r xixj = (-geom.penetrationDepth + phys.h)*geom.normal;
134
const Real Mass1 = bodies[id1]->state->mass;
135
const Real Mass2 = bodies[id2]->state->mass;
137
const Real Rho1 = bodies[id1]->rho;
138
const Real Rho2 = bodies[id2]->rho;
140
const Vector3r xixj = de2.pos - de1.pos;
380
142
if (xixj.norm() < phys.h) {
381
143
Real fpressure = 0.0;
383
// [Mueller2003], (10)
385
(bodies[id1]->press + bodies[id2]->press)/(2.0*Rho) *
386
phys.kernelFunctionCurrentPressure(xixj.norm(), phys.h);
144
if (Rho1!=0.0 and Rho2!=0.0) {
145
// from [Monaghan1992], (3.3), multiply by Mass2, because we need a force, not du/dt
146
fpressure = - Mass1 * Mass2 * (
147
bodies[id1]->press/(Rho1*Rho1) +
148
bodies[id2]->press/(Rho2*Rho2)
150
* phys.kernelFunctionCurrentPressure(xixj.norm(), phys.h);
389
153
Vector3r fvisc = Vector3r::Zero();
391
fvisc = phys.mu * Mass *
392
normalVelocity*geom.normal/Rho *
393
phys.kernelFunctionCurrentVisco(xixj.norm(), phys.h);
154
if (Rho1!=0.0 and Rho2!=0.0) {
155
// from [Morris1997], (22), multiply by Mass2, because we need a force, not du/dt
156
fvisc = phys.mu * Mass1 * Mass2 *
157
(-normalVelocity*geom.normal)/(Rho1*Rho1) *
159
phys.kernelFunctionCurrentPressure(xixj.norm(), phys.h);
160
//phys.kernelFunctionCurrentVisco(xixj.norm(), phys.h);
395
162
force = fpressure*geom.normal + fvisc;