diff --git a/dune/stuff/functions/random_ellipsoids_function.hh b/dune/stuff/functions/random_ellipsoids_function.hh
new file mode 100644
index 0000000000000000000000000000000000000000..85bc6ec59c9c70c381e7b6db05a318417b0afc91
--- /dev/null
+++ b/dune/stuff/functions/random_ellipsoids_function.hh
@@ -0,0 +1,250 @@
+// This file is part of the dune-stuff project:
+//   https://github.com/wwu-numerik/dune-stuff/
+// Copyright holders: Rene Milk, Felix Schindler
+// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
+
+#ifndef DUNE_STUFF_FUNCTION_RandomEllipsoidsFunction_HH
+#define DUNE_STUFF_FUNCTION_RandomEllipsoidsFunction_HH
+
+#include <vector>
+#include <cmath>
+#include <memory>
+
+#include <dune/common/exceptions.hh>
+
+#include <dune/stuff/common/configuration.hh>
+#include <dune/stuff/common/debug.hh>
+#include <dune/stuff/common/fvector.hh>
+#include <dune/stuff/common/random.hh>
+
+#include "interfaces.hh"
+
+namespace Dune {
+namespace Stuff {
+namespace Functions {
+
+template <size_t dim, class CoordType = double>
+struct Ellipsoid
+{
+  DSC::FieldVector<CoordType, dim> center;
+  DSC::FieldVector<CoordType, dim> radii;
+
+  bool contains(DSC::FieldVector<CoordType, dim> point) const
+  {
+    const auto shifted = point - center;
+    double sum = 0;
+    for (auto ii : DSC::valueRange(dim)) {
+      const auto pii = shifted[ii];
+      sum += std::pow(pii, 2) / std::pow(radii[ii], 2);
+    }
+    return DSC::FloatCmp::le(sum, 1.);
+  }
+};
+
+template <class EntityImp, class DomainFieldImp, size_t domainDim, class RangeFieldImp, size_t rangeDim,
+          size_t rangeDimCols = 1>
+class RandomEllipsoidsFunction
+    : public LocalizableFunctionInterface<EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols>
+{
+  typedef LocalizableFunctionInterface<EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols>
+      BaseType;
+  typedef RandomEllipsoidsFunction<EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols>
+      ThisType;
+
+  class Localfunction
+      : public LocalfunctionInterface<EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols>
+  {
+    typedef LocalfunctionInterface<EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols>
+        BaseType;
+
+  public:
+    typedef typename BaseType::EntityType EntityType;
+
+    typedef typename BaseType::DomainType DomainType;
+    typedef typename BaseType::RangeFieldType RangeFieldType;
+    typedef typename BaseType::RangeType RangeType;
+    typedef typename BaseType::JacobianRangeType JacobianRangeType;
+
+    Localfunction(const EntityType& ent, const RangeType value)
+      : BaseType(ent)
+      , value_(value)
+    {
+    }
+
+    Localfunction(const Localfunction& /*other*/) = delete;
+
+    Localfunction& operator=(const Localfunction& /*other*/) = delete;
+
+    virtual size_t order() const override
+    {
+      return 0;
+    }
+
+    virtual void evaluate(const DomainType& UNUSED_UNLESS_DEBUG(xx), RangeType& ret) const override
+    {
+      assert(this->is_a_valid_point(xx));
+      ret = value_;
+    }
+
+    virtual void jacobian(const DomainType& UNUSED_UNLESS_DEBUG(xx), JacobianRangeType& ret) const override
+    {
+      assert(this->is_a_valid_point(xx));
+      ret *= RangeFieldType(0);
+    }
+
+  private:
+    const RangeType value_;
+  }; // class Localfunction
+
+public:
+  typedef typename BaseType::EntityType EntityType;
+  typedef typename BaseType::LocalfunctionType LocalfunctionType;
+
+  typedef typename BaseType::DomainFieldType DomainFieldType;
+  static const size_t dimDomain = BaseType::dimDomain;
+
+  typedef typename BaseType::RangeFieldType RangeFieldType;
+  typedef typename BaseType::RangeType RangeType;
+
+  static const bool available = true;
+
+  static std::string static_id()
+  {
+    return BaseType::static_id() + ".RandomEllipsoidsFunction";
+  }
+
+  static Common::Configuration default_config(const std::string sub_name = "")
+  {
+    Common::Configuration config;
+    config["lower_left"]   = "[0.0 0.0 0.0]";
+    config["upper_right"]  = "[1.0 1.0 1.0]";
+    config["num_elements"] = "[2 2 2]";
+    config["values"]       = "[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0]";
+    config["name"] = static_id();
+    if (sub_name.empty())
+      return config;
+    else {
+      Common::Configuration tmp;
+      tmp.add(config, sub_name);
+      return tmp;
+    }
+  } // ... default_config(...)
+
+  static std::unique_ptr<ThisType> create(const Common::Configuration config = default_config(),
+                                          const std::string sub_name = static_id())
+  {
+    // get correct config
+    const Common::Configuration cfg         = config.has_sub(sub_name) ? config.sub(sub_name) : config;
+    const Common::Configuration default_cfg = default_config();
+    // calculate number of values and get values
+    auto num_elements =
+        cfg.get("num_elements", default_cfg.get<Common::FieldVector<size_t, dimDomain>>("num_elements"), dimDomain);
+    size_t num_values = 1;
+    for (size_t ii = 0; ii < num_elements.size(); ++ii)
+      num_values *= num_elements[ii];
+    std::vector<RangeType> values(num_values);
+    auto values_rf = cfg.get("values", default_cfg.get<std::vector<RangeFieldType>>("values"), num_values);
+    for (size_t ii = 0; ii < values_rf.size(); ++ii)
+      values[ii] = RangeType(values_rf[ii]);
+    // create
+    return Common::make_unique<ThisType>(
+        cfg.get(
+            "lower_left", default_cfg.get<Common::FieldVector<DomainFieldType, dimDomain>>("lower_left"), dimDomain),
+        cfg.get(
+            "upper_right", default_cfg.get<Common::FieldVector<DomainFieldType, dimDomain>>("upper_right"), dimDomain),
+        std::move(num_elements),
+        std::move(values),
+        cfg.get("name", default_cfg.get<std::string>("name")));
+  } // ... create(...)
+
+  RandomEllipsoidsFunction(const Common::FieldVector<DomainFieldType, dimDomain>& lowerLeft,
+                           const Common::FieldVector<DomainFieldType, dimDomain>& upperRight,
+                           const Stuff::Common::Configuration& ellipsoid_cfg, const std::string nm = static_id())
+    : lowerLeft_(lowerLeft)
+    , upperRight_(upperRight)
+    , name_(nm)
+    , ellipsoid_cfg_(ellipsoid_cfg)
+  {
+    //    randomblock_config["ellipsoids.count"] = "200";
+    //    randomblock_config["ellipsoids.min_radius"] = "0.01";
+    //    randomblock_config["ellipsoids.max_radius"] = "0.03";
+    //    randomblock_config["ellipsoids.seed"] = "0";
+    //    randomblock_config["ellipsoids.children"] = "3";
+    //    randomblock_config["ellipsoids.recursion_depth"] = "4";
+    //    randomblock_config["ellipsoids.recursion_scale"] = "0.5";
+    //    config.add(randomblock_config, "diffusion_factor");
+    typedef unsigned long CT;
+    const CT level_0_count = ellipsoid_cfg.get("ellipsoids.count", 200);
+    const CT max_depth     = ellipsoid_cfg.get("ellipsoids.recursion_depth", 1);
+    const CT children      = ellipsoid_cfg.get<CT>("ellipsoids.children", 3u, DSC::ValidateGreater<CT>(0));
+    const CT total_count = level_0_count * std::pow(children, max_depth);
+    ellipsoids_.resize(total_count);
+    const auto seed = DomainFieldType(0);
+    DSC::DefaultRNG<DomainFieldType> center_rng(
+        *std::max(lowerLeft.begin(), lowerLeft.end()), *std::min(upperRight.begin(), upperRight.end()), seed);
+    DSC::DefaultRNG<DomainFieldType> radii_rng(
+        ellipsoid_cfg.get("ellipsoids.min_radii", 0.01), ellipsoid_cfg.get("ellipsoids.max_radii", 0.04), seed);
+    for (auto ii : DSC::valueRange(0, total_count, total_count / level_0_count)) {
+      std::fill(ellipsoids_[ii].center.begin(), ellipsoids_[ii].center.end(), center_rng);
+      std::fill(ellipsoids_[ii].radii.begin(), ellipsoids_[ii].radii.end(), radii_rng);
+    }
+    for (auto current_depth : DSC::valueRange(1, max_depth + 1)) {
+    }
+  }
+
+  RandomEllipsoidsFunction(const ThisType& other) = default;
+
+  ThisType& operator=(const ThisType& other) = delete;
+
+  ThisType& operator=(ThisType&& source) = delete;
+
+  virtual std::string type() const override
+  {
+    return BaseType::static_id() + ".RandomEllipsoidsFunction";
+  }
+
+  virtual std::string name() const override
+  {
+    return name_;
+  }
+
+  virtual std::unique_ptr<LocalfunctionType> local_function(const EntityType& entity) const override
+  {
+    constexpr auto local_value = DomainFieldType(1);
+    // decide on the subdomain the center of the entity belongs to
+    const auto center = entity.geometry().center();
+    //    std::vector< size_t > whichPartition(dimDomain, 0);
+    //    const auto& ll = lowerLeft_;
+    //    const auto& ur = upperRight_;
+    //    const auto& ne = numElements_;
+    //    for (size_t dd = 0; dd < dimDomain; ++dd) {
+    //      // for points that are on upperRight_[d], this selects one partition too much
+    //      // so we need to cap this
+    //      whichPartition[dd] = std::min(size_t(std::floor(ne[dd]*((center[dd] - ll[dd])/(ur[dd] - ll[dd])))),
+    //                                    ne[dd] - 1);
+    //    }
+    //    size_t subdomain = 0;
+    //    if (dimDomain == 1)
+    //      subdomain = whichPartition[0];
+    //    else if (dimDomain == 2)
+    //      subdomain = whichPartition[0] + whichPartition[1]*ne[0];
+    //    else
+    //      subdomain = whichPartition[0] + whichPartition[1]*ne[0] + whichPartition[2]*ne[1]*ne[0];
+    //    // return the component that belongs to the subdomain
+    return std::unique_ptr<Localfunction>(new Localfunction(entity, local_value));
+  } // ... local_function(...)
+
+private:
+  const Common::FieldVector<DomainFieldType, dimDomain> lowerLeft_;
+  const Common::FieldVector<DomainFieldType, dimDomain> upperRight_;
+  std::string name_;
+  const Stuff::Common::Configuration ellipsoid_cfg_;
+  std::vector<Ellipsoid> ellipsoids_;
+}; // class RandomEllipsoidsFunction
+
+
+} // namespace Functions
+} // namespace Stuff
+} // namespace Dune
+
+#endif // DUNE_STUFF_FUNCTION_RandomEllipsoidsFunction_HH