diff --git a/CMakeLists.txt b/CMakeLists.txt
index e786a2b1bbb2a8bce1c0e55724b46eb0cb7cfe20..cf9556bdf30cf44a77cd0846b4bc006a60784ebf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -192,6 +192,7 @@ set(cpp_for_lib
     ${PROJECT_SOURCE_DIR}/cpp/full_code/test.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/filter_test.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/field_test.cpp
+    ${PROJECT_SOURCE_DIR}/cpp/full_code/Gauss_field_test.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/symmetrize_test.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/field_output_test.cpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/get_rfields.cpp
@@ -233,6 +234,7 @@ set(hpp_for_lib
     ${PROJECT_SOURCE_DIR}/cpp/full_code/joint_acc_vel_stats.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/test.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/filter_test.hpp
+    ${PROJECT_SOURCE_DIR}/cpp/full_code/Gauss_field_test.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/field_test.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/symmetrize_test.hpp
     ${PROJECT_SOURCE_DIR}/cpp/full_code/field_output_test.hpp
diff --git a/TurTLE/TEST.py b/TurTLE/TEST.py
index 6a728545d4b9bf53727404809150a56e2637c974..6c5e5a9fbd6c9e61da21034aa82ed2e15928a934 100644
--- a/TurTLE/TEST.py
+++ b/TurTLE/TEST.py
@@ -257,6 +257,9 @@ class TEST(_code):
                 dest = 'TEST_class',
                 help = 'type of simulation to run')
         subparsers.required = True
+        parser_Gauss_field_test = subparsers.add_parser(
+                'Gauss_field_test',
+                help = 'test incompressible Gaussian random fields')
         parser_filter_test = subparsers.add_parser(
                 'filter_test',
                 help = 'plain filter test')
@@ -272,7 +275,8 @@ class TEST(_code):
         parser_test_interpolation = subparsers.add_parser(
                 'test_interpolation',
                 help = 'test velocity gradient interpolation')
-        for parser in ['parser_filter_test',
+        for parser in ['parser_Gauss_field_test',
+                       'parser_filter_test',
                        'parser_field_test',
                        'parser_symmetrize_test',
                        'parser_field_output_test',
diff --git a/cpp/full_code/Gauss_field_test.cpp b/cpp/full_code/Gauss_field_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..521706f7b6809a712553f02f999c41b82016ab96
--- /dev/null
+++ b/cpp/full_code/Gauss_field_test.cpp
@@ -0,0 +1,157 @@
+/**********************************************************************
+*                                                                     *
+*  Copyright 2019 Max Planck Institute                                *
+*                 for Dynamics and Self-Organization                  *
+*                                                                     *
+*  This file is part of TurTLE.                                       *
+*                                                                     *
+*  TurTLE 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.                             *
+*                                                                     *
+*  TurTLE 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 TurTLE.  If not, see <http://www.gnu.org/licenses/>     *
+*                                                                     *
+* Contact: Cristian.Lalescu@ds.mpg.de                                 *
+*                                                                     *
+**********************************************************************/
+
+
+
+#include <string>
+#include <cmath>
+#include <random>
+#include "Gauss_field_test.hpp"
+#include "scope_timer.hpp"
+
+
+
+template <typename rnumber,
+          field_backend be,
+          field_components fc,
+          kspace_dealias_type dt>
+int make_gaussian_random_field(
+        kspace<be, dt> *kk,
+        field<rnumber, be, fc> *output_field,
+        const int rseed = 0)
+{
+    TIMEZONE("generate gaussian random field");
+    thread_local std::mt19937_64 rgen;
+    std::normal_distribution<rnumber> rdist;
+    rgen.seed(rseed + output_field->clayout->myrank*omp_get_max_threads() + omp_get_thread_num());
+    output_field->real_space_representation = false;
+    *output_field = 0.0;
+    kk->CLOOP_K2([&](
+                ptrdiff_t cindex,
+                ptrdiff_t xindex,
+                ptrdiff_t yindex,
+                ptrdiff_t zindex,
+                double k2)
+                    {
+                    if (k2 > 0)
+                    switch(fc)
+                    {
+                    case ONE:
+                      output_field->cval(cindex,0) = rdist(rgen);
+                      output_field->cval(cindex,1) = rdist(rgen);
+                        break;
+                    case THREE:
+                    for (int cc = 0; cc<3; cc++)
+                    {
+                        output_field->cval(cindex,cc,0) = rdist(rgen);
+                        output_field->cval(cindex,cc,1) = rdist(rgen);
+                    }
+                        break;
+                    case THREExTHREE:
+                    for (int cc = 0; cc<3; cc++)
+                    for (int ccc = 0; ccc<3; ccc++)
+                    {
+                        output_field->cval(cindex,cc,ccc,0) = rdist(rgen);
+                        output_field->cval(cindex,cc,ccc,1) = rdist(rgen);
+                    }
+                        break;
+                    }
+            });
+    output_field->symmetrize();
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int Gauss_field_test<rnumber>::initialize(void)
+{
+    TIMEZONE("Gauss_field_test::initialize");
+    this->read_parameters();
+    this->scalar_field = new field<rnumber, FFTW, ONE>(
+            nx, ny, nz,
+            this->comm,
+            FFTW_ESTIMATE);
+    this->vector_field = new field<rnumber, FFTW, THREE>(
+            nx, ny, nz,
+            this->comm,
+            FFTW_ESTIMATE);
+    this->kk = new kspace<FFTW, SMOOTH>(
+            this->scalar_field->clayout, this->dkx, this->dky, this->dkz);
+
+    if (this->myrank == 0)
+    {
+        hid_t stat_file = H5Fopen(
+                (this->simname + std::string(".h5")).c_str(),
+                H5F_ACC_RDWR,
+                H5P_DEFAULT);
+        this->kk->store(stat_file);
+        H5Fclose(stat_file);
+    }
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int Gauss_field_test<rnumber>::finalize(void)
+{
+    TIMEZONE("Gauss_field_test::finalize");
+    delete this->vector_field;
+    delete this->scalar_field;
+    delete this->kk;
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int Gauss_field_test<rnumber>::read_parameters()
+{
+    TIMEZONE("Gauss_field_test::read_parameters");
+    this->test::read_parameters();
+    hid_t parameter_file = H5Fopen(
+            (this->simname + std::string(".h5")).c_str(),
+            H5F_ACC_RDONLY,
+            H5P_DEFAULT);
+    this->filter_length = hdf5_tools::read_value<double>(parameter_file, "/parameters/filter_length");
+    H5Fclose(parameter_file);
+    return EXIT_SUCCESS;
+}
+
+template <typename rnumber>
+int Gauss_field_test<rnumber>::do_work(void)
+{
+    TIMEZONE("Gauss_field_test::do_work");
+    make_gaussian_random_field(this->kk, this->scalar_field);
+    make_gaussian_random_field(this->kk, this->vector_field);
+    DEBUG_MSG("L2norm = %g\n", this->vector_field->L2norm(this->kk));
+    this->kk->template rotate_divfree<rnumber>(this->vector_field->get_cdata());
+    DEBUG_MSG("L2norm = %g\n", this->vector_field->L2norm(this->kk));
+    this->kk->template project_divfree<rnumber>(this->vector_field->get_cdata());
+    DEBUG_MSG("L2norm = %g\n", this->vector_field->L2norm(this->kk));
+    make_gaussian_random_field(this->kk, this->vector_field);
+    DEBUG_MSG("L2norm = %g\n", this->vector_field->L2norm(this->kk));
+    this->kk->template project_divfree<rnumber>(this->vector_field->get_cdata());
+    DEBUG_MSG("L2norm = %g\n", this->vector_field->L2norm(this->kk));
+    return EXIT_SUCCESS;
+}
+
+template class Gauss_field_test<float>;
+template class Gauss_field_test<double>;
+
diff --git a/cpp/full_code/Gauss_field_test.hpp b/cpp/full_code/Gauss_field_test.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3854bb1f48f8b3a724a67d77fe370372901e299a
--- /dev/null
+++ b/cpp/full_code/Gauss_field_test.hpp
@@ -0,0 +1,70 @@
+/**********************************************************************
+*                                                                     *
+*  Copyright 2019 Max Planck Institute                                *
+*                 for Dynamics and Self-Organization                  *
+*                                                                     *
+*  This file is part of TurTLE.                                       *
+*                                                                     *
+*  TurTLE 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.                             *
+*                                                                     *
+*  TurTLE 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 TurTLE.  If not, see <http://www.gnu.org/licenses/>     *
+*                                                                     *
+* Contact: Cristian.Lalescu@ds.mpg.de                                 *
+*                                                                     *
+**********************************************************************/
+
+
+
+#ifndef GAUSS_FIELD_TEST_HPP
+#define GAUSS_FIELD_TEST_HPP
+
+
+
+#include <cstdlib>
+#include "base.hpp"
+#include "kspace.hpp"
+#include "field.hpp"
+#include "full_code/test.hpp"
+
+/** \brief A test of incompressible Gaussian random fields.
+ *
+ */
+
+template <typename rnumber>
+class Gauss_field_test: public test
+{
+    public:
+
+        /* parameters that are read in read_parameters */
+        double filter_length;
+
+        /* other stuff */
+        kspace<FFTW, SMOOTH> *kk;
+        field<rnumber, FFTW, ONE>   *scalar_field;
+        field<rnumber, FFTW, THREE> *vector_field;
+
+        Gauss_field_test(
+                const MPI_Comm COMMUNICATOR,
+                const std::string &simulation_name):
+            test(
+                    COMMUNICATOR,
+                    simulation_name){}
+        ~Gauss_field_test(){}
+
+        int initialize(void);
+        int do_work(void);
+        int finalize(void);
+        int read_parameters(void);
+};
+
+#endif//GAUSS_FIELD_TEST_HPP
+
diff --git a/cpp/kspace.cpp b/cpp/kspace.cpp
index 86d692a25c099ab5d97dd0fd5b247533815e61b6..610df6de6d6997646b0403ffe46c33e2e3c0de1f 100644
--- a/cpp/kspace.cpp
+++ b/cpp/kspace.cpp
@@ -527,9 +527,9 @@ void kspace<be, dt>::dealias(typename fftw_interface<rnumber>::complex *__restri
 template <field_backend be,
           kspace_dealias_type dt>
 template <typename rnumber>
-void kspace<be, dt>::force_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a)
+void kspace<be, dt>::project_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a)
 {
-    TIMEZONE("kspace::force_divfree");
+    TIMEZONE("kspace::project_divfree");
     this->CLOOP_K2(
                 [&](ptrdiff_t cindex,
                     ptrdiff_t xindex,
@@ -558,6 +558,83 @@ void kspace<be, dt>::force_divfree(typename fftw_interface<rnumber>::complex *__
         std::fill_n((rnumber*)(a), 6, 0.0);
 }
 
+/** \brief Rotate vector modes perpendicular to wavenumber
+ * This is different from project because it maintains the energy of the field,
+ * I want it in order to be able to generate random fields with prescribed
+ * spectra.
+ */
+template <field_backend be,
+          kspace_dealias_type dt>
+template <typename rnumber>
+void kspace<be, dt>::rotate_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a)
+{
+    TIMEZONE("kspace::rotate_divfree");
+    this->CLOOP_K2(
+                [&](ptrdiff_t cindex,
+                    ptrdiff_t xindex,
+                    ptrdiff_t yindex,
+                    ptrdiff_t zindex,
+                    double k2){
+                if (k2 > 0)
+            {
+            double cosTheta;
+            double usize;
+            // first compute real part of dot product u0.k
+            cosTheta = (this->kx[xindex]*((*(a + cindex*3  ))[0]) +
+                        this->ky[yindex]*((*(a + cindex*3+1))[0]) +
+                        this->kz[zindex]*((*(a + cindex*3+2))[0]) );
+            // now compute size of initial velocity vector
+            usize = sqrt(pow((*(a + cindex*3  ))[0], 2) +
+                         pow((*(a + cindex*3+1))[0], 2) +
+                         pow((*(a + cindex*3+2))[0], 2) +
+                         pow((*(a + cindex*3  ))[1], 2) +
+                         pow((*(a + cindex*3+1))[1], 2) +
+                         pow((*(a + cindex*3+2))[1], 2));
+            // finalize computation of cos Theta
+            if (usize != 0){
+            cosTheta /= (usize * sqrt(k2));
+            // now compute cross product
+            // cross product for complex vectors is complex conjugate of regular cross product
+            double cp0[3], cp1[3];
+            cp0[0] = (*(a + cindex*3+1))[0]*this->kz[zindex] - (*(a + cindex*3+2))[0]*this->ky[yindex];
+            cp0[1] = (*(a + cindex*3+2))[0]*this->kx[xindex] - (*(a + cindex*3+0))[0]*this->kz[zindex];
+            cp0[2] = (*(a + cindex*3+0))[0]*this->ky[yindex] - (*(a + cindex*3+1))[0]*this->kx[xindex];
+            cp1[0] = -((*(a + cindex*3+1))[1]*this->kz[zindex] - (*(a + cindex*3+2))[1]*this->ky[yindex]);
+            cp1[1] = -((*(a + cindex*3+2))[1]*this->kx[xindex] - (*(a + cindex*3+0))[1]*this->kz[zindex]);
+            cp1[2] = -((*(a + cindex*3+0))[1]*this->ky[yindex] - (*(a + cindex*3+1))[1]*this->kx[xindex]);
+            double cpsize = sqrt(cp0[0]*cp0[0] + cp0[1]*cp0[1] + cp0[2]*cp0[2] +
+                                 cp1[0]*cp1[0] + cp1[1]*cp1[1] + cp1[2]*cp1[2]);
+            cp0[0] /= cpsize;
+            cp0[1] /= cpsize;
+            cp0[2] /= cpsize;
+            cp1[0] /= cpsize;
+            cp1[1] /= cpsize;
+            cp1[2] /= cpsize;
+            double sinTheta = sqrt(1 - cosTheta*cosTheta);
+            // store initial velocity
+            double u0[3], u1[3];
+            u0[0] = (*(a + cindex*3+0))[0];
+            u1[0] = (*(a + cindex*3+0))[1];
+            u0[1] = (*(a + cindex*3+1))[0];
+            u1[1] = (*(a + cindex*3+1))[1];
+            u0[2] = (*(a + cindex*3+2))[0];
+            u1[2] = (*(a + cindex*3+2))[1];
+            // store final result
+            // cross product is between two complex vectors, that's why it looks more complicated
+            (*(a + cindex*3+0))[0] = u0[0]*sinTheta + ((cp0[1]*u0[2] - cp0[2]*u0[1]) - (cp1[1]*u1[2] - cp1[2]*u1[1]))*cosTheta;
+            (*(a + cindex*3+1))[0] = u0[1]*sinTheta + ((cp0[2]*u0[0] - cp0[0]*u0[2]) - (cp1[2]*u1[0] - cp1[0]*u1[2]))*cosTheta;
+            (*(a + cindex*3+2))[0] = u0[2]*sinTheta + ((cp0[0]*u0[1] - cp0[1]*u0[0]) - (cp1[0]*u1[1] - cp1[1]*u1[0]))*cosTheta;
+            (*(a + cindex*3+0))[1] = u1[0]*sinTheta - ((cp0[1]*u1[2] - cp0[2]*u1[1]) + (cp1[1]*u0[2] - cp1[2]*u0[1]))*cosTheta;
+            (*(a + cindex*3+1))[1] = u1[1]*sinTheta - ((cp0[2]*u1[0] - cp0[0]*u1[2]) + (cp1[2]*u0[0] - cp1[0]*u0[2]))*cosTheta;
+            (*(a + cindex*3+2))[1] = u1[2]*sinTheta - ((cp0[0]*u1[1] - cp0[1]*u1[0]) + (cp1[0]*u0[1] - cp1[1]*u0[0]))*cosTheta;
+            }
+            }
+        }
+    );
+    if (this->layout->myrank == this->layout->rank[0][0])
+        std::fill_n((rnumber*)(a), 6, 0.0);
+}
+
 template <field_backend be,
           kspace_dealias_type dt>
 template <typename rnumber,
@@ -1047,8 +1124,18 @@ template double kspace<FFTW, SMOOTH>::L2norm<double, THREE>(
 template double kspace<FFTW, SMOOTH>::L2norm<double, THREExTHREE>(
         const typename fftw_interface<double>::complex *__restrict__ a);
 
+template void kspace<FFTW, SMOOTH>::project_divfree<float>(
+       typename fftw_interface<float>::complex *__restrict__ a);
+template void kspace<FFTW, SMOOTH>::project_divfree<double>(
+       typename fftw_interface<double>::complex *__restrict__ a);
+
 template void kspace<FFTW, SMOOTH>::force_divfree<float>(
        typename fftw_interface<float>::complex *__restrict__ a);
 template void kspace<FFTW, SMOOTH>::force_divfree<double>(
        typename fftw_interface<double>::complex *__restrict__ a);
 
+template void kspace<FFTW, SMOOTH>::rotate_divfree<float>(
+       typename fftw_interface<float>::complex *__restrict__ a);
+template void kspace<FFTW, SMOOTH>::rotate_divfree<double>(
+       typename fftw_interface<double>::complex *__restrict__ a);
+
diff --git a/cpp/kspace.hpp b/cpp/kspace.hpp
index ea82d54be7b9f915f5ec475c3c19ba4b10161acc..1377acebc1d897dee02fb1fb3de59a3480e2455b 100644
--- a/cpp/kspace.hpp
+++ b/cpp/kspace.hpp
@@ -220,7 +220,14 @@ class kspace
             }
         }
         template <typename rnumber>
-        void force_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a);
+        void project_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a);
+        // TODO: can the following be done in a cleaner way?
+        template <typename rnumber>
+        void force_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a){
+            this->template project_divfree<rnumber>(a);
+        }
+        template <typename rnumber>
+        void rotate_divfree(typename fftw_interface<rnumber>::complex *__restrict__ a);
 };
 
 #endif//KSPACE_HPP