diff --git a/lbmpy_tests/shan_chen/test_shan_chen_two_component.py b/lbmpy_tests/shan_chen/test_shan_chen_two_component.py
new file mode 100644
index 0000000000000000000000000000000000000000..999799e283a572ba1062886dcea489885c582b21
--- /dev/null
+++ b/lbmpy_tests/shan_chen/test_shan_chen_two_component.py
@@ -0,0 +1,179 @@
+"""
+Test Shan-Chen two-component implementation against reference implementation
+"""
+
+import lbmpy
+
+import pystencils as ps
+import sympy as sp
+import numpy as np
+
+
+def test_shan_chen_two_component():
+    from lbmpy.enums import Stencil
+    from lbmpy import LBMConfig, ForceModel, create_lb_update_rule
+    from lbmpy.macroscopic_value_kernels import macroscopic_values_setter
+    from lbmpy.creationfunctions import create_stream_pull_with_output_kernel
+    from lbmpy.maxwellian_equilibrium import get_weights
+
+    N = 64
+    omega_a = 1.
+    omega_b = 1.
+
+    # interaction strength
+    g_aa = 0.
+    g_ab = g_ba = 6.
+    g_bb = 0.
+
+    rho0 = 1.
+
+    stencil = lbmpy.LBStencil(Stencil.D2Q9)
+    weights = get_weights(stencil, c_s_sq=sp.Rational(1, 3))
+
+    dim = stencil.D
+    dh = ps.create_data_handling((N, ) * dim, periodicity=True, default_target=ps.Target.CPU)
+
+    src_a = dh.add_array('src_a', values_per_cell=stencil.Q)
+    dst_a = dh.add_array_like('dst_a', 'src_a')
+
+    src_b = dh.add_array('src_b', values_per_cell=stencil.Q)
+    dst_b = dh.add_array_like('dst_b', 'src_b')
+
+    ρ_a = dh.add_array('rho_a')
+    ρ_b = dh.add_array('rho_b')
+    u_a = dh.add_array('u_a', values_per_cell=stencil.D)
+    u_b = dh.add_array('u_b', values_per_cell=stencil.D)
+    u_bary = dh.add_array_like('u_bary', u_a.name)
+
+    f_a = dh.add_array('f_a', values_per_cell=stencil.D)
+    f_b = dh.add_array_like('f_b', f_a.name)
+
+    def psi(dens):
+        return rho0 * (1. - sp.exp(-dens / rho0))
+
+    zero_vec = sp.Matrix([0] * stencil.D)
+
+    force_a = zero_vec
+    for factor, ρ in zip([g_aa, g_ab], [ρ_a, ρ_b]):
+        force_a += sum((psi(ρ[d]) * w_d * sp.Matrix(d)
+                        for d, w_d in zip(stencil, weights)),
+                       zero_vec) * psi(ρ_a.center) * -1 * factor
+
+    force_b = zero_vec
+    for factor, ρ in zip([g_ba, g_bb], [ρ_a, ρ_b]):
+        force_b += sum((psi(ρ[d]) * w_d * sp.Matrix(d)
+                        for d, w_d in zip(stencil, weights)),
+                       zero_vec) * psi(ρ_b.center) * -1 * factor
+
+    f_expressions = ps.AssignmentCollection([
+        ps.Assignment(f_a.center_vector, force_a),
+        ps.Assignment(f_b.center_vector, force_b)
+    ])
+
+    # calculate the velocity without force correction
+    u_temp = ps.Assignment(u_bary.center_vector,
+                           (ρ_a.center * u_a.center_vector
+                            - f_a.center_vector / 2 + ρ_b.center * u_b.center_vector
+                            - f_b.center_vector / 2) / (ρ_a.center + ρ_b.center))
+
+    # add the force correction to the velocity
+    u_corr = ps.Assignment(u_bary.center_vector,
+                           u_bary.center_vector
+                           + (f_a.center_vector / 2 + f_b.center_vector / 2) / (ρ_a.center + ρ_b.center))
+
+    lbm_config_a = LBMConfig(stencil=stencil, relaxation_rate=omega_a, compressible=True,
+                             velocity_input=u_bary, density_input=ρ_a, force_model=ForceModel.GUO,
+                             force=f_a, kernel_type='collide_only')
+
+    lbm_config_b = LBMConfig(stencil=stencil, relaxation_rate=omega_b, compressible=True,
+                             velocity_input=u_bary, density_input=ρ_b, force_model=ForceModel.GUO,
+                             force=f_b, kernel_type='collide_only')
+
+    collision_a = create_lb_update_rule(lbm_config=lbm_config_a,
+                                        optimization={'symbolic_field': src_a})
+
+    collision_b = create_lb_update_rule(lbm_config=lbm_config_b,
+                                        optimization={'symbolic_field': src_b})
+
+    stream_a = create_stream_pull_with_output_kernel(collision_a.method, src_a, dst_a,
+                                                     {'density': ρ_a, 'velocity': u_a})
+    stream_b = create_stream_pull_with_output_kernel(collision_b.method, src_b, dst_b,
+                                                     {'density': ρ_b, 'velocity': u_b})
+
+    config = ps.CreateKernelConfig(target=dh.default_target)
+
+    stream_a_kernel = ps.create_kernel(stream_a, config=config).compile()
+    stream_b_kernel = ps.create_kernel(stream_b, config=config).compile()
+    collision_a_kernel = ps.create_kernel(collision_a, config=config).compile()
+    collision_b_kernel = ps.create_kernel(collision_b, config=config).compile()
+
+    force_kernel = ps.create_kernel(f_expressions, config=config).compile()
+    u_temp_kernel = ps.create_kernel(u_temp, config=config).compile()
+    u_corr_kernel = ps.create_kernel(u_corr, config=config).compile()
+
+    init_a = macroscopic_values_setter(collision_a.method, velocity=(0, 0),
+                                       pdfs=src_a.center_vector, density=ρ_a.center)
+    init_b = macroscopic_values_setter(collision_b.method, velocity=(0, 0),
+                                       pdfs=src_b.center_vector, density=ρ_b.center)
+    init_a_kernel = ps.create_kernel(init_a, ghost_layers=0).compile()
+    init_b_kernel = ps.create_kernel(init_b, ghost_layers=0).compile()
+
+    sync_pdfs = dh.synchronization_function([src_a.name, src_b.name])
+    sync_ρs = dh.synchronization_function([ρ_a.name, ρ_b.name])
+
+    dh.fill(ρ_a.name, 0.1, slice_obj=ps.make_slice[:, :0.5])
+    dh.fill(ρ_a.name, 0.9, slice_obj=ps.make_slice[:, 0.5:])
+
+    dh.fill(ρ_b.name, 0.9, slice_obj=ps.make_slice[:, :0.5])
+    dh.fill(ρ_b.name, 0.1, slice_obj=ps.make_slice[:, 0.5:])
+
+    dh.run_kernel(init_a_kernel)
+    dh.run_kernel(init_b_kernel)
+
+    dh.fill(u_a.name, 0.0)
+    dh.fill(u_b.name, 0.0)
+    dh.run_kernel(u_temp_kernel)
+
+    dh.fill(f_a.name, 0.0)
+    dh.fill(f_b.name, 0.0)
+
+    dh.run_kernel(init_a_kernel)
+    dh.run_kernel(init_b_kernel)
+
+    for i in range(1000):
+        sync_ρs()
+        dh.run_kernel(force_kernel)
+        dh.run_kernel(u_corr_kernel)
+        dh.run_kernel(collision_a_kernel)
+        dh.run_kernel(collision_b_kernel)
+
+        sync_pdfs()
+        dh.run_kernel(stream_a_kernel)
+        dh.run_kernel(stream_b_kernel)
+        dh.run_kernel(u_temp_kernel)
+
+        dh.swap(src_a.name, dst_a.name)
+        dh.swap(src_b.name, dst_b.name)
+    
+    # reference generated with https://github.com/lbm-principles-practice/code/blob/master/chapter9/shanchen.cpp using the parameters
+    # const int nsteps = 1000;
+    # const int noutput = 1000;
+    # const int nfluids = 2;
+    # const double gA = 0;
+
+    ref_a = np.array([0.213948, 0.0816724, 0.0516763, 0.0470179, 0.0480882, 0.0504771, 0.0531983, 0.0560094, 0.0588071,
+                      0.0615311, 0.064102, 0.0664467, 0.0684708, 0.070091, 0.0712222, 0.0718055, 0.0718055, 0.0712222,
+                      0.070091, 0.0684708, 0.0664467, 0.064102, 0.0615311, 0.0588071, 0.0560094, 0.0531983, 0.0504771,
+                      0.0480882, 0.0470179, 0.0516763, 0.0816724, 0.213948, 0.517153, 0.833334, 0.982884, 1.0151,
+                      1.01361, 1.0043, 0.993178, 0.981793, 0.970546, 0.959798, 0.949751, 0.940746, 0.933035, 0.926947,
+                      0.922713, 0.920548, 0.920548, 0.922713, 0.926947, 0.933035, 0.940746, 0.949751, 0.959798,
+                      0.970546, 0.981793, 0.993178, 1.0043, 1.01361, 1.0151, 0.982884, 0.833334, 0.517153])
+    ref_b = np.array([0.517153, 0.833334, 0.982884, 1.0151, 1.01361, 1.0043, 0.993178, 0.981793, 0.970546, 0.959798,
+                      0.949751, 0.940746, 0.933035, 0.926947, 0.922713, 0.920548, 0.920548, 0.922713, 0.926947,
+                      0.933035, 0.940746, 0.949751, 0.959798, 0.970546, 0.981793, 0.993178, 1.0043, 1.01361, 1.0151,
+                      0.982884, 0.833334, 0.517153, 0.213948, 0.0816724, 0.0516763, 0.0470179, 0.0480882, 0.0504771,
+                      0.0531983, 0.0560094, 0.0588071, 0.0615311, 0.064102, 0.0664467, 0.0684708, 0.070091, 0.0712222,
+                      0.0718055, 0.0718055, 0.0712222, 0.070091, 0.0684708, 0.0664467, 0.064102, 0.0615311, 0.0588071,
+                      0.0560094, 0.0531983, 0.0504771, 0.0480882, 0.0470179, 0.0516763, 0.0816724, 0.213948])
+    assert np.allclose(dh.gather_array(ρ_a.name)[0], ref_a)
+    assert np.allclose(dh.gather_array(ρ_b.name)[0], ref_b)