diff --git a/CMakeLists.txt b/CMakeLists.txt
index 89048a4ba41af69a7e35ceb76762576b7adc4911..aa5e8c13fe89ef2610e5bcf1a1581089737485ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -300,6 +300,7 @@ set(cpp_for_lib
     ${PROJECT_SOURCE_DIR}/cpp/full_code/test_interpolation.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEparticles.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEcomplex_particles.cpp
+    ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVE_Stokes_particles.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEp_extra_sampling.cpp
     ${PROJECT_SOURCE_DIR}/cpp/particles/particles_inner_computer.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/ornstein_uhlenbeck_process.cpp
@@ -348,6 +349,7 @@ set(hpp_for_lib
     ${PROJECT_SOURCE_DIR}/cpp/full_code/test_interpolation.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEparticles.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEcomplex_particles.hpp
+    ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVE_Stokes_particles.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEp_extra_sampling.hpp
     ${PROJECT_SOURCE_DIR}/cpp/particles/particles_inner_computer.hpp
     ${PROJECT_SOURCE_DIR}/cpp/particles/particles_inner_computer_2nd_order.hpp
@@ -430,41 +432,56 @@ enable_testing()
 if (BUILD_TESTING)
     file(MAKE_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
     ### basic functionality
-    add_test(NAME test_fftw
-             COMMAND turtle.test_fftw
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_Parseval
-             COMMAND turtle.test_Parseval
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_fftw
+        COMMAND turtle.test_fftw
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_Parseval
+        COMMAND turtle.test_Parseval
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
     ### compare DNS output to stored results
-    add_test(NAME test_NSVEparticles
-             COMMAND turtle.test_NSVEparticles
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_NSVEparticles
+        COMMAND turtle.test_NSVEparticles
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
     ### simple runs of post-processing tools
-    add_test(NAME test_pp_single_to_double
-             COMMAND turtle PP field_single_to_double --simname dns_nsveparticles --iter0 32 --iter1 32
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_pp_get_rfields
-             COMMAND turtle PP get_rfields --simname dns_nsveparticles --iter0 0 --iter1 64
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_pp_joint_acc_vel_stats
-             COMMAND turtle PP joint_acc_vel_stats --simname dns_nsveparticles --iter0 0 --iter1 64
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_pp_resize
-             COMMAND turtle PP resize --simname dns_nsveparticles --new_nx 96 --new_ny 96 --new_nz 96 --new_simname dns_nsveparticles_resized
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_pp_single_to_double
+        COMMAND turtle PP field_single_to_double --simname dns_nsveparticles --iter0 32 --iter1 32
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_pp_get_rfields
+        COMMAND turtle PP get_rfields --simname dns_nsveparticles --iter0 0 --iter1 64
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_pp_joint_acc_vel_stats
+        COMMAND turtle PP joint_acc_vel_stats --simname dns_nsveparticles --iter0 0 --iter1 64
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_pp_resize
+        COMMAND turtle PP resize --simname dns_nsveparticles --new_nx 96 --new_ny 96 --new_nz 96 --new_simname dns_nsveparticles_resized
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
     ### simple runs of different DNS
-    add_test(NAME test_NSVEp_extra_sampling
-             COMMAND turtle DNS NSVEp_extra_sampling -n 32 --src-simname dns_nsveparticles --src-iteration 32 --simname dns_nsvep_extra_sampling --nparticles 1000
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_NSVEcomplex_particles
-             COMMAND turtle DNS NSVEcomplex_particles -n 32 --src-simname dns_nsveparticles --src-iteration 32 --simname dns_nsvecomplex_particles --nparticles 1000
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_static_field
-             COMMAND turtle DNS static_field --simname dns_static_field --nparticles 10000
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
-    add_test(NAME test_kraichnan_field
-             COMMAND turtle DNS kraichnan_field --simname dns_kraichnan_field --nparticles 10000
-             WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_NSVEp_extra_sampling
+        COMMAND turtle DNS NSVEp_extra_sampling -n 32 --src-simname dns_nsveparticles --src-iteration 32 --simname dns_nsvep_extra_sampling --nparticles 1000
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_NSVEcomplex_particles
+        COMMAND turtle DNS NSVEcomplex_particles -n 32 --src-simname dns_nsveparticles --src-iteration 32 --simname dns_nsvecomplex_particles --nparticles 1000
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_static_field
+        COMMAND turtle DNS static_field --simname dns_static_field --nparticles 10000
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_kraichnan_field
+        COMMAND turtle DNS kraichnan_field --simname dns_kraichnan_field --nparticles 10000
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
+    add_test(
+        NAME test_NSVE_Stokes_particles
+        COMMAND turtle DNS NSVE_Stokes_particles  -n 32 --src-simname dns_nsveparticles --src-iteration 32 --simname dns_nsve_tokes_particles --nparticles 10000
+        WORKING_DIRECTORY ${TEST_OUTPUT_DIRECTORY})
 endif(BUILD_TESTING)
 
diff --git a/TurTLE/DNS.py b/TurTLE/DNS.py
index b8e4bd15ba1365db9bbca1a8f68ec6d8c50913e3..aa2a4bd29796252195f62870671289e08d94b8fc 100644
--- a/TurTLE/DNS.py
+++ b/TurTLE/DNS.py
@@ -439,7 +439,13 @@ class DNS(_code):
         assert (self.parameters['niter_todo'] % self.parameters['niter_stat'] == 0)
         assert (self.parameters['niter_todo'] % self.parameters['niter_out']  == 0)
         assert (self.parameters['niter_out']  % self.parameters['niter_stat'] == 0)
-        if self.dns_type in ['NSVEparticles_no_output', 'NSVEcomplex_particles', 'NSVEparticles', 'static_field', 'kraichnan_field']:
+        if self.dns_type in [
+                'NSVEparticles_no_output',
+                'NSVEcomplex_particles',
+                'NSVE_Stokes_particles',
+                'NSVEparticles',
+                'static_field',
+                'kraichnan_field']:
             assert (self.parameters['niter_todo'] % self.parameters['niter_part'] == 0)
             assert (self.parameters['niter_out']  % self.parameters['niter_part'] == 0)
         _code.write_par(self, iter0 = iter0)
@@ -648,6 +654,10 @@ class DNS(_code):
                 'NSVEparticles',
                 help = 'plain Navier-Stokes vorticity formulation, with basic fluid tracers')
 
+        parser_NSVE_Stokes_particles = subparsers.add_parser(
+                'NSVE_Stokes_particles',
+                help = 'plain Navier-Stokes vorticity formulation, with passive Stokes drag particles')
+
         parser_NSVEp2p = subparsers.add_parser(
                 'NSVEcomplex_particles',
                 help = 'plain Navier-Stokes vorticity formulation, with oriented active particles')
@@ -660,6 +670,7 @@ class DNS(_code):
                 'NSVEparticles_no_output',
                 'NSVEp2',
                 'NSVEp2p',
+                'NSVE_Stokes_particles',
                 'NSVEp_extra',
                 'static_field',
                 'kraichnan_field']:
@@ -673,6 +684,7 @@ class DNS(_code):
                 'NSVEparticles_no_output',
                 'NSVEp2',
                 'NSVEp2p',
+                'NSVE_Stokes_particles',
                 'NSVEp_extra',
                 'static_field',
                 'kraichnan_field']:
@@ -726,7 +738,14 @@ class DNS(_code):
         self.dns_type = opt.DNS_class
         self.name = self.dns_type + '-' + self.fluid_precision + '-v' + TurTLE.__version__
         # merge parameters if needed
-        if self.dns_type in ['NSVEparticles', 'NSVEcomplex_particles', 'NSVEparticles_no_output', 'NSVEp_extra_sampling', 'static_field', 'kraichnan_field']:
+        if self.dns_type in [
+                'NSVEparticles',
+                'NSVEcomplex_particles',
+                'NSVE_Stokes_particles',
+                'NSVEparticles_no_output',
+                'NSVEp_extra_sampling',
+                'static_field',
+                'kraichnan_field']:
             for k in self.NSVEp_extra_parameters.keys():
                 self.parameters[k] = self.NSVEp_extra_parameters[k]
         if type(extra_parameters) != type(None):
@@ -797,7 +816,14 @@ class DNS(_code):
             # hardcoded FFTW complex representation size
             field_size = 3*(opt.nx+2)*opt.ny*opt.nz*self.fluid_dtype.itemsize
             checkpoint_size = field_size
-            if self.dns_type in ['kraichnan_field', 'static_field', 'NSVEparticles', 'NSVEcomplex_particles', 'NSVEparticles_no_output', 'NSVEp_extra_sampling']:
+            if self.dns_type in [
+                    'kraichnan_field',
+                    'static_field',
+                    'NSVEparticles',
+                    'NSVEcomplex_particles',
+                    'NSVE_Stokes_particles',
+                    'NSVEparticles_no_output',
+                    'NSVEp_extra_sampling']:
                 rhs_size = self.parameters['tracers0_integration_steps']
                 if type(opt.tracers0_integration_steps) != type(None):
                     rhs_size = opt.tracers0_integration_steps
@@ -837,7 +863,9 @@ class DNS(_code):
                 integration_steps = self.NSVEp_extra_parameters['tracers0_integration_steps']
             if 'tracers{0}_integration_steps'.format(species) in self.parameters.keys():
                 integration_steps = self.parameters['tracers{0}_integration_steps'.format(species)]
-            if self.dns_type == 'NSVEcomplex_particles' and species == 0:
+            if self.dns_type in [
+                    'NSVEcomplex_particles',
+                    'NSVE_Stokes_particles'] and species == 0:
                 ncomponents = 6
             with h5py.File(self.get_checkpoint_0_fname(), 'a') as data_file:
                 nn = self.parameters['nparticles']
@@ -1021,6 +1049,8 @@ class DNS(_code):
                     if self.dns_type in ['NSVEcomplex_particles']:
                         particle_file.create_group('tracers0/orientation')
                         particle_file.create_group('tracers0/velocity_gradient')
+                    if self.dns_type in ['NSVE_Stokes_particles']:
+                        particle_file.create_group('tracers0/momentum')
                     if self.dns_type in ['NSVEp_extra_sampling']:
                         particle_file.create_group('tracers0/velocity_gradient')
                         particle_file.create_group('tracers0/pressure')
@@ -1041,6 +1071,7 @@ class DNS(_code):
                 'static_field',
                 'NSVEparticles',
                 'NSVEcomplex_particles',
+                'NSVE_Stokes_particles',
                 'NSVEparticles_no_output',
                 'NSVEp_extra_sampling']:
             if not os.path.exists(self.get_checkpoint_0_fname()):
@@ -1093,6 +1124,7 @@ class DNS(_code):
                 'static_field',
                 'NSVEparticles',
                 'NSVEcomplex_particles',
+                'NSVE_Stokes_particles',
                 'NSVEparticles_no_output',
                 'NSVEp_extra_sampling']:
             self.generate_particle_data(opt = opt)
diff --git a/cpp/full_code/NSVE_Stokes_particles.cpp b/cpp/full_code/NSVE_Stokes_particles.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3606b162ce0be6b9904fa5a74ca63dcd1d011cf7
--- /dev/null
+++ b/cpp/full_code/NSVE_Stokes_particles.cpp
@@ -0,0 +1,215 @@
+/**********************************************************************
+*                                                                     *
+*  Copyright 2019 Max Planck Institute                                *
+*                 for Dynamics and Self-Organization                  *
+*                                                                     *
+*  This file is part of bfps.                                         *
+*                                                                     *
+*  bfps 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.                             *
+*                                                                     *
+*  bfps 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 bfps.  If not, see <http://www.gnu.org/licenses/>       *
+*                                                                     *
+* Contact: Cristian.Lalescu@ds.mpg.de                                 *
+*                                                                     *
+**********************************************************************/
+
+
+
+#include <string>
+#include <cmath>
+#include "NSVE_Stokes_particles.hpp"
+#include "scope_timer.hpp"
+#include "particles/particles_sampling.hpp"
+#include "particles/p2p_ghost_collisions.hpp"
+#include "particles/particles_inner_computer_2nd_order.hpp"
+
+template <typename rnumber>
+int NSVE_Stokes_particles<rnumber>::initialize(void)
+{
+    TIMEZONE("NSVE_Stokes_particles::intialize");
+    this->NSVE<rnumber>::initialize();
+    this->pressure = new field<rnumber, FFTW, ONE>(
+            this->fs->cvelocity->rlayout->sizes[2],
+            this->fs->cvelocity->rlayout->sizes[1],
+            this->fs->cvelocity->rlayout->sizes[0],
+            this->fs->cvelocity->rlayout->comm,
+            this->fs->cvelocity->fftw_plan_rigor);
+
+    particles_inner_computer_2nd_order_Stokes<double, long long int> current_particles_inner_computer;
+    current_particles_inner_computer.set_drag_coefficient(0.1);
+
+    DEBUG_MSG_WAIT(MPI_COMM_WORLD, "before call to particles_system_builder\n");
+    this->ps = particles_system_builder_with_p2p(
+                this->fs->cvelocity,                                                    // (field object)
+                this->fs->kk,                                                           // (kspace object, contains dkx, dky, dkz)
+                tracers0_integration_steps,                                             // to check coherency between parameters and hdf input file (nb rhs)
+                (long long int)nparticles,                                              // to check coherency between parameters and hdf input file
+                this->fs->get_current_fname(),                                          // particles input filename
+                std::string("/tracers0/state/") + std::to_string(this->fs->iteration),  // dataset name for initial input
+                std::string("/tracers0/rhs/")  + std::to_string(this->fs->iteration),   // dataset name for initial input
+                tracers0_neighbours,                                                    // parameter (interpolation no neighbours)
+                tracers0_smoothness,                                                    // parameter
+                this->comm,
+                this->fs->iteration+1,
+                std::move(p2p_ghost_collisions<double, long long int>()),
+                std::move(particles_inner_computer_2nd_order_Stokes<double, long long int>()),
+                this->tracers0_cutoff);
+    DEBUG_MSG_WAIT(MPI_COMM_WORLD, "after call to particles_system_builder\n");
+    this->particles_output_writer_mpi = new particles_output_hdf5<
+        long long int, double, 6>(
+                MPI_COMM_WORLD,
+                "tracers0",
+                nparticles,
+                tracers0_integration_steps);
+    this->particles_output_writer_mpi->setParticleFileLayout(this->ps->getParticleFileLayout());
+    this->particles_sample_writer_mpi = new particles_output_sampling_hdf5<
+        long long int, double, 3>(
+                MPI_COMM_WORLD,
+                this->ps->getGlobalNbParticles(),
+                (this->simname + "_particles.h5"),
+                "tracers0",
+                "position/0");
+    this->particles_sample_writer_mpi->setParticleFileLayout(this->ps->getParticleFileLayout());
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int NSVE_Stokes_particles<rnumber>::step(void)
+{
+    TIMEZONE("NSVE_Stokes_particles::step");
+    this->fs->compute_velocity(this->fs->cvorticity);
+    this->fs->cvelocity->ift();
+    this->ps->completeLoop(this->dt);
+    this->NSVE<rnumber>::step();
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int NSVE_Stokes_particles<rnumber>::write_checkpoint(void)
+{
+    TIMEZONE("NSVE_Stokes_particles::write_checkpoint");
+    this->NSVE<rnumber>::write_checkpoint();
+    this->particles_output_writer_mpi->open_file(this->fs->get_current_fname());
+    this->particles_output_writer_mpi->template save<6>(
+            this->ps->getParticlesState(),
+            this->ps->getParticlesRhs(),
+            this->ps->getParticlesIndexes(),
+            this->ps->getLocalNbParticles(),
+            this->fs->iteration);
+    this->particles_output_writer_mpi->close_file();
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int NSVE_Stokes_particles<rnumber>::finalize(void)
+{
+    TIMEZONE("NSVE_Stokes_particles::finalize");
+    delete this->pressure;
+    delete this->ps.release();
+    delete this->particles_output_writer_mpi;
+    delete this->particles_sample_writer_mpi;
+    this->NSVE<rnumber>::finalize();
+    return EXIT_SUCCESS;
+}
+
+/** \brief Compute fluid stats and sample fields at particle locations.
+ */
+
+template <typename rnumber>
+int NSVE_Stokes_particles<rnumber>::do_stats()
+{
+    TIMEZONE("NSVE_Stokes_particles::do_stats");
+    /// fluid stats go here
+    this->NSVE<rnumber>::do_stats();
+
+
+    /// either one of two conditions suffices to compute statistics:
+    /// 1) current iteration is a multiple of niter_part
+    /// 2) we are within niter_part_fine_duration/2 of a multiple of niter_part_fine_period
+    if (!(this->iteration % this->niter_part == 0 ||
+          ((this->iteration + this->niter_part_fine_duration/2) % this->niter_part_fine_period <=
+           this->niter_part_fine_duration)))
+        return EXIT_SUCCESS;
+
+    /// allocate temporary data array
+    /// initialize pdata0 with the positions, and pdata1 with the orientations
+    std::unique_ptr<double[]> pdata0 = this->ps->extractParticlesState(0, 3);
+    std::unique_ptr<double[]> pdata1 = this->ps->extractParticlesState(3, 6);
+    std::unique_ptr<double[]> pdata2(new double[9*this->ps->getLocalNbParticles()]);
+
+    /// sample position
+    this->particles_sample_writer_mpi->template save_dataset<3>(
+            "tracers0",
+            "position",
+            pdata0.get(), // we need to use pdata0.get() here, because it's 3D, whereas getParticlesState may give something else
+            &pdata0,
+            this->ps->getParticlesIndexes(),
+            this->ps->getLocalNbParticles(),
+            this->ps->get_step_idx()-1);
+
+    /// sample particle momentum
+    this->particles_sample_writer_mpi->template save_dataset<3>(
+            "tracers0",
+            "momentum",
+            pdata0.get(),
+            &pdata1,
+            this->ps->getParticlesIndexes(),
+            this->ps->getLocalNbParticles(),
+            this->ps->get_step_idx()-1);
+
+    /// sample velocity
+    std::fill_n(pdata1.get(), 3*this->ps->getLocalNbParticles(), 0);
+    if (!(this->iteration % this->niter_stat == 0))
+    {
+        // we need to compute velocity field manually, because it didn't happen in NSVE::do_stats()
+        this->fs->compute_velocity(this->fs->cvorticity);
+        *this->tmp_vec_field = this->fs->cvelocity->get_cdata();
+        this->tmp_vec_field->ift();
+    }
+    this->ps->sample_compute_field(*this->tmp_vec_field, pdata1.get());
+    this->particles_sample_writer_mpi->template save_dataset<3>(
+            "tracers0",
+            "velocity",
+            pdata0.get(),
+            &pdata1,
+            this->ps->getParticlesIndexes(),
+            this->ps->getLocalNbParticles(),
+            this->ps->get_step_idx()-1);
+
+    // deallocate temporary data array
+    delete[] pdata0.release();
+    delete[] pdata1.release();
+
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int NSVE_Stokes_particles<rnumber>::read_parameters(void)
+{
+    TIMEZONE("NSVE_Stokes_particles::read_parameters");
+    this->NSVE<rnumber>::read_parameters();
+    hid_t parameter_file = H5Fopen((this->simname + ".h5").c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
+    this->niter_part = hdf5_tools::read_value<int>(parameter_file, "parameters/niter_part");
+    this->niter_part_fine_period = hdf5_tools::read_value<int>(parameter_file, "parameters/niter_part_fine_period");
+    this->niter_part_fine_duration = hdf5_tools::read_value<int>(parameter_file, "parameters/niter_part_fine_duration");
+    this->nparticles = hdf5_tools::read_value<int>(parameter_file, "parameters/nparticles");
+    this->tracers0_integration_steps = hdf5_tools::read_value<int>(parameter_file, "parameters/tracers0_integration_steps");
+    this->tracers0_neighbours = hdf5_tools::read_value<int>(parameter_file, "parameters/tracers0_neighbours");
+    this->tracers0_smoothness = hdf5_tools::read_value<int>(parameter_file, "parameters/tracers0_smoothness");
+    this->tracers0_cutoff = hdf5_tools::read_value<double>(parameter_file, "parameters/tracers0_cutoff");
+    H5Fclose(parameter_file);
+    return EXIT_SUCCESS;
+}
+
+template class NSVE_Stokes_particles<float>;
+template class NSVE_Stokes_particles<double>;
+
diff --git a/cpp/full_code/NSVE_Stokes_particles.hpp b/cpp/full_code/NSVE_Stokes_particles.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..eec5247530a5b43647d847be262c99345495cd78
--- /dev/null
+++ b/cpp/full_code/NSVE_Stokes_particles.hpp
@@ -0,0 +1,89 @@
+/**********************************************************************
+*                                                                     *
+*  Copyright 2017 Max Planck Institute                                *
+*                 for Dynamics and Self-Organization                  *
+*                                                                     *
+*  This file is part of bfps.                                         *
+*                                                                     *
+*  bfps 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.                             *
+*                                                                     *
+*  bfps 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 bfps.  If not, see <http://www.gnu.org/licenses/>       *
+*                                                                     *
+* Contact: Cristian.Lalescu@ds.mpg.de                                 *
+*                                                                     *
+**********************************************************************/
+
+
+
+#ifndef NSVE_STOKES_PARTICLES_HPP
+#define NSVE_STOKES_PARTICLES_HPP
+
+
+
+#include <cstdlib>
+#include "base.hpp"
+#include "vorticity_equation.hpp"
+#include "full_code/NSVE.hpp"
+#include "particles/particles_system_builder.hpp"
+#include "particles/particles_output_hdf5.hpp"
+#include "particles/particles_sampling.hpp"
+
+/** \brief Navier-Stokes solver that includes simple Lagrangian tracers.
+ *
+ *  Child of Navier Stokes vorticity equation solver, this class calls all the
+ *  methods from `NSVE`, and in addition integrates simple Lagrangian tracers
+ *  in the resulting velocity field.
+ */
+
+template <typename rnumber>
+class NSVE_Stokes_particles: public NSVE<rnumber>
+{
+    public:
+
+        /* parameters that are read in read_parameters */
+        int niter_part;
+        int niter_part_fine_period;
+        int niter_part_fine_duration;
+        int nparticles;
+        int tracers0_integration_steps;
+        int tracers0_neighbours;
+        int tracers0_smoothness;
+        double tracers0_cutoff;
+
+
+        /* other stuff */
+        std::unique_ptr<abstract_particles_system<long long int, double>> ps;
+        field<rnumber, FFTW, ONE> *pressure;
+
+        particles_output_hdf5<long long int, double,6> *particles_output_writer_mpi;
+        particles_output_sampling_hdf5<long long int, double, 3> *particles_sample_writer_mpi;
+
+
+        NSVE_Stokes_particles(
+                const MPI_Comm COMMUNICATOR,
+                const std::string &simulation_name):
+            NSVE<rnumber>(
+                    COMMUNICATOR,
+                    simulation_name){}
+        ~NSVE_Stokes_particles(){}
+
+        int initialize(void);
+        int step(void);
+        int finalize(void);
+
+        int read_parameters(void);
+        int write_checkpoint(void);
+        int do_stats(void);
+};
+
+#endif//NSVE_STOKES_PARTICLES_HPP
+
diff --git a/cpp/particles/abstract_particles_system.hpp b/cpp/particles/abstract_particles_system.hpp
index 2f2f510f4bdad22b26b243607c7bbddcd2536771..e7f6cb250777ce7ca9498634fe0f8d2b329e9f17 100644
--- a/cpp/particles/abstract_particles_system.hpp
+++ b/cpp/particles/abstract_particles_system.hpp
@@ -61,6 +61,7 @@ public:
     virtual void shift_rhs_vectors() = 0;
 
     virtual void completeLoop(const real_number dt) = 0;
+    virtual void complete2ndOrderLoop(const real_number dt) = 0;
 
     virtual void completeLoopWithVorticity(
             const real_number dt,
diff --git a/cpp/particles/particles_inner_computer_2nd_order.hpp b/cpp/particles/particles_inner_computer_2nd_order.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..075914685ecb02d055947c8f1f0cd85fd8a97d26
--- /dev/null
+++ b/cpp/particles/particles_inner_computer_2nd_order.hpp
@@ -0,0 +1,84 @@
+/******************************************************************************
+*                                                                             *
+*  Copyright 2019 Max Planck Institute for Dynamics and Self-Organization     *
+*                                                                             *
+*  This file is part of bfps.                                                 *
+*                                                                             *
+*  bfps 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.                                     *
+*                                                                             *
+*  bfps 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 bfps.  If not, see <http://www.gnu.org/licenses/>               *
+*                                                                             *
+* Contact: Cristian.Lalescu@ds.mpg.de                                         *
+*                                                                             *
+******************************************************************************/
+
+
+
+#ifndef PARTICLES_INNER_COMPUTER_2ND_ORDER_HPP
+#define PARTICLES_INNER_COMPUTER_2ND_ORDER_HPP
+
+#include <cstring>
+#include <cassert>
+
+template <class real_number, class partsize_t>
+class particles_inner_computer_2nd_order_Stokes{
+    double drag_coefficient;
+public:
+    template <int size_particle_state, int size_particle_rhs>
+    void compute_interaction(const partsize_t number_of_particles, real_number particle_state[], real_number particle_rhs[]) const{
+    }
+
+    template <int size_particle_state>
+    void enforce_unit_orientation(const partsize_t /*nb_particles*/, real_number /*pos_part*/[]) const{
+    }
+
+    template <int size_particle_state, int size_particle_rhs>
+    void add_Lagrange_multipliers(const partsize_t /*nb_particles*/, real_number /*pos_part*/[], real_number /*rhs_part*/[]) const{
+    }
+
+    template <int size_particle_state, int size_particle_rhs, int size_particle_rhs_extra>
+    void compute_interaction_with_extra(
+            const partsize_t number_of_particles,
+            real_number particle_state[],
+            real_number particle_rhs[],
+            const real_number sampled_velocity[]) const{
+        assert(size_particle_state == 6);
+        assert(size_particle_rhs == 6);
+        assert(size_particle_rhs_extra == 3);
+        #pragma omp parallel for
+        for(partsize_t idx_part = 0 ; idx_part < number_of_particles ; ++idx_part){
+            particle_rhs[idx_part*size_particle_rhs + IDXC_X] = particle_state[idx_part*size_particle_state + 3 + IDXC_X];
+            particle_rhs[idx_part*size_particle_rhs + IDXC_Y] = particle_state[idx_part*size_particle_state + 3 + IDXC_Y];
+            particle_rhs[idx_part*size_particle_rhs + IDXC_Z] = particle_state[idx_part*size_particle_state + 3 + IDXC_Z];
+            particle_rhs[idx_part*size_particle_rhs + 3 + IDXC_X] = - this->drag_coefficient * (particle_state[idx_part*size_particle_state + 3 + IDXC_X] - sampled_velocity[idx_part*size_particle_rhs_extra + IDXC_X]);
+            particle_rhs[idx_part*size_particle_rhs + 3 + IDXC_Y] = - this->drag_coefficient * (particle_state[idx_part*size_particle_state + 3 + IDXC_Y] - sampled_velocity[idx_part*size_particle_rhs_extra + IDXC_Y]);
+            particle_rhs[idx_part*size_particle_rhs + 3 + IDXC_Z] = - this->drag_coefficient * (particle_state[idx_part*size_particle_state + 3 + IDXC_Z] - sampled_velocity[idx_part*size_particle_rhs_extra + IDXC_Z]);
+        }
+    }
+
+    constexpr static bool isEnable() {
+        return true;
+    }
+
+    void set_drag_coefficient(double mu)
+    {
+        this->drag_coefficient = mu;
+    }
+
+    double get_drag_coefficient()
+    {
+        return this->drag_coefficient;
+    }
+};
+
+#endif//PARTICLES_INNER_COMPUTER_2ND_ORDER_HPP
+
diff --git a/cpp/particles/particles_system.hpp b/cpp/particles/particles_system.hpp
index cdb523bb69de8c4b8d27ef319b33f29b8dc71db5..f276abfd6cbba028352027b43ebd98d0dfacc161 100644
--- a/cpp/particles/particles_system.hpp
+++ b/cpp/particles/particles_system.hpp
@@ -313,6 +313,21 @@ public:
         shift_rhs_vectors();
     }
 
+    void complete2ndOrderLoop(const real_number dt) final {
+        assert(size_particle_positions == 6);
+        assert(size_particle_rhs == 6);
+        std::unique_ptr<real_number[]> sampled_velocity(new real_number[getLocalNbParticles()*3]());
+        std::fill_n(sampled_velocity.get(), 3*getLocalNbParticles(), 0);
+        sample_compute_field(default_field, sampled_velocity.get());
+        this->computer_particules_inner.template compute_interaction_with_extra<size_particle_positions, size_particle_rhs, 3>(
+                            my_nb_particles, my_particles_positions.get(), my_particles_rhs.front().get(),
+                            sampled_velocity.get());
+        move(dt);
+        redistribute();
+        inc_step_idx();
+        shift_rhs_vectors();
+    }
+
     void completeLoopWithVorticity(
             const real_number dt,
             const real_number particle_extra_field[]) final {
diff --git a/documentation/chapters/cpp_doxygen.rst b/documentation/chapters/cpp_doxygen.rst
index 1e4246a162083d4508f590d7370d2d29028cd598..51d1c9cca6c637fbce1335a3b8d6c358ddb6a2fd 100644
--- a/documentation/chapters/cpp_doxygen.rst
+++ b/documentation/chapters/cpp_doxygen.rst
@@ -21,3 +21,13 @@ CPP
 .. doxygenclass:: NSVE
     :project: TurTLE
     :members:
+
+.. doxygenclass:: particles_distr_mpi
+    :project: TurTLE
+    :path: ...
+    :members: [...]
+    :protected-members:
+    :private-members:
+    :undoc-members:
+    :outline:
+    :no-link: