diff --git a/opm/models/discretization/common/nullfvbaseelementcontext.hh b/opm/models/discretization/common/nullfvbaseelementcontext.hh
new file mode 100644
index 00000000000..5effc3ddcf7
--- /dev/null
+++ b/opm/models/discretization/common/nullfvbaseelementcontext.hh
@@ -0,0 +1,312 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*
+
+ Copyright 2026 Equinor ASA
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ OPM 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OPM. If not, see .
+
+ Consult the COPYING file in the top-level source directory of this
+ module for the precise wording of the license and the list of
+ copyright holders.
+*/
+/*!
+ * \file
+ *
+ * \brief GPU-compatible stub of FvBaseElementContext.
+ *
+ * All methods are annotated with OPM_HOST_DEVICE and return dummy/default
+ * values. This class is intended as a placeholder so that GPU kernels that
+ * receive an element context can compile; it does not implement any real
+ * behaviour.
+ *
+ * The heavy Dune/grid infrastructure present in FvBaseElementContext is
+ * intentionally absent here because those types are not usable inside a
+ * CUDA/HIP kernel.
+ */
+#ifndef OPM_FV_BASE_ELEMENT_CONTEXT_GPU_HH
+#define OPM_FV_BASE_ELEMENT_CONTEXT_GPU_HH
+
+#include
+#include
+#include
+
+#include
+
+namespace Opm
+{
+
+/*!
+ * \ingroup FiniteVolumeDiscretizations
+ *
+ * \brief GPU-compatible stub mirroring the public interface of FvBaseElementContext.
+ *
+ * Uses the same TypeTag-based template parameter as FvBaseElementContext; all
+ * concrete types are extracted via GetPropType at compile time.
+ *
+ * \tparam TypeTag The type tag from which Scalar, PrimaryVariables, etc. are derived.
+ */
+template
+class NullFvBaseElementContext
+{
+public:
+ using Scalar = GetPropType;
+ using PrimaryVariables = GetPropType;
+ using IntensiveQuantities = GetPropType;
+ using ExtensiveQuantities = GetPropType;
+ using Problem = GetPropType;
+ using Model = GetPropType;
+ using GradientCalculator = GetPropType;
+
+ // -----------------------------------------------------------------------
+ // Construction / assignment
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE NullFvBaseElementContext() = default;
+ OPM_HOST_DEVICE ~NullFvBaseElementContext() = default;
+ OPM_HOST_DEVICE NullFvBaseElementContext(const NullFvBaseElementContext&) = default;
+ OPM_HOST_DEVICE NullFvBaseElementContext(NullFvBaseElementContext&&) noexcept = default;
+ OPM_HOST_DEVICE NullFvBaseElementContext& operator=(const NullFvBaseElementContext&) = default;
+ OPM_HOST_DEVICE NullFvBaseElementContext& operator=(NullFvBaseElementContext&&) noexcept
+ = default;
+
+ // -----------------------------------------------------------------------
+ // Stencil / element update stubs
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE void updateAll()
+ {
+ }
+ OPM_HOST_DEVICE void updateStencil()
+ {
+ }
+ OPM_HOST_DEVICE void updatePrimaryStencil()
+ {
+ }
+ OPM_HOST_DEVICE void updateStencilTopology()
+ {
+ }
+ OPM_HOST_DEVICE void updateAllIntensiveQuantities()
+ {
+ }
+ OPM_HOST_DEVICE void updateIntensiveQuantities(unsigned /*timeIdx*/)
+ {
+ }
+ OPM_HOST_DEVICE void updatePrimaryIntensiveQuantities(unsigned /*timeIdx*/)
+ {
+ }
+ OPM_HOST_DEVICE void updateIntensiveQuantities(const PrimaryVariables& /*priVars*/,
+ unsigned /*dofIdx*/,
+ unsigned /*timeIdx*/)
+ {
+ }
+ OPM_HOST_DEVICE void updateAllExtensiveQuantities()
+ {
+ }
+ OPM_HOST_DEVICE void updateExtensiveQuantities(unsigned /*timeIdx*/)
+ {
+ }
+
+ // -----------------------------------------------------------------------
+ // Focus DOF
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE void setFocusDofIndex(unsigned dofIdx)
+ {
+ focusDofIdx_ = static_cast(dofIdx);
+ }
+ OPM_HOST_DEVICE unsigned focusDofIndex() const
+ {
+ return focusDofIdx_;
+ }
+
+ // -----------------------------------------------------------------------
+ // Linearization type
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE LinearizationType linearizationType() const
+ {
+ return LinearizationType {};
+ }
+
+ // -----------------------------------------------------------------------
+ // Problem / model accessors — return references to dummy stored objects
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE const Problem& problem() const
+ {
+ return problem_;
+ }
+ OPM_HOST_DEVICE const Model& model() const
+ {
+ return model_;
+ }
+
+ // -----------------------------------------------------------------------
+ // DOF / face counts
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE std::size_t numDof(unsigned /*timeIdx*/) const
+ {
+ return 0;
+ }
+ OPM_HOST_DEVICE std::size_t numPrimaryDof(unsigned /*timeIdx*/) const
+ {
+ return 0;
+ }
+ OPM_HOST_DEVICE std::size_t numInteriorFaces(unsigned /*timeIdx*/) const
+ {
+ return 0;
+ }
+ OPM_HOST_DEVICE std::size_t numBoundaryFaces(unsigned /*timeIdx*/) const
+ {
+ return 0;
+ }
+
+ // -----------------------------------------------------------------------
+ // Global space index / volume
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE unsigned globalSpaceIndex(unsigned /*dofIdx*/, unsigned /*timeIdx*/) const
+ {
+ return 0;
+ }
+
+ OPM_HOST_DEVICE Scalar dofVolume(unsigned /*dofIdx*/, unsigned /*timeIdx*/) const
+ {
+ return Scalar {0};
+ }
+
+ OPM_HOST_DEVICE Scalar dofTotalVolume(unsigned /*dofIdx*/, unsigned /*timeIdx*/) const
+ {
+ return Scalar {0};
+ }
+
+ // -----------------------------------------------------------------------
+ // Boundary
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE bool onBoundary() const
+ {
+ return false;
+ }
+
+ // -----------------------------------------------------------------------
+ // Intensive quantities
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE const IntensiveQuantities& intensiveQuantities(unsigned /*dofIdx*/,
+ unsigned /*timeIdx*/) const
+ {
+ return intensiveQuantitiesStashed_;
+ }
+
+ OPM_HOST_DEVICE IntensiveQuantities& intensiveQuantities(unsigned /*dofIdx*/,
+ unsigned /*timeIdx*/)
+ {
+ return intensiveQuantitiesStashed_;
+ }
+
+ OPM_HOST_DEVICE const IntensiveQuantities* thermodynamicHint(unsigned /*dofIdx*/,
+ unsigned /*timeIdx*/) const
+ {
+ return nullptr;
+ }
+
+ // -----------------------------------------------------------------------
+ // Primary variables
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE const PrimaryVariables& primaryVars(unsigned /*dofIdx*/,
+ unsigned /*timeIdx*/) const
+ {
+ return priVarsStashed_;
+ }
+
+ // -----------------------------------------------------------------------
+ // Stash / restore
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE bool haveStashedIntensiveQuantities() const
+ {
+ return stashedDofIdx_ != -1;
+ }
+
+ OPM_HOST_DEVICE int stashedDofIdx() const
+ {
+ return stashedDofIdx_;
+ }
+
+ OPM_HOST_DEVICE void stashIntensiveQuantities(unsigned dofIdx)
+ {
+ stashedDofIdx_ = static_cast(dofIdx);
+ }
+
+ OPM_HOST_DEVICE void restoreIntensiveQuantities(unsigned /*dofIdx*/)
+ {
+ stashedDofIdx_ = -1;
+ }
+
+ // -----------------------------------------------------------------------
+ // Gradient calculator
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE const GradientCalculator& gradientCalculator() const
+ {
+ return gradientCalculator_;
+ }
+
+ // -----------------------------------------------------------------------
+ // Extensive quantities
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE const ExtensiveQuantities& extensiveQuantities(unsigned /*fluxIdx*/,
+ unsigned /*timeIdx*/) const
+ {
+ return extensiveQuantitiesStashed_;
+ }
+
+ // -----------------------------------------------------------------------
+ // Storage cache flag
+ // -----------------------------------------------------------------------
+
+ OPM_HOST_DEVICE bool enableStorageCache() const
+ {
+ return enableStorageCache_;
+ }
+ OPM_HOST_DEVICE void setEnableStorageCache(bool yesno)
+ {
+ enableStorageCache_ = yesno;
+ }
+
+private:
+ // Dummy stored objects returned by reference accessors.
+ // On device these are default-constructed and carry no meaningful data.
+ Problem problem_ {};
+ Model model_ {};
+ GradientCalculator gradientCalculator_ {};
+ IntensiveQuantities intensiveQuantitiesStashed_ {};
+ ExtensiveQuantities extensiveQuantitiesStashed_ {};
+ PrimaryVariables priVarsStashed_ {};
+
+ int stashedDofIdx_ {-1};
+ int focusDofIdx_ {-1};
+ bool enableStorageCache_ {false};
+};
+
+} // namespace Opm
+
+#endif // OPM_FV_BASE_ELEMENT_CONTEXT_GPU_HH