diff --git a/apps/benchmarks/FluidParticleCoupling/ObliqueDryCollision.cpp b/apps/benchmarks/FluidParticleCoupling/ObliqueDryCollision.cpp
index fb1e42957ef2de7b349259947d59897fa9d7efee..18adc77137d0591fedcec9e297af97e6b41a18d2 100644
--- a/apps/benchmarks/FluidParticleCoupling/ObliqueDryCollision.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/ObliqueDryCollision.cpp
@@ -111,20 +111,7 @@ int main( int argc, char ** argv )
 
    const real_t particleMass =  real_t(1) / ss->shapes[sphereShape]->getInvMass();
    const real_t Mij = particleMass; // * particleMass / ( real_t(2) * particleMass ); // Mij = M for sphere-wall collision
-   const real_t lnDryResCoeff = std::log(restitutionCoeff);
-
-   // normal material parameters
-   const real_t stiffnessN = Mij * ( math::pi * math::pi + lnDryResCoeff * lnDryResCoeff ) / (collisionTime * collisionTime); // Costa et al., Eq. 18
-   const real_t dampingN = - real_t(2) * Mij * lnDryResCoeff / collisionTime; // Costa et al., Eq. 18
-
-   WALBERLA_LOG_INFO_ON_ROOT("normal: stiffness = " << stiffnessN << ", damping = " << dampingN);
-
-   // from Thornton et al
-   const real_t kappa = real_t(2) * ( real_t(1) - nu ) / ( real_t(2) - nu ) ;
-   const real_t stiffnessT = kappa * stiffnessN;
-   const real_t dampingT = std::sqrt(kappa) * dampingN;
-
-   WALBERLA_LOG_INFO_ON_ROOT("tangential: kappa = " << kappa << ", stiffness T = " << stiffnessT << ", damping T = " << dampingT);
+   const real_t kappa = real_t(2) * ( real_t(1) - nu ) / ( real_t(2) - nu ) ;    // from Thornton et al
 
    real_t uTin = uNin * impactAngle;
 
@@ -154,10 +141,7 @@ int main( int argc, char ** argv )
    kernel::DoubleCast           double_cast;
    kernel::LinearSpringDashpot  dem(1);
    mpi::ReduceContactHistory    rch;
-   dem.setStiffnessN(0,0,stiffnessN);
-   dem.setStiffnessT(0,0,stiffnessT);
-   dem.setDampingN(0,0,dampingN);
-   dem.setDampingT(0,0,dampingT);
+   dem.setStiffnessAndDamping(0,0,restitutionCoeff,collisionTime,kappa,Mij);
    dem.setFrictionCoefficientStatic(0,0,frictionCoeff_s);
    dem.setFrictionCoefficientDynamic(0,0,frictionCoeff_d);
 
diff --git a/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp b/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp
index 966a55925f85fea9a051687ae6836afbfc27ca7b..12ef798b27eb670f4b32135f656be9217999a197 100644
--- a/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp
@@ -694,15 +694,7 @@ int main( int argc, char **argv )
 
    const real_t particleMass = densitySphere * sphereVolume;
    const real_t Mij = particleMass; // * particleMass / ( real_t(2) * particleMass ); // Mij = M for sphere-wall collision
-   const real_t lnDryResCoeff = std::log(restitutionCoeff);
-
-   const real_t stiffnessN = Mij * ( math::pi * math::pi + lnDryResCoeff * lnDryResCoeff ) / (collisionTime * collisionTime); // Costa et al., Eq. 18
-   const real_t dampingN = - real_t(2) * Mij * lnDryResCoeff / collisionTime; // Costa et al., Eq. 18
-
-   // from Biegert et al
    const real_t kappa = real_t(2) * ( real_t(1) - poissonsRatio ) / ( real_t(2) - poissonsRatio ) ;
-   const real_t stiffnessT = kappa * stiffnessN;
-   const real_t dampingT = std::sqrt(kappa) * dampingN;
 
    Vector3<uint_t> domainSize( uint_c(domainSizeNonDim[0] * diameter ), uint_c(domainSizeNonDim[1] * diameter ), uint_c(domainSizeNonDim[2] * diameter ) );
 
@@ -735,10 +727,6 @@ int main( int argc, char **argv )
 
    WALBERLA_LOG_INFO_ON_ROOT("Collision Response properties:" );
    WALBERLA_LOG_INFO_ON_ROOT(" - collision time = " << collisionTime );
