diff --git a/src/pe/cr/ContactResolvers.h b/src/pe/cr/ContactResolvers.h
new file mode 100644
index 0000000000000000000000000000000000000000..d90b6783559c68628ca8f0d91f8b5288a7129d56
--- /dev/null
+++ b/src/pe/cr/ContactResolvers.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include "pe/Types.h"
+#include "ICR.h"
+#include "pe/contact/Contact.h"
+#include "pe/contact/ContactFunctions.h"
+
+namespace walberla {
+namespace pe {
+namespace cr {
+
+class ResolveContactSpringDashpotHaffWerner {
+public:
+   void operator()( ContactID c ) const
+   {
+      WALBERLA_LOG_DETAIL( "resolving contact: " << c->getID() );
+      BodyID b1( c->getBody1()->getTopSuperBody() );
+      BodyID b2( c->getBody2()->getTopSuperBody() );
+
+      // Global position of contact
+      const Vec3 gpos( c->getPosition() );
+
+      // The absolute value of the penetration length
+      real_t delta( -c->getDistance() );
+
+      // Calculating the relative velocity in normal and tangential direction
+      // The negative signs result from the different definition of the relative
+      // normal velocity of the pe (see Contact::getType)
+      const real_t relVelN( -c->getNormalRelVel() );
+      const Vec3   relVel ( -c->getRelVel() );
+      const Vec3   relVelT( relVel - ( relVelN * c->getNormal() ) );
+
+      real_t fNabs( 0 );
+      Vec3   fN;
+
+      // Calculating the normal force based on a linear spring-dashpot force model
+      fNabs = getStiffness(c) * delta + getDampingN(c) * relVelN;
+      if( fNabs < real_c(0) ) fNabs = real_c(0);
+      fN = fNabs * c->getNormal();
+
+      // Calculating the tangential force based on the model by Haff and Werner
+      const real_t fTabs( std::min( getDampingT(c) * relVelT.length(), getFriction(c) * fNabs ) );
+      const Vec3   fT   ( fTabs * relVelT.getNormalizedOrZero() );
+
+      // Add normal force at contact point
+      b1->addForceAtPos(  fN, gpos );
+      b2->addForceAtPos( -fN, gpos );
+
+      // Add tangential force at contact point
+      b1->addForceAtPos(  fT, gpos );
+      b2->addForceAtPos( -fT, gpos );
+
+      WALBERLA_LOG_DETAIL("nForce: " << fN << "\ntForce: " << fT);
+   }
+};
+
+}  // namespace cr
+} // namespace pe
+}  // namespace walberla
diff --git a/src/pe/cr/DEM.cpp b/src/pe/cr/DEM.cpp
deleted file mode 100644
index e4915c755efb69c49e0d9499db4e98f5ca1f90ad..0000000000000000000000000000000000000000
--- a/src/pe/cr/DEM.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-//======================================================================================================================
-//
-//  This file is part of waLBerla. waLBerla is free software: you can
-//  redistribute it and/or modify it under the terms of the GNU General Public
-//  License as published by the Free Software Foundation, either version 3 of
-//  the License, or (at your option) any later version.
-//
-//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
-//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-//  for more details.
-//
-//  You should have received a copy of the GNU General Public License along
-//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
-//
-//! \file DEM.cpp
-//! \author Klaus Iglberger
-//! \author Sebastian Eibl <sebastian.eibl@fau.de>
-//! \brief Source file for the DEM solver
-//
-//======================================================================================================================
-
-
-//*************************************************************************************************
-// Includes
-//*************************************************************************************************
-
-#include "pe/cr/DEM.h"
-#include "pe/ccd/ICCD.h"
-#include "pe/fcd/IFCD.h"
-#include "pe/bg/IBG.h"
-#include "pe/rigidbody/BodyStorage.h"
-#include "pe/rigidbody/RigidBody.h"
-#include "pe/contact/Contact.h"
-#include "pe/contact/ContactFunctions.h"
-#include "pe/synchronization/SyncForces.h"
-
-#include "core/logging/all.h"
-
-namespace walberla {
-namespace pe {
-namespace cr {
-
-DEM::DEM(    const shared_ptr<BodyStorage>&    globalBodyStorage
-           , const shared_ptr<BlockStorage>&   blockStorage
-           , domain_decomposition::BlockDataID storageID
-           , domain_decomposition::BlockDataID ccdID
-           , domain_decomposition::BlockDataID fcdID
-           , WcTimingTree*                     tt)
-   : globalBodyStorage_(globalBodyStorage)
-   , blockStorage_(blockStorage)
-   , storageID_(storageID)
-   , ccdID_(ccdID)
-   , fcdID_(fcdID)
-   , tt_(tt)
-   , maxPenetration_(0)
-   , numberOfContacts_(0)
-   , numberOfContactsTreated_(0)
-{
-
-}
-
-void DEM::timestep( real_t dt )
-{
-   maxPenetration_          = real_c(0.0);
-   numberOfContacts_        = 0;
-   numberOfContactsTreated_ = 0;
-
-   for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it){
-      IBlock & currentBlock = *it;
-
-      ccd::ICCD* ccd = currentBlock.getData< ccd::ICCD >( ccdID_ );
-      fcd::IFCD* fcd = currentBlock.getData< fcd::IFCD >( fcdID_ );
-      ccd->generatePossibleContacts( tt_ );
-      if (tt_ != NULL) tt_->start("FCD");
-      Contacts& cont = fcd->generateContacts( ccd->getPossibleContacts() );
-      if (tt_ != NULL) tt_->stop("FCD");
-
-      for (auto cIt = cont.begin(); cIt != cont.end(); ++cIt){
-         const real_t overlap( -cIt->getDistance() );
-         if( overlap > maxPenetration_ )
-            maxPenetration_ = overlap;
-         if (shouldContactBeTreated( &(*cIt), currentBlock.getAABB() ))
-         {
-            ++numberOfContactsTreated_;
-            resolveContact( &(*cIt) );
-         }
-      }
-
-      numberOfContacts_ += cont.size();
-
-      cont.clear();
-   }
-
-//   if (numContacts > 0)
-//      WALBERLA_LOG_DEVEL_ON_ROOT("#Contacts: " << numContacts << "." );
-
-   if (tt_ != NULL) tt_->start("ForceSync");
-   reduceForces( *blockStorage_, storageID_, *globalBodyStorage_);
-   if (tt_ != NULL) tt_->stop("ForceSync");
-
-   for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it)
-   {
-      IBlock & currentBlock = *it;
-      Storage * storage = currentBlock.getData< Storage >( storageID_ );
-      BodyStorage& localStorage = (*storage)[0];
-      BodyStorage& shadowStorage = (*storage)[1];
-
-      // Updating the positions and velocities of all locally owned and global rigid bodies (but not shadow copies).
-      WALBERLA_LOG_DETAIL( "Time integration starts...\n" );
-
-      if (tt_ != NULL) tt_->start("Integration");
-
-      for( auto bodyIt = localStorage.begin(); bodyIt != localStorage.end(); ++bodyIt )
-      {
-         WALBERLA_LOG_DETAIL( "Time integration of body with system id " << bodyIt->getSystemID());// << "\n" << *bodyIt );
-
-         // Resetting the contact node and removing all attached contacts
-      //      bodyIt->resetNode();
-         bodyIt->clearContacts();
-
-         move( *bodyIt, dt );
-
-         // Resetting the acting forces
-         bodyIt->resetForceAndTorque();
-      }
-
-      if (tt_ != NULL) tt_->stop("Integration");
-
-      // Reset forces of shadow copies
-      for( auto bodyIt = shadowStorage.begin(); bodyIt != shadowStorage.end(); ++bodyIt ) {
-         bodyIt->clearContacts();
-         bodyIt->resetForceAndTorque();
-      }
-
-   }
-}
-
-//=================================================================================================
-//
-//  SOLVER FUNCTIONS
-//
-//=================================================================================================
-
-//*************************************************************************************************
-/*!\brief Resolves the given colliding contact.
- *
- * \param c The colliding contact.
- * \return The overlap of the contact.
- *
- * TODO
- */
-void DEM::resolveContact( ContactID c ) const
-{
-   WALBERLA_LOG_DETAIL( "resolving contact: " << c->getID() );
-   BodyID b1( c->getBody1()->getTopSuperBody() );
-   BodyID b2( c->getBody2()->getTopSuperBody() );
-
-   // Global position of contact
-   const Vec3 gpos( c->getPosition() );
-
-   // The absolute value of the penetration length
-   real_t delta( -c->getDistance() );
-
-   // Calculating the relative velocity in normal and tangential direction
-   // The negative signs result from the different definition of the relative
-   // normal velocity of the pe (see Contact::getType)
-   const real_t relVelN( -c->getNormalRelVel() );
-   const Vec3   relVel ( -c->getRelVel() );
-   const Vec3   relVelT( relVel - ( relVelN * c->getNormal() ) );
-
-   real_t fNabs( 0 );
-   Vec3   fN;
-
-   // Calculating the normal force based on the non-linear extended Hertz model
-   // This force model is only applied in case of a sphere/sphere collision, since only
-   // then an effective radius can be computed.
-//   if( dem::forceModel == dem::hertz && c->hasEffectiveRadius() )
-//   {
-//      const real_t alpha   ( 1.5 );
-//      const real_t beta    ( 0.5 );
-//      const real_t Reff    ( c->getEffectiveRadius() );
-//      const real_t Eeff    ( c->getEffectiveYoungModulus() );
-//      const real_t k       ( ( real_c(4)/real_c(3) ) * Eeff * sqrt( Reff ) );
-
-//      fNabs = k*std::pow( delta, alpha ) + c->getDampingN()*relVelN*std::pow( delta, beta );
-//      if( fNabs < real_c(0) ) fNabs = real_c(0);
-//      fN = fNabs * c->getNormal();
-//   }
-
-//   // Calculating the normal force based on a linear spring-dashpot force model
-//   else
-   {
-      fNabs = getStiffness(c) * delta + getDampingN(c) * relVelN;
-      if( fNabs < real_c(0) ) fNabs = real_c(0);
-      fN = fNabs * c->getNormal();
-   }
-
-   // Calculating the tangential force based on the model by Haff and Werner
-   const real_t fTabs( std::min( getDampingT(c) * relVelT.length(), getFriction(c) * fNabs ) );
-   const Vec3   fT   ( fTabs * relVelT.getNormalizedOrZero() );
-
-   // Add normal force at contact point
-   b1->addForceAtPos(  fN, gpos );
-   b2->addForceAtPos( -fN, gpos );
-
-   // Add tangential force at contact point
-   b1->addForceAtPos(  fT, gpos );
-   b2->addForceAtPos( -fT, gpos );
-
-   WALBERLA_LOG_DETAIL("nForce: " << fN << "\ntForce: " << fT);
-}
-//*************************************************************************************************
-
-//=================================================================================================
-//
-//  SIMULATION FUNCTIONS
-//
-//=================================================================================================
-
-//*************************************************************************************************
-/*!\brief Calculation of a time step of \a dt.
- *
- * \param dt Time step size.
- * \return void
- *
- * Calculating one single time step of size \a dt for the capsule. The global position, the
- * linear and angular velocity and the orientation of the capsule are changed depending on
- * the acting forces and the current velocities.
- */
-void DEM::move( BodyID id, real_t dt )
-{
-   // Checking the state of the body
-   WALBERLA_ASSERT( id->checkInvariants(), "Invalid body state detected" );
-   WALBERLA_ASSERT( !id->hasSuperBody(), "Invalid superordinate body detected" );
-
-   // Moving the capsule according to the acting forces (don't move a sleeping capsule)
-   if( id->isAwake() && !id->hasInfiniteMass() )
-   {
-      // Calculating the linear acceleration by the equation
-      //   force * m^(-1) + gravity
-      const Vec3 vdot( id->getForce() * id->getInvMass() + getGlobalLinearAcceleration() );
-
-      // Calculating the angular acceleration by the equation
-      //   R * Iinv * R^T * torque
-      const Vec3 wdot( id->getInvInertia() * id->getTorque() );
-
-      // Calculating the translational displacement
-      id->setPosition( id->getPosition() + id->getLinearVel() * dt + 0.5 * vdot * dt * dt );
-
-      // Calculating the rotation angle
-      const Vec3 phi( id->getAngularVel() * dt + 0.5 * wdot * dt * dt);
-
-      // Calculating the new orientation
-      if (!floatIsEqual(phi.length(), 0))
-         id->rotate( Quat( phi, phi.length() ) );
-      WALBERLA_ASSERT_FLOAT_EQUAL( id->getRotation().getDeterminant(), real_c(1 ), "Corrupted rotation matrix determinant" );
-
-      // Updating the linear velocity
-      id->setLinearVel(id->getLinearVel() + vdot * dt);
-
-      // Updating the angular velocity
-      id->setAngularVel( id->getAngularVel() + wdot * dt );
-
-      // Setting the axis-aligned bounding box
-      id->calcBoundingBox();
-
-      // Calculating the current motion of the capsule
-      id->calcMotion();
-   }
-
-   // Resetting the acting forces
-   id->resetForceAndTorque();
-
-   // Checking the state of the rigid body
-   WALBERLA_ASSERT( id->checkInvariants(), "Invalid capsule state detected" );
-}
-//*************************************************************************************************
-
-}  // namespace cr
-} // namespace pe
-}  // namespace walberla
diff --git a/src/pe/cr/DEM.h b/src/pe/cr/DEM.h
index 100d921ceb2f46b2f2095ec378c7709c67afe22a..f5269b06fa53a1fae90b286532429f0720507c5e 100644
--- a/src/pe/cr/DEM.h
+++ b/src/pe/cr/DEM.h
@@ -28,6 +28,8 @@
 //*************************************************************************************************
 
 #include "ICR.h"
