diff --git a/dune/tectonic/body.hh b/dune/tectonic/body.hh
index cadcbc52974fb274146ab9d000ef72bebc28d370..3365eac427f962180616221d4592e0bcdb0b854c 100644
--- a/dune/tectonic/body.hh
+++ b/dune/tectonic/body.hh
@@ -15,8 +15,8 @@ template <int dimension> struct Body {
   double virtual getShearViscosity() const = 0;
   double virtual getBulkViscosity() const = 0;
 
-  double virtual getDensity() const = 0;
-  double virtual getGravity() const = 0;
+  ScalarFunction virtual const &getDensityField() const = 0;
+  VectorField virtual const &getGravityField() const = 0;
 };
 
 #endif
diff --git a/dune/tectonic/gravity.hh b/dune/tectonic/gravity.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9af62f17d86248d6deeddec1f4b0eb7f3cf65afc
--- /dev/null
+++ b/dune/tectonic/gravity.hh
@@ -0,0 +1,34 @@
+#ifndef GRAVITY_HH
+#define GRAVITY_HH
+
+#include <dune/common/function.hh>
+#include <dune/common/fvector.hh>
+
+template <int dimension>
+class Gravity
+    : public Dune::VirtualFunction<Dune::FieldVector<double, dimension>,
+                                   Dune::FieldVector<double, dimension>> {
+public:
+  Gravity(
+      Dune::VirtualFunction<Dune::FieldVector<double, dimension>,
+                            Dune::FieldVector<double, 1>> const &_densityField,
+      Dune::FieldVector<double, dimension> const &_zenith, double _gravity)
+      : densityField(_densityField), zenith(_zenith), gravity(_gravity) {}
+
+  void evaluate(Dune::FieldVector<double, dimension> const &x,
+                Dune::FieldVector<double, dimension> &y) const {
+    y = zenith;
+
+    Dune::FieldVector<double, 1> density;
+    densityField.evaluate(x, density);
+
+    y *= -gravity * density;
+  }
+
+private:
+  Dune::VirtualFunction<Dune::FieldVector<double, dimension>,
+                        Dune::FieldVector<double, 1>> const &densityField;
+  Dune::FieldVector<double, dimension> const &zenith;
+  double const gravity;
+};
+#endif
diff --git a/src/assemblers.cc b/src/assemblers.cc
index 80f17a476497cdc9787d177df914a05b61e1d1df..83565cce966b7bfb67de5dcb6751bd2eef2edca8 100644
--- a/src/assemblers.cc
+++ b/src/assemblers.cc
@@ -6,11 +6,11 @@
 
 #include <dune/fufem/assemblers/localassemblers/boundarymassassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/l2functionalassembler.hh>
-#include <dune/fufem/assemblers/localassemblers/massassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/neumannboundaryassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/stvenantkirchhoffassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/viscosityassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/vonmisesstressassembler.hh>
+#include <dune/fufem/assemblers/localassemblers/weightedmassassembler.hh>
 #include <dune/fufem/boundarypatch.hh>
 #include <dune/fufem/functions/basisgridfunction.hh>
 #include <dune/fufem/functions/constantfunction.hh>
@@ -37,11 +37,18 @@ void MyAssembler<GridView, dimension>::assembleFrictionalBoundaryMass(
 }
 
 template <class GridView, int dimension>
