← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3488: SPH-code refactoring.

 

------------------------------------------------------------
revno: 3488
committer: Anton Gladky <gladky.anton@xxxxxxxxx>
timestamp: Fri 2014-10-17 19:14:29 +0200
message:
  SPH-code refactoring.
added:
  examples/sph/dam_break.py
modified:
  doc/references.bib
  examples/sph/sph_box.py
  examples/sph/toystar.py
  examples/sph/watercolumn.py
  pkg/common/SPHEngine.cpp
  pkg/common/SPHEngine.hpp
  pkg/dem/ViscoelasticPM.cpp
  pkg/dem/ViscoelasticPM.hpp


--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== modified file 'doc/references.bib'
--- doc/references.bib	2014-10-16 12:19:03 +0000
+++ doc/references.bib	2014-10-17 17:14:29 +0000
@@ -775,6 +775,7 @@
   pages = {7341--7354},
   number = {C4}
 }
+
 @book{Dallavalle1948,
   title = {Micrometrics : The technology of fine particles},
   publisher = {Pitman Pub. Corp},
@@ -815,3 +816,13 @@
 	doi="10.1007/s10035-008-0116-0",
 	url="http://www.springerlink.com/content/w0x307g110421035";
 }
+
+@article{Monaghan1992,
+  author = {{Monaghan}, J.~J.},
+  title = "{Smoothed particle hydrodynamics}",
+  journal = {\araa},
+  year = 1992,
+  volume = 30,
+  pages = {543-574},
+  doi = {10.1146/annurev.aa.30.090192.002551}
+}

=== added file 'examples/sph/dam_break.py'
--- examples/sph/dam_break.py	1970-01-01 00:00:00 +0000
+++ examples/sph/dam_break.py	2014-10-17 17:14:29 +0000
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+from yade import utils, plot, qt
+o = Omega()
+
+# Physical parameters
+fr = 0.5;
+rho= 1000.0
+
+k = 1000.0
+mu = 10.0
+tc = 0.01; en = 0.7; et = 0.7;
+vel = 0.0
+
+#Rad = 0.006
+#h = 0.011
+
+Rad = 0.015
+h = 0.03
+
+#Rad = 0.02
+#h = 0.04
+
+o.dt = 0.0005
+
+X = 4.0
+Z = 3.0
+yCoeff = 4.0
+
+SpheresX = 1.0
+SpheresZ = 2.0
+
+# Add material
+mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True, h=h, mu=mu,tc=tc, en=en, et=et, KernFunctionPressure = 1, KernFunctionVisco = 1))
+idBox = pack.regularHexa(pack.inAlignedBox((0.0,-Rad*yCoeff,0.0),(X,Rad*yCoeff,Z)),radius=Rad,gap=0.0,color=(0,1,1), material=mat1, mask = 1, fixed=True)
+
+idBoxAdd = []
+idSpheresAdd = []
+
+for i in range(len(idBox)):
+  if (((idBox[i].state.pos[0])<yCoeff*Rad) or
+      ((idBox[i].state.pos[0])>(X-yCoeff*Rad - 2.0*Rad)) or
+      ((idBox[i].state.pos[2])<(yCoeff*Rad)) or
+      ((idBox[i].state.pos[2])>(Z - 2.0*Rad))):
+    idBoxAdd.append(idBox[i])
+  elif (((idBox[i].state.pos[0])<SpheresX) and
+        ((idBox[i].state.pos[2])<SpheresZ) and
+        ((idBox[i].state.pos[1])>-Rad) and
+        ((idBox[i].state.pos[1])<2.0*Rad)):
+          idBox[i].shape.color = Vector3(1,0,0)
+          idBox[i].state.fixed = False
+          idBox[i].state.blockedDOFs = 'y'
+          idSpheresAdd.append(idBox[i])
+    
+
+
+O.bodies.append(idBoxAdd)
+idSpheres = O.bodies.append(idSpheresAdd)
+
+    
+# Add engines
+o.engines = [
+  ForceResetter(),
+  InsertionSortCollider([Bo1_Sphere_Aabb(label='is2aabb')],ompThreads=1),
+  InteractionLoop(
+    [Ig2_Sphere_Sphere_ScGeom(label='ss2sc')],
+    [Ip2_ViscElMat_ViscElMat_ViscElPhys()],
+    [Law2_ScGeom_ViscElPhys_Basic()],
+  ),
+  NewtonIntegrator(damping=0.01,gravity=[0,0,-9.81]),
+  SPHEngine(mask=1, k=k, rho0 = rho, h=h, KernFunctionDensity= 1),
+  PyRunner(command='addPlotData()',iterPeriod=10,initRun=True,dead=False),
+]
+
+enlargeF = h/Rad*1.1
+print "enlargeF = %g"%enlargeF
+is2aabb.aabbEnlargeFactor = enlargeF
+ss2sc.interactionDetectionFactor = enlargeF
+
+
+# Function to add data to plot
+def addPlotData(): 
+  plot.addData(t = O.time, eKin = utils.kineticEnergy())
+  
+plot.plots={'t':('eKin')};
+plot.plot()
+
+qt.View()