+#include "Integrators.h"
+#include "ContactResolvers.h"
 #include "pe/Types.h"
 
 #include "domain_decomposition/BlockStorage.h"
@@ -39,15 +41,17 @@ namespace cr {
 /**
  * \ingroup pe
  */
-class DEM : public ICR
+template< typename Integrator, typename ContactResolver >
+class DEMSolver : public ICR
 {
 public:
-   DEM(  const shared_ptr<BodyStorage>&    globalBodyStorage
-       , const shared_ptr<BlockStorage>&   blockStorage
-       , domain_decomposition::BlockDataID storageID
-       , domain_decomposition::BlockDataID ccdID
-       , domain_decomposition::BlockDataID fcdID
-       , WcTimingTree*                     tt = NULL);
+   DEMSolver( const Integrator & integrate, const ContactResolver & resolveContact
+            , const shared_ptr<BodyStorage>&    globalBodyStorage
+            , const shared_ptr<BlockStorage>&   blockStorage
+            , domain_decomposition::BlockDataID storageID
+            , domain_decomposition::BlockDataID ccdID
+            , domain_decomposition::BlockDataID fcdID
+            , WcTimingTree*                     tt = NULL);
 
    /// forwards to timestep
    /// Convenience operator to make class a functor.
@@ -59,9 +63,8 @@ public:
    virtual inline size_t            getNumberOfContacts()          const WALBERLA_OVERRIDE { return numberOfContacts_; }
    virtual inline size_t            getNumberOfContactsTreated()   const WALBERLA_OVERRIDE { return numberOfContactsTreated_; }
 private:
-   void resolveContact( ContactID c ) const;
-   void move( BodyID id, real_t dt );
-
+   const Integrator                  integrate_;
+   const ContactResolver             resolveContact_;
    shared_ptr<BodyStorage>           globalBodyStorage_;
    shared_ptr<BlockStorage>          blockStorage_;
    domain_decomposition::BlockDataID storageID_;
@@ -74,6 +77,24 @@ private:
    size_t                            numberOfContactsTreated_;
 };
 
+class DEM : public DEMSolver<IntegrateImplictEuler, ResolveContactSpringDashpotHaffWerner>
+{
+public:
+   DEM(  const shared_ptr<BodyStorage>&    globalBodyStorage
+       , const shared_ptr<BlockStorage>&   blockStorage
+       , domain_decomposition::BlockDataID storageID
+       , domain_decomposition::BlockDataID ccdID
+       , domain_decomposition::BlockDataID fcdID
+       , WcTimingTree*                     tt = NULL)
+   : DEMSolver<IntegrateImplictEuler, ResolveContactSpringDashpotHaffWerner>(
+              IntegrateImplictEuler(), ResolveContactSpringDashpotHaffWerner(),
+              globalBodyStorage, blockStorage, storageID, ccdID, fcdID, tt )
+   {
+   }
+};
+
 }  // namespace cr
 } // namespace pe
 }  // namespace walberla
