From 0f1e91f365db2e1a3cd147e3dc62c6bce4761031 Mon Sep 17 00:00:00 2001
From: Dmitri Naumov <dmitri.naumov@ufz.de>
Date: Tue, 25 Feb 2020 19:04:05 +0100
Subject: [PATCH] [PL/RM] Add saturation dependent swelling.

Uses the optional solid phase swelling_stress_rate
property.
Stores previous values of saturation and the swelling
stress, because of the incremental form.
---
 .../RichardsMechanics/IntegrationPointData.h  |  5 ++
 .../RichardsMechanicsFEM-impl.h               | 69 +++++++++++++++----
 2 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/ProcessLib/RichardsMechanics/IntegrationPointData.h b/ProcessLib/RichardsMechanics/IntegrationPointData.h
index a8d5e31b7e1..313928111d7 100644
--- a/ProcessLib/RichardsMechanics/IntegrationPointData.h
+++ b/ProcessLib/RichardsMechanics/IntegrationPointData.h
@@ -36,6 +36,7 @@ struct IntegrationPointData final
             MathLib::KelvinVector::KelvinVectorDimensions<
                 DisplacementDim>::value;
         sigma_eff.setZero(kelvin_vector_size);
+        sigma_sw.setZero(kelvin_vector_size);
         eps.setZero(kelvin_vector_size);
 
         // Previous time step values are not initialized and are set later.
@@ -47,6 +48,7 @@ struct IntegrationPointData final
         DisplacementDim, NPoints * DisplacementDim>
         N_u_op;
     typename BMatricesType::KelvinVectorType sigma_eff, sigma_eff_prev;
+    typename BMatricesType::KelvinVectorType sigma_sw, sigma_sw_prev;
     typename BMatricesType::KelvinVectorType eps, eps_prev;
 
     typename ShapeMatrixTypeDisplacement::NodalRowVectorType N_u;
@@ -56,6 +58,7 @@ struct IntegrationPointData final
     typename ShapeMatricesTypePressure::GlobalDimNodalMatrixType dNdx_p;
 
     double saturation = std::numeric_limits<double>::quiet_NaN();
+    double saturation_prev = std::numeric_limits<double>::quiet_NaN();
     double porosity = std::numeric_limits<double>::quiet_NaN();
     double porosity_prev = std::numeric_limits<double>::quiet_NaN();
 
@@ -69,6 +72,8 @@ struct IntegrationPointData final
     {
         eps_prev = eps;
         sigma_eff_prev = sigma_eff;
+        sigma_sw_prev = sigma_sw;
+        saturation_prev = saturation;
         porosity_prev = porosity;
         material_state_variables->pushBackState();
     }
diff --git a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
index 4a9a21f6d1f..6b11108f6be 100644
--- a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
+++ b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
@@ -243,7 +243,10 @@ void RichardsMechanicsLocalAssembler<
         variables[static_cast<int>(MPL::Variable::volumetric_strain_rate)]
             .emplace<double>(identity2.transpose() * B * u_dot);
 
+        auto& sigma_sw = _ip_data[ip].sigma_sw;
+        auto const& sigma_sw_prev = _ip_data[ip].sigma_sw_prev;
         auto& S_L = _ip_data[ip].saturation;
+        auto const S_L_prev = _ip_data[ip].saturation_prev;
 
         double p_cap_ip;
         NumLib::shapeFunctionInterpolate(-p_L, N_p, p_cap_ip);
@@ -290,6 +293,8 @@ void RichardsMechanicsLocalAssembler<
         S_L = medium->property(MPL::PropertyType::saturation)
                   .template value<double>(variables, x_position, t, dt);
         variables[static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
+        variables[static_cast<int>(MPL::Variable::liquid_saturation_rate)] =
+            (S_L - S_L_prev) / dt;
 
         double const dS_L_dp_cap =
             medium->property(MPL::PropertyType::saturation)
@@ -310,6 +315,18 @@ void RichardsMechanicsLocalAssembler<
         GlobalDimMatrixType const rho_K_over_mu =
             K_intrinsic * rho_LR * k_rel / mu;
 
+        sigma_sw = sigma_sw_prev;
+        if (solid_phase.hasProperty(MPL::PropertyType::swelling_stress_rate))
+        {
+            using DimMatrix = Eigen::Matrix<double, 3, 3>;
+            sigma_sw +=
+                MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
+                    solid_phase
+                        .property(MPL::PropertyType::swelling_stress_rate)
+                        .template value<DimMatrix>(variables, x_position, t,
+                                                   dt)) *
+                dt;
+        }
         //
         // displacement equation, displacement part
         //