-   WALBERLA_LOG_INFO_ON_ROOT(" - damping coeff n = " << dampingN );
-   WALBERLA_LOG_INFO_ON_ROOT(" - stiffness coeff n = " << stiffnessN );
-   WALBERLA_LOG_INFO_ON_ROOT(" - damping coeff t = " << dampingT );
-   WALBERLA_LOG_INFO_ON_ROOT(" - stiffness coeff t= " << stiffnessT );
    WALBERLA_LOG_INFO_ON_ROOT(" - coeff of restitution = " << restitutionCoeff );
    WALBERLA_LOG_INFO_ON_ROOT(" - coeff of friction = " << frictionCoeff );
 
@@ -875,10 +863,7 @@ int main( int argc, char **argv )
 
    // linear model
    mesa_pd::kernel::LinearSpringDashpot linearCollisionResponse(1);
-   linearCollisionResponse.setStiffnessN(0,0,stiffnessN);
-   linearCollisionResponse.setDampingN(0,0,dampingN);
-   linearCollisionResponse.setStiffnessT(0,0,stiffnessT);
-   linearCollisionResponse.setDampingT(0,0,dampingT);
+   linearCollisionResponse.setStiffnessAndDamping(0,0,restitutionCoeff,collisionTime,kappa,Mij);
    //linearCollisionResponse.setFrictionCoefficientStatic(0,0,frictionCoeff); // not used in this test case
    linearCollisionResponse.setFrictionCoefficientDynamic(0,0,frictionCoeff);
 
diff --git a/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp b/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp
index 8a339e6915f29dff6fcaea552b68923deb5540ce..0890c4ef497d9b840374a0cb4fe75bea2d4ff7c7 100644
--- a/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp
@@ -666,16 +666,6 @@ int main( int argc, char **argv )
 
    const real_t particleMass = densityRatio * sphereVolume;
    const real_t Mij = particleMass; // * particleMass / ( real_t(2) * particleMass ); // Mij = M for sphere-wall collision
-   const real_t lnDryResCoeff = std::log(restitutionCoeff);
-   const real_t stiffnessCoeff = Mij * ( math::pi * math::pi + lnDryResCoeff * lnDryResCoeff ) / (collisionTime * collisionTime); // Costa et al., Eq. 18
-   const real_t dampingCoeff = - real_t(2) * Mij * lnDryResCoeff / collisionTime; // Costa et al., Eq. 18
-   //const real_t contactDuration = real_t(2) * math::pi * Mij / ( std::sqrt( real_t(4) * Mij * stiffnessCoeff - dampingCoeff * dampingCoeff )); //formula from Uhlman
-
-   const real_t var_a = std::sqrt( math::pi * math::pi + (std::log(restitutionCoeff) * std::log(restitutionCoeff) ) );
-   const real_t TnLimit1 = var_a * diameter / uIn * std::exp(-std::asin(math::pi / var_a ) / math::pi); // Costa et al, Eq. 20
-   const real_t TnLimit2 = std::sqrt(diameter / gravitationalAcceleration * var_a * var_a / std::abs(real_t(1) - densityFluid/densitySphere)); // Costa et al, Eq. 21
-
-   const real_t overlapDueToWeight = std::abs(densitySphere - densityFluid) * gravitationalAcceleration * sphereVolume / stiffnessCoeff; // Costa et al., given in text after Eq. 34
 
    const real_t uInCrit = real_t(9) * StCrit * viscosity / ( densityRatio * diameter);
 
@@ -741,12 +731,8 @@ int main( int argc, char **argv )
    }
    else
    {
-      WALBERLA_LOG_INFO_ON_ROOT(" - using linear collision model with fixed parameters:" );
-      WALBERLA_LOG_INFO_ON_ROOT("  - damping coeff = " << dampingCoeff );
-      WALBERLA_LOG_INFO_ON_ROOT("  - stiffness coeff = " << stiffnessCoeff );
-      WALBERLA_LOG_INFO_ON_ROOT(" - overlap due to particle weight = " << overlapDueToWeight);
+      WALBERLA_LOG_INFO_ON_ROOT(" - using linear collision model with fixed parameters" );
    }
-   WALBERLA_LOG_INFO_ON_ROOT(" - TnCrit1 = " << TnLimit1 << ", TnCrit2 = " << TnLimit2 );
    WALBERLA_LOG_INFO_ON_ROOT(" - coeff of restitution = " << restitutionCoeff );
    WALBERLA_LOG_INFO_ON_ROOT(" - number of RPD sub cycles = " << numRPDSubCycles );
    WALBERLA_LOG_INFO_ON_ROOT(" - lubrication correction = " << (useLubricationCorrection ? "yes" : "no") );
@@ -963,12 +949,11 @@ int main( int argc, char **argv )
 
    // linear model
    mesa_pd::kernel::LinearSpringDashpot linearCollisionResponse(1);