+
+#include "DEM.impl.h"
diff --git a/src/pe/cr/DEM.impl.h b/src/pe/cr/DEM.impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a910f72cacde157d4d50cbbba716b43e32f5aed
--- /dev/null
+++ b/src/pe/cr/DEM.impl.h
@@ -0,0 +1,160 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file DEM.cpp
+//! \author Klaus Iglberger
+//! \author Sebastian Eibl <sebastian.eibl@fau.de>
+//! \brief Source file for the DEM solver
+//
+//======================================================================================================================
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include "pe/cr/DEM.h"
+#include "pe/ccd/ICCD.h"
+#include "pe/fcd/IFCD.h"
+#include "pe/bg/IBG.h"
+#include "pe/rigidbody/BodyStorage.h"
+#include "pe/rigidbody/RigidBody.h"
+#include "pe/contact/Contact.h"
+#include "pe/contact/ContactFunctions.h"
+#include "pe/synchronization/SyncForces.h"
+
+#include "core/logging/all.h"
+
+namespace walberla {
+namespace pe {
+namespace cr {
+
+template< typename Integrator, typename ContactResolver >
+DEMSolver<Integrator,ContactResolver>::DEMSolver(
+             const Integrator & integrate, const ContactResolver & resolveContact
+           , const shared_ptr<BodyStorage>&    globalBodyStorage
+           , const shared_ptr<BlockStorage>&   blockStorage
+           , domain_decomposition::BlockDataID storageID
+           , domain_decomposition::BlockDataID ccdID
+           , domain_decomposition::BlockDataID fcdID
+           , WcTimingTree*                     tt)
+   : integrate_(integrate), resolveContact_(resolveContact)
+   ,globalBodyStorage_(globalBodyStorage)
+   , blockStorage_(blockStorage)
+   , storageID_(storageID)
+   , ccdID_(ccdID)
+   , fcdID_(fcdID)
+   , tt_(tt)
+   , maxPenetration_(0)
+   , numberOfContacts_(0)
+   , numberOfContactsTreated_(0)
+{
+
+}
+
+template< typename Integrator, typename ContactResolver >
+void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt )
+{
+   maxPenetration_          = real_c(0.0);
+   numberOfContacts_        = 0;
+   numberOfContactsTreated_ = 0;
+
+   for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it){
+      IBlock & currentBlock = *it;
+
+      ccd::ICCD* ccd = currentBlock.getData< ccd::ICCD >( ccdID_ );
+      fcd::IFCD* fcd = currentBlock.getData< fcd::IFCD >( fcdID_ );
+      ccd->generatePossibleContacts( tt_ );
+      if (tt_ != NULL) tt_->start("FCD");
+      Contacts& cont = fcd->generateContacts( ccd->getPossibleContacts() );
+      if (tt_ != NULL) tt_->stop("FCD");
+
+      for (auto cIt = cont.begin(); cIt != cont.end(); ++cIt){
+         const real_t overlap( -cIt->getDistance() );
+         if( overlap > maxPenetration_ )
+            maxPenetration_ = overlap;
+         if (shouldContactBeTreated( &(*cIt), currentBlock.getAABB() ))
+         {
+            ++numberOfContactsTreated_;
+            resolveContact_( &(*cIt) );
+         }
+      }
+
+      numberOfContacts_ += cont.size();
+
+      cont.clear();
+   }
+
+//   if (numContacts > 0)
+//      WALBERLA_LOG_DEVEL_ON_ROOT("#Contacts: " << numContacts << "." );
+
+   if (tt_ != NULL) tt_->start("ForceSync");
+   reduceForces( *blockStorage_, storageID_, *globalBodyStorage_);
+   if (tt_ != NULL) tt_->stop("ForceSync");
+
+   for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it)
+   {
+      IBlock & currentBlock = *it;
+      Storage * storage = currentBlock.getData< Storage >( storageID_ );
+      BodyStorage& localStorage = (*storage)[0];
+      BodyStorage& shadowStorage = (*storage)[1];
+
+      // Updating the positions and velocities of all locally owned and global rigid bodies (but not shadow copies).
+      WALBERLA_LOG_DETAIL( "Time integration starts...\n" );
+
+      if (tt_ != NULL) tt_->start("Integration");
+
+      for( auto bodyIt = localStorage.begin(); bodyIt != localStorage.end(); ++bodyIt )
+      {
+         WALBERLA_LOG_DETAIL( "Time integration of body with system id " << bodyIt->getSystemID());// << "\n" << *bodyIt );
+
+         // Resetting the contact node and removing all attached contacts
+      //      bodyIt->resetNode();
+         bodyIt->clearContacts();
+
+         // Checking the state of the body
+         WALBERLA_ASSERT( bodyIt->checkInvariants(), "Invalid body state detected" );
+         WALBERLA_ASSERT( !bodyIt->hasSuperBody(), "Invalid superordinate body detected" );
+         
+         // Moving the capsule according to the acting forces (don't move a sleeping capsule)
+         if( bodyIt->isAwake() && !bodyIt->hasInfiniteMass() )
+         {
+            integrate_( *bodyIt, dt, *this );
+         }
+         
+         // Resetting the acting forces
+         bodyIt->resetForceAndTorque();
+         
+         // Checking the state of the rigid body
+         WALBERLA_ASSERT( bodyIt->checkInvariants(), "Invalid capsule state detected" );
+
+         // Resetting the acting forces
+         bodyIt->resetForceAndTorque();
+      }
+
+      if (tt_ != NULL) tt_->stop("Integration");
+
+      // Reset forces of shadow copies
+      for( auto bodyIt = shadowStorage.begin(); bodyIt != shadowStorage.end(); ++bodyIt ) {
+         bodyIt->clearContacts();
+         bodyIt->resetForceAndTorque();
+      }
+
+   }
+}
+
+}  // namespace cr
+} // namespace pe
+}  // namespace walberla
diff --git a/src/pe/cr/Integrators.h b/src/pe/cr/Integrators.h
new file mode 100644
index 0000000000000000000000000000000000000000..7675caf6d51f7ce27b6f015e68bafdb14654ac9d
--- /dev/null
+++ b/src/pe/cr/Integrators.h
@@ -0,0 +1,108 @@
+#pragma once
+
+#include "pe/Types.h"
+#include "ICR.h"
+
+namespace walberla {
+namespace pe {
+namespace cr {
+
+//*************************************************************************************************
+/*!\brief Integrate the trajectory of one body using implict Euler.
+*
+* \param id Body ID.
+* \param dt Time step size.
+* \param solver Solver.
+* \return void
+*
+* The implicit Euler algorithm, also known as backward Euler, is used. It is a first-order
+* integrator that does conserves energy (i.e. it is symplectic.)
+*/
+class IntegrateImplictEuler {
+public:
+   void operator()( BodyID id, real_t dt, ICR & solver ) const
+   {
+      // Calculating the linear acceleration by the equation
+      //   force * m^(-1) + gravity
+      const Vec3 vdot( id->getForce() * id->getInvMass() + solver.getGlobalLinearAcceleration() );
+
+      // Calculating the angular acceleration by the equation
+      //   R * Iinv * R^T * torque
+      const Vec3 wdot( id->getInvInertia() * id->getTorque() );
+
+      // Updating the linear velocity
+      id->setLinearVel( id->getLinearVel() + vdot * dt );
+
+      // Updating the angular velocity
+      id->setAngularVel( id->getAngularVel() + wdot * dt );
+
+      // Calculating the translational displacement
+      id->setPosition( id->getPosition() + id->getLinearVel() * dt );
+
+      // Calculating the rotation angle
+      const Vec3 phi( id->getAngularVel() * dt );
+
+      // Calculating the new orientation
+      if (!floatIsEqual(phi.length(), 0))
+         id->rotate( Quat( phi, phi.length() ) );
+      WALBERLA_ASSERT_FLOAT_EQUAL( id->getRotation().getDeterminant(), real_c(1 ), "Corrupted rotation matrix determinant" );
+
+      // Setting the axis-aligned bounding box
+      id->calcBoundingBox();
+
+      // Calculating the current motion of the capsule
+      id->calcMotion();
+   }
+};
+
+//*************************************************************************************************
+/*!\brief Integrate the trajectory of one body using explicit Euler.
+*
+* \param id Body ID.
+* \param dt Time step size.
+* \param solver Solver.
+* \return void
+*
+* The explicit Euler algorithm, also known as forward Euler, is used. It is a first-order
+* integrator that does not conserve energy (i.e. it is not symplectic.)
+*/
+class IntegrateExplictEuler {
+public:
+   void operator()( BodyID id, real_t dt, ICR & solver ) const
+   {
+      // Calculating the linear acceleration by the equation
+      //   force * m^(-1) + gravity
+      const Vec3 vdot( id->getForce() * id->getInvMass() + solver.getGlobalLinearAcceleration() );
+
+      // Calculating the angular acceleration by the equation
+      //   R * Iinv * R^T * torque
+      const Vec3 wdot( id->getInvInertia() * id->getTorque() );
+
+      // Calculating the translational displacement
+      id->setPosition( id->getPosition() + id->getLinearVel() * dt + 0.5 * vdot * dt * dt );
+
+      // Calculating the rotation angle
+      const Vec3 phi( id->getAngularVel() * dt + 0.5 * wdot * dt * dt);
+
+      // Calculating the new orientation
+      if (!floatIsEqual(phi.length(), 0))
+         id->rotate( Quat( phi, phi.length() ) );
+      WALBERLA_ASSERT_FLOAT_EQUAL( id->getRotation().getDeterminant(), real_c(1 ), "Corrupted rotation matrix determinant" );
+
+      // Updating the linear velocity
+      id->setLinearVel( id->getLinearVel() + vdot * dt );
+
+      // Updating the angular velocity
+      id->setAngularVel( id->getAngularVel() + wdot * dt );
+
+      // Setting the axis-aligned bounding box
+      id->calcBoundingBox();
+
+      // Calculating the current motion of the capsule
+      id->calcMotion();
+   }
+};
+
+}  // namespace cr
+} // namespace pe
+}  // namespace walberla
diff --git a/src/pe/cr/PlainIntegrator.cpp b/src/pe/cr/PlainIntegrator.cpp
deleted file mode 100644
index 0267e80225ef58785794268c2e9f29e2fdb0f928..0000000000000000000000000000000000000000
--- a/src/pe/cr/PlainIntegrator.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-//======================================================================================================================
-//
-//  This file is part of waLBerla. waLBerla is free software: you can
-//  redistribute it and/or modify it under the terms of the GNU General Public
-//  License as published by the Free Software Foundation, either version 3 of
-//  the License, or (at your option) any later version.
-//
-//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
-//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-//  for more details.
-//
-//  You should have received a copy of the GNU General Public License along
-//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
-//
-//! \file PlainIntegrator.h
-//! \author Klaus Iglberger
-//! \author Sebastian Eibl <sebastian.eibl@fau.de>
-//! \brief Source file for the Plain Integrator solver
-//
-//======================================================================================================================
-
-
-//*************************************************************************************************
-// Includes
-//*************************************************************************************************
-
-#include "pe/cr/PlainIntegrator.h"
-#include "pe/ccd/ICCD.h"
-#include "pe/fcd/IFCD.h"
-#include "pe/bg/IBG.h"
-#include "pe/rigidbody/BodyStorage.h"
-#include "pe/rigidbody/RigidBody.h"
-
-#include "core/logging/all.h"
-#include "core/timing/TimingTree.h"
-
-namespace walberla {
-namespace pe {
-namespace cr {
-
-PlainIntegrator::PlainIntegrator(const shared_ptr<BodyStorage>&      globalBodyStorage,
-                                 const shared_ptr<BlockStorage>&     blockStorage,
-                                 domain_decomposition::BlockDataID   storageID,
-                                 WcTimingTree*                       tt)
-   : globalBodyStorage_(globalBodyStorage)
-   , blockStorage_(blockStorage)
-   , storageID_(storageID)
-   , tt_(tt)
-{
-
-}
-
-void PlainIntegrator::timestep( const real_t dt )
-{
-   if (tt_!=NULL) tt_->start("PlainIntegrator");
-   if (tt_!=NULL) tt_->start("Integrate Bodies");
-   for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it){
-      IBlock & currentBlock = *it;
-      Storage * storage = currentBlock.getData< Storage >( storageID_ );
-      BodyStorage& localStorage = (*storage)[0];
-      for (auto bd = localStorage.begin(); bd != localStorage.end(); ++bd){
-         move(*bd, dt);
-      }
-   }
-   if (tt_!=NULL) tt_->stop("Integrate Bodies");
-   if (tt_!=NULL) tt_->stop("PlainIntegrator");
-}
-
-//=================================================================================================
-//
-//  SIMULATION FUNCTIONS
-//
-//=================================================================================================
-
-//*************************************************************************************************
-/*!\brief Calculation of a time step of \a dt.
- *
- * \param dt Time step size.
- * \return void
- *
- * Calculating one single time step of size \a dt for the capsule. The global position, the
- * linear and angular velocity and the orientation of the capsule are changed depending on
- * the acting forces and the current velocities.
- */
-void PlainIntegrator::move( BodyID id, real_t dt )
-{
-   // Checking the state of the body
-   WALBERLA_ASSERT( id->checkInvariants(), "Invalid capsule state detected" );
-   WALBERLA_ASSERT( !id->hasSuperBody(), "Invalid superordinate body detected" );
-
-   // Resetting the contact node and removing all attached contacts
-//      id->resetNode();
-   id->clearContacts();
-
-   // Moving the capsule according to the acting forces (don't move a sleeping capsule)
-   if( id->isAwake() && !id->hasInfiniteMass() ) {
-      // Calculating the linear acceleration by the equation
-      //   force * m^(-1) + gravity
-      const Vec3 vdot( id->getForce() * id->getInvMass() + getGlobalLinearAcceleration() );
-
-      // Calculating the angular acceleration by the equation
-      //   R * Iinv * R^T * torque
-      const Vec3 wdot( id->getInvInertia() * id->getTorque() );
-
-      // Updating the linear velocity
-      id->setLinearVel(id->getLinearVel() + vdot * dt);
-
-      // Updating the angular velocity
-      id->setAngularVel( id->getAngularVel() + wdot * dt );
-
-      // Calculating the translational displacement
-      id->setPosition( id->getPosition() + id->getLinearVel() * dt );
-
-      // Calculating the rotation angle
-      const Vec3 phi( id->getAngularVel() * dt );
-
-      // Calculating the new orientation
-      id->rotate( Quat( phi, phi.length() ) );
-      WALBERLA_ASSERT( realIsEqual( id->getRotation().getDeterminant(), real_c(1) ), "Corrupted rotation matrix determinant" );
-
-      // Setting the axis-aligned bounding box
-      id->calcBoundingBox();
-
-      // Calculating the current motion of the capsule
-      id->calcMotion();
-   }
-
-   // Resetting the acting forces
-   id->resetForceAndTorque();
-
-   // Checking the state of the capsule
-   WALBERLA_ASSERT( id->checkInvariants(), "Invalid capsule state detected" );
-}
-//*************************************************************************************************
-
-} // namespace cr
-} // namespace pe
-} // namespace walberla
diff --git a/src/pe/cr/PlainIntegrator.h b/src/pe/cr/PlainIntegrator.h
index 378af07f64685bed667819b0a2541d9b498ab7f5..271847f5d3d9b601452553d08d4a85bae8a4eb71 100644
--- a/src/pe/cr/PlainIntegrator.h
+++ b/src/pe/cr/PlainIntegrator.h
@@ -29,6 +29,7 @@
 
 #include "ICR.h"
 #include "pe/Types.h"
