Revision 496c81a5c6e53a04073e11a4b96c85024abea7a3 authored by Thomas Poulet on 05 June 2019, 12:49:37 UTC, committed by GitHub on 05 June 2019, 12:49:37 UTC
2 parent s e57928f + df76c92
Raw File
RedbackMechMaterialCCanisotropic.C
/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/*     REDBACK - Rock mEchanics with Dissipative feedBACKs      */
/*                                                              */
/*              (c) 2014 CSIRO and UNSW Australia               */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*            Prepared by CSIRO and UNSW Australia              */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "Ellipse.h"
#include "RedbackMechMaterialCCanisotropic.h"
#include <cmath> //used for fabs

registerMooseObject("RedbackApp", RedbackMechMaterialCCanisotropic);

template <>
InputParameters
validParams<RedbackMechMaterialCCanisotropic>()
{
  InputParameters params = validParams<RedbackMechMaterialCC>();
  params.addParam<Real>(
      "initial_anisotropy_param", 0, "Initial anisotropy coefficient (from Dafalias 2013)");

  return params;
}

RedbackMechMaterialCCanisotropic::RedbackMechMaterialCCanisotropic(
    const InputParameters & parameters)
  : RedbackMechMaterialCC(parameters),
    _initial_anisotropy_param(getParam<Real>("initial_anisotropy_param")),
    _anisotropy_coeff(declareProperty<Real>("anisotropy_coeff"))
{
}

void
RedbackMechMaterialCCanisotropic::stepInitQpProperties()
{
  RedbackMechMaterialCC::stepInitQpProperties();
  // Variable initialisation (called at each step)
  if (_t == 0)
    _anisotropy_coeff[_qp] = _initial_anisotropy_param; // TODO: implement \dot{alpha}
  else
    _anisotropy_coeff[_qp] =
        _anisotropy_coeff[_qp] + 0 * (_slope_yield_surface - _anisotropy_coeff[_qp]) *
                                     _dt; // TODO:check the sign of the anisotropy coefficient
}

/**
 * Get unitary flow tensor in deviatoric direction, modified Cam-Clay
 */
void
RedbackMechMaterialCCanisotropic::getFlowTensor(const RankTwoTensor & sig,
                                                Real q,
                                                Real p,
                                                Real /*q_y*/,
                                                Real /*p_y*/,
                                                Real pc,
                                                RankTwoTensor & flow_tensor)
{
  if (pc > 0)
    pc *= -1;

  Real M_squared = _slope_yield_surface * _slope_yield_surface;
  Real alpha_squared = _anisotropy_coeff[_qp] * _anisotropy_coeff[_qp];
  if (q != 0)
    flow_tensor = 3.0 * ((q - _anisotropy_coeff[_qp] * p) / q) * sig.deviatoric() /
                  (M_squared - alpha_squared);
  else
    flow_tensor.zero(); // TODO: is that the right thing to do?
  flow_tensor.addIa(2.0 * p - pc -
                    2.0 * _anisotropy_coeff[_qp] * (q - _anisotropy_coeff[_qp] * p) /
                        (M_squared - alpha_squared) / 3.0); //(p > 0 ? 1:-1)
  // TODO: do we need to normalise? If so, do we need the sqrt(3/2) factor?
  // flow_tensor /= std::pow(2.0/3.0,0.5)*flow_tensor.L2norm();
}

/**
 * Compute the flow incrmement for modified Cam-clay
 * pc ... pre-consolidation pressure (pc = -getYieldStress(eqvpstrain))
 */
Real
RedbackMechMaterialCCanisotropic::getFlowIncrement(
    Real sig_eqv, Real pressure, Real q_yield_stress, Real p_yield_stress, Real pc)
{
  pc *= -1;
  if (Ellipse::isPointOutsideOfRotatedEllipse(/*m=*/_slope_yield_surface,
                                              /*p_0=*/pc,
                                              /*alpha=*/_anisotropy_coeff[_qp],
                                              /*x=*/pressure,
                                              /*y=*/sig_eqv))
  {
    Real flow_incr_vol = _ref_pe_rate * _dt *
                         std::pow(std::fabs(pressure - p_yield_stress), _exponent) * _exponential;
    Real flow_incr_dev = _ref_pe_rate * _dt *
                         std::pow(std::fabs(sig_eqv - q_yield_stress), _exponent) * _exponential;
    return std::pow(flow_incr_vol * flow_incr_vol + flow_incr_dev * flow_incr_dev, 0.5);
  }
  else
    return 0;
}

Real
RedbackMechMaterialCCanisotropic::getDerivativeFlowIncrement(const RankTwoTensor & /*sig*/,
                                                             Real pressure,
                                                             Real sig_eqv,
                                                             Real pc,
                                                             Real q_yield_stress,
                                                             Real p_yield_stress)
{
  if (Ellipse::isPointOutsideOfRotatedEllipse(/*m=*/_slope_yield_surface,
                                              /*p_0=*/pc,
                                              /*alpha=*/_anisotropy_coeff[_qp],
                                              /*x=*/pressure,
                                              /*y=*/sig_eqv))
  {
    Real delta_lambda_p = _ref_pe_rate * _dt *
                          std::pow(std::fabs(pressure - p_yield_stress), _exponent) * _exponential;
    Real delta_lambda_q = _ref_pe_rate * _dt *
                          std::pow(std::fabs(sig_eqv - q_yield_stress), _exponent) * _exponential;
    Real delta_lambda =
        (std::pow(delta_lambda_p * delta_lambda_p + delta_lambda_q * delta_lambda_q, 0.5));
    Real der_flow_incr_dev = _ref_pe_rate * _dt * _exponent *
                             std::pow(std::fabs(sig_eqv - q_yield_stress), _exponent - 1.0) *
                             _exponential;
    Real der_flow_incr_vol = _ref_pe_rate * _dt * _exponent *
                             std::pow(std::fabs(pressure - p_yield_stress), _exponent - 1.0) *
                             _exponential;
    return (delta_lambda_q * der_flow_incr_dev + delta_lambda_p * der_flow_incr_vol) / delta_lambda;
  }
  else
    return 0;
}

