From a50df00c6bbf89accc0eca8e246ccfeacb6d50a9 Mon Sep 17 00:00:00 2001
From: Dmitri Naumov <github@naumov.de>
Date: Fri, 7 Feb 2020 15:35:27 +0100
Subject: [PATCH] [PL/RM] Add variable porosity.

This needs storage of porosity after successful time step.
---
 .../LocalAssemblerInterface.h                 |   6 ++
 .../RichardsMechanicsFEM-impl.h               | 102 +++++++++++++++---
 .../RichardsMechanics/RichardsMechanicsFEM.h  |   6 ++
 .../RichardsMechanicsProcess.cpp              |   3 +
 4 files changed, 104 insertions(+), 13 deletions(-)

diff --git a/ProcessLib/RichardsMechanics/LocalAssemblerInterface.h b/ProcessLib/RichardsMechanics/LocalAssemblerInterface.h
index 0a671c920d0..20cd0294063 100644
--- a/ProcessLib/RichardsMechanics/LocalAssemblerInterface.h
+++ b/ProcessLib/RichardsMechanics/LocalAssemblerInterface.h
@@ -46,6 +46,12 @@ struct LocalAssemblerInterface : public ProcessLib::LocalAssemblerInterface,
         std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
         std::vector<double>& cache) const = 0;
 
+    virtual std::vector<double> const& getIntPtPorosity(
+        const double t,
+        std::vector<GlobalVector*> const& x,
+        std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
+        std::vector<double>& cache) const = 0;
+
     // TODO move to NumLib::ExtrapolatableElement
     virtual unsigned getNumberOfIntegrationPoints() const = 0;
 
diff --git a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
index 0f0126813e3..05f99990569 100644
--- a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
+++ b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM-impl.h
@@ -62,8 +62,14 @@ RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
             _process_data.solid_materials, _process_data.material_ids,
             e.getID());
 
+    auto const& medium = _process_data.media_map->getMedium(_element.getID());
+    auto const& solid_phase = medium->phase("Solid");
+
+    ParameterLib::SpatialPosition x_position;
+    x_position.setElementID(_element.getID());
     for (unsigned ip = 0; ip < n_integration_points; ip++)
     {
+        x_position.setIntegrationPoint(ip);
         _ip_data.emplace_back(solid_material);
         auto& ip_data = _ip_data[ip];
         auto const& sm_u = shape_matrices_u[ip];
@@ -88,6 +94,14 @@ RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
         ip_data.N_p = shape_matrices_p[ip].N;
         ip_data.dNdx_p = shape_matrices_p[ip].dNdx;
 
+        // Initial porosity. Could be read from intergration point data or mesh.
+        ip_data.porosity =
+            solid_phase.property(MPL::porosity)
+                .template initialValue<double>(
+                    x_position,
+                    std::numeric_limits<
+                        double>::quiet_NaN() /* t independent */);
+
         _secondary_data.N_u[ip] = shape_matrices_u[ip].N;
     }
 }
@@ -98,7 +112,7 @@ void RichardsMechanicsLocalAssembler<
     ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
     DisplacementDim>::assemble(double const t, double const dt,
                                std::vector<double> const& local_x,
-                               std::vector<double> const& /*local_xdot*/,
+                               std::vector<double> const& local_xdot,
                                std::vector<double>& local_M_data,
                                std::vector<double>& local_K_data,
                                std::vector<double>& local_rhs_data)
@@ -115,6 +129,16 @@ void RichardsMechanicsLocalAssembler<
             displacement_size> const>(local_x.data() + displacement_index,
                                       displacement_size);
 
+    auto p_L_dot =
+        Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
+            pressure_size> const>(local_xdot.data() + pressure_index,
+                                  pressure_size);
+
+    auto u_dot =
+        Eigen::Map<typename ShapeMatricesTypeDisplacement::template VectorType<
+            displacement_size> const>(local_xdot.data() + displacement_index,
+                                      displacement_size);
+
     auto K = MathLib::createZeroedMatrix<
         typename ShapeMatricesTypeDisplacement::template MatrixType<
             displacement_size + pressure_size,