=== modified file 'examples/sph/sph_box.py'
--- examples/sph/sph_box.py	2014-04-09 09:11:49 +0000
+++ examples/sph/sph_box.py	2014-10-17 17:14:29 +0000
@@ -11,28 +11,29 @@
 fr = 0.5;
 rho=1000.0
 
-k = 1.0
-mu = 0.001
-tc = 0.0001; en = 0.7; et = 0.7;
-Rad = 10.0e-3
+k = 2000.0
+tc = 0.001; en = 0.5; et = 0.5;
+Rad = 7.0e-3
+h = 2*7.0e-3
 o.dt = 0.00025
 
 # Add material
-mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True,mu=mu,tc=tc, en=en, et=et))
+mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True,  h=h, tc=tc, en=en, et=et, KernFunctionPressure = 1, KernFunctionVisco = 1))
+mat2 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=False,tc=tc, en=en, et=et))
 
 # Add spheres
-d = 0.18
+d = 0.17
 idSpheres = O.bodies.append(
   pack.regularHexa(
     pack.inAlignedBox(
-    (-d,-d,-d), # lower angle
-    (d,d,d)),   # upper angle
-    radius=Rad,gap=0.2*Rad, material=mat1,color=(0,1,1)))
+    (-d*0.5,-d*0.5,-d), # lower angle
+    (d*0.5,d*0.5,d)),   # upper angle
+    radius=Rad,gap=0.01*Rad, mask=3, material=mat1,color=(0,1,1)))
     
 
 id1 = O.bodies.append(geom.facetBox((Vector3(0.0,0,0.0)),
   (Vector3(0.2, 0.2, 0.2)),
-  material=mat1, mask=1, color=(1,0,0), wire=True))
+  material=mat2, mask=5, color=(1,0,0), wire=True))
 
 # Add engines
 o.engines = [
@@ -44,9 +45,13 @@
     [Law2_ScGeom_ViscElPhys_Basic()],
   ),
   NewtonIntegrator(damping=0.0,gravity=[0,0,-9.81]),
-  SPHEngine(mask=1, k=k, rho0 = rho),
+  SPHEngine(mask=3, k=k, rho0 = rho, h=h, KernFunctionDensity= 1),
 ]
 
+enlargeF = h/Rad*1.1
+print "enlargeF = %g"%enlargeF
+is2aabb.aabbEnlargeFactor = enlargeF
+ss2sc.interactionDetectionFactor = enlargeF
 
 O.step()
 qt.View()

=== modified file 'examples/sph/toystar.py'
--- examples/sph/toystar.py	2014-04-10 06:21:57 +0000
+++ examples/sph/toystar.py	2014-10-17 17:14:29 +0000
@@ -12,13 +12,13 @@
 rho=1000.0
 
 k = 1.0
-mu = 0.01
 tc = 0.0001; en = 0.7; et = 0.7;
 Rad = 10.0e-3
+h = 2*Rad
 o.dt = 0.00001
 
 # Add material
-mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True,mu=mu,tc=tc, en=en, et=et))
+mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True,h=h,tc=tc, en=en, et=et, KernFunctionPressure = 1, KernFunctionVisco = 1))
 
 # Add spheres
 d = 0.8
@@ -42,10 +42,15 @@
   ),
   CentralGravityEngine(accel=50.0, label='gr', centralBody=idCentralBody),
   NewtonIntegrator(damping=0.1),
-  SPHEngine(mask=1, k=k, rho0 = rho),
+  SPHEngine(mask=1, k=k, rho0 = rho, h=h, KernFunctionDensity= 1),
   VTKRecorder(iterPeriod=1000, mask=1, fileName='./cpt/spheres-', recorders=['spheres','velocity','colors','intr','ids','mask','materialId','stress']),
 ]
 
 
