diff --git a/generate_all_operators.py b/generate_all_operators.py
index 50a66bcd0e613cad016ff67423ef3ebfba7e3e31..6ce4a12dcab8ddddd60fb2e05107591d8415a84a 100644
--- a/generate_all_operators.py
+++ b/generate_all_operators.py
@@ -49,6 +49,8 @@ from hog.forms import (
     nonlinear_diffusion,
     nonlinear_diffusion_newton_galerkin,
     supg_diffusion,
+    advection,
+    supg_advection,
     grad_rho_by_rho_dot_u,
 )
 from hog.forms_boundary import (
@@ -628,6 +630,18 @@ def all_operators(
     ops.append(OperatorInfo("P2", "SUPGDiffusion", TrialSpace(P2), TestSpace(P2), 
                             form=partial(supg_diffusion, velocity_function_space=P2, diffusivityXdelta_function_space=P2), 
                             type_descriptor=type_descriptor, geometries=list(geometries), opts=opts, blending=blending))
+    
+    ops.append(OperatorInfo("P2", "AdvectionConstCp", TrialSpace(P2), TestSpace(P2), 
+                            form=partial(advection, velocity_function_space=P2, coefficient_function_space=P2, constant_cp = True), 
+                            type_descriptor=type_descriptor, geometries=list(geometries), opts=opts, blending=blending))
+
+    ops.append(OperatorInfo("P2", "AdvectionVarCp", TrialSpace(P2), TestSpace(P2), 
+                            form=partial(advection, velocity_function_space=P2, coefficient_function_space=P2), 
+                            type_descriptor=type_descriptor, geometries=list(geometries), opts=opts, blending=blending))
+    
+    ops.append(OperatorInfo("P2", "SUPGAdvection", TrialSpace(P2), TestSpace(P2), 
+                            form=partial(supg_advection, velocity_function_space=P2, coefficient_function_space=P2), 
+                            type_descriptor=type_descriptor, geometries=list(geometries), opts=opts, blending=blending))
 
     ops.append(OperatorInfo("P2", "BoundaryMass", TrialSpace(P2), TestSpace(P2), form=None,
                             form_boundary=mass_boundary, type_descriptor=type_descriptor, geometries=list(geometries),
diff --git a/hog/forms.py b/hog/forms.py
index b3f87b4d9d92f2f43a7797b67904bd7339af486c..774752bb4c99066c8a46b8157c2bb01c7bc11209 100644
--- a/hog/forms.py
+++ b/hog/forms.py
@@ -812,6 +812,97 @@ Weak formulation
     )
 
 
+def advection(
+    trial: TrialSpace,
+    test: TestSpace,
+    geometry: ElementGeometry,
+    symbolizer: Symbolizer,
+    velocity_function_space: FunctionSpace,
+    coefficient_function_space: FunctionSpace,
+    constant_cp: bool = False,
+    blending: GeometryMap = IdentityMap(),
+) -> Form:
+    docstring = f"""
+advection operator which needs to be used in combination with SUPG
+
+Geometry map:    {blending}
+
+Weak formulation
+
+    T: trial function (scalar space: {trial})
+    s: test function  (scalar space: {test})
+    u: velocity function (vectorial space: {velocity_function_space})
+
+    ∫ cp ( u · ∇T ) s
+"""
+
+    from hog.recipes.integrands.volume.advection import integrand
+
+    return process_integrand(
+        integrand,
+        trial,
+        test,
+        geometry,
+        symbolizer,
+        blending=blending,
+        is_symmetric=False,
+        docstring=docstring,
+        fe_coefficients={
+            "ux": velocity_function_space,
+            "uy": velocity_function_space,
+            "uz": velocity_function_space,
+        } if constant_cp else {
+            "ux": velocity_function_space,
+            "uy": velocity_function_space,
+            "uz": velocity_function_space,
+            "cp": coefficient_function_space,
+        },
+    )
+
+
+def supg_advection(
+    trial: TrialSpace,
+    test: TestSpace,
+    geometry: ElementGeometry,
+    symbolizer: Symbolizer,
+    velocity_function_space: FunctionSpace,
+    coefficient_function_space: FunctionSpace,
+    blending: GeometryMap = IdentityMap(),
+) -> Form:
+    docstring = f"""
+advection operator which needs to be used in combination with SUPG
+
+Geometry map:    {blending}
+
+Weak formulation
+
+    T: trial function (scalar space: {trial})
+    s: test function  (scalar space: {test})
+    u: velocity function (vectorial space: {velocity_function_space})
+
+    ∫ cp ( u · ∇T ) 𝛿(u · ∇s)
+"""
+
+    from hog.recipes.integrands.volume.supg_advection import integrand
+
+    return process_integrand(
+        integrand,
+        trial,
+        test,
+        geometry,
+        symbolizer,
+        blending=blending,
+        is_symmetric=False,
+        docstring=docstring,
+        fe_coefficients={
+            "ux": velocity_function_space,
+            "uy": velocity_function_space,
+            "uz": velocity_function_space,
+            "cp_times_delta": coefficient_function_space,
+        },
+    )
+
+
 def supg_diffusion(
     trial: TrialSpace,
     test: TestSpace,
diff --git a/hog/recipes/integrands/volume/advection.py b/hog/recipes/integrands/volume/advection.py
new file mode 100644
index 0000000000000000000000000000000000000000..5bdaeacf294a68dd6795471a625b78235811375e
--- /dev/null
+++ b/hog/recipes/integrands/volume/advection.py
@@ -0,0 +1,51 @@
+# HyTeG Operator Generator
+# Copyright (C) 2024  HyTeG Team
+#
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from hog.recipes.common import *
+
+
+def integrand(
+    *,
+    v,
+    jac_a_inv,
+    jac_a_abs_det,
+    jac_b_inv,
+    jac_b_abs_det,
+    grad_u,
+    grad_v,
+    k,
+    scalars,
+    volume_geometry,
+    tabulate,
+    **_,
+):
+    if volume_geometry.dimensions > 2:
+        u = sp.Matrix([[k["ux"]], [k["uy"]], [k["uz"]]])
+    else:
+        u = sp.Matrix([[k["ux"]], [k["uy"]]])
+
+    if "cp" in k.keys():
+        coeff = k["cp"]
+    else:
+        coeff = scalars("cp")
+
+    return (
+        coeff
+        * dot(jac_b_inv.T * tabulate(jac_a_inv.T * grad_u), u)
+        * v
+        * tabulate(jac_a_abs_det)
+        * jac_b_abs_det
+    )
diff --git a/hog/recipes/integrands/volume/supg_advection.py b/hog/recipes/integrands/volume/supg_advection.py
new file mode 100644
index 0000000000000000000000000000000000000000..560bf45b97216dafd68e49679f6e9fdffd3955ee
--- /dev/null
+++ b/hog/recipes/integrands/volume/supg_advection.py
@@ -0,0 +1,45 @@
+# HyTeG Operator Generator
+# Copyright (C) 2024  HyTeG Team
+#
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from hog.recipes.common import *
+
+
+def integrand(
+    *,
+    v,
+    jac_a_inv,
+    jac_a_abs_det,
+    jac_b_inv,
+    jac_b_abs_det,
+    grad_u,
+    grad_v,
+    k,
+    volume_geometry,
+    tabulate,
+    **_,
+):
+    if volume_geometry.dimensions > 2:
+        u = sp.Matrix([[k["ux"]], [k["uy"]], [k["uz"]]])
+    else:
+        u = sp.Matrix([[k["ux"]], [k["uy"]]])
+
+    return (
+        k["cp_times_delta"]
+        * dot(jac_b_inv.T * tabulate(jac_a_inv.T * grad_u), u)
+        * dot(jac_b_inv.T * tabulate(jac_a_inv.T * grad_v), u)
+        * tabulate(jac_a_abs_det)
+        * jac_b_abs_det
+    )