@@ -134,6 +158,10 @@ void RichardsMechanicsLocalAssembler<
             displacement_size + pressure_size>>(
         local_rhs_data, displacement_size + pressure_size);
 
+    auto const& identity2 = MathLib::KelvinVector::Invariants<
+        MathLib::KelvinVector::KelvinVectorDimensions<DisplacementDim>::value>::
+        identity2;
+
     auto const& medium = _process_data.media_map->getMedium(_element.getID());
     auto const& liquid_phase = medium->phase("AqueousLiquid");
     auto const& solid_phase = medium->phase("Solid");
@@ -168,6 +196,9 @@ void RichardsMechanicsLocalAssembler<
                 dNdx_u, N_u, x_coord, _is_axially_symmetric);
 
         auto& eps = _ip_data[ip].eps;
+        variables[static_cast<int>(MPL::Variable::volumetric_strain_rate)]
+            .emplace<double>(identity2.transpose() * B * u_dot);
+
         auto& S_L = _ip_data[ip].saturation;
 
         double p_cap_ip;
@@ -176,6 +207,8 @@ void RichardsMechanicsLocalAssembler<
         variables[static_cast<int>(MPL::Variable::capillary_pressure)] =
             p_cap_ip;
         variables[static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
+        variables[static_cast<int>(MPL::Variable::phase_pressure_rate)] =
+            N_p.dot(p_L_dot);
 
         auto const temperature =
             medium->property(MPL::PropertyType::reference_temperature)
@@ -194,17 +227,21 @@ void RichardsMechanicsLocalAssembler<
         auto const K_LR =
             liquid_phase.property(MPL::PropertyType::bulk_modulus)
                 .template value<double>(variables, x_position, t, dt);
-        auto const porosity =
-            solid_phase.property(MPL::PropertyType::porosity)
-                .template value<double>(variables, x_position, t, dt);
+
+        // Use previous time step porosity for porosity update, ...
+        variables[static_cast<int>(MPL::Variable::porosity)] =
+            _ip_data[ip].porosity_prev;
+        auto& porosity = _ip_data[ip].porosity;
+        porosity = solid_phase.property(MPL::PropertyType::porosity)
+                       .template value<double>(variables, x_position, t, dt);
+        // ... then use new porosity.
+        variables[static_cast<int>(MPL::Variable::porosity)] = porosity;
+
         auto const rho_LR =
             liquid_phase.property(MPL::PropertyType::density)
                 .template value<double>(variables, x_position, t, dt);
 
         auto const& b = _process_data.specific_body_force;
-        auto const& identity2 = MathLib::KelvinVector::Invariants<
-            MathLib::KelvinVector::KelvinVectorDimensions<
-                DisplacementDim>::value>::identity2;
 
         S_L = medium->property(MPL::PropertyType::saturation)
                   .template value<double>(variables, x_position, t, dt);
@@ -338,6 +375,10 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
             displacement_size + pressure_size>>(
         local_rhs_data, displacement_size + pressure_size);
 
+    auto const& identity2 = MathLib::KelvinVector::Invariants<
+        MathLib::KelvinVector::KelvinVectorDimensions<DisplacementDim>::value>::
+        identity2;
+
     typename ShapeMatricesTypePressure::NodalMatrixType laplace_p =
         ShapeMatricesTypePressure::NodalMatrixType::Zero(pressure_size,
                                                          pressure_size);
@@ -409,6 +450,10 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
         variables[static_cast<int>(MPL::Variable::capillary_pressure)] =
             p_cap_ip;
         variables[static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
+        variables[static_cast<int>(MPL::Variable::phase_pressure_rate)] =
+            N_p.dot(p_L_dot);
+        variables[static_cast<int>(MPL::Variable::volumetric_strain_rate)]
+            .emplace<double>(identity2.transpose() * B * u_dot);
         auto const temperature =
             medium->property(MPL::PropertyType::reference_temperature)
                 .template value<double>(variables, x_position, t, dt);
@@ -429,16 +474,20 @@ void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
         auto const K_LR =
             liquid_phase.property(MPL::PropertyType::bulk_modulus)
                 .template value<double>(variables, x_position, t, dt);
-        auto const porosity =
-            solid_phase.property(MPL::PropertyType::porosity)
-                .template value<double>(variables, x_position, t, dt);
+
+        // Use previous time step porosity for porosity update, ...
+        variables[static_cast<int>(MPL::Variable::porosity)] =
+            _ip_data[ip].porosity_prev;
+        auto& porosity = _ip_data[ip].porosity;
+        porosity = solid_phase.property(MPL::PropertyType::porosity)
+                       .template value<double>(variables, x_position, t, dt);
+        // ... then use new porosity.
+        variables[static_cast<int>(MPL::Variable::porosity)] = porosity;
+
         auto const rho_LR =
             liquid_phase.property(MPL::PropertyType::density)
                 .template value<double>(variables, x_position, t, dt);
         auto const& b = _process_data.specific_body_force;
-        auto const& identity2 = MathLib::KelvinVector::Invariants<
-            MathLib::KelvinVector::KelvinVectorDimensions<
-                DisplacementDim>::value>::identity2;
 
         S_L = medium->property(MPL::PropertyType::saturation)
                   .template value<double>(variables, x_position, t, dt);
@@ -668,6 +717,7 @@ std::vector<double> const& RichardsMechanicsLocalAssembler<
 
     return cache;
 }
+
 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
           typename IntegrationMethod, int DisplacementDim>
 std::vector<double> const& RichardsMechanicsLocalAssembler<
@@ -775,6 +825,32 @@ std::vector<double> const& RichardsMechanicsLocalAssembler<
     return cache;
 }
 
