diff --git a/src/scheme/FluxingAdvectionSolver.cpp b/src/scheme/FluxingAdvectionSolver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d76c13bad1ef91f1e2e60b19ddea09d565be05ac
--- /dev/null
+++ b/src/scheme/FluxingAdvectionSolver.cpp
@@ -0,0 +1,133 @@
+#include <scheme/FluxingAdvectionSolver.hpp>
+
+#include <language/utils/EvaluateAtPoints.hpp>
+#include <mesh/Connectivity.hpp>
+#include <mesh/IMesh.hpp>
+#include <mesh/Mesh.hpp>
+#include <scheme/DiscreteFunctionP0.hpp>
+#include <scheme/DiscreteFunctionUtils.hpp>
+#include <scheme/IDiscreteFunctionDescriptor.hpp>
+
+template <size_t Dimension>
+class FluxingAdvectionSolver
+{
+ private:
+  using Rd = TinyVector<Dimension>;
+
+  using MeshType = Mesh<Connectivity<Dimension>>;
+
+  using DiscreteScalarFunction = DiscreteFunctionP0<Dimension, double>;
+
+  const MeshType& m_old_mesh;
+  const std::shared_ptr<const MeshType> m_new_mesh;
+  const DiscreteFunctionP0<Dimension, const double> m_old_q;
+
+ public:
+  // CellValue<double>
+  // compute_PFnp1(const DiscreteFunctionP0<Dimension, const double> F, const double& dt, const double& dx)
+  // {
+  //   CellValue<double> PFnp1{m_mesh.connectivity()};
+
+  //   DiscreteFunctionP0<Dimension, double> deltaF  = compute_delta2Fn(F);
+  //   DiscreteFunctionP0<Dimension, double> deltaF0 = compute_delta2Fn(m_Fn);
+
+  //   for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
+  //     PFnp1[cell_id] = m_Fn[cell_id][0] + m_Fn[cell_id][1] -
+  //                      (0.5 * dt / dx) * m_lambda * (deltaF[cell_id][0] - deltaF[cell_id][1]) -
+  //                      (0.5 * dt / dx) * m_lambda * (deltaF0[cell_id][0] - deltaF0[cell_id][1]);
+  //   }
+  //   return PFnp1;
+  // }
+
+  // DiscreteFunctionP0<Dimension, double>
+  // apply(const double& dt, const double& eps)
+  // {
+  //   const DiscreteFunctionP0<Dimension, const double>& F0 = m_Fn;
+  //   DiscreteFunctionP0<Dimension, double> Fnp1            = copy(F0);
+  //   DiscreteFunctionP0<Dimension, double> deltaFn         = compute_delta2Fn(F0);
+
+  //   for (size_t p = 0; p < 2; ++p) {
+  //     CellId first_cell_id = 0;
+  //     const double dx      = m_dx_table[first_cell_id];
+
+  //     DiscreteFunctionP0<Dimension, double> deltaFnp1 = compute_delta2Fn(Fnp1);
+
+  //     const CellValue<const double> PFnp1  = compute_PFnp1(Fnp1, dt, dx);
+  //     const CellValue<const double> APFnp1 = getA(PFnp1);
+  //     const CellArray<const double> MPFnp1 = compute_M(PFnp1, APFnp1);
+  //     const CellValue<const double> PFn    = compute_PFn(F0);
+  //     const CellValue<const double> APFn   = getA(PFn);
+  //     const CellArray<const double> MPFn   = compute_M(PFn, APFn);
+
+  //     for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
+  //       Fnp1[cell_id][0] = 1. / (1 + 0.5 * dt / eps) *
+  //                          ((0.5 * dt / eps) * MPFnp1[cell_id][0] + F0[cell_id][0] -
+  //                           (0.5 * dt / dx) * m_lambda * (deltaFnp1[cell_id][0] + deltaFn[cell_id][0]) +
+  //                           (0.5 * dt / eps) * (MPFn[cell_id][0] - F0[cell_id][0]));
+  //       Fnp1[cell_id][1] = 1. / (1 + 0.5 * dt / eps) *
+  //                          ((0.5 * dt / eps) * MPFnp1[cell_id][1] + F0[cell_id][1] +
+  //                           (0.5 * dt / dx) * m_lambda * (deltaFnp1[cell_id][1] + deltaFn[cell_id][1]) +
+  //                           (0.5 * dt / eps) * (MPFn[cell_id][1] - F0[cell_id][1]));
+  //     }
+  //   }
+
+  //   return Fnp1;
+  // }
+
+  DiscreteFunctionP0<Dimension, double>
+  apply()
+  {
+    //    std::shared_ptr<const MeshType> mesh =
+    //  std::make_shared<MeshType>(m_new_mesh.shared_connectivity(), m_new_mesh.xr());
+    DiscreteFunctionP0<Dimension, double> new_q(m_new_mesh);
+    if (m_new_mesh->shared_connectivity() != m_old_mesh.shared_connectivity()) {
+      throw NormalError("Old and new meshes must share the same connectivity");
+    }
+    return new_q;
+  }
+
+  FluxingAdvectionSolver(const std::shared_ptr<const MeshType> old_mesh,
+                         const std::shared_ptr<const MeshType> new_mesh,
+                         const DiscreteFunctionP0<Dimension, const double>& old_q)
+    : m_old_mesh{*old_mesh}, m_new_mesh{new_mesh}, m_old_q{old_q}
+  {}
+
+  ~FluxingAdvectionSolver() = default;
+};
+
+std::shared_ptr<const IDiscreteFunction>
+FluxingAdvectionSolverHandler(const std::shared_ptr<const IMesh> new_mesh,
+                              const std::shared_ptr<const IDiscreteFunction>& old_q)
+{
+  const std::shared_ptr<const IMesh> old_mesh = getCommonMesh({old_q});
+  if (old_q->descriptor().type() != DiscreteFunctionType::P0) {
+    throw NormalError("Invalid discrete function type. Expecting P0.");
+  }
+
+  switch (old_mesh->dimension()) {
+  case 1: {
+    constexpr size_t Dimension = 1;
+    using MeshType             = Mesh<Connectivity<Dimension>>;
+
+    const std::shared_ptr<const MeshType> old_mesh0 = std::dynamic_pointer_cast<const MeshType>(old_mesh);
+
+    const DiscreteFunctionP0<Dimension, double>& old_q0 =
+      dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*old_q);
+
+    const std::shared_ptr<const MeshType> new_mesh0 = std::dynamic_pointer_cast<const MeshType>(new_mesh);
+
+    FluxingAdvectionSolver<Dimension> solver(old_mesh0, new_mesh0, old_q0);
+
+    return std::make_shared<const DiscreteFunctionP0<Dimension, double>>(solver.apply());
+  }
+  case 2: {
+    throw NotImplementedError("Fluxing advection solver not implemented in dimension 2");
+  }
+  case 3: {
+    throw NotImplementedError("Fluxing advection solver not implemented in dimension 3");
+  }
+  default: {
+    throw UnexpectedError("Invalid mesh dimension");
+  }
+  }
+}
diff --git a/src/scheme/FluxingAdvectionSolver.hpp b/src/scheme/FluxingAdvectionSolver.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..762c5a691ef08de75fd15fcdae38ca5003367165
--- /dev/null
+++ b/src/scheme/FluxingAdvectionSolver.hpp
@@ -0,0 +1,11 @@
+#ifndef FLUXING_ADVECION_SOLVER_HPP
+#define FLUXING_ADVECION_SOLVER_HPP
+
+#include <language/utils/FunctionSymbolId.hpp>
+#include <scheme/IDiscreteFunction.hpp>
+
+std::shared_ptr<const IDiscreteFunction> FluxingAdvectionSolverHandler(
+  const std::shared_ptr<const IMesh> new_mesh,
+  const std::shared_ptr<const IDiscreteFunction>& old_q);
+
+#endif   // FLUXING_ADVECION_SOLVER_HPP