+enlargeF = h/Rad*1.1
+print "enlargeF = %g"%enlargeF
+is2aabb.aabbEnlargeFactor = enlargeF
+ss2sc.interactionDetectionFactor = enlargeF
+
 O.step()
 qt.View()

=== modified file 'examples/sph/watercolumn.py'
--- examples/sph/watercolumn.py	2014-04-09 14:03:16 +0000
+++ examples/sph/watercolumn.py	2014-10-17 17:14:29 +0000
@@ -8,19 +8,21 @@
 fr = 0.0;
 rho=1000.0
 
-k = 5.0
-mu = 0.001
-tc = 0.0001; en = 0.7; et = 0.7;
+k = 5000.0
+tc = 0.001; en = 0.7; et = 0.7;
 vel = 0.05
-Rad = 15.0e-3
+Rad = 12.0e-3
+h = 2*Rad
 o.dt = 0.0002
 
 
 scaleF =  0.001
 
 # Add material
-mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True,mu=mu,tc=tc, en=en, et=et))
-id1 = O.bodies.append(ymport.gmsh("box.mesh", scale=scaleF, material=mat1, color=(1,0,0), mask = 1, wire=True))
+mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=True,h=h,tc=tc, en=en, et=et, KernFunctionPressure = 1, KernFunctionVisco = 1))
+mat2 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho, SPHmode=False,h=h,tc=tc, en=en, et=et))
+
+id1 = O.bodies.append(ymport.gmsh("box.mesh", scale=scaleF, material=mat2, color=(1,0,0), mask = 5, wire=True))
 
 d = 15.0*scaleF
 
@@ -30,8 +32,7 @@
     pack.inAlignedBox(
     (0,       -2000.0*scaleF,  0.0),
     (1000*scaleF, 200*scaleF,  50.0*scaleF)),
-    radius=d,gap=0.01*d, material=mat1, mask=1, color=(0,1,1)))
-
+    radius=d,gap=0.001*d, material=mat1, mask=3, color=(0,1,1)))
 
 print len(idSpheres)
 
@@ -45,7 +46,7 @@
     [Law2_ScGeom_ViscElPhys_Basic()],
   ),
   NewtonIntegrator(damping=0.05,gravity=[0,-9.81,0]),
-  SPHEngine(mask=1, k=k, rho0 = rho),
+  SPHEngine(mask=3, k=k, rho0 = rho, h = h, KernFunctionDensity= 1),
   VTKRecorder(iterPeriod=100,fileName='./cpt/spheres-', recorders=['spheres','velocity','colors','intr','ids','mask','materialId','stress']),
   VTKRecorder(iterPeriod=100,fileName='./cpt/facet-',   recorders=['facets'],label='VTK_box2'),
   PyRunner(command='addPlotData()',iterPeriod=50,dead=False),
@@ -56,6 +57,11 @@
 
 plot.plots={'t':('Ekin')}; plot.plot()
 
+enlargeF = h/Rad*1.1
+print "enlargeF = %g"%enlargeF
+is2aabb.aabbEnlargeFactor = enlargeF
+ss2sc.interactionDetectionFactor = enlargeF
+
 O.run(1, True)
 
 qt.View()

=== modified file 'pkg/common/SPHEngine.cpp'
--- pkg/common/SPHEngine.cpp	2014-10-15 06:44:01 +0000
+++ pkg/common/SPHEngine.cpp	2014-10-17 17:14:29 +0000
@@ -12,17 +12,9 @@
     YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
       if(mask>0 && (b->groupMask & mask)==0) continue;
       this->calculateSPHRho(b);
-      b->press=k*(b->rho - b->rho0);
-    } YADE_PARALLEL_FOREACH_BODY_END();
-  }
-  /*
-  {
-    YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
-      if(mask>0 && (b->groupMask & mask)==0) continue;
-      this->calculateSPHCs(b);
-    } YADE_PARALLEL_FOREACH_BODY_END();
-  }
-  */
+      b->press=std::max(0.0, k*(b->rho - b->rho0));
+    } YADE_PARALLEL_FOREACH_BODY_END();
+  }
 }
 
 void SPHEngine::calculateSPHRho(const shared_ptr<Body>& b) {
@@ -32,7 +24,7 @@
   Real rho = 0;
   
   // Pointer to kernel function
-  KernelFunction kernelFunctionCurDensity = returnKernelFunction (KernFunctionDensity, KernFunctionDensity, Norm);
+  KernelFunction kernelFunctionCurDensity = returnKernelFunction (KernFunctionDensity, Norm);
   
   // Calculate rho for every particle
   for(Body::MapId2IntrT::iterator it=b->intrs.begin(),end=b->intrs.end(); it!=end; ++it) {
@@ -49,255 +41,53 @@
       Real Mass = b2->state->mass;
       if (Mass == 0) Mass = b->state->mass;
       
-      const Real SmoothDist = -geom.penetrationDepth + phys.h;
+      const Real SmoothDist = (b2->state->pos - b->state->pos).norm();
      
-      // [Mueller2003], (3)
-      rho += b2->state->mass*kernelFunctionCurDensity(SmoothDist, phys.h);
+      // [Monaghan1992], (2.7) (3.8) 
+      rho += b2->state->mass*kernelFunctionCurDensity(SmoothDist, h);
     }
-    // [Mueller2003], (3), we need to consider the density of the current body (?)
-    rho += b->state->mass*kernelFunctionCurDensity(0.0, s->radius);
   }