+template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
+          typename IntegrationMethod, int DisplacementDim>
+std::vector<double> const& RichardsMechanicsLocalAssembler<
+    ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
+    DisplacementDim>::
+    getIntPtPorosity(
+        const double /*t*/,
+        std::vector<GlobalVector*> const& /*x*/,
+        std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
+        std::vector<double>& cache) const
+{
+    auto const num_intpts = _ip_data.size();
+
+    cache.clear();
+    auto cache_mat = MathLib::createZeroedMatrix<
+        Eigen::Matrix<double, 1, Eigen::Dynamic, Eigen::RowMajor>>(cache, 1,
+                                                                   num_intpts);
+
+    for (unsigned ip = 0; ip < num_intpts; ++ip)
+    {
+        cache_mat[ip] = _ip_data[ip].porosity;
+    }
+
+    return cache;
+}
+
 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
           typename IntegrationMethod, int DisplacementDim>
 void RichardsMechanicsLocalAssembler<ShapeFunctionDisplacement,
diff --git a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM.h b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM.h
index ab14411a5b7..56301cf5a43 100644
--- a/ProcessLib/RichardsMechanics/RichardsMechanicsFEM.h
+++ b/ProcessLib/RichardsMechanics/RichardsMechanicsFEM.h
@@ -167,6 +167,12 @@ public:
         std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
         std::vector<double>& cache) const override;
 
+    std::vector<double> const& getIntPtPorosity(
+        const double t,
+        std::vector<GlobalVector*> const& x,
+        std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
+        std::vector<double>& cache) const override;
+
     std::vector<double> const& getIntPtSigma(
         const double t,
         std::vector<GlobalVector*> const& x,
diff --git a/ProcessLib/RichardsMechanics/RichardsMechanicsProcess.cpp b/ProcessLib/RichardsMechanics/RichardsMechanicsProcess.cpp
index c05497d0809..04b727787a6 100644
--- a/ProcessLib/RichardsMechanics/RichardsMechanicsProcess.cpp
+++ b/ProcessLib/RichardsMechanics/RichardsMechanicsProcess.cpp
@@ -195,6 +195,9 @@ void RichardsMechanicsProcess<DisplacementDim>::initializeConcreteProcess(
     add_secondary_variable("saturation", 1,
                            &LocalAssemblerIF::getIntPtSaturation);
 
+    add_secondary_variable("porosity", 1,
+                           &LocalAssemblerIF::getIntPtPorosity);
+
     //
     // enable output of internal variables defined by material models
     //
-- 
GitLab