Skip to content
Snippets Groups Projects
Unverified Commit ddcd99bd authored by wenqing's avatar wenqing Committed by GitHub
Browse files

Merge pull request #2989 from wenqing/permeablility_stress

PermeabilityMohrCoulombFailureIndexModel
parents f0d2e66a f5506166
No related branches found
No related tags found
No related merge requests found
Showing
with 567 additions and 1 deletion
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::c_
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::b_
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::phi_
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::k0_
Parameter name to be used as initial permeability.
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::k_max_
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::kr_
\copydoc MaterialPropertyLib::PermeabilityMohrCoulombFailureIndexModel::t_sigma_max_
......@@ -140,3 +140,28 @@
doi = "10.1007/s10596-013-9341-7",
publisher={Springer}
}
@article{wangetalPerm2020,
title={Analysis of coupled thermal-hydro-mechanical processes during small
scale in situ heater experiment in Callovo-Oxfordian clay rock introducing
a failure-index permeability mode},
author={Wang, Wenqing and Shao, Hua and Nagel, Thomas and Fischer,
Thomas and Kolditz, Olaf},
journal={international journal of rock mechanics and mining sciences},
volume={under review},
number={},
pages={},
year={2020},
}
@article{labuz2012mohr,
title={Mohr--Coulomb failure criterion},
author={Labuz, Joseph F and Zang, Arno},
journal={Rock mechanics and rock engineering},
volume={45},
number={6},
pages={975--979},
year={2012},
publisher={Springer}
}
......@@ -27,7 +27,7 @@
namespace
{
std::unique_ptr<MaterialPropertyLib::Property> createProperty(
int const /*geometry_dimension*/,
int const geometry_dimension,
BaseLib::ConfigTree const& config,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
ParameterLib::CoordinateSystem const* const local_coordinate_system,
......@@ -73,6 +73,13 @@ std::unique_ptr<MaterialPropertyLib::Property> createProperty(
return createIdealGasLaw(config);
}
if (boost::iequals(property_type,
"PermeabilityMohrCoulombFailureIndexModel"))
{
return createPermeabilityMohrCoulombFailureIndexModel(
geometry_dimension, config, parameters, local_coordinate_system);
}
if (boost::iequals(property_type, "PermeabilityOrthotropicPowerLaw"))
{
return createPermeabilityOrthotropicPowerLaw(config,
......
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
* Created on June 5, 2020, 9:07 AM
*/
#include "CreatePermeabilityMohrCoulombFailureIndexModel.h"
#include <string>
#include "BaseLib/ConfigTree.h"
#include "Parameter.h"
#include "ParameterLib/CoordinateSystem.h"
#include "ParameterLib/Parameter.h"
#include "ParameterLib/Utils.h"
#include "PermeabilityMohrCoulombFailureIndexModel.h"
namespace MaterialPropertyLib
{
std::unique_ptr<Property> createPermeabilityMohrCoulombFailureIndexModel(
int const geometry_dimension,
BaseLib::ConfigTree const& config,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
ParameterLib::CoordinateSystem const* const local_coordinate_system)
{
if ((geometry_dimension != 2) && (geometry_dimension != 3))
{
OGS_FATAL(
"The PermeabilityMohrCoulombFailureIndexModel is implemented only "
"for 2D or 3D problems");
}
//! \ogs_file_param{properties__property__type}
config.checkConfigParameter("type",
"PermeabilityMohrCoulombFailureIndexModel");
// Second access for storage.
//! \ogs_file_param{properties__property__name}
auto property_name = config.peekConfigParameter<std::string>("name");
DBUG("Create PermeabilityMohrCoulombFailureIndexModel property {:s}.",
property_name);
std::string const& parameter_name =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__initial_permeability}
config.getConfigParameter<std::string>(
"initial_permeability");
auto const& parameter_k0 = ParameterLib::findParameter<double>(
parameter_name, parameters, 0, nullptr);
auto const kr =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__reference_permeability}
config.getConfigParameter<double>("reference_permeability");
auto const b =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__fitting_factor}
config.getConfigParameter<double>("fitting_factor");
auto const c =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__cohesion}
config.getConfigParameter<double>("cohesion");
auto const phi =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__friction_angle}
config.getConfigParameter<double>("friction_angle");
auto const max_k =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__maximum_permeability}
config.getConfigParameter<double>("maximum_permeability");
auto const t_sigma_max =
//! \ogs_file_param{properties__property__PermeabilityMohrCoulombFailureIndexModel__tensile_strength_parameter}
config.getConfigParameter<double>("tensile_strength_parameter");
if (geometry_dimension == 2)
{
return std::make_unique<PermeabilityMohrCoulombFailureIndexModel<2>>(
std::move(property_name), parameter_k0, kr, b, c, phi, max_k,
t_sigma_max, local_coordinate_system);
}
return std::make_unique<PermeabilityMohrCoulombFailureIndexModel<3>>(
std::move(property_name), parameter_k0, kr, b, c, phi, max_k,
t_sigma_max, local_coordinate_system);
}
} // namespace MaterialPropertyLib
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
* Created on June 5, 2020, 9:07 AM
*/
#pragma once
#include <memory>
#include <vector>
namespace BaseLib
{
class ConfigTree;
}
namespace ParameterLib
{
struct CoordinateSystem;
struct ParameterBase;
} // namespace ParameterLib
namespace MaterialPropertyLib
{
class Property;
}
namespace MaterialPropertyLib
{
std::unique_ptr<Property> createPermeabilityMohrCoulombFailureIndexModel(
int const geometry_dimension,
BaseLib::ConfigTree const& config,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
ParameterLib::CoordinateSystem const* const local_coordinate_system);
} // namespace MaterialPropertyLib
......@@ -26,6 +26,7 @@
#include "CreateIdealGasLaw.h"
#include "CreateLinear.h"
#include "CreateParameter.h"
#include "CreatePermeabilityMohrCoulombFailureIndexModel.h"
#include "CreatePermeabilityOrthotropicPowerLaw.h"
#include "CreatePorosityFromMassBalance.h"
#include "CreateSaturationDependentSwelling.h"
......
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
* Created on June 4, 2020, 10:13 AM
*/
#include "PermeabilityMohrCoulombFailureIndexModel.h"
#include <boost/math/constants/constants.hpp>
#include <cmath>
#include <limits>
#include "BaseLib/Error.h"
#include "MaterialLib/MPL/Medium.h"
#include "MaterialLib/MPL/Utils/FormEigenTensor.h"
#include "MaterialLib/MPL/Utils/GetSymmetricTensor.h"
#include "MathLib/KelvinVector.h"
#include "MathLib/MathTools.h"
#include "ParameterLib/CoordinateSystem.h"
#include "ParameterLib/Parameter.h"
namespace MaterialPropertyLib
{
template <int DisplacementDim>
PermeabilityMohrCoulombFailureIndexModel<DisplacementDim>::
PermeabilityMohrCoulombFailureIndexModel(
std::string name, ParameterLib::Parameter<double> const& k0,
double const kr, double const b, double const c, double const phi,
double const k_max, double const t_sigma_max,
ParameterLib::CoordinateSystem const* const local_coordinate_system)
: k0_(k0),
kr_(kr),
b_(b),
c_(c),
phi_(boost::math::constants::degree<double>() * phi),
k_max_(k_max),
t_sigma_max_(t_sigma_max),
local_coordinate_system_(local_coordinate_system)
{
const double t_sigma_upper = c_ / std::tan(phi_);
if (t_sigma_max_ <= 0.0 || t_sigma_max_ > t_sigma_upper ||
std::fabs(t_sigma_max_ - t_sigma_upper) <
std::numeric_limits<double>::epsilon())
{
OGS_FATAL(
"Tensile strength parameter of {:e} is out of the range (0, "
"c/tan(phi)) = (0, {:e})",
t_sigma_max_, t_sigma_upper);
}
name_ = std::move(name);
}
template <int DisplacementDim>
void PermeabilityMohrCoulombFailureIndexModel<DisplacementDim>::checkScale()
const
{
if (!std::holds_alternative<Medium*>(scale_))
{
OGS_FATAL(
"The property 'PermeabilityMohrCoulombFailureIndexModel' is "
"implemented on the 'medium' scale only.");
}
}
template <int DisplacementDim>
PropertyDataType
PermeabilityMohrCoulombFailureIndexModel<DisplacementDim>::value(
VariableArray const& variable_array,
ParameterLib::SpatialPosition const& pos, double const t,
double const /*dt*/) const
{
auto const& stress_vector = std::get<SymmetricTensor<DisplacementDim>>(
variable_array[static_cast<int>(Variable::stress)]);
auto const& stress_tensor =
formEigenTensor<3>(static_cast<PropertyDataType>(stress_vector));
Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, 3, 3>>
eigenvalue_solver(stress_tensor);
// Principle stress
auto const sigma = eigenvalue_solver.eigenvalues();
auto k_data = k0_(t, pos);
double const max_sigma = std::max(std::fabs(sigma[0]), std::fabs(sigma[2]));
if (max_sigma < std::numeric_limits<double>::epsilon())
{
return fromVector(k_data);
}
double const sigma_m = 0.5 * (sigma[2] + sigma[0]);
double const tau_m = 0.5 * std::fabs(sigma[2] - sigma[0]);
double f = 0.0;
if (sigma_m > t_sigma_max_)
{
// tensile failure criterion
f = sigma_m / t_sigma_max_;
double const tau_tt =
c_ * std::cos(phi_) - t_sigma_max_ * std::sin(phi_);
f = std::max(f, tau_m / tau_tt);
}
else
{
// Mohr Coulomb failure criterion
f = tau_m / (c_ * std::cos(phi_) - sigma_m * std::sin(phi_));
}
if (f >= 1.0)
{
const double exp_value = std::exp(b_ * f);
for (auto& k_i : k_data)
{
k_i = std::min(k_i + kr_ * exp_value, k_max_);
}
}
// Local coordinate transformation is only applied for the case that the
// initial intrinsic permeability is given with orthotropic assumption.
if (local_coordinate_system_ && (k_data.size() == DisplacementDim))
{
Eigen::Matrix<double, DisplacementDim, DisplacementDim> const e =
local_coordinate_system_->transformation<DisplacementDim>(pos);
Eigen::Matrix<double, DisplacementDim, DisplacementDim> k =
Eigen::Matrix<double, DisplacementDim, DisplacementDim>::Zero();
for (int i = 0; i < DisplacementDim; ++i)
{
Eigen::Matrix<double, DisplacementDim, DisplacementDim> const
ei_otimes_ei = e.col(i) * e.col(i).transpose();
k += k_data[i] * ei_otimes_ei;
}
return k;
}
return fromVector(k_data);
}
template <int DisplacementDim>
PropertyDataType
PermeabilityMohrCoulombFailureIndexModel<DisplacementDim>::dValue(
VariableArray const& /*variable_array*/, Variable const /*variable*/,
ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/,
double const /*dt*/) const
{
OGS_FATAL(
"The derivative of the intrinsic permeability k(sigma, ...) with "
"respect to stress tensor (sigma) is not implemented because that "
"dk/du is normally omitted.");
}
template class PermeabilityMohrCoulombFailureIndexModel<2>;
template class PermeabilityMohrCoulombFailureIndexModel<3>;
} // namespace MaterialPropertyLib
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
* Created on June 4, 2020, 10:13 AM
*/
#pragma once
#include "MaterialLib/MPL/Property.h"
#include "MaterialLib/MPL/VariableType.h"
namespace ParameterLib
{
struct CoordinateSystem;
template <typename T>
struct Parameter;
} // namespace ParameterLib
namespace MaterialPropertyLib
{
/**
* \brief A failure index dependent permeability model \cite wangetalPerm2020
*
* \f[ \mathbf{k} =
* \mathbf{k}_0+ H(f-1) k_\text{r} \mathrm{e}^{b f}\mathbf{I}\f]
*
* where
* \f$\mathbf{k}_0\f$ is the intrinsic permeability
* of the undamaged material,
* \f$H\f$ is the Heaviside step function, \f$f\f$ is the failure index,
* \f$k_\text{r}\f$ is a reference permeability,
* \f$b\f$ is a fitting parameter.
* \f$k_\text{r}\f$ and \f$b\f$ can be calibrated by experimental data.
*
* The failure index \f$f\f$ is calculated from the Mohr Coulomb failure
* criterion comparing an acting shear stress for the shear dominated failure.
* The tensile failure is governed by an input parameter of
* tensile_strength_parameter .
*
* The Mohr Coulomb failure
* criterion \cite labuz2012mohr takes
* the form
* \f[\tau(\sigma)=c-\sigma \mathrm{tan} \phi\f]
* with \f$\tau\f$ the shear stress, \f$c\f$ the cohesion, \f$\sigma\f$ the
* normal stress, and \f$\phi\f$ the internal friction angle.
*
* The failure index of the Mohr Coulomb model is calculated by
* \f[
* f_{MC}=\frac{|\tau_m| }{\cos(\phi)\tau(\sigma_m)}
* \f]
* with
* \f$\tau_m=(\sigma_3-\sigma_1)/2\f$
* and \f$\sigma_m=(\sigma_1+\sigma_3)/2\f$,
* where \f$\sigma_1\f$ and \f$\sigma_3\f$ are the minimum and maximum shear
* stress, respectively.
*
* The tensile failure index is calculated by
* \f[
* f_{t} = \sigma_m / \sigma^t_{max}
* \f]
* with, \f$0 < \sigma^t_{max} < c \tan(\phi) \f$, a parameter of tensile
* strength for the cutting of the apex of the Mohr Coulomb model.
*
* The tensile stress status is determined by a condition of \f$\sigma_m>
* \sigma^t_{max}\f$. The failure index is then calculated by
* \f[
* f =
* \begin{cases}
* f_{MC}, & \sigma_{m} \leq \sigma^t_{max}\\
* max(f_{MC}, f_t), & \sigma_{m} > \sigma^t_{max}\\
* \end{cases}
* \f]
*
* The computed permeability components are restricted with an upper bound,
* i.e. \f$\mathbf{k}:=k_{ij} < k_{max}\f$.
*
* If \f$\mathbf{k}_0\f$ is orthogonal, i.e input two or three numbers
* for its diagonal entries, a coordinate system rotation of \f$\mathbf{k}\f$
* is possible if it is needed.
*
* Note: the conventional mechanics notations are used, which mean that tensile
* stress is positive.
*
*/
template <int DisplacementDim>
class PermeabilityMohrCoulombFailureIndexModel final : public Property
{
public:
PermeabilityMohrCoulombFailureIndexModel(
std::string name, ParameterLib::Parameter<double> const& k0,
double const kr, double const b, double const c, double const phi,
double const k_max, double const t_sigma_max,
ParameterLib::CoordinateSystem const* const local_coordinate_system);
void checkScale() const override;
PropertyDataType value(VariableArray const& variable_array,
ParameterLib::SpatialPosition const& pos,
double const t, double const dt) const override;
PropertyDataType dValue(VariableArray const& variable_array,
Variable const variable,
ParameterLib::SpatialPosition const& pos,
double const t, double const dt) const override;
private:
/// Intrinsic permeability for undamaged material. It can be a scalar or
/// tensor for anisotropic material.
ParameterLib::Parameter<double> const& k0_;
/// Reference permeability.
double const kr_;
/// Fitting parameter.
double const b_;
/// Cohesion.
double const c_;
/// Angle of internal friction.
double const phi_;
/// Maximum permeability.
double const k_max_;
/// Tensile strength parameter.
double const t_sigma_max_;
ParameterLib::CoordinateSystem const* const local_coordinate_system_;
};
} // namespace MaterialPropertyLib
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
* Created on June 8, 2020, 9:17 AM
*/
#include <gtest/gtest.h>
#include <Eigen/Eigen>
#include <boost/math/constants/constants.hpp>
#include "MaterialLib/MPL/Medium.h"
#include "MaterialLib/MPL/Properties/CreatePermeabilityMohrCoulombFailureIndexModel.h"
#include "MaterialLib/MPL/Properties/PermeabilityMohrCoulombFailureIndexModel.h"
#include "MaterialLib/MPL/Utils/FormEigenTensor.h"
#include "MathLib/KelvinVector.h"
#include "ParameterLib/ConstantParameter.h"
#include "TestMPL.h"
#include "Tests/TestTools.h"
TEST(MaterialPropertyLib, PermeabilityMohrCoulombFailureIndexModel)
{
ParameterLib::ConstantParameter<double> const k0("k0", 1.e-20);
double const kr = 1.0e-19;
double const b = 3.0;
double const c = 1.0e+6;
double const phi = 15.0;
double const k_max = 1.e-10;
double const t_sigma_max = c;
auto const k_model = MPL::PermeabilityMohrCoulombFailureIndexModel<3>(
"k_f", k0, kr, b, c, phi, k_max, t_sigma_max, nullptr);
const int symmetric_tensor_size = 6;
using SymmetricTensor = Eigen::Matrix<double, symmetric_tensor_size, 1>;
// Under failure, i,e stress beyond the yield.
SymmetricTensor stress;
stress[0] = -1.36040e+7;
stress[1] = -1.78344e+7;
stress[2] = -1.36627e+7;
stress[3] = -105408;
stress[4] = -25377.2;
stress[5] = -1.39944e+7;
MPL::VariableArray vars;
vars[static_cast<int>(MPL::Variable::stress)].emplace<SymmetricTensor>(
stress);
ParameterLib::SpatialPosition const pos;
double const t = std::numeric_limits<double>::quiet_NaN();
double const dt = std::numeric_limits<double>::quiet_NaN();
auto const k = MPL::formEigenTensor<3>(k_model.value(vars, pos, t, dt));
double const k_expected = 1.1398264890628033e-15;
ASSERT_LE(std::fabs(k_expected - k(0, 0)) / k_expected, 1e-10)
<< "for expected changed permeability " << k_expected
<< " and for computed changed permeability." << k(0, 0);
// Stress outside of the yield surface. No change in permeability
stress[0] = -1.2e+7;
stress[1] = -1.5e+7;
stress[2] = -1.2e+7;
stress[3] = -1e+5;
stress[4] = -2200.2;
stress[5] = -8e+5;
vars[static_cast<int>(MPL::Variable::stress)] = stress;
auto const k_non_f =
MPL::formEigenTensor<3>(k_model.value(vars, pos, t, dt));
auto const k_non_f_expected = k0(t, pos)[0];
ASSERT_LE(std::fabs(k_non_f_expected - k_non_f(0, 0)) / k_non_f_expected,
1e-19)
<< "for expected untouched permeability" << k_non_f_expected
<< " and for computed untouched permeability." << k_non_f(0, 0);
// Stress at the apex. No change in permeability.
const double val =
2.0 * c / std::tan(phi * boost::math::constants::degree<double>());
stress[0] = 0.7 * val;
stress[1] = 0.3 * val;
stress[2] = 0.3 * val;
stress[3] = 0.0;
stress[4] = 0.0;
stress[5] = 0.0;
vars[static_cast<int>(MPL::Variable::stress)] = stress;
auto const k_apex_f =
MPL::formEigenTensor<3>(k_model.value(vars, pos, t, dt));
double const k_apex_expacted = 7.2849707418474819e-15;
ASSERT_LE(std::fabs(k_apex_expacted - k_apex_f(0, 0)) / k_apex_expacted,
1e-19)
<< "for expected untouched permeability" << k_non_f_expected
<< " and for computed untouched permeability." << k_apex_f(0, 0);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment