diff --git a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
index 7a1dce59408f9dfd53d83e03349c72a443062ca7..98f57b37cdc1f97058b1956617413004a44ca0d9 100644
--- a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
+++ b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
@@ -13,6 +13,7 @@
 
 #include <cassert>
 
+#include "ComputeMicroPorosity.h"
 #include "IntegrationPointData.h"
 #include "MaterialLib/MPL/Medium.h"
 #include "MaterialLib/MPL/Utils/FormEigenTensor.h"
@@ -231,7 +232,16 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
             medium->property(MPL::PropertyType::saturation)
                 .template value<double>(variables, x_position, t, dt);
 
-        _ip_data[ip].saturation_m_prev = _ip_data[ip].saturation_prev;
+        if (medium->hasProperty(MPL::PropertyType::saturation_micro))
+        {
+            MPL::VariableArray vars;
+            vars[static_cast<int>(MPL::Variable::capillary_pressure)] =
+                p_cap_ip;
+            double const S_L_m =
+                medium->property(MPL::PropertyType::saturation_micro)
+                    .template value<double>(vars, x_position, t, dt);
+            _ip_data[ip].saturation_m_prev = S_L_m;
+        }
 
         // Set eps_m_prev from potentially non-zero eps and sigma_sw from
         // restart.
@@ -805,8 +815,9 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
 
         // Swelling and possibly volumetric strain rate update.
         auto& sigma_sw = _ip_data[ip].sigma_sw;
+        auto const& sigma_sw_prev = _ip_data[ip].sigma_sw_prev;
+        if (!medium->hasProperty(MPL::PropertyType::saturation_micro))
         {
-            auto const& sigma_sw_prev = _ip_data[ip].sigma_sw_prev;
 
             // If there is swelling, compute it. Update volumetric strain rate,
             // s.t. it corresponds to the mechanical part only.
@@ -832,33 +843,79 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
                     MPL::Variable::volumetric_strain)]) +=
                     identity2.transpose() * C_el.inverse() * sigma_sw_prev;
             }
+        }
 
