diff --git a/python/wrap/core.cpp b/python/wrap/core.cpp
index 996b41ba..525607d0 100644
--- a/python/wrap/core.cpp
+++ b/python/wrap/core.cpp
@@ -1,88 +1,89 @@
 /**
  * @file
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2017 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #include "surface_statistics.hh"
 #include "statistics.hh"
 #include "wrap.hh"
 #include <pybind11/stl.h>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_TAMAAS__
 
 /* -------------------------------------------------------------------------- */
 namespace wrap {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void wrapStatistics(py::module& mod) {
   auto name = makeDimensionName("Statistics", dim);
   py::class_<Statistics<dim>>(mod, name.c_str())
       .def_static("computePowerSpectrum",
                   &Statistics<dim>::computePowerSpectrum)
       .def_static("computeAutocorrelation",
                   &Statistics<dim>::computeAutocorrelation)
       .def_static("computeMoments", &Statistics<dim>::computeMoments)
       .def_static("computeSpectralRMSSlope",
-                  &Statistics<dim>::computeSpectralRMSSlope);
+                  &Statistics<dim>::computeSpectralRMSSlope)
+      .def_static("computeRMSHeights", &Statistics<dim>::computeRMSHeights);
 }
 
 /* -------------------------------------------------------------------------- */
 void wrapCore(py::module& mod) {
   // Exposing SurfaceStatistics (legacy)
   py::class_<SurfaceStatistics>(mod, "SurfaceStatistics")
       .def_static("computeMaximum", &SurfaceStatistics::computeMaximum)
       .def_static("computeMinimum", &SurfaceStatistics::computeMinimum)
       .def_static("computeSpectralRMSSlope",
                   &SurfaceStatistics::computeSpectralRMSSlope)
       .def_static("computeRMSSlope", &SurfaceStatistics::computeRMSSlope)
       .def_static("computeMoments", &SurfaceStatistics::computeMoments)
       .def_static("computeSkewness", &SurfaceStatistics::computeSkewness)
       .def_static("computeKurtosis", &SurfaceStatistics::computeKurtosis)
       .def_static("computeSpectralMeanCurvature",
                   &SurfaceStatistics::computeSpectralMeanCurvature)
       .def_static("computeSpectralStdev",
                   &SurfaceStatistics::computeSpectralStdev)
       .def_static("computeAnalyticFractalMoment",
                   &SurfaceStatistics::computeAnalyticFractalMoment)
       .def_static("computePerimeter", &SurfaceStatistics::computePerimeter)
       .def_static("computeContactArea", &SurfaceStatistics::computeContactArea)
       .def_static("computeContactAreaRatio",
                   &SurfaceStatistics::computeContactAreaRatio)
       .def_static("computeSpectralDistribution",
                   &SurfaceStatistics::computeSpectralDistribution)
       .def_static("computeSum", &SurfaceStatistics::computeSum)
       .def_static("computeAutocorrelation",
                   &SurfaceStatistics::computeAutocorrelation)
       .def_static("computePowerSpectrum",
                   &SurfaceStatistics::computePowerSpectrum);
 
   wrapStatistics<1>(mod);
   wrapStatistics<2>(mod);
 }
 
 }  // namespace wrap
 /* -------------------------------------------------------------------------- */
 __END_TAMAAS__
diff --git a/python/wrap/surface.cpp b/python/wrap/surface.cpp
index 7b622629..5975865a 100644
--- a/python/wrap/surface.cpp
+++ b/python/wrap/surface.cpp
@@ -1,170 +1,184 @@
 /**
  * @file
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2017 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
-#include "wrap.hh"
 #include "isopowerlaw.hh"
 #include "surface_generator_filter.hh"
 #include "surface_generator_filter_fft.hh"
+#include "surface_generator_random_phase.hh"
+#include "wrap.hh"
 #include <pybind11/stl.h>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_TAMAAS__
 
 /* -------------------------------------------------------------------------- */
 namespace wrap {
 
 using namespace py::literals;
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 class PyFilter : public Filter<dim> {
 public:
   using Filter<dim>::Filter;
 
   // Overriding pure virtual functions
   void
   computeFilter(GridHermitian<Real, dim>& filter_coefficients) const override {
     PYBIND11_OVERLOAD_PURE(void, Filter<dim>, computeFilter,
                            filter_coefficients);
   }
 };
 
 template <UInt dim>
 void wrapFilter(py::module& mod) {
   auto name = makeDimensionName("Filter", dim);
   py::class_<Filter<dim>, PyFilter<dim>>(mod, name.c_str())
-    .def(py::init<>())
-    .def("computeFilter", &Filter<dim>::computeFilter);
+      .def(py::init<>())
+      .def("computeFilter", &Filter<dim>::computeFilter);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void wrapIsopowerlaw(py::module& mod) {
   std::string name = makeDimensionName("Isopowerlaw", dim);
   py::class_<Isopowerlaw<dim>, Filter<dim>>(mod, name.c_str())
       .def(py::init<>())
       .def_property("q0", &Isopowerlaw<dim>::getQ0, &Isopowerlaw<dim>::setQ0)
       .def_property("q1", &Isopowerlaw<dim>::getQ1, &Isopowerlaw<dim>::setQ1)
       .def_property("q2", &Isopowerlaw<dim>::getQ2, &Isopowerlaw<dim>::setQ2)
       .def_property("hurst", &Isopowerlaw<dim>::getHurst,
                     &Isopowerlaw<dim>::setHurst)
       .def("rmsHeights", &Isopowerlaw<dim>::rmsHeights)
       .def("moments", &Isopowerlaw<dim>::moments)
       .def("alpha", &Isopowerlaw<dim>::alpha)
       .def("rmsSlopes", &Isopowerlaw<dim>::rmsSlopes)
       // legacy wrapper code
       .def("getQ0", &Isopowerlaw<dim>::getQ0,
            py::return_value_policy::reference)
       .def("getQ1", &Isopowerlaw<dim>::getQ1,
            py::return_value_policy::reference)
       .def("getQ2", &Isopowerlaw<dim>::getQ2,
            py::return_value_policy::reference)
       .def("setQ0", &Isopowerlaw<dim>::setQ0,
            py::return_value_policy::reference)
       .def("setQ1", &Isopowerlaw<dim>::setQ1,
            py::return_value_policy::reference)
       .def("setQ2", &Isopowerlaw<dim>::setQ2,
            py::return_value_policy::reference)
       .def("setHurst", &Isopowerlaw<dim>::setHurst)
       .def("getHurst", &Isopowerlaw<dim>::getHurst,
            py::return_value_policy::reference);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
-void wrapSurfaceGeneratorFilter(py::module& mod) {
-  std::string name = makeDimensionName("SurfaceGeneratorFilter", dim);
-  py::class_<SurfaceGeneratorFilter<dim>>(mod, name.c_str())
-      .def(py::init<>())
-      .def("buildSurface", &SurfaceGeneratorFilter<dim>::buildSurface,
-           "Build rough surface")
-      .def("setFilter", &SurfaceGeneratorFilter<dim>::setFilter,
-           "Set PSD filter", "filter"_a)
+void wrapSurfaceGenerators(py::module& mod) {
+  std::string generator_name = makeDimensionName("SurfaceGenerator", dim);
+  py::class_<SurfaceGenerator<dim>>(mod, generator_name.c_str())
+      .def("buildSurface", &SurfaceGenerator<dim>::buildSurface)
       .def("setSizes",
            py::overload_cast<const std::array<UInt, dim>&>(
-               &SurfaceGeneratorFilter<dim>::setSizes),
+               &SurfaceGenerator<dim>::setSizes),
            "surface_sizes"_a)
-      .def_property("random_seed", &SurfaceGeneratorFilter<dim>::getRandomSeed,
-                    &SurfaceGeneratorFilter<dim>::setRandomSeed)
+      .def_property("random_seed", &SurfaceGenerator<dim>::getRandomSeed,
+                    &SurfaceGenerator<dim>::setRandomSeed);
+
+  std::string filter_name = makeDimensionName("SurfaceGeneratorFilter", dim);
+  py::class_<SurfaceGeneratorFilter<dim>, SurfaceGenerator<dim>>(
+      mod, filter_name.c_str())
+      .def(py::init<>())
+      .def("setFilter", &SurfaceGeneratorFilter<dim>::setFilter,
+           "Set PSD filter", "filter"_a)
+      .def("setSpectrum", &SurfaceGeneratorFilter<dim>::setFilter,
+           "Set PSD spectrum", "filter"_a)
       // legacy wrapper code
       .def("setRandomSeed", &SurfaceGeneratorFilter<dim>::setRandomSeed,
            "[[Deprecated: use property]]");
+
+  std::string random_name =
+      makeDimensionName("SurfaceGeneratorRandomPhase", dim);
+  py::class_<SurfaceGeneratorRandomPhase<dim>, SurfaceGenerator<dim>>(
+      mod, random_name.c_str())
+      .def(py::init<>())
+      .def("setSpectrum", &SurfaceGeneratorRandomPhase<dim>::setSpectrum,
+           "Set PSD Spectrum", "spectrum"_a);
 }
 
 /* -------------------------------------------------------------------------- */
 // Legacy wrap
 void wrapSurfaceGeneratorFilterFFT(py::module& mod) {
   py::class_<SurfaceGeneratorFilterFFT>(mod, "SurfaceGeneratorFilterFFT")
       .def(py::init<>())
       .def("getQ0",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<UInt>(&f.getQ0());
            })
       .def("getQ1",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<UInt>(&f.getQ1());
            })
       .def("getQ2",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<UInt>(&f.getQ2());
            })
       .def("getHurst",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<Real>(&f.getHurst());
            })
       .def("analyticalRMS", &SurfaceGeneratorFilterFFT::analyticalRMS)
       .def("buildSurface", &SurfaceGeneratorFilterFFT::buildSurface)
       .def("getGridSize",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<UInt>(&f.getGridSize());
            })
       .def("getRandomSeed",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<long>(&f.getRandomSeed());
            })
       .def("getRMS",
            [](SurfaceGeneratorFilterFFT& f) {
              return smart_pointer<Real>(&f.getRMS());
            })
       .def("Init", &SurfaceGeneratorFilterFFT::Init);
 }
 
 /* -------------------------------------------------------------------------- */
 void wrapSurface(py::module& mod) {
   wrapFilter<1>(mod);
   wrapFilter<2>(mod);
   wrapIsopowerlaw<1>(mod);
   wrapIsopowerlaw<2>(mod);
-  wrapSurfaceGeneratorFilter<1>(mod);
-  wrapSurfaceGeneratorFilter<2>(mod);
+  wrapSurfaceGenerators<1>(mod);
+  wrapSurfaceGenerators<2>(mod);
 
   // legacy wrap
   wrapSurfaceGeneratorFilterFFT(mod);
 }
 
 }  // namespace wrap
 /* -------------------------------------------------------------------------- */
 __END_TAMAAS__
diff --git a/src/SConscript b/src/SConscript
index b005dcfb..7e220943 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -1,131 +1,132 @@
 import os
 Import('main_env')
 
 
 def prepend(path, list):
     return [os.path.join(path, x) for x in list]
 
 
 env = main_env.Clone()
 
 # Core
 core_list = """
 fft_plan_manager.cpp
 fftransform.cpp
 fftransform_fftw.cpp
 grid.cpp
 grid_hermitian.cpp
 statistics.cpp
 surface.cpp
 tamaas.cpp
 legacy_types.cpp
 loop.cpp
 """.split()
 core_list = prepend('core', core_list)
 core_list.append('tamaas_info.cpp')
 
 # Lib roughcontact
 generator_list = """
 surface_generator.cpp
 surface_generator_filter.cpp
 surface_generator_filter_fft.cpp
+surface_generator_random_phase.cpp
 isopowerlaw.cpp
 """.split()
 generator_list = prepend('surface', generator_list)
 
 # Lib PERCOLATION
 percolation_list = """
 flood_fill.cpp
 """.split()
 percolation_list = prepend('percolation', percolation_list)
 
 # BEM PERCOLATION
 bem_list = """
 bem_kato.cpp
 bem_polonski.cpp
 bem_gigi.cpp
 bem_gigipol.cpp
 bem_penalty.cpp
 bem_uzawa.cpp
 bem_fft_base.cpp
 bem_functional.cpp
 bem_meta_functional.cpp
 elastic_energy_functional.cpp
 exponential_adhesion_functional.cpp
 squared_exponential_adhesion_functional.cpp
 maugis_adhesion_functional.cpp
 complimentary_term_functional.cpp
 bem_grid.cpp
 bem_grid_polonski.cpp
 bem_grid_kato.cpp
 bem_grid_teboulle.cpp
 bem_grid_condat.cpp
 """.split()
 bem_list = prepend('bem', bem_list)
 
 # Model
 model_list = """
 model.cpp
 model_factory.cpp
 model_type.cpp
 model_template.cpp
 be_engine.cpp
 westergaard.cpp
 elastic_functional.cpp
 meta_functional.cpp
 adhesion_functional.cpp
 volume_potential.cpp
 kelvin.cpp
 mindlin.cpp
 boussinesq.cpp
 
 elasto_plastic/isotropic_hardening.cpp
 elasto_plastic/elasto_plastic_model.cpp
 elasto_plastic/residual.cpp
 """.split()
 model_list = prepend('model', model_list)
 
 # Solvers
 solvers_list = """
 contact_solver.cpp
 polonsky_keer_rey.cpp
 kato.cpp
 beck_teboulle.cpp
 condat.cpp
 polonsky_keer_tan.cpp
 ep_solver.cpp
 epic.cpp
 """.split()
 solvers_list = prepend('solvers', solvers_list)
 
 # GPU API
 gpu_list = """
 fftransform_cufft.cpp
 """.split()
 gpu_list = prepend('gpu', gpu_list)
 
 # Assembling total list
 rough_contact_list = \
   core_list + generator_list + percolation_list + model_list + solvers_list
 
 # For some reason collapse OMP loops don't compile on intel
 if env['CXX'] != 'icpc':
     rough_contact_list += bem_list
 
 # Adding GPU if needed
 if env['backend'] == 'cuda':
     rough_contact_list += gpu_list
 
 # Generating dependency files
 # env.AppendUnique(CXXFLAGS=['-MMD'])
 
 # for file_name in rough_contact_list:
 #     obj = file_name.replace('.cpp', '.os')
 #     dep_file_name = file_name.replace('.cpp', '.d')
 #     env.SideEffect(dep_file_name, obj)
 #     env.ParseDepends(dep_file_name)
 
 # Adding extra warnings for Tamaas base lib
 env.AppendUnique(CXXFLAGS=['-Wextra'])
 libTamaas = env.SharedLibrary('Tamaas', rough_contact_list)
 Export('libTamaas')
diff --git a/src/core/statistics.cpp b/src/core/statistics.cpp
index 79a5583d..61d5df62 100644
--- a/src/core/statistics.cpp
+++ b/src/core/statistics.cpp
@@ -1,159 +1,162 @@
 /**
  * @file
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2016-2017 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #include "statistics.hh"
 #include "loop.hh"
 #include "static_types.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_TAMAAS__
 
+template <UInt dim>
+Real Statistics<dim>::computeRMSHeights(Grid<Real, dim>& surface) {
+  return std::sqrt(surface.var());
+}
+
 template <UInt dim>
 Real Statistics<dim>::computeSpectralRMSSlope(Grid<Real, dim>& surface) {
   auto h_size = GridHermitian<Real, dim>::hermitianDimensions(surface.sizes());
   auto wavevectors =
       FFTransform<Real, dim>::template computeFrequencies<true>(h_size);
   auto psd = computePowerSpectrum(surface);
 
-  Real rms_slope_mean = 0;
-
-  rms_slope_mean = Loop::reduce<operation::plus>(
+  Real rms_slope_mean = Loop::reduce<operation::plus>(
       [] CUDA_LAMBDA(VectorProxy<Real, dim> q, Complex & psd_val) {
         return q.l2squared() * psd_val.real();
       },
       range<VectorProxy<Real, dim>>(wavevectors), psd);
 
-  rms_slope_mean /= wavevectors.getNbPoints();  // average
+  //rms_slope_mean /= wavevectors.getNbPoints();  // average
   rms_slope_mean *= 2;  // because we have a hermitian surface
-  return rms_slope_mean;
+  return std::sqrt(rms_slope_mean);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 GridHermitian<Real, dim>
 Statistics<dim>::computePowerSpectrum(Grid<Real, dim>& surface) {
   auto h_size = GridHermitian<Real, dim>::hermitianDimensions(surface.sizes());
   GridHermitian<Real, dim> psd(h_size, surface.getNbComponents());
   FFTPlanManager::get().createPlan(surface, psd).forwardTransform();
 
   Real factor = surface.getNbPoints();
   factor = 1. / (factor * factor);
 
   // Squaring the fourier transform of surface and normalizing
   Loop::loop(
       [factor] CUDA_LAMBDA(Complex & c) {
         c *= conj(c);
         c *= factor;
       },
       psd);
 
   FFTPlanManager::get().destroyPlan(surface, psd);
   return psd;
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 Grid<Real, dim>
 Statistics<dim>::computeAutocorrelation(Grid<Real, dim>& surface) {
   Grid<Real, dim> acf(surface.sizes(), surface.getNbComponents());
   auto psd = computePowerSpectrum(surface);
   FFTPlanManager::get().createPlan(acf, psd).backwardTransform();
   acf *= acf.getNbPoints();
   FFTPlanManager::get().destroyPlan(acf, psd);
   return acf;
 }
 
 /* -------------------------------------------------------------------------- */
 namespace {
 template <UInt dim>
 class moment_helper {
 public:
   moment_helper(const std::array<UInt, dim>& exp) : exponent(exp) {}
 
   CUDA_LAMBDA Complex operator()(VectorProxy<const Real, dim> q,
                                  const Complex& phi) const {
     Real mul = 1;
     for (UInt i = 0; i < dim; ++i)
       mul *= std::pow(q(i), exponent[i]);
     return mul * phi;
   }
 
 private:
   std::array<UInt, dim> exponent;
 };
 }  // namespace
 
 template <>
 std::vector<Real> Statistics<1>::computeMoments(Grid<Real, 1>& surface) {
   constexpr UInt dim = 1;
   std::vector<Real> moments(3);
   const auto psd = computePowerSpectrum(surface);
   const auto wavevectors =
       FFTransform<Real, dim>::template computeFrequencies<true>(psd.sizes());
   moments[0] = psd.sum().real();
   moments[1] = Loop::reduce<operation::plus>(moment_helper<dim>{{{2}}},
                                              range<PVector>(wavevectors), psd)
                    .real();
   moments[2] = Loop::reduce<operation::plus>(moment_helper<dim>{{{4}}},
                                              range<PVector>(wavevectors), psd)
                    .real();
   return moments;
 }
 
 template <>
 std::vector<Real> Statistics<2>::computeMoments(Grid<Real, 2>& surface) {
   constexpr UInt dim = 2;
   std::vector<Real> moments(3);
   const auto psd = computePowerSpectrum(surface);
   const auto wavevectors =
       FFTransform<Real, dim>::template computeFrequencies<true>(psd.sizes());
   moments[0] = psd.sum().real();
   auto m02 = Loop::reduce<operation::plus>(moment_helper<dim>{{{0, 2}}},
                                            range<PVector>(wavevectors), psd)
                  .real();
   auto m20 = Loop::reduce<operation::plus>(moment_helper<dim>{{{2, 0}}},
                                            range<PVector>(wavevectors), psd)
                  .real();
   moments[1] = 0.5 * (m02 + m20);
   auto m22 = Loop::reduce<operation::plus>(moment_helper<dim>{{{2, 2}}},
                                            range<PVector>(wavevectors), psd)
                  .real();
   auto m40 = Loop::reduce<operation::plus>(moment_helper<dim>{{{4, 0}}},
                                            range<PVector>(wavevectors), psd)
                  .real();
   auto m04 = Loop::reduce<operation::plus>(moment_helper<dim>{{{0, 4}}},
                                            range<PVector>(wavevectors), psd)
                  .real();
   moments[2] = (3 * m22 + m40 + m04) / 3.;
   return moments;
 }
 
 template struct Statistics<1>;
 template struct Statistics<2>;
 
 __END_TAMAAS__