-   linearCollisionResponse.setStiffnessN(0,0,stiffnessCoeff);
-   linearCollisionResponse.setDampingN(0,0,dampingCoeff);
+   linearCollisionResponse.setStiffnessAndDamping(0,0,restitutionCoeff,collisionTime,real_t(0),Mij); // no response in tangential direction
 
    // nonlinear model for ACTM
    mesa_pd::kernel::NonLinearSpringDashpot nonLinearCollisionResponse(1, collisionTime);
-   nonLinearCollisionResponse.setLnCORsqr(0,0,lnDryResCoeff * lnDryResCoeff);
+   nonLinearCollisionResponse.setLnCORsqr(0,0,std::log(restitutionCoeff) * std::log(restitutionCoeff));
    nonLinearCollisionResponse.setMeff(0,0,Mij);
 
    mesa_pd::mpi::ReduceProperty reduceProperty;
diff --git a/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h b/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h
index f5c1b8e224bdf5e61eb3bd23e545211e63f12f59..2e86c1c1d150ea53a4dc5344c3823a2e6a905aa0 100644
--- a/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h
+++ b/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h
@@ -81,6 +81,21 @@ public:
                    const real_t& penetrationDepth,
                    const real_t& dt) const;
 
+   real_t calcCoefficientOfRestitution(const size_t type1,
+                                       const size_t type2,
+                                       const real_t effectiveMass);
+
+   real_t calcCollisionTime(const size_t type1,
+                            const size_t type2,
+                            const real_t effectiveMass);
+
+   void setStiffnessAndDamping(const size_t type1,
+                               const size_t type2,
+                               const real_t coefficientOfRestitution,
+                               const real_t collisionTime,
+                               const real_t poissonsRatio,
+                               const real_t effectiveMass);
+
    {% for param in parameters %}
    /// assumes this parameter is symmetric
    void set{{param | capFirst}}(const size_t type1, const size_t type2, const real_t& val);
@@ -174,7 +189,7 @@ inline void LinearSpringDashpot::operator()(const size_t p_idx1,
          impactVelocityMagnitude = relVel.length();
       }
 
-      //TODO: move to own tangential integration kernel?
+      //TODO: move to own tangential displacement integration kernel
       Vec3 rotatedTangentialDisplacement = tangentialSpringDisplacement - contactNormal * (contactNormal * tangentialSpringDisplacement);
       Vec3 newTangentialSpringDisplacement = rotatedTangentialDisplacement.sqrLength() <= real_t(0) ? // avoid division by zero
                                              Vec3(real_t(0)) :
@@ -218,7 +233,6 @@ inline void LinearSpringDashpot::operator()(const size_t p_idx1,
          // if tangential force falls below coulomb limit, we are back in sticking
          if( fTLS.length() < fFrictionAbsDynamic )
          {
-            //TODO really?
             isSticking = true;
          }
       }
@@ -248,6 +262,39 @@ inline void LinearSpringDashpot::operator()(const size_t p_idx1,
    }
 }
 
+inline real_t LinearSpringDashpot::calcCoefficientOfRestitution(const size_t type1,
+                                                                const size_t type2,
+                                                                const real_t effectiveMass)
+{
+   auto a = real_t(0.5) * getDampingN(type1, type2) / effectiveMass;
+   return std::exp(-a * math::pi / std::sqrt(getStiffnessN(type1, type2) / effectiveMass - a*a));
+}
+
+inline real_t LinearSpringDashpot::calcCollisionTime(const size_t type1,
+                                                     const size_t type2,
+                                                     const real_t effectiveMass)
+{
+   auto a = real_t(0.5) * getDampingN(type1, type2) / effectiveMass;
+   return math::pi / std::sqrt( getStiffnessN(type1, type2)/effectiveMass - a*a);
+}
+
+inline void LinearSpringDashpot::setStiffnessAndDamping(const size_t type1,
+                                                        const size_t type2,
+                                                        const real_t coefficientOfRestitution,
+                                                        const real_t collisionTime,
+                                                        const real_t poissonsRatio,
+                                                        const real_t effectiveMass)
+{
+   const real_t kappa = real_t(2) * ( real_t(1) - poissonsRatio ) / ( real_t(2) - poissonsRatio ) ;
+   const real_t lnDryResCoeff = std::log(coefficientOfRestitution);
+
+   setStiffnessN(type1, type2, effectiveMass * ( math::pi * math::pi + lnDryResCoeff * lnDryResCoeff ) / (collisionTime * collisionTime) );
+   setDampingN  (type1, type2, - real_t(2) * effectiveMass * lnDryResCoeff / collisionTime );
+
+   setStiffnessT(type1, type2, kappa * getStiffnessN(type1, type2) );
+   setDampingT  (type1, type2, std::sqrt(kappa) * getDampingN(type1, type2) );
+}
+
 } //namespace kernel
 } //namespace mesa_pd
 } //namespace walberla