+#include "Integrators.h"
 
 #include "domain_decomposition/BlockStorage.h"
 
@@ -36,14 +37,16 @@ namespace walberla {
 namespace pe {
 namespace cr {
 
-class PlainIntegrator : public ICR
-                      , private NonCopyable
+template< typename Integrator >
+class PlainIntegratorSolver : public ICR
+                            , private NonCopyable
 {
 public:
-   PlainIntegrator( const shared_ptr<BodyStorage>&      globalBodyStorage,
-                    const shared_ptr<BlockStorage>&     blockStorage,
-                    domain_decomposition::BlockDataID   storageID,
-                    WcTimingTree* tt = NULL );
+   PlainIntegratorSolver( const Integrator & integrate,
+                          const shared_ptr<BodyStorage>&      globalBodyStorage,
+                          const shared_ptr<BlockStorage>&     blockStorage,
+                          domain_decomposition::BlockDataID   storageID,
+                          WcTimingTree* tt = NULL );
 
    /// forwards to timestep
    /// Convenience operator to make class a functor.
@@ -51,14 +54,28 @@ public:
    /// Advances the simulation dt seconds.
    void timestep( const real_t dt );
 private:
-   void move( BodyID id, real_t dt );
-
+   const Integrator                  integrate_;
    shared_ptr<BodyStorage>           globalBodyStorage_;
    shared_ptr<BlockStorage>          blockStorage_;
    domain_decomposition::BlockDataID storageID_;
    WcTimingTree*                     tt_;
 };
+   
+class PlainIntegrator : public PlainIntegratorSolver<IntegrateImplictEuler>
+{
+public:
+   PlainIntegrator(  const shared_ptr<BodyStorage>&    globalBodyStorage
+                   , const shared_ptr<BlockStorage>&   blockStorage
+                   , domain_decomposition::BlockDataID storageID
+                   , WcTimingTree*                     tt = NULL)
+   : PlainIntegratorSolver<IntegrateImplictEuler>( IntegrateImplictEuler(), globalBodyStorage, blockStorage,
+                                                   storageID, tt )
+   {
+   }
+};
 
 } // namespace cr
 } // namespace pe
 } // namespace walberla