diff --git a/src/core/statistics.hh b/src/core/statistics.hh
index 3b98ad3b..7fcd6a67 100644
--- a/src/core/statistics.hh
+++ b/src/core/statistics.hh
@@ -1,57 +1,59 @@
 /**
  * @file
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2016-2017 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #ifndef __STATISTICS_HH__
 #define __STATISTICS_HH__
 /* -------------------------------------------------------------------------- */
 #include "fft_plan_manager.hh"
 #include "grid.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_TAMAAS__
 /* -------------------------------------------------------------------------- */
 
 /**
  * @brief Suitcase class for all statistics related functions
  */
 template <UInt dim>
 struct Statistics {
+  /// Compute hrms
+  static Real computeRMSHeights(Grid<Real, dim>& surface);
   /// Compute hrms' in fourier space
   static Real computeSpectralRMSSlope(Grid<Real, dim>& surface);
   /// Compute PSD of surface
   static GridHermitian<Real, dim>
   computePowerSpectrum(Grid<Real, dim>& surface);
   /// Compute autocorrelation
   static Grid<Real, dim> computeAutocorrelation(Grid<Real, dim>& surface);
   /// Compute spectral moments
   static std::vector<Real> computeMoments(Grid<Real, dim>& surface);
 
   using PVector = VectorProxy<const Real, dim>;
 };
 
 /* -------------------------------------------------------------------------- */
 __END_TAMAAS__
 #endif  // __STATISTICS_HH__