void
RedbackMechMaterialCCanisotropic::getJac(const RankTwoTensor & sig,
                                         const RankFourTensor & E_ijkl,
                                         Real flow_incr,
                                         Real sig_eqv,
                                         Real pressure,
                                         Real p_yield_stress,
                                         Real q_yield_stress,
                                         Real pc,
                                         RankFourTensor & dresid_dsig)
{
  unsigned i, j, k, l;
  RankTwoTensor sig_dev, flow_dirn_vol, flow_dirn_dev, fij, flow_dirn, flow_tensor;
  RankTwoTensor dfi_dft;
  RankFourTensor dfd_dsig, dfi_dsig;
  Real f1, f2, f3, f4, f5;
  Real dfi_dseqv;

  pc *= -1; // TODO: check sign at very beginning, only once, and stick to
            // whatever convention!

  sig_dev = sig.deviatoric();

  dfi_dseqv =
      getDerivativeFlowIncrement(sig, pressure, sig_eqv, pc, q_yield_stress, p_yield_stress);
  getFlowTensor(sig, sig_eqv, pressure, q_yield_stress, p_yield_stress, pc, flow_dirn);

  /* The following calculates the tensorial derivative (Jacobian) of the
   * residual with respect to stress, dr_dsig
   * It consists of two terms: The first is
   * dr_dsig = (dfi_dseqv_dev*flow_dirn_dev(k,l)) * flow_dirn_dev(i,j)
   * which is the tensorial product of the flow increment tensor times the flow
   * direction tensor
   *
   * The second is the product of the flow increment tensor times the derivative
   * of the flow direction tensor
   * with respect to the stress tensor. See also REDBACK's documentation
   * */

  // This loop calculates the first term
  for (i = 0; i < 3; ++i)
    for (j = 0; j < 3; ++j)
      for (k = 0; k < 3; ++k)
        for (l = 0; l < 3; ++l)
          dfi_dsig(i, j, k, l) = flow_dirn(i, j) * flow_dirn(k, l) * dfi_dseqv;

  // Real flow_tensor_norm = flow_dirn.L2norm();

  // This loop calculates the second term. Read REDBACK's documentation
  // (same as J2 plasticity case)
  f1 = 0.0;
  f2 = 0.0;
  if (sig_eqv > 1e-8)
  {
    f1 = 3.0 / (_slope_yield_surface * _slope_yield_surface -
                _anisotropy_coeff[_qp] * _anisotropy_coeff[_qp]);
    f2 = f1 * (1.0 - _anisotropy_coeff[_qp] * p_yield_stress / q_yield_stress);
    f3 = -f1 *
         (1.0 - _anisotropy_coeff[_qp] * p_yield_stress / q_yield_stress -
          2 * _slope_yield_surface * _slope_yield_surface / 9.0) /
         3.0;
    f4 = -f1 * (_anisotropy_coeff[_qp] / (3.0 * q_yield_stress));
    f5 = f1 *
         (3.0 * _anisotropy_coeff[_qp] * p_yield_stress / (2.0 * q_yield_stress * q_yield_stress));
  }
  for (i = 0; i < 3; ++i)
    for (j = 0; j < 3; ++j)
      for (k = 0; k < 3; ++k)
        for (l = 0; l < 3; ++l)
          dfd_dsig(i, j, k, l) =
              f2 * deltaFunc(i, k) * deltaFunc(j, l) + f3 * deltaFunc(i, j) * deltaFunc(k, l) +
              f4 * sig_dev(i, j) * deltaFunc(k, l) + f5 * sig_dev(i, j) * sig_dev(k, l) +
              f4 * deltaFunc(i, j) * sig_dev(k, l); // d_flow_dirn/d_sig - 2nd part

  // dfd_dsig = dft_dsig1/flow_tensor_norm - 3.0 * dft_dsig2 /
  // (2*sig_eqv*flow_tensor_norm*flow_tensor_norm*flow_tensor_norm);
  // //d_flow_dirn/d_sig
  // TODO: check if the previous two lines (i.e normalizing the flow vector)
  // should be activated or not. Currently we are using the non-unitary flow
  // vector

  dresid_dsig = E_ijkl.invSymm() + dfd_dsig * flow_incr + dfi_dsig; // Jacobian
}

void
RedbackMechMaterialCCanisotropic::get_py_qy(
    Real p, Real q, Real & p_y, Real & q_y, Real yield_stress, bool & is_plastic)
{
  Ellipse::distanceCCanisotropic(
      _slope_yield_surface, -yield_stress, _anisotropy_coeff[_qp], p, q, p_y, q_y);
  Real pc = -yield_stress;
  is_plastic = Ellipse::isPointOutsideOfRotatedEllipse(
      /*m=*/_slope_yield_surface,
      /*p_0=*/pc,
      /*alpha=*/_anisotropy_coeff[_qp],
      /*x=*/p,
      /*y=*/q);
}
back to top