-void MyAssembler<GridView, dimension>::assembleMass(double density, Matrix &M) {
-  MassAssembler<Grid, LocalVertexBasis, LocalVertexBasis,
-                Dune::ScaledIdentityMatrix<double, dimension>> const localMass;
-  vertexAssembler.assembleOperator(localMass, M);
-  M *= density;
+void MyAssembler<GridView, dimension>::assembleMass(
+    Dune::VirtualFunction<LocalVector, LocalScalarVector> const &
+        densityFunction,
+    Matrix &M) {
+  // NOTE: We treat the weight as a constant function
+  QuadratureRuleKey quadKey(dimension, 0);
+
+  WeightedMassAssembler<Grid, LocalVertexBasis, LocalVertexBasis,
+                        Dune::VirtualFunction<LocalVector, LocalScalarVector>,
+                        Dune::ScaledIdentityMatrix<double, dimension>>
+  localWeightedMass(gridView.grid(), densityFunction, quadKey);
+  vertexAssembler.assembleOperator(localWeightedMass, M);
 }
 
 template <class GridView, int dimension>
@@ -62,18 +69,11 @@ void MyAssembler<GridView, dimension>::assembleViscosity(double shearViscosity,
 }
 
 template <class GridView, int dimension>
-void MyAssembler<GridView, dimension>::assembleBodyForce(double gravity,
-                                                         double density,
-                                                         LocalVector zenith,
-                                                         Vector &f) {
-  LocalVector weightedGravitationalDirection = zenith;
-  weightedGravitationalDirection *= density * gravity;
-  weightedGravitationalDirection *= -1;
-
-  ConstantFunction<LocalVector, LocalVector> const gravityFunction(
-      weightedGravitationalDirection);
+void MyAssembler<GridView, dimension>::assembleBodyForce(
+    Dune::VirtualFunction<LocalVector, LocalVector> const &gravityField,
+    Vector &f) {
   L2FunctionalAssembler<Grid, LocalVertexBasis, LocalVector>
-  gravityFunctionalAssembler(gravityFunction);
+  gravityFunctionalAssembler(gravityField);
   vertexAssembler.assembleFunctional(gravityFunctionalAssembler, f);
 }
 
diff --git a/src/assemblers.hh b/src/assemblers.hh
index 0987f2a18625e04e8b83768084f8ba746047b443..a00681581382d72f95db4a5de6e45d6c0838600b 100644
--- a/src/assemblers.hh
+++ b/src/assemblers.hh
@@ -32,6 +32,7 @@ template <class GridView, int dimension> class MyAssembler {
 private:
   using Grid = typename GridView::Grid;
   using LocalVector = typename Vector::block_type;
+  using LocalScalarVector = typename ScalarVector::block_type;
 
   using LocalCellBasis = typename CellBasis::LocalFiniteElement;
   using LocalVertexBasis = typename VertexBasis::LocalFiniteElement;
@@ -47,15 +48,18 @@ template <class GridView, int dimension> class MyAssembler {
       BoundaryPatch<GridView> const &frictionalBoundary,
       ScalarMatrix &frictionalBoundaryMass);
 
-  void assembleMass(double density, Matrix &M);
+  void assembleMass(Dune::VirtualFunction<
+                        LocalVector, LocalScalarVector> const &densityFunction,
+                    Matrix &M);
 
   void assembleElasticity(double E, double nu, Matrix &A);
 
   void assembleViscosity(double shearViscosity, double bulkViscosity,
                          Matrix &C);
 
-  void assembleBodyForce(double gravity, double density, LocalVector zenith,
-                         Vector &f);
+  void assembleBodyForce(
+      Dune::VirtualFunction<LocalVector, LocalVector> const &gravityField,
+      Vector &f);
 
   void assembleNeumann(BoundaryPatch<GridView> const &neumannBoundary,
                        Vector &f,
diff --git a/src/mybody.hh b/src/mybody.hh
index 47d3d26c3d189b72320194f170d8041aaf126b25..ec735642edbca78cf2e0d63f02421c2f4131da77 100644
--- a/src/mybody.hh
+++ b/src/mybody.hh
@@ -3,7 +3,10 @@
 
 #include <dune/common/fvector.hh>
 
+#include <dune/fufem/functions/constantfunction.hh>
+
 #include <dune/tectonic/body.hh>
+#include <dune/tectonic/gravity.hh>
 
 #include "mygeometry.hh"
 
@@ -11,14 +14,18 @@ template <int dimension> class MyBody : public Body<dimension> {
   using typename Body<dimension>::ScalarFunction;
   using typename Body<dimension>::VectorField;
 
+  using MyConstantFunction = ConstantFunction<
+      Dune::FieldVector<double, dimension>, Dune::FieldVector<double, 1>>;
+
 public:
   MyBody(Dune::ParameterTree const &parset, MyGeometry const &mygeometry)
       : poissonRatio_(parset.get<double>("body.poissonRatio")),
         youngModulus_(parset.get<double>("body.youngModulus")),
         shearViscosity_(parset.get<double>("body.shearViscosity")),
         bulkViscosity_(parset.get<double>("body.bulkViscosity")),
-        density_(parset.get<double>("body.density")),
-        gravity_(parset.get<double>("gravity")) {}
+        densityField_(parset.get<double>("body.density")),
+        gravityField_(densityField_, mygeometry.zenith,
+                      parset.get<double>("gravity")) {}
 
   double getPoissonRatio() const override { return poissonRatio_; }
 
@@ -27,16 +34,18 @@ template <int dimension> class MyBody : public Body<dimension> {
   double getShearViscosity() const override { return shearViscosity_; }
   double getBulkViscosity() const override { return bulkViscosity_; }
 
-  double getDensity() const override { return density_; }
-  double getGravity() const override { return gravity_; }
+  ScalarFunction const &getDensityField() const override {
+    return densityField_;
+  }
+  VectorField const &getGravityField() const override { return gravityField_; }
 
 private:
   double const poissonRatio_;
   double const youngModulus_;
   double const shearViscosity_;
   double const bulkViscosity_;
-  double const density_;
-  double const gravity_;
+  MyConstantFunction const densityField_;
+  Gravity<dimension> const gravityField_;
 };
 
 #endif
diff --git a/src/one-body-sample.cc b/src/one-body-sample.cc
index 52b5573b1649f9c85d41027b8e4f93e23b998c7d..38659cfd41ca6f284911896470355b8a02c3182e 100644
--- a/src/one-body-sample.cc
+++ b/src/one-body-sample.cc
@@ -165,7 +165,7 @@ int main(int argc, char *argv[]) {
                                    body.getPoissonRatio(), A);
     myAssembler.assembleViscosity(body.getShearViscosity(),
                                   body.getBulkViscosity(), C);
-    myAssembler.assembleMass(body.getDensity(), M);
+    myAssembler.assembleMass(body.getDensityField(), M);
     EnergyNorm<Matrix, Vector> const ANorm(A), MNorm(M);
     // Q: Does it make sense to weigh them in this manner?
     SumNorm<Vector> const AMNorm(1.0, ANorm, 1.0, MNorm);
@@ -178,8 +178,7 @@ int main(int argc, char *argv[]) {
 
     // Assemble forces
     Vector gravityFunctional;
-    myAssembler.assembleBodyForce(body.getGravity(), body.getDensity(),
-                                  myGeometry.zenith, gravityFunctional);
+    myAssembler.assembleBodyForce(body.getGravityField(), gravityFunctional);
 
     // Problem formulation: right-hand side
     auto const computeExternalForces = [&](double _relativeTime, Vector &_ell) {
@@ -204,7 +203,8 @@ int main(int argc, char *argv[]) {
       // volume * gravity * density / area    = normal stress
       // V      * g       * rho     / A       = sigma_n
       // m^d    * N/kg    * kg/m^d  / m^(d-1) = N/m^(d-1)
-      normalStress = -volume * body.getGravity() * body.getDensity() / area;
+      normalStress = -volume * parset.get<double>("gravity") *
+                     parset.get<double>("body.density") / area;
     }
     FrictionData const frictionData(parset.sub("boundary.friction"),
                                     normalStress);