diff --git a/Environment/VolumeTreeNode.h b/Environment/VolumeTreeNode.h
index 3331c41bf5e060bb904f5a78f78485af0440d04b..093708a61fc8b376b92920b3e4bfb9fc94f11cf1 100644
--- a/Environment/VolumeTreeNode.h
+++ b/Environment/VolumeTreeNode.h
@@ -66,6 +66,24 @@ namespace corsika::environment {
       }
     }
 
+    /**
+     * Traverses the VolumeTree pre- or post-order and calls the functor  \p func for each
+     * node. \p func takes a reference to VolumeTreeNode as argument. The return value \p
+     * func is ignored.
+     */
+    template <typename TCallable, bool preorder = true>
+    void walk(TCallable func) {
+      if constexpr (preorder) {
+        func(*this);
+        std::for_each(fChildNodes.begin(), fChildNodes.end(),
+                      [&](auto& v) { v->walk(func); });
+      } else {
+        std::for_each(fChildNodes.begin(), fChildNodes.end(),
+                      [&](auto& v) { v->walk(func); });
+        t(*this);
+      }
+    }
+
     void AddChild(VTNUPtr pChild) {
       pChild->fParentNode = this;
       fChildNodes.push_back(std::move(pChild));
@@ -88,6 +106,8 @@ namespace corsika::environment {
 
     auto const& GetModelProperties() const { return *fModelProperties; }
 
+    IMPSharedPtr GetModelPropertiesPtr() const { return fModelProperties; }
+
     template <typename TModelProperties, typename... Args>
     auto SetModelProperties(Args&&... args) {
       static_assert(std::is_base_of_v<IModelProperties, TModelProperties>,