From 2046c6907e9f84588fdcaf2915e73891a67ff60f Mon Sep 17 00:00:00 2001
From: Norihiro Watanabe <norihiro.watanabe@ufz.de>
Date: Fri, 23 Sep 2016 14:23:28 +0200
Subject: [PATCH] add MohrCoulomb model for fractures

---
 .../FractureModels/CreateMohrCoulomb.cpp      |  65 ++++++++++
 .../FractureModels/CreateMohrCoulomb.h        |  28 +++++
 MaterialLib/FractureModels/MohrCoulomb.cpp    | 115 ++++++++++++++++++
 MaterialLib/FractureModels/MohrCoulomb.h      |  86 +++++++++++++
 4 files changed, 294 insertions(+)
 create mode 100644 MaterialLib/FractureModels/CreateMohrCoulomb.cpp
 create mode 100644 MaterialLib/FractureModels/CreateMohrCoulomb.h
 create mode 100644 MaterialLib/FractureModels/MohrCoulomb.cpp
 create mode 100644 MaterialLib/FractureModels/MohrCoulomb.h

diff --git a/MaterialLib/FractureModels/CreateMohrCoulomb.cpp b/MaterialLib/FractureModels/CreateMohrCoulomb.cpp
new file mode 100644
index 00000000000..84342c90089
--- /dev/null
+++ b/MaterialLib/FractureModels/CreateMohrCoulomb.cpp
@@ -0,0 +1,65 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "CreateMohrCoulomb.h"
+
+#include "MohrCoulomb.h"
+
+namespace MaterialLib
+{
+namespace Fracture
+{
+
+template <int DisplacementDim>
+std::unique_ptr<FractureModelBase<DisplacementDim>>
+createMohrCoulomb(
+    std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters,
+    BaseLib::ConfigTree const& config)
+{
+    config.checkConfigParameter("type", "MohrCoulomb");
+    DBUG("Create MohrCoulomb material");
+
+    auto& Kn = ProcessLib::findParameter<double>(
+        config, "kn", parameters, 1);
+
+    auto& Ks = ProcessLib::findParameter<double>(
+        config, "ks", parameters, 1);
+
+    auto& friction_angle = ProcessLib::findParameter<double>(
+        config, "friction_angle", parameters, 1);
+
+    auto& dilatancy_angle = ProcessLib::findParameter<double>(
+        config, "dilatancy_angle", parameters, 1);
+
+    auto& cohesion = ProcessLib::findParameter<double>(
+        config, "cohesion", parameters, 1);
+
+
+    typename MohrCoulomb<DisplacementDim>::MaterialProperties mp{
+        Kn, Ks, friction_angle, dilatancy_angle, cohesion};
+
+    return std::unique_ptr<MohrCoulomb<DisplacementDim>>{
+        new MohrCoulomb<DisplacementDim>{mp}};
+}
+
+
+template
+std::unique_ptr<FractureModelBase<2>>
+createMohrCoulomb(
+    std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters,
+    BaseLib::ConfigTree const& config);
+
+template
+std::unique_ptr<FractureModelBase<3>>
+createMohrCoulomb(
+    std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters,
+    BaseLib::ConfigTree const& config);
+
+}  // namespace Fracture
+}  // namespace MaterialLib
diff --git a/MaterialLib/FractureModels/CreateMohrCoulomb.h b/MaterialLib/FractureModels/CreateMohrCoulomb.h
new file mode 100644
index 00000000000..3ee7c7da854
--- /dev/null
+++ b/MaterialLib/FractureModels/CreateMohrCoulomb.h
@@ -0,0 +1,28 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include "ProcessLib/Utils/ProcessUtils.h"  // required for findParameter
+#include "FractureModelBase.h"
+
+namespace MaterialLib
+{
+namespace Fracture
+{
+
+template <int DisplacementDim>
+std::unique_ptr<FractureModelBase<DisplacementDim>>
+createMohrCoulomb(
+    std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters,
+    BaseLib::ConfigTree const& config);
+
+}  // namespace Fracture
+}  // namespace MaterialLib
+
diff --git a/MaterialLib/FractureModels/MohrCoulomb.cpp b/MaterialLib/FractureModels/MohrCoulomb.cpp
new file mode 100644
index 00000000000..8cfddaaf8ca
--- /dev/null
+++ b/MaterialLib/FractureModels/MohrCoulomb.cpp
@@ -0,0 +1,115 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "MohrCoulomb.h"
+
+#include "BaseLib/Error.h"
+#include "MathLib/MathTools.h"
+
+namespace MaterialLib
+{
+namespace Fracture
+{
+
+namespace
+{
+
+struct MaterialPropertyValues
+{
+    double Kn = 0.0;
+    double Ks = 0.0;
+    double phi = 0.0; // friction angle
+    double psi = 0.0; // dilation angle
+    double c = 0.0;
+
+    template <typename MaterialProperties>
+    MaterialPropertyValues(
+            MaterialProperties const& mp,
+            double const t,
+            ProcessLib::SpatialPosition const& x)
+    {
+        Kn = mp.normal_stiffness(t,x)[0];
+        Ks = mp.shear_stiffness(t,x)[0];
+        phi = MathLib::to_radians(mp.friction_angle(t,x)[0]);
+        psi = MathLib::to_radians(mp.dilatancy_angle(t,x)[0]);
+        c = mp.cohesion(t,x)[0];
+    }
+};
+
+} // no namespace
+
+template <int DisplacementDim>
+void MohrCoulomb<DisplacementDim>::computeConstitutiveRelation(
+        double const t,
+        ProcessLib::SpatialPosition const& x,
+        Eigen::Ref<Eigen::VectorXd const> w_prev,
+        Eigen::Ref<Eigen::VectorXd const> w,
+        Eigen::Ref<Eigen::VectorXd const> sigma_prev,
+        Eigen::Ref<Eigen::VectorXd> sigma,
+        Eigen::Ref<Eigen::MatrixXd> Kep)
+{
+    if (DisplacementDim == 3)
+    {
+        OGS_FATAL("MohrCoulomb fracture model does not support 3D case.");
+        return;
+    }
+    MaterialPropertyValues const mat(_mp, t, x);
+    Eigen::VectorXd const dw = w - w_prev;
+
+    Eigen::MatrixXd Ke(2,2);
+    Ke.setZero();
+    Ke(0,0) = mat.Ks;
+    Ke(1,1) = mat.Kn;
+
+    sigma.noalias() = sigma_prev + Ke * dw;
+
+    // if opening
+    if (sigma[1] > 0)
+    {
+        Kep.setZero();
+        sigma.setZero();
+        return;
+    }
+
+    // check shear yield function (Fs)
+    double const Fs = std::abs(sigma[0]) + sigma[1] * tan(mat.phi) - mat.c;
+    if (Fs < .0)
+    {
+        Kep = Ke;
+        return;
+    }
+
+    Eigen::VectorXd dFs_dS(2);
+    dFs_dS[0] = MathLib::sgn(sigma[0]);
+    dFs_dS[1] = tan(mat.phi);
+
+    // plastic potential function: Qs = |tau| + Sn * tan da
+    Eigen::VectorXd dQs_dS(2);
+    dQs_dS[0] = MathLib::sgn(sigma[0]);
+    dQs_dS[1] = tan(mat.psi);
+
+    // plastic multiplier
+    Eigen::RowVectorXd const A = dFs_dS.transpose() * Ke / (dFs_dS.transpose() * Ke * dQs_dS);
+    double const d_eta = A * dw;
+
+    // plastic part of the dispalcement
+    Eigen::VectorXd const dwp = dQs_dS * d_eta;
+
+    // correct stress
+    sigma.noalias() = sigma_prev + Ke * (dw - dwp);
+
+    // Kep
+    Kep = Ke - Ke * dQs_dS * A;
+}
+
+template class MohrCoulomb<2>;
+template class MohrCoulomb<3>;
+
+}   // namespace Fracture
+}  // namespace MaterialLib
diff --git a/MaterialLib/FractureModels/MohrCoulomb.h b/MaterialLib/FractureModels/MohrCoulomb.h
new file mode 100644
index 00000000000..40eb458aa2f
--- /dev/null
+++ b/MaterialLib/FractureModels/MohrCoulomb.h
@@ -0,0 +1,86 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <Eigen/Eigen>
+
+#include "ProcessLib/Parameter/Parameter.h"
+
+#include "FractureModelBase.h"
+
+namespace MaterialLib
+{
+namespace Fracture
+{
+
+/**
+ * Mohr-Coulomb fracture model
+ */
+template <int DisplacementDim>
+class MohrCoulomb final : public FractureModelBase<DisplacementDim>
+{
+public:
+    /// Variables specific to the material model
+    struct MaterialProperties
+    {
+        using P = ProcessLib::Parameter<double>;
+        using X = ProcessLib::SpatialPosition;
+
+        MaterialProperties(
+                P const& normal_stiffness, P const& shear_stiffness,
+                P const& friction_angle, P const& dilatancy_angle,
+                P const& cohesion)
+            : normal_stiffness(normal_stiffness), shear_stiffness(shear_stiffness),
+              friction_angle(friction_angle), dilatancy_angle(dilatancy_angle),
+              cohesion(cohesion)
+        {
+        }
+
+        P const& normal_stiffness;
+        P const& shear_stiffness;
+        P const& friction_angle;
+        P const& dilatancy_angle;
+        P const& cohesion;
+    };
+
+public:
+
+    explicit MohrCoulomb(
+        MaterialProperties const& material_properties)
+        : _mp(material_properties)
+    {
+    }
+
+    void computeConstitutiveRelation(
+            double const t,
+            ProcessLib::SpatialPosition const& x,
+            Eigen::Ref<Eigen::VectorXd const> w_prev,
+            Eigen::Ref<Eigen::VectorXd const> w,
+            Eigen::Ref<Eigen::VectorXd const> sigma_prev,
+            Eigen::Ref<Eigen::VectorXd> sigma,
+            Eigen::Ref<Eigen::MatrixXd> Kep) override;
+
+private:
+
+    MaterialProperties _mp;
+};
+
+}  // namespace Fracture
+}  // namespace MaterialLib
+
+namespace MaterialLib
+{
+namespace Fracture
+{
+extern template class MohrCoulomb<2>;
+extern template class MohrCoulomb<3>;
+}  // namespace Fractrue
+}  // namespace MaterialLib
+
-- 
GitLab