@@ -327,7 +344,7 @@ void RichardsMechanicsLocalAssembler<
 
         double const rho = rho_SR * (1 - porosity) + S_L * porosity * rho_LR;
         rhs.template segment<displacement_size>(displacement_index).noalias() +=
-            N_u_op.transpose() * rho * b * w;
+            N_u_op.transpose() * rho * b * w - B.transpose() * sigma_sw * w;
 
         //
         // pressure equation, pressure part.
@@ -505,7 +522,10 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
 
         auto& eps = _ip_data[ip].eps;
         auto& sigma_eff = _ip_data[ip].sigma_eff;
+        auto& sigma_sw = _ip_data[ip].sigma_sw;
+        auto const& sigma_sw_prev = _ip_data[ip].sigma_sw_prev;
         auto& S_L = _ip_data[ip].saturation;
+        auto const S_L_prev = _ip_data[ip].saturation_prev;
         auto const alpha =
             solid_phase.property(MPL::PropertyType::biot_coefficient)
                 .template value<double>(variables, x_position, t, dt);
@@ -536,6 +556,8 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
         S_L = medium->property(MPL::PropertyType::saturation)
                   .template value<double>(variables, x_position, t, dt);
         variables[static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
+        variables[static_cast<int>(MPL::Variable::liquid_saturation_rate)] =
+            (S_L - S_L_prev) / dt;
 
         double const dS_L_dp_cap =
             medium->property(MPL::PropertyType::saturation)
@@ -560,6 +582,19 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
 
         GlobalDimMatrixType const rho_Ki_over_mu = K_intrinsic * rho_LR / mu;
 
+        sigma_sw = sigma_sw_prev;
+        if (solid_phase.hasProperty(MPL::PropertyType::swelling_stress_rate))
+        {
+            using DimMatrix = Eigen::Matrix<double, 3, 3>;
+            sigma_sw +=
+                MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
+                    solid_phase
+                        .property(MPL::PropertyType::swelling_stress_rate)
+                        .template value<DimMatrix>(variables, x_position, t,
+                                                   dt)) *
+                dt;
+        }
+
         //
         // displacement equation, displacement part
         //
@@ -575,24 +610,15 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
 
         double const rho = rho_SR * (1 - porosity) + S_L * porosity * rho_LR;
         local_rhs.template segment<displacement_size>(displacement_index)
-            .noalias() -=
-            (B.transpose() * sigma_eff - N_u_op.transpose() * rho * b) * w;
+            .noalias() -= (B.transpose() * (sigma_eff + sigma_sw) -
+                           N_u_op.transpose() * rho * b) *
+                          w;
 
         //
         // displacement equation, pressure part
         //
         Kup.noalias() += B.transpose() * alpha * S_L * identity2 * N_p * w;
 
-        /* For future implementation including swelling.
-        double const dsigma_eff_dp_cap = -K_intrinsic * m_swell * n *
-                                         std::pow(S_L, n - 1) * dS_L_dp_cap *
-                                         identity2;
-        local_Jac
-            .template block<displacement_size, pressure_size>(
-                displacement_index, pressure_index)
-            .noalias() -= B.transpose() * dsigma_eff_dp_cap * N_p * w;
-        */
-
         local_Jac
             .template block<displacement_size, pressure_size>(
                 displacement_index, pressure_index)
@@ -604,6 +630,23 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
                 displacement_index, pressure_index)
             .noalias() +=
             N_u_op.transpose() * porosity * rho_LR * dS_L_dp_cap * b * N_p * w;
+
+        if (solid_phase.hasProperty(MPL::PropertyType::swelling_stress_rate))
+        {
+            using DimMatrix = Eigen::Matrix<double, 3, 3>;
+            auto const dsigma_sw_dS_L =
+                MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
+                    solid_phase
+                        .property(MPL::PropertyType::swelling_stress_rate)
+                        .template dValue<DimMatrix>(
+                            variables, MPL::Variable::liquid_saturation,
+                            x_position, t, dt));
+            local_Jac
+                .template block<displacement_size, pressure_size>(
+                    displacement_index, pressure_index)
+                .noalias() +=
+                B.transpose() * dsigma_sw_dS_L * dS_L_dp_cap * N_p * w;
+        }
         //
         // pressure equation, displacement part.
         //
-- 
GitLab