+
+#include "PlainIntegrator.impl.h"
diff --git a/src/pe/cr/PlainIntegrator.impl.h b/src/pe/cr/PlainIntegrator.impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b9c4ce45101e774ed936da68e81caab088f1f95
--- /dev/null
+++ b/src/pe/cr/PlainIntegrator.impl.h
@@ -0,0 +1,93 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file PlainIntegrator.h
+//! \author Klaus Iglberger
+//! \author Sebastian Eibl <sebastian.eibl@fau.de>
+//! \brief Source file for the Plain Integrator solver
+//
+//======================================================================================================================
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include "pe/cr/PlainIntegrator.h"
+#include "pe/ccd/ICCD.h"
+#include "pe/fcd/IFCD.h"
+#include "pe/bg/IBG.h"
+#include "pe/rigidbody/BodyStorage.h"
+#include "pe/rigidbody/RigidBody.h"
+
+#include "core/logging/all.h"
+#include "core/timing/TimingTree.h"
+
+namespace walberla {
+namespace pe {
+namespace cr {
+
+template< typename Integrator >
+PlainIntegratorSolver<Integrator>::PlainIntegratorSolver( const Integrator & integrate,
+                                                         const shared_ptr<BodyStorage>&      globalBodyStorage,
+                                                         const shared_ptr<BlockStorage>&     blockStorage,
+                                                         domain_decomposition::BlockDataID   storageID,
+                                                         WcTimingTree*                       tt)
+   : integrate_(integrate)
+   , globalBodyStorage_(globalBodyStorage)
+   , blockStorage_(blockStorage)
+   , storageID_(storageID)
+   , tt_(tt)
+{
+
+}
+
+template< typename Integrator >
+void PlainIntegratorSolver<Integrator>::timestep( const real_t dt )
+{
+   if (tt_!=NULL) tt_->start("PlainIntegrator");
+   if (tt_!=NULL) tt_->start("Integrate Bodies");
+   for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it){
+      IBlock & currentBlock = *it;
+      Storage * storage = currentBlock.getData< Storage >( storageID_ );
+      BodyStorage& localStorage = (*storage)[0];
+      for (auto bd = localStorage.begin(); bd != localStorage.end(); ++bd){
+         // Checking the state of the body
+         WALBERLA_ASSERT( bd->checkInvariants(), "Invalid capsule state detected" );
+         WALBERLA_ASSERT( !bd->hasSuperBody(), "Invalid superordinate body detected" );
+
+         // Resetting the contact node and removing all attached contacts
+      //      bd->resetNode();
+         bd->clearContacts();
+
+         // Moving the capsule according to the acting forces (don't move a sleeping capsule)
+         if( bd->isAwake() && !bd->hasInfiniteMass() ) {
+            integrate_( *bd, dt, *this );
+         }
+
+         // Resetting the acting forces
+         bd->resetForceAndTorque();
+
+         // Checking the state of the capsule
+         WALBERLA_ASSERT( bd->checkInvariants(), "Invalid capsule state detected" );
+      }
+   }
+   if (tt_!=NULL) tt_->stop("Integrate Bodies");
+   if (tt_!=NULL) tt_->stop("PlainIntegrator");
+}
+
+} // namespace cr
+} // namespace pe
+} // namespace walberla