diff --git a/ProcessLib/ComponentTransport/ComponentTransportFEM.h b/ProcessLib/ComponentTransport/ComponentTransportFEM.h
index eca4a81f9eb7a3ece16d28bb6d938324136ea973..77bfe3850e45d8433148c541023be641a4ed222d 100644
--- a/ProcessLib/ComponentTransport/ComponentTransportFEM.h
+++ b/ProcessLib/ComponentTransport/ComponentTransportFEM.h
@@ -62,9 +62,21 @@ template <typename ShapeFunction, typename IntegrationMethod,
           unsigned GlobalDim>
 class LocalAssemblerData : public ComponentTransportLocalAssemblerInterface
 {
+    // Pressure always first
+    static const int pressure_index = 0;
+    static const int pressure_size = ShapeFunction::NPOINTS;
+    // per component
+    static const int concentration_size = ShapeFunction::NPOINTS;
+
     using ShapeMatricesType = ShapeMatrixPolicyType<ShapeFunction, GlobalDim>;
     using ShapeMatrices = typename ShapeMatricesType::ShapeMatrices;
 
+    using LocalBlockMatrixType =
+        typename ShapeMatricesType::template MatrixType<pressure_size,
+                                                        pressure_size>;
+    using LocalSegmentVectorType =
+        typename ShapeMatricesType::template VectorType<pressure_size>;
+
     using LocalMatrixType =
         Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
     using LocalVectorType = Eigen::Matrix<double, Eigen::Dynamic, 1>;
@@ -137,17 +149,86 @@ public:
         auto local_b = MathLib::createZeroedVector<LocalVectorType>(
             local_b_data, local_matrix_size);
 
+        // Nodal DOFs include pressure
+        auto const num_comp = num_nodal_dof - 1;
+
+        // Get block matrices
+        auto Kpp = local_K.template block<pressure_size, pressure_size>(
+            pressure_index, pressure_index);
+        auto Mpp = local_M.template block<pressure_size, pressure_size>(
+            pressure_index, pressure_index);
+        auto Bp = local_b.template segment<pressure_size>(pressure_index);
+
+        auto local_p = Eigen::Map<const NodalVectorType>(
+            &local_x[pressure_index], pressure_size);
+
+        for (int comp_id = 0; comp_id < num_comp; ++comp_id)
+        {
+            /*  Partitioned assembler matrix
+             *  |  pp | pc1 | pc2 | pc3 |
+             *  |-----|-----|-----|-----|
+             *  | c1p | c1c1|  0  |  0  |
+             *  |-----|-----|-----|-----|
+             *  | c2p |  0  | c2c2|  0  |
+             *  |-----|-----|-----|-----|
+             *  | c3p |  0  |  0  | c3c3|
+             */
+            auto concentration_index =
+                pressure_size + comp_id * concentration_size;
+
+            auto KCC =
+                local_K.template block<concentration_size, concentration_size>(
+                    concentration_index, concentration_index);
+            auto MCC =
+                local_M.template block<concentration_size, concentration_size>(
+                    concentration_index, concentration_index);
+            auto MCp =
+                local_M.template block<concentration_size, pressure_size>(
+                    concentration_index, pressure_index);
+            auto MpC =
+                local_M.template block<pressure_size, concentration_size>(
+                    pressure_index, concentration_index);
+
+            auto local_C = Eigen::Map<const NodalVectorType>(
+                &local_x[concentration_index], concentration_size);
+
+            // Prevent duplicate computation in loops
+            Kpp.setZero();
+            Mpp.setZero();
+
+            assembleBlockMatrices(comp_id, t, local_C, local_p, KCC, MCC, MCp,
+                                  MpC, Kpp, Mpp, Bp);
+        }
+    }
+
+    void assembleBlockMatrices(
+        int const comp_id,
+        double const t,
+        Eigen::Ref<const NodalVectorType> const& C_nodal_values,
+        Eigen::Ref<const NodalVectorType> const& p_nodal_values,
+        Eigen::Ref<LocalBlockMatrixType>
+            KCC,
+        Eigen::Ref<LocalBlockMatrixType>
+            MCC,
+        Eigen::Ref<LocalBlockMatrixType>
+            MCp,
+        Eigen::Ref<LocalBlockMatrixType>
+            MpC,
+        Eigen::Ref<LocalBlockMatrixType>
+            Kpp,
+        Eigen::Ref<LocalBlockMatrixType>
+            Mpp,
+        Eigen::Ref<LocalSegmentVectorType>
+            Bp)
+    {
+        assert(comp_id <= static_cast<int>(_process_variables[0].size() - 1));
+
         unsigned const n_integration_points =
             _integration_method.getNumberOfPoints();
 
         SpatialPosition pos;
         pos.setElementID(_element.getID());
 
-        auto const num_nodes = ShapeFunction::NPOINTS;
-        auto p_nodal_values =
-            Eigen::Map<const NodalVectorType>(&local_x[num_nodes], num_nodes);
-        auto C_nodal_values =
-            Eigen::Map<const NodalVectorType>(&local_x[0], num_nodes);
         auto const& b = _process_data.specific_body_force;
 
         MaterialLib::Fluid::FluidProperty::ArrayType vars;
@@ -155,16 +236,6 @@ public:
         GlobalDimMatrixType const& I(
             GlobalDimMatrixType::Identity(GlobalDim, GlobalDim));
 
-        auto KCC = local_K.template block<num_nodes, num_nodes>(0, 0);
-        auto MCC = local_M.template block<num_nodes, num_nodes>(0, 0);
-        auto MCp = local_M.template block<num_nodes, num_nodes>(0, num_nodes);
-        auto Kpp =
-            local_K.template block<num_nodes, num_nodes>(num_nodes, num_nodes);
-        auto Mpp =
-            local_M.template block<num_nodes, num_nodes>(num_nodes, num_nodes);
-        auto MpC = local_M.template block<num_nodes, num_nodes>(num_nodes, 0);
-        auto Bp = local_b.template block<num_nodes, 1>(num_nodes, 0);
-
         for (std::size_t ip(0); ip < n_integration_points; ++ip)
         {
             pos.setIntegrationPoint(ip);
@@ -177,8 +248,9 @@ public:
 
             double C_int_pt = 0.0;
             double p_int_pt = 0.0;
-            // Order matters: First C, then p!
-            NumLib::shapeFunctionInterpolate(local_x, N, C_int_pt, p_int_pt);
+
+            NumLib::shapeFunctionInterpolate(C_nodal_values, N, C_int_pt);
+            NumLib::shapeFunctionInterpolate(p_nodal_values, N, p_int_pt);
 
             // porosity model
             auto const porosity =
@@ -281,6 +353,16 @@ public:
         assert(!indices.empty());
         auto const local_x = current_solution.get(indices);
 
+        // concentration index of the component ranking first
+        auto const concentration_index = 1 * ShapeFunction::NPOINTS;
+        // assuming that fluid density always depends on concentration of the
+        // first component.
+        // get local_C and local_p
+        auto const C_nodal_values = Eigen::Map<const NodalVectorType>(
+            &local_x[concentration_index], concentration_size);
+        auto const p_nodal_values = Eigen::Map<const NodalVectorType>(
+            &local_x[pressure_index], pressure_size);
+
         cache.clear();
         auto cache_mat = MathLib::createZeroedMatrix<
             Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
@@ -290,9 +372,6 @@ public:
         pos.setElementID(_element.getID());
 
         MaterialLib::Fluid::FluidProperty::ArrayType vars;
-        auto const num_nodes = ShapeFunction::NPOINTS;
-        auto const p_nodal_values =
-            Eigen::Map<const NodalVectorType>(&local_x[num_nodes], num_nodes);
 
         for (unsigned ip = 0; ip < n_integration_points; ++ip)
         {
@@ -314,8 +393,10 @@ public:
             {
                 double C_int_pt = 0.0;
                 double p_int_pt = 0.0;
-                NumLib::shapeFunctionInterpolate(local_x, N, C_int_pt,
-                                                 p_int_pt);
+
+                NumLib::shapeFunctionInterpolate(C_nodal_values, N, C_int_pt);
+                NumLib::shapeFunctionInterpolate(p_nodal_values, N, p_int_pt);
+
                 vars[static_cast<int>(
                     MaterialLib::Fluid::PropertyVariableType::C)] = C_int_pt;
                 vars[static_cast<int>(
@@ -365,6 +446,16 @@ public:
             return shape_matrices;
         }();
 
+        // concentration index of the component ranking first
+        auto const concentration_index = 1 * ShapeFunction::NPOINTS;
+        // assuming that fluid density always depends on concentration of the
+        // first component.
+        // get local_C and local_p
+        auto const C_nodal_values = Eigen::Map<const NodalVectorType>(
+            &local_x[concentration_index], concentration_size);
+        auto const p_nodal_values = Eigen::Map<const NodalVectorType>(
+            &local_x[pressure_index], pressure_size);
+
         SpatialPosition pos;
         pos.setElementID(_element.getID());
 
@@ -372,8 +463,11 @@ public:
 
         // local_x contains the local concentration and pressure values
         NumLib::shapeFunctionInterpolate(
-            local_x, shape_matrices.N,
-            vars[static_cast<int>(MaterialLib::Fluid::PropertyVariableType::C)],
+            C_nodal_values, shape_matrices.N,
+            vars[static_cast<int>(
+                MaterialLib::Fluid::PropertyVariableType::C)]);
+        NumLib::shapeFunctionInterpolate(
+            p_nodal_values, shape_matrices.N,
             vars[static_cast<int>(
                 MaterialLib::Fluid::PropertyVariableType::p)]);
 
@@ -388,8 +482,6 @@ public:
             MaterialLib::Fluid::FluidPropertyType::Viscosity, vars);
         GlobalDimMatrixType const K_over_mu = K / mu;
 
-        auto const p_nodal_values = Eigen::Map<const NodalVectorType>(
-            &local_x[local_x.size()/2], ShapeFunction::NPOINTS);
         GlobalDimVectorType q =
             -K_over_mu * shape_matrices.dNdx * p_nodal_values;