void
FiniteStrainRatePlasticMaterial::computeQpStress()
{
  RankTwoTensor dp,sig;

  //Obtain previous plastic rate of deformation tensor
  dp=_plastic_strain_old[_qp];

  //Solve J2 plastic constitutive equations based on current strain increment
  //Returns current  stress and plastic rate of deformation tensor

  returnMap(_stress_old[_qp], _strain_increment[_qp], _elasticity_tensor[_qp], dp, sig);
  _stress[_qp] = sig;

  //Rotate the stress to the current configuration
  _stress[_qp] = _rotation_increment[_qp] * _stress[_qp] * _rotation_increment[_qp].transpose();

  //Updates current plastic rate of deformation tensor
  _plastic_strain[_qp] = dp;

  //Evaluate and update current equivalent plastic strain
  _eqv_plastic_strain[_qp] = std::pow(2.0/3.0,0.5) * dp.L2norm();

  //Calculate elastic strain increment
  RankTwoTensor delta_ee = _strain_increment[_qp]-(_plastic_strain[_qp]-_plastic_strain_old[_qp]);

  //Update elastic strain tensor in intermediate configuration
  _elastic_strain[_qp] = _elastic_strain_old[_qp] + delta_ee;

  //Rotate elastic strain tensor to the current configuration
  _elastic_strain[_qp] = _rotation_increment[_qp] * _elastic_strain[_qp] * _rotation_increment[_qp].transpose();

  //Rotate to plastic rate of deformation tensor the current configuration
  _plastic_strain[_qp] = _rotation_increment[_qp] * _plastic_strain[_qp] * _rotation_increment[_qp].transpose();

  //Update strain in intermediate configuration
  _total_strain[_qp] = _total_strain_old[_qp] + _strain_increment[_qp];

  //Rotate strain to current configuration
  _total_strain[_qp] = _rotation_increment[_qp] * _total_strain[_qp] * _rotation_increment[_qp].transpose();

}
void
FiniteStrainPlasticMaterial::computeQpStress()
{

  // perform the return-mapping algorithm
  returnMap(_stress_old[_qp],
            _eqv_plastic_strain_old[_qp],
            _plastic_strain_old[_qp],
            _strain_increment[_qp],
            _elasticity_tensor[_qp],
            _stress[_qp],
            _eqv_plastic_strain[_qp],
            _plastic_strain[_qp]);

  // Rotate the stress tensor to the current configuration
  _stress[_qp] = _rotation_increment[_qp] * _stress[_qp] * _rotation_increment[_qp].transpose();

  // Rotate plastic strain tensor to the current configuration
  _plastic_strain[_qp] =
      _rotation_increment[_qp] * _plastic_strain[_qp] * _rotation_increment[_qp].transpose();

  _Jacobian_mult[_qp] = _elasticity_tensor[_qp];
}
Esempio n. 3
0
void
FiniteStrainPlasticBase::computeQpStress()
{
  if (_fspb_debug == 3)
  {
    checkJacobian();
    mooseError("Jacobian has been checked.  Exiting with no error");
  }

  preReturnMap();

  /**
   * the idea in the following is to potentially subdivide the
   * strain increment into smaller portions
   * First one subdivision is tried, and if that fails then
   * 2 are tried, then 4, etc.  This is in the hope that the
   * time-step for the entire mesh need not be cut if there
   * are only a few "bad" quadpoints where the return-map
   * is difficult
   */

  bool return_successful = false;

  // number of subdivisions of the strain increment currently being tried
  unsigned int num_subdivisions = 1;

  while (num_subdivisions <= _max_subdivisions && !return_successful)
  {
    // prepare the variables for this set of strain increments
    RankTwoTensor dep = _strain_increment[_qp]/num_subdivisions;
    RankTwoTensor stress_previous = _stress_old[_qp];
    RankTwoTensor plastic_strain_previous = _plastic_strain_old[_qp];
    std::vector<Real> intnl_previous;
    intnl_previous.resize(_intnl_old[_qp].size());
    for (unsigned int a = 0; a < _intnl_old[_qp].size(); ++a)
      intnl_previous[a] = _intnl_old[_qp][a];


    // now do the work: apply the "dep" over num_subdivisions "substeps"
    for (unsigned substep = 0 ; substep < num_subdivisions ; ++substep)
    {
      return_successful = returnMap(stress_previous, plastic_strain_previous, _intnl_old[_qp], dep, _elasticity_tensor[_qp], _stress[_qp], _plastic_strain[_qp], _intnl[_qp], _f[_qp], _iter[_qp]);
      if (return_successful)
      {
        // record the updated variables in readiness for the next substep
        stress_previous = _stress[_qp];
        plastic_strain_previous = _plastic_strain[_qp];
        for (unsigned int a = 0; a < _intnl_old[_qp].size(); ++a)
          intnl_previous[a] = _intnl[_qp][a];
      }
      else
        break; // oh dear, we need to increase the number of subdivisions
    }

    if (!return_successful)
      num_subdivisions *= 2;
  }

  if (!return_successful)
  {
    _console << "After making " << num_subdivisions << " subdivisions of the strain increment with L2norm " << _strain_increment[_qp].L2norm() << " the returnMap algorithm failed\n";
    _fspb_debug_stress = _stress_old[_qp];
    _fspb_debug_pm.assign(numberOfYieldFunctions(), 1); // this is chosen arbitrarily - please change if a more suitable value occurs to you!
    _fspb_debug_intnl.resize(numberOfInternalParameters());
    for (unsigned a = 0 ; a < numberOfInternalParameters() ; ++a)
      _fspb_debug_intnl[a] = _intnl_old[_qp][a];
    checkDerivatives();
    checkJacobian();
    mooseError("Exiting\n");
  }


  postReturnMap();

  //Update measures of strain
  _elastic_strain[_qp] = _elastic_strain_old[_qp] + _strain_increment[_qp] - (_plastic_strain[_qp] - _plastic_strain_old[_qp]);
  _total_strain[_qp] = _total_strain_old[_qp] + _strain_increment[_qp];

  //Rotate the tensors to the current configuration
  _stress[_qp] = _rotation_increment[_qp]*_stress[_qp]*_rotation_increment[_qp].transpose();
  _elastic_strain[_qp] = _rotation_increment[_qp] * _elastic_strain[_qp] * _rotation_increment[_qp].transpose();
  _total_strain[_qp] = _rotation_increment[_qp] * _total_strain[_qp] * _rotation_increment[_qp].transpose();
  _plastic_strain[_qp] = _rotation_increment[_qp] * _plastic_strain[_qp] * _rotation_increment[_qp].transpose();
}