-            if (solid_phase.hasProperty(MPL::PropertyType::transport_porosity))
-            {
-                variables_prev[static_cast<int>(
-                    MPL::Variable::transport_porosity)] =
-                    _ip_data[ip].transport_porosity_prev;
+        auto const mu =
+            liquid_phase.property(MPL::PropertyType::viscosity)
+                .template value<double>(variables, x_position, t, dt);
 
-                _ip_data[ip].transport_porosity =
-                    solid_phase.property(MPL::PropertyType::transport_porosity)
-                        .template value<double>(variables, variables_prev,
-                                                x_position, t, dt);
-                variables[static_cast<int>(MPL::Variable::transport_porosity)] =
-                    _ip_data[ip].transport_porosity;
-            }
-            else
-            {
-                variables[static_cast<int>(MPL::Variable::transport_porosity)] =
-                    phi;
+        // TODO (naumov) saturation_micro must be always defined together with
+        // the micro_porosity_parameters.
+        if (medium->hasProperty(MPL::PropertyType::saturation_micro))
+        {
+            double const phi_M_prev = _ip_data[ip].transport_porosity_prev;
+            double const phi_prev = _ip_data[ip].porosity_prev;
+            double const phi_m_prev = phi_prev - phi_M_prev;
+            double const p_L_m_prev = _ip_data[ip].liquid_pressure_m_prev;
+
+            auto const S_L_m_prev = _ip_data[ip].saturation_m_prev;
+
+            auto const [delta_phi_m, delta_e_sw, delta_p_L_m, delta_sigma_sw] =
+                computeMicroPorosity<DisplacementDim>(
+                    identity2.transpose() * C_el.inverse(), rho_LR, mu,
+                    *_process_data.micro_porosity_parameters, alpha, phi,
+                    -p_cap_ip, p_L_m_prev, variables_prev, S_L_m_prev,
+                    phi_m_prev, x_position, t, dt,
+                    medium->property(MPL::PropertyType::saturation_micro),
+                    solid_phase.property(
+                        MPL::PropertyType::swelling_stress_rate));
+
+            auto& phi_M = _ip_data[ip].transport_porosity;
+            phi_M = phi - (phi_m_prev + delta_phi_m);
+            variables_prev[static_cast<int>(
+                MPL::Variable::transport_porosity)] = phi_M_prev;
+            variables[static_cast<int>(MPL::Variable::transport_porosity)] =
+                phi_M;
+
+            auto& p_L_m = _ip_data[ip].liquid_pressure_m;
+            p_L_m = p_L_m_prev + delta_p_L_m;
+            {  // Update micro saturation.
+                MPL::VariableArray variables_prev;
+                variables_prev[static_cast<int>(
+                    MPL::Variable::capillary_pressure)] = -p_L_m_prev;
+                MPL::VariableArray variables;
+                variables[static_cast<int>(MPL::Variable::capillary_pressure)] =
+                    -p_L_m;
+
+                _ip_data[ip].saturation_m =
+                    medium->property(MPL::PropertyType::saturation_micro)
+                        .template value<double>(variables, x_position, t, dt);
             }
+            sigma_sw = sigma_sw_prev + delta_sigma_sw;
+        }
+
+        if (solid_phase.hasProperty(MPL::PropertyType::transport_porosity))
+        {
+            variables_prev[static_cast<int>(
+                MPL::Variable::transport_porosity)] =
+                _ip_data[ip].transport_porosity_prev;
+
+            _ip_data[ip].transport_porosity =
+                solid_phase.property(MPL::PropertyType::transport_porosity)
+                    .template value<double>(variables, variables_prev,
+                                            x_position, t, dt);
+            variables[static_cast<int>(MPL::Variable::transport_porosity)] =
+                _ip_data[ip].transport_porosity;
+        }
+        else
+        {
+            variables[static_cast<int>(MPL::Variable::transport_porosity)] =
+                phi;
         }
 
         double const k_rel =
             medium->property(MPL::PropertyType::relative_permeability)
                 .template value<double>(variables, x_position, t, dt);
-        auto const mu =
-            liquid_phase.property(MPL::PropertyType::viscosity)
-                .template value<double>(variables, x_position, t, dt);
 
         // Set mechanical variables for the intrinsic permeability model
         // For stress dependent permeability.
@@ -938,7 +995,17 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
             .noalias() +=
             N_u_op.transpose() * phi * rho_LR * dS_L_dp_cap * b * N_p * w;
 
-        if (solid_phase.hasProperty(MPL::PropertyType::swelling_stress_rate))
+        if (medium->hasProperty(MPL::PropertyType::saturation_micro))
+        {
+            // For the swelling stress with double structure model the
+            // corresponding Jacobian u-p entry would be:
+            // -B.transpose() *
+            //     dsigma_sw_dS_L_m* dS_L_m_dp_cap_m*(p_L_m - p_L_m_prev) /
+            //     p_cap_dot_ip / dt* N_p* w;
+            // but it does not improve convergence and sometimes worsen it.
+        }
+        else if (solid_phase.hasProperty(
+                     MPL::PropertyType::swelling_stress_rate))
         {
             using DimMatrix = Eigen::Matrix<double, 3, 3>;
             auto const dsigma_sw_dS_L =
@@ -1040,6 +1107,31 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
 
         local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
             dNdx_p.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
+
+        if (medium->hasProperty(MPL::PropertyType::saturation_micro))
+        {
+            double const alpha_bar = _process_data.micro_porosity_parameters
+                                         ->mass_exchange_coefficient;
+            auto const p_L_m = _ip_data[ip].liquid_pressure_m;
+            local_rhs.template segment<pressure_size>(pressure_index)
+                .noalias() -=
+                N_p.transpose() * alpha_bar / mu * (-p_cap_ip - p_L_m) * w;
+
+            local_Jac
+                .template block<pressure_size, pressure_size>(pressure_index,
+                                                              pressure_index)
+                .noalias() += N_p.transpose() * alpha_bar / mu * N_p * w;
+            if (p_cap_dot_ip != 0)
+            {
+                double const p_L_m_prev = _ip_data[ip].liquid_pressure_m_prev;
+                local_Jac
+                    .template block<pressure_size, pressure_size>(
+                        pressure_index, pressure_index)
+                    .noalias() += N_p.transpose() * alpha_bar / mu *
+                                  (p_L_m - p_L_m_prev) / (dt * p_cap_dot_ip) *
+                                  N_p * w;
+            }
+        }
     }
 
     if (_process_data.apply_mass_lumping)