diff --git a/src/mesa_pd/kernel/LinearSpringDashpot.h b/src/mesa_pd/kernel/LinearSpringDashpot.h
index 5239f29b6ef41879ee8ff913ff977fbfcc0f4d12..46db0270b614fed6e80c45f802400fff39370b5c 100644
--- a/src/mesa_pd/kernel/LinearSpringDashpot.h
+++ b/src/mesa_pd/kernel/LinearSpringDashpot.h
@@ -86,6 +86,21 @@ public:
                    const real_t& penetrationDepth,
                    const real_t& dt) const;
 
+   real_t calcCoefficientOfRestitution(const size_t type1,
+                                       const size_t type2,
+                                       const real_t effectiveMass);
+
+   real_t calcCollisionTime(const size_t type1,
+                            const size_t type2,
+                            const real_t effectiveMass);
+
+   void setStiffnessAndDamping(const size_t type1,
+                               const size_t type2,
+                               const real_t coefficientOfRestitution,
+                               const real_t collisionTime,
+                               const real_t poissonsRatio,
+                               const real_t effectiveMass);
+
    
    /// assumes this parameter is symmetric
    void setStiffnessN(const size_t type1, const size_t type2, const real_t& val);
@@ -278,7 +293,7 @@ inline void LinearSpringDashpot::operator()(const size_t p_idx1,
          impactVelocityMagnitude = relVel.length();
       }
 
-      //TODO: move to own tangential integration kernel?
+      //TODO: move to own tangential displacement integration kernel
       Vec3 rotatedTangentialDisplacement = tangentialSpringDisplacement - contactNormal * (contactNormal * tangentialSpringDisplacement);
       Vec3 newTangentialSpringDisplacement = rotatedTangentialDisplacement.sqrLength() <= real_t(0) ? // avoid division by zero
                                              Vec3(real_t(0)) :
@@ -322,7 +337,6 @@ inline void LinearSpringDashpot::operator()(const size_t p_idx1,
          // if tangential force falls below coulomb limit, we are back in sticking
          if( fTLS.length() < fFrictionAbsDynamic )
          {
-            //TODO really?
             isSticking = true;
          }
       }
@@ -352,6 +366,39 @@ inline void LinearSpringDashpot::operator()(const size_t p_idx1,
    }
 }
 
+inline real_t LinearSpringDashpot::calcCoefficientOfRestitution(const size_t type1,
+                                                                const size_t type2,
+                                                                const real_t effectiveMass)
+{
+   auto a = real_t(0.5) * getDampingN(type1, type2) / effectiveMass;
+   return std::exp(-a * math::pi / std::sqrt(getStiffnessN(type1, type2) / effectiveMass - a*a));
+}
+
+inline real_t LinearSpringDashpot::calcCollisionTime(const size_t type1,
+                                                     const size_t type2,
+                                                     const real_t effectiveMass)
+{
+   auto a = real_t(0.5) * getDampingN(type1, type2) / effectiveMass;
+   return math::pi / std::sqrt( getStiffnessN(type1, type2)/effectiveMass - a*a);
+}
+
+inline void LinearSpringDashpot::setStiffnessAndDamping(const size_t type1,
+                                                        const size_t type2,
+                                                        const real_t coefficientOfRestitution,
+                                                        const real_t collisionTime,
+                                                        const real_t poissonsRatio,
+                                                        const real_t effectiveMass)
+{
+   const real_t kappa = real_t(2) * ( real_t(1) - poissonsRatio ) / ( real_t(2) - poissonsRatio ) ;
+   const real_t lnDryResCoeff = std::log(coefficientOfRestitution);
+
+   setStiffnessN(type1, type2, effectiveMass * ( math::pi * math::pi + lnDryResCoeff * lnDryResCoeff ) / (collisionTime * collisionTime) );
+   setDampingN  (type1, type2, - real_t(2) * effectiveMass * lnDryResCoeff / collisionTime );
+
+   setStiffnessT(type1, type2, kappa * getStiffnessN(type1, type2) );
+   setDampingT  (type1, type2, std::sqrt(kappa) * getDampingN(type1, type2) );
+}
+
 } //namespace kernel
 } //namespace mesa_pd
 } //namespace walberla
\ No newline at end of file