+  // Self mass contribution
+  rho += b->state->mass*kernelFunctionCurDensity(0.0, h);
   b->rho = rho;
 }
 
-void SPHEngine::calculateSPHCs(const shared_ptr<Body>& b) {
-  if (b->Cs<0) {
-    b->Cs = 0.0;
-  }
-  Real Cs = 0;
-  
-  // Pointer to kernel function
-  KernelFunction kernelFunctionCurDensity = returnKernelFunction (KernFunctionDensity, KernFunctionDensity, Norm);
-  
-  // Calculate Cs for every particle
-  for(Body::MapId2IntrT::iterator it=b->intrs.begin(),end=b->intrs.end(); it!=end; ++it) {
-    const shared_ptr<Body> b2 = Body::byId((*it).first,scene);
-    Sphere* s=dynamic_cast<Sphere*>(b->shape.get());
-    if(!s) continue;
-    
-    if (((*it).second)->geom and ((*it).second)->phys) {
-      const ScGeom geom = *(YADE_PTR_CAST<ScGeom>(((*it).second)->geom));
-      const ViscElPhys phys=*(YADE_PTR_CAST<ViscElPhys>(((*it).second)->phys));
-      
-      if((b2->groupMask & mask)==0)  continue;
-      
-      Real Mass = b2->state->mass;
-      if (Mass == 0) Mass = b->state->mass;
-      
-      const Real SmoothDist = -geom.penetrationDepth + phys.h;
-     
-      // [Mueller2003], (15)
-      Cs += b2->state->mass/b2->rho*kernelFunctionCurDensity(SmoothDist, phys.h);
-    }
-  }
-  b->Cs = Cs;
-}
-
-Real smoothkernelPoly6(const double & rr, const double & hh) {
-  if (rr<=hh) {
-    const Real h = 1; const Real r = rr/hh;
-    //return 315/(64*M_PI*pow(h,9))*pow((h*h - r*r), 3);
-    return 315/(64*M_PI)*pow((h - r*r), 3);
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelPoly6Grad(const double & rr, const double & hh) {
-  if (rr<=hh) {
-    const Real h = 1; const Real r = rr/hh;
-    //return -315/(64*M_PI*pow(h,9))*(-6*r*pow((h*h-r*r), 2));
-    return -315/(64*M_PI)*(-6*r*pow((h-r*r), 2));
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelPoly6Lapl(const double & rr, const double & hh) {
-  if (rr<=hh) {
-    const Real h = 1; const Real r = rr/hh;
-    //return 315/(64*M_PI*pow(h,9))*(-6*(h*h-r*r)*(h*h - 5*r*r));
-    return 315/(64*M_PI)*(-6*(h*h-r*r)*(h*h - 5*r*r));
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelSpiky(const double & rr, const double & hh) {
-  if (rr<=hh) {
-    const Real h = 1; const Real r = rr/hh;
-    //return 15/(M_PI*pow(h,6))*(pow((h-r), 3));             // [Mueller2003], (21)
-    return 15/(M_PI)*(pow((h-r), 3));             // [Mueller2003], (21)
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelSpikyGrad(const double & rr, const double & hh) {
-  if (rr<=hh) {
-    const Real h = 1; const Real r = rr/hh;
-    //return -15/(M_PI*pow(h,6))*(-3*pow((h-r),2));
-    return -15/(M_PI)*(-3*pow((h-r),2));
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelSpikyLapl(const double & rr, const double & hh) {
-  if (rr<=hh) {
-    const Real h = 1; const Real r = rr/hh;
-    //return 15/(M_PI*pow(h,6))*(6*(h-r));
-    return 15/(M_PI)*(6*(h-r));
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelVisco(const double & rr, const double & hh) {
-  if (rr<=hh and rr!=0 and hh!=0) {
-    const Real h = 1; const Real r = rr/hh;
-    //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)
-    return 15/(2*M_PI)*(-r*r*r/(2) + r*r + h/(2*r) -1);   // [Mueller2003], (21)
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelViscoGrad(const double & rr, const double & hh) {
-  if (rr<=hh and rr!=0 and hh!=0) {
-    const Real h = 1; const Real r = rr/hh;
-    //return -15/(2*M_PI*pow(h,3))*(-3*r*r/(2*h*h*h) + 2*r/(h*h) - h/(2*r*r));
-    return -15/(2*M_PI)*(-3*r*r/(2) + 2*r - h/(2*r*r));
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelViscoLapl(const double & rr, const double & hh) {
-  if (rr<=hh and rr!=0 and hh!=0) {
-    const Real h = 1; const Real r = rr/hh;
-    //return 45/(M_PI*pow(h,6))*(h - rrj);                     // [Mueller2003], (22+)
-    //return 15/(2*M_PI*pow(h,3))*(-3*r*r/(2*h*h*h) + 2*r/(h*h) - h/(2*r*r));
-    return 15/(2*M_PI)*(-3*r*r/(2) + 2*r - h/(2*r*r));
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelLucy(const double & rr, const double & hh) {
-  if (rr<=hh and rr!=0 and hh!=0) {
-    //const Real h = 1; 
-    //return 5/(9*M_PI*pow(h,2))*(1+3*r/h)*pow((1-r/h),3);
-    const Real r = rr/hh;
-    return 5/(9*M_PI)*(1+3*r)*pow((1-r),3);
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelLucyGrad(const double & rr, const double & hh) {
-  if (rr<=hh and rr!=0 and hh!=0) {
-    //const Real h = 1; 
-    //return -5/(9*M_PI*pow(h,2))*(-12*r/(h*h))*pow((1-r/h),2);
-    const Real r = rr/hh;
-    return -5/(9*M_PI)*(-12*r)*pow((1-r),2);
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelLucyLapl(const double & rr, const double & hh) {
-  if (rr<=hh and rr!=0 and hh!=0) {
-    //const Real h = 1; 
-    //return  5/(9*M_PI*pow(h,2))*(-12/(h*h))*(1-r/h)*(1-3*r/h);
-    const Real r = rr/hh;
-    return  5/(9*M_PI)*(-12)*(1-r)*(1-3*r);
-  } else {
-    return 0;
-  }
-}
-
-Real smoothkernelMonaghan(const double & rr, const double & hh) {
-  Real ret = 0.0;
-  if (hh!=0) {
-    //const Real h = 1; 
-    const Real r = rr/hh;
-    if (rr/hh<0.5) {
-      //ret = 40/(7*M_PI*h*h)*(1 - 6*pow((r/h),2) + 6*pow((r/h),3));
-      ret = 40/(7*M_PI)*(1 - 6*pow((r),2) + 6*pow((r),3));
-    } else {
-      //ret = 80/(7*M_PI*h*h)*pow((1 - (r/h)), 3);
-      ret = 80/(7*M_PI)*pow((1 - (r)), 3);
-    }
-  }
-  return ret;
-}
-
-Real smoothkernelMonaghanGrad(const double & rr, const double & hh) {
-  Real ret = 0.0;
-  if (hh!=0) {
-    const Real h = 1; const Real r = rr/hh;
-    if (rr/hh<0.5) {
-      //ret = -40/(7*M_PI*h*h)*( - 6*r/(h*h))*(2 - 3 * r/(h*h*h));
-      ret = -40/(7*M_PI)*( - 6*r)*(2 - 3 * r);
-    } else {
-      //ret = -80/(7*M_PI*h*h)*( -3/h)*pow((1 -r/h), 2);
-      ret = -80/(7*M_PI)*( -3/h)*pow((1 -r), 2);
-    }
-  }
-  return ret;
-}
-
-Real smoothkernelMonaghanLapl(const double & rr, const double & hh) {
-  Real ret = 0.0;
-  if (hh!=0) {
-    //const Real h = 1; 
-    const Real r = rr/hh;
-    if (rr/hh<0.5) {
-      //ret = 40/(7*M_PI*h*h)*( - 12/(h*h))*(1 - 3 * r/(h*h*h*h*h));
-      ret = 40/(7*M_PI)*( - 12)*(1 - 3 * r);
-    } else {
-      //ret = 80/(7*M_PI*h*h)*( 6/(h*h))*(1 -r/h);
-      ret = 80/(7*M_PI)*( 6)*(1 -r);
-    }
-  }
-  return ret;
+Real smoothkernelLucy(const double & r, const double & h) {
+  if (r<=h) {
+    // Lucy Kernel function, 
+    return 105./(16.*M_PI*h*h*h) * (1 + 3 * r / h) * pow((1.0 - r / h), 3);
+  } else {
+    return 0;
+  }
+}
+
+Real smoothkernelLucyGrad(const double & r, const double & h) {
+  if (r<=h) {
+    // 1st derivative of Lucy Kernel function, 
+    return 105./(16.*M_PI*h*h*h) * (-12 * r) * (1/( h * h ) - 2 * r / (h * h * h ) + r * r / (h * h * h * h));
+  } else {
+    return 0;
+  }
+}
+
+Real smoothkernelLucyLapl(const double & r, const double & h) {
+  if (r<=h) {
+    // 2nd derivative of Lucy Kernel function, 
+    return 105./(16.*M_PI*h*h*h) * (-12) / (h * h * h * h) * (h * h - 2 * r * h + 3 * r * r);
+  } else {
+    return 0;
+  }
+}
+
+KernelFunction returnKernelFunction(const int a, const typeKernFunctions typeF) {
+  return returnKernelFunction(a, a, typeF);
 }
 
 KernelFunction returnKernelFunction(const int a, const int b, const typeKernFunctions typeF) {
   if (a != b) {
     throw runtime_error("Kernel types should be equal!");
   }
-  if (a==Poly6) {
-    if (typeF==Norm) {
-      return smoothkernelPoly6;
-    } else if (typeF==Grad) {
-      return smoothkernelPoly6Grad;
-    } else if (typeF==Lapl) {
-      return smoothkernelPoly6Lapl;
-    } else {
-      KERNELFUNCDESCR
-    }
-  } else if (a==Spiky) {
-    if (typeF==Norm) {
-      return smoothkernelSpiky;
-    } else if (typeF==Grad) {
-      return smoothkernelSpikyGrad;
-    } else if (typeF==Lapl) {
-      return smoothkernelSpikyLapl;
-    } else {
-      KERNELFUNCDESCR
-    }
-  } else if (a==Visco) {
-    if (typeF==Norm) {
-      return smoothkernelVisco;
-    } else if (typeF==Grad) {
-      return smoothkernelViscoGrad;
-    } else if (typeF==Lapl) {
-      return smoothkernelViscoLapl;
-    } else {
-    }
-  } else if (a==Lucy) {
+  if (a==Lucy) {
     if (typeF==Norm) {
       return smoothkernelLucy;
     } else if (typeF==Grad) {
@@ -307,23 +97,12 @@
     } else {
       KERNELFUNCDESCR
     }
-  } else if (a==Monaghan) {
-    if (typeF==Norm) {
-      return smoothkernelMonaghan;
-    } else if (typeF==Grad) {
-      return smoothkernelMonaghanGrad;
-    } else if (typeF==Lapl) {
-      return smoothkernelMonaghanLapl;
-    } else {
-      KERNELFUNCDESCR
-    }
   } else {
     KERNELFUNCDESCR
   }
 }
 
 bool computeForceSPH(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I, Vector3r & force) {
-  
   const ScGeom& geom=*static_cast<ScGeom*>(_geom.get());
   Scene* scene=Omega::instance().getScene().get();
   ViscElPhys& phys=*static_cast<ViscElPhys*>(_phys.get());
@@ -333,66 +112,29 @@
   
   const BodyContainer& bodies = *scene->bodies;
   
-  //////////////////////////////////////////////////////////////////
-  // Copy-paste
-  
   const State& de1 = *static_cast<State*>(bodies[id1]->state.get());
   const State& de2 = *static_cast<State*>(bodies[id2]->state.get());
   
-    // Handle periodicity.
-  const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(I->cellDist): Vector3r::Zero(); 
-  const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(I->cellDist): Vector3r::Zero(); 
-
-  const Vector3r c1x = (geom.contactPoint - de1.pos);
-  const Vector3r c2x = (geom.contactPoint - de2.pos - shift2);
-  
-  const Vector3r relativeVelocity = (de1.vel+de1.angVel.cross(c1x)) - (de2.vel+de2.angVel.cross(c2x)) + shiftVel;
-  const Real normalVelocity	= geom.normal.dot(relativeVelocity);
-  //const Vector3r shearVelocity	= relativeVelocity-normalVelocity*geom.normal;
-  
-  // Copy-paste
-  //////////////////////////////////////////////////////////////////
-  
-  if (phys.h<0) {
-    Sphere* s1=dynamic_cast<Sphere*>(bodies[id1]->shape.get());
-    Sphere* s2=dynamic_cast<Sphere*>(bodies[id2]->shape.get());
-    if (s1 and s2) {
-      phys.h = s1->radius + s2->radius;
-    } else if (s1 and not(s2)) {
-      phys.h = s1->radius;
-    } else {
-      phys.h = s2->radius;
-    }
-  }
-  
-  Real Mass = bodies[id2]->state->mass;
-  if (Mass==0.0 and bodies[id1]->state->mass!= 0.0) {
-    Mass = bodies[id1]->state->mass;
-  }
-  
-  Real Rho = bodies[id2]->rho;
-  if (Rho==0.0 and bodies[id1]->rho!=0.0) {
-    Rho = bodies[id1]->rho;
-  }
-  
-  const Vector3r xixj = (-geom.penetrationDepth + phys.h)*geom.normal;
+  const Real Mass1 = bodies[id1]->state->mass;
+  const Real Mass2 = bodies[id2]->state->mass;
+  
+  const Real Rho1 = bodies[id1]->rho;
+  const Real Rho2 = bodies[id2]->rho;
+  
+  const Vector3r xixj = de2.pos - de1.pos;
   
   if (xixj.norm() < phys.h) {
     Real fpressure = 0.0;
-    if (Rho!=0.0) {
-      // [Mueller2003], (10)
-      fpressure = -Mass * 
-                  (bodies[id1]->press + bodies[id2]->press)/(2.0*Rho) *
-                  phys.kernelFunctionCurrentPressure(xixj.norm(), phys.h);
+    if (bodies[id1]->rho!=0.0 and bodies[id2]->rho!=0.0) {
+      // from [Monaghan1992], (3.3), multiply by Mass2, because we need a force, not du/dt
+      fpressure = - Mass1 * Mass2 * (
+                  bodies[id1]->press/(Rho1*Rho1) + 
+                  bodies[id2]->press/(Rho2*Rho2) 
+                  ) 
+                  * phys.kernelFunctionCurrentPressure(xixj.norm(), phys.h);
     }
     
-    Vector3r fvisc = Vector3r::Zero();
-    if (Rho!=0.0) {
-      fvisc = phys.mu * Mass * 
-                  normalVelocity*geom.normal/Rho *
-                  phys.kernelFunctionCurrentVisco(xixj.norm(), phys.h);
-    }
-    force = fpressure*geom.normal + fvisc;
+    force = fpressure*geom.normal;
     return true;
   } else {
     return false;

=== modified file 'pkg/common/SPHEngine.hpp'
--- pkg/common/SPHEngine.hpp	2014-10-15 06:44:01 +0000
+++ pkg/common/SPHEngine.hpp	2014-10-17 17:14:29 +0000
@@ -6,40 +6,29 @@
 
 typedef Real (* KernelFunction)(const double & r, const double & h);
 
-enum KernFunctions {Poly6=1, Spiky=2, Visco=3, Lucy=4, Monaghan=5};
+enum KernFunctions {Lucy=1};
 #define KERNELFUNCDESCR throw runtime_error("Type of kernel function undefined! The following kernel functions are available: Poly6=1, Spiky=2, Visco=3, Lucy=4, Monaghan=5.");
 
 enum typeKernFunctions {Norm, Grad, Lapl};
 class SPHEngine: public PartialEngine{
   public:
     void calculateSPHRho(const shared_ptr<Body>& b);
-    void calculateSPHCs (const shared_ptr<Body>& b);
     virtual void action();
   YADE_CLASS_BASE_DOC_ATTRS(SPHEngine,PartialEngine,"Apply given torque (momentum) value at every subscribed particle, at every step. ",
     ((int, mask,-1,, "Bitmask for SPH-particles."))
     ((Real,k,-1,,    "Gas constant for SPH-interactions (only for SPH-model). See Mueller [Mueller2003]_ .")) // [Mueller2003], (11)
     ((Real,rho0,-1,, "Rest density. See Mueller [Mueller2003]_ ."))                                           // [Mueller2003], (1)
-    ((int,KernFunctionDensity, Poly6,, "Kernel function for density calculation (by default - Poly6). The following kernel functions are available: Poly6=1, Spiky=2, Visco=3, Lucy=4, Monaghan=5."))
+    ((Real,h,-1,,    "Core radius. See Mueller [Mueller2003]_ ."))                                            // [Mueller2003], (1)
+    ((int,KernFunctionDensity, Lucy,, "Kernel function for density calculation (by default - Lucy). The following kernel functions are available: Lucy=1."))
   );
 };
 REGISTER_SERIALIZABLE(SPHEngine);
-Real smoothkernelPoly6(const double & r, const double & h);       // [Mueller2003] (20)
-Real smoothkernelPoly6Grad(const double & r, const double & h);
-Real smoothkernelPoly6Lapl(const double & r, const double & h);
-Real smoothkernelSpiky(const double & r, const double & h);       // [Mueller2003] (21)
-Real smoothkernelSpikyGrad(const double & r, const double & h);
-Real smoothkernelSpikyLapl(const double & r, const double & h);
-Real smoothkernelVisco(const double & r, const double & h);       // [Mueller2003] (22)
-Real smoothkernelViscoGrad(const double & r, const double & h);   // [Mueller2003] (22)
-Real smoothkernelViscoLapl(const double & r, const double & h);
 Real smoothkernelLucy(const double & r, const double & h);         
 Real smoothkernelLucyGrad(const double & r, const double & h);     
 Real smoothkernelLucyLapl(const double & r, const double & h);
-Real smoothkernelMonaghan(const double & r, const double & h);         
-Real smoothkernelMonaghanGrad(const double & r, const double & h);     
-Real smoothkernelMonaghanLapl(const double & r, const double & h);
 
 KernelFunction returnKernelFunction(const int a, const int b, const typeKernFunctions typeF);
+KernelFunction returnKernelFunction(const int a, const typeKernFunctions typeF);
 
 bool computeForceSPH(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I, Vector3r & force);
 #endif

=== modified file 'pkg/dem/ViscoelasticPM.cpp'
--- pkg/dem/ViscoelasticPM.cpp	2014-10-15 06:44:01 +0000
+++ pkg/dem/ViscoelasticPM.cpp	2014-10-17 17:14:29 +0000
@@ -256,6 +256,7 @@
 	if (mat1->SPHmode and mat2->SPHmode)  {
 		phys->SPHmode=true;
 		phys->mu=(mat1->mu+mat2->mu)/2.0;
+		phys->h=(mat1->h+mat2->h)/2.0;
 	}
 	
 	phys->kernelFunctionCurrentPressure = returnKernelFunction (mat1->KernFunctionPressure, mat2->KernFunctionPressure, Grad);

=== modified file 'pkg/dem/ViscoelasticPM.hpp'
--- pkg/dem/ViscoelasticPM.hpp	2014-10-15 06:44:01 +0000
+++ pkg/dem/ViscoelasticPM.hpp	2014-10-17 17:14:29 +0000
@@ -35,8 +35,9 @@
 #ifdef YADE_SPH
 		((bool,SPHmode,false,,"True, if SPH-mode is enabled."))
 		((Real,mu,-1,, "Viscosity. See Mueller [Mueller2003]_ ."))                                              // [Mueller2003], (14)
-		((int,KernFunctionPressure,Spiky,, "Kernel function for pressure calculation (by default - Spiky). The following kernel functions are available: Poly6=1, Spiky=2, Visco=3, Lucy=4, Monaghan=5."))
-		((int,KernFunctionVisco,   Visco,, "Kernel function for viscosity calculation (by default - Visco). The following kernel functions are available: Poly6=1, Spiky=2, Visco=3, Lucy=4, Monaghan=5."))
+		((Real,h,-1,,  "Core radius. See Mueller [Mueller2003]_ ."))                                            // [Mueller2003], (1)
+		((int,KernFunctionPressure,Lucy,, "Kernel function for pressure calculation (by default - Lucy). The following kernel functions are available: Lucy=1."))
+		((int,KernFunctionVisco,   Lucy,, "Kernel function for viscosity calculation (by default - Lucy). The following kernel functions are available: Lucy=1."))
 #endif
 		((unsigned int,mRtype,1,,"Rolling resistance type, see [Zhou1999536]_. mRtype=1 - equation (3) in [Zhou1999536]_; mRtype=2 - equation (4) in [Zhou1999536]_.")),
 		createIndex();