diff --git a/src/core/tamaas.hh b/src/core/tamaas.hh
index 9044ab1e..31634f51 100644
--- a/src/core/tamaas.hh
+++ b/src/core/tamaas.hh
@@ -1,158 +1,159 @@
 /**
  * @mainpage Welcome to Tamaas !
  *
  * @section Introduction
  * Tamaas is a spectral-boundary-element based contact library. It is made with
  * love to be fast and friendly!
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  * @author Valentine Rey <valentine.rey@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2016-2017 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #ifndef __TAMAAS_HH__
 #define __TAMAAS_HH__
 /* -------------------------------------------------------------------------- */
 // Standard includes
 #include <exception>
 #include <iostream>
 #include <memory>
 #include <string>
 /* -------------------------------------------------------------------------- */
 // Special thrust includes
 #include <thrust/complex.h>
 #include <thrust/random.h>
 
 #ifdef USE_CUDA
 #include "unified_allocator.hh"
 #else
 #include "fftw_allocator.hh"
 #endif
 
 /// @section Namespace macros
 #define __BEGIN_TAMAAS__ namespace tamaas {
 #define __END_TAMAAS__ }
 
 /// @section Cuda specific definitions
 #define CUDA_LAMBDA __device__ __host__
 
 #ifdef USE_CUDA
 #define DEFAULT_ALLOCATOR UnifiedAllocator<T>
 #else
 #define DEFAULT_ALLOCATOR FFTWAllocator<T>
 #endif
 
 /* -------------------------------------------------------------------------- */
 
 /// @section Standard definitions pulled from C++14
 namespace std {
 #if __cplusplus < 201402L
 /// exchange
 template <class T, class U = T>
 T exchange(T& obj, U&& new_value) {
   T old_value = move(obj);
   obj = forward<U>(new_value);
   return old_value;
 }
 /// make_unique
 template <typename T, typename... Args>
 unique_ptr<T> make_unique(Args&&... args) {
   return unique_ptr<T>(new T(forward<Args>(args)...));
 }
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 __BEGIN_TAMAAS__
 /* -------------------------------------------------------------------------- */
 
 /// @section Common types definitions
 using Real = double;        ///< default floating point type
 using UInt = unsigned int;  ///< default unsigned integer type
 using Int = int;            ///< default signed integer type
 template <typename T>
 using complex = thrust::complex<T>;  ///< template complex wrapper
 using Complex = complex<Real>;       ///< default floating point complex type
 static constexpr Real zero_threshold = 1e-14;
 
 /// @section Defining random toolbox
 using ::thrust::random::normal_distribution;
+using ::thrust::random::uniform_real_distribution;
 using random_engine = ::thrust::random::default_random_engine;
 
 /* -------------------------------------------------------------------------- */
 /// initialize tamaas (0 threads => let OMP_NUM_THREADS decide)
 void initialize(UInt num_threads = 0);
 /// cleanup tamaas
 void finalize();
 /* -------------------------------------------------------------------------- */
 
 /// Generic exception class
 class Exception : public std::exception {
 public:
   /// Constructor
   Exception(const std::string& mesg) : msg(mesg) {}
 
   virtual const char* what() const noexcept { return msg.c_str(); }
 
   virtual ~Exception() = default;
 
 private:
   std::string msg;  ///< message of exception
 };
 /* -------------------------------------------------------------------------- */
 /// Enumeration of reduction operations
 enum class operation { plus, times, min, max };
 /* -------------------------------------------------------------------------- */
 __END_TAMAAS__
 /* -------------------------------------------------------------------------- */
 
 /// @section Convenience macros
 #define TAMAAS_EXCEPTION(mesg)                                                 \
   {                                                                            \
     std::stringstream sstr;                                                    \
     sstr << __FILE__ << ":" << __LINE__ << ":FATAL: " << mesg << std::endl;    \
     std::cerr.flush();                                                         \
     throw ::tamaas::Exception(sstr.str());                                     \
   }
 
 #define SURFACE_FATAL(mesg) TAMAAS_EXCEPTION(mesg)
 
 #if defined(TAMAAS_DEBUG)
 #define TAMAAS_ASSERT(cond, reason)                                            \
   do {                                                                         \
     if (!(cond)) {                                                             \
       TAMAAS_EXCEPTION(#cond " assert failed: " << reason);                    \
     }                                                                          \
   } while (0)
 #define TAMAAS_DEBUG_EXCEPTION(reason) TAMAAS_EXCEPTION(reason)
 #else
 #define TAMAAS_ASSERT(cond, reason)
 #define TAMAAS_DEBUG_EXCEPTION(reason)
 #endif
 #define TAMAAS_ACCESSOR(var, type, name)                                       \
   type& get##name() { return var; }                                            \
   void set##name(const type& new_var) { var = new_var; }
 
 /* -------------------------------------------------------------------------- */
 
 #endif  // TAMAAS_HH
diff --git a/src/surface/isopowerlaw.cpp b/src/surface/isopowerlaw.cpp
index ee43a104..55e2358b 100644
--- a/src/surface/isopowerlaw.cpp
+++ b/src/surface/isopowerlaw.cpp
@@ -1,110 +1,110 @@
 /**
  * @file
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2016 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #include "isopowerlaw.hh"
 #include "fftransform.hh"
 #include <map>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_TAMAAS__
 
 template <UInt dim>
 void Isopowerlaw<dim>::computeFilter(
     GridHermitian<Real, dim>& filter_coefficients) const {
   auto wavevectors = FFTransform<Real, dim>::template computeFrequencies<true>(
       filter_coefficients.sizes());
 
   Loop::loop(  // loop here cannot capture this
       [this] CUDA_LAMBDA(Complex & coeff, VectorProxy<Real, dim> q) {
         coeff = (*this)(q);
       },
       filter_coefficients, range<VectorProxy<Real, dim>>(wavevectors));
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 Real Isopowerlaw<dim>::rmsHeights() const {
   return std::sqrt(M_PI * ((hurst + 1) / hurst * q1 * q1 -
                            1. / hurst * std::pow(q1, 2 * (hurst + 1)) *
                                std::pow(q2, -2 * hurst) -
                            q0 * q0));
 }
 
 /* -------------------------------------------------------------------------- */
 
 /**
  * Analytical moments, cf. Yastrebov et al. (2015)
  * "From infinitesimal to full contact between rough surfaces: Evolution
  * of the contact area", appendix A
  */
 template <>
 std::vector<Real> Isopowerlaw<2>::moments() const {
   std::map<UInt, Real> T;
   T[0] = 2 * M_PI;
   T[2] = M_PI;
   T[4] = 3 * M_PI / 4.;
   Real xi = q0 / q1;
   Real zeta = q2 / q1;
 
   std::vector<Real> moments;
-
+  moments.reserve(3);
   using namespace std;
   for (int q : {0, 2, 4}) {
     Real m = T[q] * pow(q1, q - 2 * hurst) *
              ((1 - pow(xi, q + 2)) / (q + 2) +
               (pow(zeta, q - 2 * hurst) - 1) / (q - 2 * hurst));
     moments.push_back(m);
   }
 
   return moments;
 }
 
 template <>
 std::vector<Real> Isopowerlaw<1>::moments() const {
   TAMAAS_EXCEPTION("Moments have not been implemented for 1D surfaces");
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 Real Isopowerlaw<dim>::alpha() const {
   std::vector<Real> m = moments();
   return m[0] * m[2] / (m[1] * m[1]);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 Real Isopowerlaw<dim>::rmsSlopes() const {
   std::vector<Real> m = moments();
   return std::sqrt(2 * m[1]);
 }
 
 template class Isopowerlaw<1>;
 template class Isopowerlaw<2>;
 
 __END_TAMAAS__
diff --git a/src/surface/surface_generator_filter.hh b/src/surface/surface_generator_filter.hh
index 884202d6..304be513 100644
--- a/src/surface/surface_generator_filter.hh
+++ b/src/surface/surface_generator_filter.hh
@@ -1,81 +1,81 @@
 /**
  * @file
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2016 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 
 #ifndef SURFACE_GENERATOR_FILTER_H
 #define SURFACE_GENERATOR_FILTER_H
 /* -------------------------------------------------------------------------- */
 #include "filter.hh"
 #include "surface_generator.hh"
 #include "tamaas.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_TAMAAS__
 
 template <UInt dim>
 class SurfaceGeneratorFilter : public SurfaceGenerator<dim> {
 public:
   /// Default constructor
   SurfaceGeneratorFilter() = default;
   /// Destructor
   virtual ~SurfaceGeneratorFilter();
 
 public:
   /// Build surface with Hu & Tonder algorithm
   Grid<Real, dim>& buildSurface() override;
-  /// Set filter object (need namespace for swig)
-  void setFilter(::tamaas::Filter<dim>* new_filter);
+  /// Set filter object
+  void setFilter(Filter<dim>* new_filter);
 
 protected:
   /// Apply filter coefficients on white noise
   void applyFilterOnSource();
   /// Generate white noise with given distribution
   template <typename T>
   void generateWhiteNoise();
 
 protected:
   Filter<dim>* filter = nullptr;  ///< not owned
   GridHermitian<Real, dim> filter_coefficients;
   Grid<Real, dim> white_noise;
 };
 
 /* -------------------------------------------------------------------------- */
 /* Template implementations                                                   */
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 template <typename T>
 void SurfaceGeneratorFilter<dim>::generateWhiteNoise() {
   random_engine gen(this->random_seed);
   T distribution;
 
   for (auto& noise : white_noise)
     noise = distribution(gen);
 }
 
 __END_TAMAAS__
 
 #endif
diff --git a/src/surface/surface_generator_random_phase.cpp b/src/surface/surface_generator_random_phase.cpp
new file mode 100644
index 00000000..1dcdd0f9
--- /dev/null
+++ b/src/surface/surface_generator_random_phase.cpp
@@ -0,0 +1,76 @@
+/**
+ * @file
+ *
+ * @author Lucas Frérot <lucas.frerot@epfl.ch>
+ *
+ * @section LICENSE
+ *
+ * Copyright (©)  2016 EPFL  (Ecole Polytechnique  Fédérale de
+ * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
+ * Solides)
+ *
+ * Tamaas is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as  published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Tamaas 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  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+#include "surface_generator_random_phase.hh"
+#include "fft_plan_manager.hh"
+#include "fftransform.hh"
+#include <iostream>
+/* -------------------------------------------------------------------------- */
+namespace tamaas {
+/* -------------------------------------------------------------------------- */
+
+template <UInt dim>
+Grid<Real, dim>& SurfaceGeneratorRandomPhase<dim>::buildSurface() {
+  if (this->grid.dataSize() == 0)
+    TAMAAS_EXCEPTION("the size of the grid is zero, did you call setSizes() ?");
+  if (this->filter == nullptr)
+    TAMAAS_EXCEPTION("filter is null, did you call setFilter() ?");
+
+  // Resizing arrays
+  auto hermitian_dim =
+      GridHermitian<Real, dim>::hermitianDimensions(this->grid.sizes());
+  this->white_noise.resize(hermitian_dim);
+  this->surface_coefficients.resize(hermitian_dim);
+
+  /// Generating white noise with uniform distribution for phase
+  this->generateWhiteNoise<uniform_real_distribution<Real>>();
+
+  /// Applying filters
+  filter->computeFilter(this->surface_coefficients);
+
+  Loop::loop([](Complex& coeff,
+                Real& phase) { coeff *= thrust::polar(1., 2 * M_PI * phase); },
+             this->surface_coefficients, this->white_noise);
+
+  FFTPlanManager::get()
+      .createPlan(this->grid, this->surface_coefficients)
+      .backwardTransform();
+  FFTPlanManager::get().destroyPlan(this->grid, this->surface_coefficients);
+
+  /// Normalizing surface for hrms independent of number of points
+  this->grid *= this->grid.dataSize();
+
+  return this->grid;
+}
+
+/* -------------------------------------------------------------------------- */
+template class SurfaceGeneratorRandomPhase<1>;
+template class SurfaceGeneratorRandomPhase<2>;
+/* -------------------------------------------------------------------------- */
+
+}  // namespace tamaas
diff --git a/src/surface/surface_generator_filter.hh b/src/surface/surface_generator_random_phase.hh
similarity index 73%
copy from src/surface/surface_generator_filter.hh
copy to src/surface/surface_generator_random_phase.hh
index 884202d6..f4e86376 100644
--- a/src/surface/surface_generator_filter.hh
+++ b/src/surface/surface_generator_random_phase.hh
@@ -1,81 +1,75 @@
 /**
  * @file
  *
- * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
+ * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @section LICENSE
  *
  * Copyright (©)  2016 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Tamaas is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Tamaas 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 
-#ifndef SURFACE_GENERATOR_FILTER_H
-#define SURFACE_GENERATOR_FILTER_H
+#ifndef SURFACE_GENERATOR_RANDOM_PHASE_H
+#define SURFACE_GENERATOR_RANDOM_PHASE_H
 /* -------------------------------------------------------------------------- */
 #include "filter.hh"
 #include "surface_generator.hh"
 #include "tamaas.hh"
 /* -------------------------------------------------------------------------- */
-
-__BEGIN_TAMAAS__
+namespace tamaas {
+/* -------------------------------------------------------------------------- */
 
 template <UInt dim>
-class SurfaceGeneratorFilter : public SurfaceGenerator<dim> {
-public:
-  /// Default constructor
-  SurfaceGeneratorFilter() = default;
-  /// Destructor
-  virtual ~SurfaceGeneratorFilter();
-
+class SurfaceGeneratorRandomPhase : public SurfaceGenerator<dim> {
 public:
-  /// Build surface with Hu & Tonder algorithm
+  /// Build surface with uniform random phase
   Grid<Real, dim>& buildSurface() override;
-  /// Set filter object (need namespace for swig)
-  void setFilter(::tamaas::Filter<dim>* new_filter);
+  /// Set filter object
+  void setSpectrum(Filter<dim>* new_filter) {
+    filter = new_filter;
+  }
 
 protected:
-  /// Apply filter coefficients on white noise
-  void applyFilterOnSource();
   /// Generate white noise with given distribution
   template <typename T>
   void generateWhiteNoise();
 
 protected:
   Filter<dim>* filter = nullptr;  ///< not owned
-  GridHermitian<Real, dim> filter_coefficients;
+  GridHermitian<Real, dim> surface_coefficients;
   Grid<Real, dim> white_noise;
 };
 
 /* -------------------------------------------------------------------------- */
 /* Template implementations                                                   */
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim>
 template <typename T>
-void SurfaceGeneratorFilter<dim>::generateWhiteNoise() {
+void SurfaceGeneratorRandomPhase<dim>::generateWhiteNoise() {
   random_engine gen(this->random_seed);
   T distribution;
 
   for (auto& noise : white_noise)
     noise = distribution(gen);
 }
 
-__END_TAMAAS__
+}  // namespace tamaas
 
 #endif