Пример #1
0
void
AxisymmetricRZ::computeStrain( const unsigned qp,
                               const SymmTensor & total_strain_old,
                               SymmTensor & total_strain_new,
                               SymmTensor & strain_increment )
{
  strain_increment.xx() = _grad_disp_r[qp](0);
  strain_increment.yy() = _grad_disp_z[qp](1);
  strain_increment.zz() = (_solid_model.q_point(qp)(0) != 0.0 ? _disp_r[qp]/_solid_model.q_point(qp)(0) : 0.0);
  strain_increment.xy() = 0.5*(_grad_disp_r[qp](1) + _grad_disp_z[qp](0));
  if (_large_strain)
  {
    strain_increment.xx() += 0.5*(_grad_disp_r[qp](0)*_grad_disp_r[qp](0) +
                                  _grad_disp_z[qp](0)*_grad_disp_z[qp](0));
    strain_increment.yy() += 0.5*(_grad_disp_r[qp](1)*_grad_disp_r[qp](1) +
                                  _grad_disp_z[qp](1)*_grad_disp_z[qp](1));
    strain_increment.zz() += 0.5*(strain_increment.zz()*strain_increment.zz());
    strain_increment.xy() += 0.5*(_grad_disp_r[qp](0)*_grad_disp_r[qp](1) +
                                  _grad_disp_z[qp](0)*_grad_disp_z[qp](1));
  }

  total_strain_new = strain_increment;

  strain_increment -= total_strain_old;
}
Пример #2
0
bool
ConstitutiveModel::applyThermalStrain(unsigned qp,
                                      SymmTensor & strain_increment,
                                      SymmTensor & d_strain_dT)
{
  if (_has_temp && _t_step != 0)
  {
    Real inc_thermal_strain;
    Real d_thermal_strain_d_temp;

    Real old_temp;
    if (_t_step == 1 && _has_stress_free_temp)
      old_temp = _stress_free_temp;
    else
      old_temp = _temperature_old[qp];

    Real current_temp = _temperature[qp];

    Real delta_t = current_temp - old_temp;

    Real alpha = _alpha;

    if (_alpha_function)
    {
      Point p;
      Real alpha_current_temp = _alpha_function->value(current_temp,p);
      Real alpha_old_temp = _alpha_function->value(old_temp,p);

      if (_mean_alpha_function)
      {
        Real small(1e-6);

        Real numerator = alpha_current_temp * (current_temp - _ref_temp) - alpha_old_temp * (old_temp - _ref_temp);
        Real denominator = 1.0 + alpha_old_temp * (old_temp - _ref_temp);
        if (denominator < small)
          mooseError("Denominator too small in thermal strain calculation");
        inc_thermal_strain = numerator / denominator;
        d_thermal_strain_d_temp = alpha_current_temp * (current_temp - _ref_temp);
      }
      else
      {
        inc_thermal_strain = delta_t * 0.5 * (alpha_current_temp + alpha_old_temp);
        d_thermal_strain_d_temp = alpha_current_temp;
      }
    }
    else
    {
      inc_thermal_strain = delta_t * alpha;
      d_thermal_strain_d_temp = alpha;
    }

    strain_increment.addDiag(-inc_thermal_strain);
    d_strain_dT.addDiag(-d_thermal_strain_d_temp);

  }

  bool modified = true;
  return modified;
}
Real
volumetricStrain(const SymmTensor & symm_strain)
{
  Real value = symm_strain.trace();
  value += symm_strain.xx() * symm_strain.yy() + symm_strain.yy() * symm_strain.zz() +
           symm_strain.zz() * symm_strain.xx() +
           symm_strain.xx() * symm_strain.yy() * symm_strain.zz();
  return value;
}
Пример #4
0
Real
StressDivergence::computeQpJacobian()
{
  Real sum_C3x3 = _Jacobian_mult[_qp].sum_3x3();
  RealGradient sum_C3x1 = _Jacobian_mult[_qp].sum_3x1();

  Real jacobian = 0.0;
  // B^T_i * C * B_j
  jacobian += _Jacobian_mult[_qp].stiffness(
      _component, _component, _grad_test[_i][_qp], _grad_phi[_j][_qp]); // B^T_i * C *B_j

  if (_volumetric_locking_correction)
  {
    // jacobian = Bbar^T_i * C * Bbar_j where Bbar = B + Bvol
    // jacobian = B^T_i * C * B_j + Bvol^T_i * C * Bvol_j +  Bvol^T_i * C * B_j + B^T_i * C * Bvol_j

    // Bvol^T_i * C * Bvol_j
    jacobian += sum_C3x3 * (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) *
                (_avg_grad_phi[_j][_component] - _grad_phi[_j][_qp](_component)) / 9.0;

    // B^T_i * C * Bvol_j
    jacobian += sum_C3x1(_component) * _grad_test[_i][_qp](_component) *
                (_avg_grad_phi[_j][_component] - _grad_phi[_j][_qp](_component)) / 3.0;

    // Bvol^T_i * C * B_j
    SymmTensor phi;
    if (_component == 0)
    {
      phi.xx() = _grad_phi[_j][_qp](0);
      phi.xy() = _grad_phi[_j][_qp](1);
      phi.xz() = _grad_phi[_j][_qp](2);
    }
    else if (_component == 1)
    {
      phi.yy() = _grad_phi[_j][_qp](1);
      phi.xy() = _grad_phi[_j][_qp](0);
      phi.yz() = _grad_phi[_j][_qp](2);
    }
    else if (_component == 2)
    {
      phi.zz() = _grad_phi[_j][_qp](2);
      phi.xz() = _grad_phi[_j][_qp](0);
      phi.yz() = _grad_phi[_j][_qp](1);
    }

    SymmTensor tmp(_Jacobian_mult[_qp] * phi);

    jacobian += (tmp.xx() + tmp.yy() + tmp.zz()) *
                (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) / 3.0;
  }

  if (_dt > 0)
    return jacobian * (1 + _alpha + _zeta / _dt);
  else
    return jacobian;
}
Пример #5
0
void
PlaneStrain::computeStrain( const unsigned qp,
                               const SymmTensor & total_strain_old,
                               SymmTensor & total_strain_new,
                               SymmTensor & strain_increment )
{
  strain_increment.xx() = _grad_disp_x[qp](0);
  strain_increment.yy() = _grad_disp_y[qp](1);
  strain_increment.zz() = 0;
  strain_increment.xy() = 0.5*(_grad_disp_x[qp](1) + _grad_disp_y[qp](0));
  strain_increment.yz() = 0;
  strain_increment.zx() = 0;
  if (_large_strain)
  {
    strain_increment.xx() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](0) +
                                  _grad_disp_y[qp](0)*_grad_disp_y[qp](0));
    strain_increment.yy() += 0.5*(_grad_disp_x[qp](1)*_grad_disp_x[qp](1) +
                                  _grad_disp_y[qp](1)*_grad_disp_y[qp](1));
    strain_increment.xy() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](1) +
                                  _grad_disp_y[qp](0)*_grad_disp_y[qp](1));
  }

  total_strain_new = strain_increment;

  strain_increment -= total_strain_old;
}
Real
vonMisesStress(const SymmTensor & symm_stress)
{
  Real value = std::pow(symm_stress.xx() - symm_stress.yy(), 2) +
               std::pow(symm_stress.yy() - symm_stress.zz(), 2) +
               std::pow(symm_stress.zz() - symm_stress.xx(), 2) +
               6 * (std::pow(symm_stress.xy(), 2) + std::pow(symm_stress.yz(), 2) +
                    std::pow(symm_stress.zx(), 2));
  return std::sqrt(value / 2.0);
}
Пример #7
0
Real
StressDivergenceRSpherical::computeQpOffDiagJacobian(unsigned int jvar)
{

  if ( _temp_coupled && jvar == _temp_var )
  {
    SymmTensor test;
    test.xx() = _grad_test[_i][_qp](0);
    test.yy() = _test[_i][_qp] / _q_point[_qp](0);
    test.zz() = test.yy();
    return _d_stress_dT[_qp].doubleContraction(test) * _phi[_j][_qp];
  }

  return 0;
}
Пример #8
0
bool PoroElasticity::formPermeabilityTensor (SymmTensor& K,
                                             const Vectors&,
                                             const FiniteElement&,
                                             const Vec3& X) const
{
  const PoroMaterial* pmat = dynamic_cast<const PoroMaterial*>(material);
  if (!pmat) return false;

  Vec3 permeability = pmat->getPermeability(X);

  K.zero();
  for (size_t i = 1; i <= K.dim(); i++)
    K(i,i) = permeability(i);

  return true;
}
Пример #9
0
Real
MaterialTensorAux::principalValue( const SymmTensor & tensor, unsigned int index )
{
  ColumnMajorMatrix eval(3,1);
  ColumnMajorMatrix evec(3,3);
  tensor.columnMajorMatrix().eigen(eval, evec);
  // Eigen computes low to high.  We want high first.
  int i = -index + 2;
  return eval(i);
}
Пример #10
0
Real
calcPrincipleValues(const SymmTensor & symm_tensor, unsigned int index, RealVectorValue & direction)
{
    ColumnMajorMatrix eval(3,1);
    ColumnMajorMatrix evec(3,3);
    symm_tensor.columnMajorMatrix().eigen(eval, evec);
    // Eigen computes low to high.  We want high first.
    direction(0) = evec(0,index);
    direction(1) = evec(1,index);
    direction(2) = evec(2,index);
    return eval(index);
}
Пример #11
0
Real
StressDivergenceRZ::computeQpOffDiagJacobian(unsigned int jvar)
{

  if ( _rdisp_coupled && jvar == _rdisp_var )
  {
    return calculateJacobian( _component, 0 );
  }
  else if ( _zdisp_coupled && jvar == _zdisp_var )
  {
    return calculateJacobian( _component, 1 );
  }
  else if ( _temp_coupled && jvar == _temp_var )
  {
    SymmTensor test;
    if (_component == 0)
    {
      test.xx() = _grad_test[_i][_qp](0);
      test.xy() = 0.5*_grad_test[_i][_qp](1);
      test.zz() = _test[_i][_qp] / _q_point[_qp](0);
    }
    else
    {
      test.xy() = 0.5*_grad_test[_i][_qp](0);
      test.yy() = _grad_test[_i][_qp](1);
    }
    return _d_stress_dT[_qp].doubleContraction(test) * _phi[_j][_qp];
  }

  return 0;
}
Пример #12
0
void
Nonlinear::computeStrainIncrement( const ColumnMajorMatrix & Fhat,
                                   SymmTensor & strain_increment )
{

  //
  // A calculation of the strain at the mid-interval is probably more
  // accurate (second vs. first order).  This would require the
  // incremental deformation gradient at the mid-step, which we
  // currently don't have.  We would then have to calculate the
  // rotation for the whole step.
  //
  //
  // We are looking for:
  //     log( Uhat )
  //  =  log( sqrt( Fhat^T*Fhat ) )
  //  =  log( sqrt( Chat ) )
  // A Taylor series expansion gives:
  //     ( Chat - 0.25 * Chat^T*Chat - 0.75 * I )
  //  =  ( - 0.25 * Chat^T*Chat + Chat - 0.75 * I )
  //  =  ( (0.25*Chat - 0.75*I) * (Chat - I) )
  //  =  ( B * A )
  //    B
  //  = 0.25*Chat - 0.75*I
  //  = 0.25*(Chat - I) - 0.5*I
  //  = 0.25*A - 0.5*I
  //

  const Real Uxx = Fhat(0,0);
  const Real Uxy = Fhat(0,1);
  const Real Uxz = Fhat(0,2);
  const Real Uyx = Fhat(1,0);
  const Real Uyy = Fhat(1,1);
  const Real Uyz = Fhat(1,2);
  const Real Uzx = Fhat(2,0);
  const Real Uzy = Fhat(2,1);
  const Real Uzz = Fhat(2,2);

  const Real Axx = Uxx*Uxx + Uyx*Uyx + Uzx*Uzx - 1.0;
  const Real Axy = Uxx*Uxy + Uyx*Uyy + Uzx*Uzy;
  const Real Axz = Uxx*Uxz + Uyx*Uyz + Uzx*Uzz;
  const Real Ayy = Uxy*Uxy + Uyy*Uyy + Uzy*Uzy - 1.0;
  const Real Ayz = Uxy*Uxz + Uyy*Uyz + Uzy*Uzz;
  const Real Azz = Uxz*Uxz + Uyz*Uyz + Uzz*Uzz - 1.0;

  const Real Bxx = 0.25 * Axx - 0.5;
  const Real Bxy = 0.25 * Axy;
  const Real Bxz = 0.25 * Axz;
  const Real Byy = 0.25 * Ayy - 0.5;
  const Real Byz = 0.25 * Ayz;
  const Real Bzz = 0.25 * Azz - 0.5;

  strain_increment.xx( -(Bxx*Axx + Bxy*Axy + Bxz*Axz) );
  strain_increment.xy( -(Bxx*Axy + Bxy*Ayy + Bxz*Ayz) );
  strain_increment.zx( -(Bxx*Axz + Bxy*Ayz + Bxz*Azz) );
  strain_increment.yy( -(Bxy*Axy + Byy*Ayy + Byz*Ayz) );
  strain_increment.yz( -(Bxy*Axz + Byy*Ayz + Byz*Azz) );
  strain_increment.zz( -(Bxz*Axz + Byz*Ayz + Bzz*Azz) );

}
Пример #13
0
ColumnMajorMatrix
CrackFrontDefinition::rotateToCrackFrontCoords(const SymmTensor tensor, const unsigned int node_index) const
{
  ColumnMajorMatrix tensor_CMM;
  tensor_CMM(0,0) = tensor.xx();
  tensor_CMM(0,1) = tensor.xy();
  tensor_CMM(0,2) = tensor.xz();
  tensor_CMM(1,0) = tensor.xy();
  tensor_CMM(1,1) = tensor.yy();
  tensor_CMM(1,2) = tensor.yz();
  tensor_CMM(2,0) = tensor.xz();
  tensor_CMM(2,1) = tensor.yz();
  tensor_CMM(2,2) = tensor.zz();

  ColumnMajorMatrix tmp = _rot_matrix[node_index] * tensor_CMM;
  ColumnMajorMatrix rotT = _rot_matrix[node_index].transpose();
  ColumnMajorMatrix rotated_tensor = tmp * rotT;

  return rotated_tensor;
}
Пример #14
0
void
CardiacHolzapfel2009Material::computeQpStressProperties(const SymmTensor &C, const SymmTensor & /*E*/)
{
  const SymmTensor CC(square(C));
  // invariants (We will not need all of them. However, defining them avoids to forget any.)
  const Real I1(C.trace());
  /*const Real I2(0.5*(I1*I1-CC.trace()));*/
  /*const Real I3(_J[_qp]);               */
  const Real I4f(_Ef[_qp]*(C*_Ef[_qp]));
  const Real I4s(_Es[_qp]*(C*_Es[_qp]));
  /*const Real I4n(_En[_qp]*(C*_En[_qp])); */
  /*const Real I5f(_Ef[_qp]*(CC*_Ef[_qp]));*/
  /*const Real I5s(_Es[_qp]*(CC*_Es[_qp]));*/
  /*const Real I5n(_En[_qp]*(CC*_En[_qp]));*/
  const Real I8fs(_Ef[_qp]*(C*_Es[_qp]));
  /*const Real I8fn(_Ef[_qp]*(C*_En[_qp]));*/
  /*const Real I8sn(_Es[_qp]*(C*_En[_qp]));*/

  // the following will be needed in the stress as well as in the energy and stress_derivative
  const Real  i_term(   _p[A1 ]*std::exp(_p[B1 ]*(I1 -3)        ) );
  const Real  f_term( 2*_p[Af ]*std::exp(_p[Bf ]*(I4f-1)*(I4f-1)) );
  const Real  s_term( 2*_p[As ]*std::exp(_p[Bs ]*(I4s-1)*(I4s-1)) );
  const Real fs_term(   _p[Afs]*std::exp(_p[Bfs]* I8fs  * I8fs  ) );

  // elastic energy contribution
  _W[_qp] =  i_term             /(2*_p[B1 ])
         + ( f_term - 2*_p[Af ])/(2*_p[Bf ])
         + ( s_term - 2*_p[As ])/(2*_p[Bs ])
         + (fs_term - 2*_p[Afs])/(2*_p[Bfs]);

  // tensors for constructing stress and stress_derivative
  const SymmTensor EfEf(kron(_Ef[_qp]));
  const SymmTensor EsEs(kron(_Es[_qp]));
  const SymmTensor EfEs(kronSym(_Ef[_qp],_Es[_qp]));

  // stress
  _stress[_qp] = scaledID(i_term) + EfEf*(I4f-1)*f_term + EsEs*(I4s-1)*s_term + EfEs*I8fs*fs_term;

  // stress derivative                          /* fancy lambda function syntax makes things much easier here */
  _stress_derivative[_qp].fill_from_minor_iter( [&](const unsigned int M,
                                                    const unsigned int N,
                                                    const unsigned int P,
                                                    const unsigned int Q) -> Real { return                          _p[B1 ]  *  i_term *  _id(M,N)  * _id(P,Q)
                                                                                           + (1 + (I4f-1)*(I4f-1)*2*_p[Bf ]) *  f_term * EfEf(M,N) * EfEf(P,Q)
                                                                                           + (1 + (I4f-1)*(I4f-1)*2*_p[Bf ]) *  s_term * EsEs(M,N) * EsEs(P,Q)
                                                                                           + (1 +  I8fs          *2*_p[Bfs]) * fs_term * EfEs(M,N) * EfEs(P,Q); } );
}
Пример #15
0
bool Elasticity::kinematics (const Vector& eV,
			     const Vector& N, const Matrix& dNdX, double r,
			     Matrix& B, Tensor&, SymmTensor& eps) const
{
  // Evaluate the strain-displacement matrix, B
  if (axiSymmetry)
  {
    if (!this->formBmatrix(B,N,dNdX,r))
      return false;
  }
  else
  {
    if (!this->formBmatrix(B,dNdX))
      return false;
  }

  if (eV.empty() || eps.dim() == 0)
    return true;

  // Evaluate the strains
  return B.multiply(eV,eps); // eps = B*eV
}
Пример #16
0
Real
component(const SymmTensor & symm_tensor, unsigned int index, RealVectorValue & direction)
{
    direction.zero();
    if (index < 3)
        direction(index) = 1.0;

    else if (index == 3)//xy
    {
        direction(0) = std::sqrt(0.5);
        direction(1) = direction(0);
    }
    else if (index == 4)//yz
    {
        direction(1) = std::sqrt(0.5);
        direction(2) = direction(1);
    }
    else if (index == 5)//zx
    {
        direction(0) = std::sqrt(0.5);
        direction(2) = direction(0);
    }
    return symm_tensor.component(index);
}
Пример #17
0
void
ReturnMappingModel::computeStress(const Elem & /*current_elem*/,
                                  const SymmElasticityTensor & elasticityTensor,
                                  const SymmTensor & stress_old,
                                  SymmTensor & strain_increment,
                                  SymmTensor & stress_new,
                                  SymmTensor & inelastic_strain_increment)
{
  // compute deviatoric trial stress
  SymmTensor dev_trial_stress(stress_new);
  dev_trial_stress.addDiag(-dev_trial_stress.trace() / 3.0);

  // compute effective trial stress
  Real dts_squared = dev_trial_stress.doubleContraction(dev_trial_stress);
  Real effective_trial_stress = std::sqrt(1.5 * dts_squared);

  // compute effective strain increment
  SymmTensor dev_strain_increment(strain_increment);
  dev_strain_increment.addDiag(-strain_increment.trace() / 3.0);
  _effective_strain_increment = dev_strain_increment.doubleContraction(dev_strain_increment);
  _effective_strain_increment = std::sqrt(2.0 / 3.0 * _effective_strain_increment);

  const SymmIsotropicElasticityTensor * iso_e_t =
      dynamic_cast<const SymmIsotropicElasticityTensor *>(&elasticityTensor);
  if (!iso_e_t)
    mooseError("Models derived from ReturnMappingModel require a SymmIsotropicElasticityTensor");
  _three_shear_modulus = 3.0 * iso_e_t->shearModulus();

  computeStressInitialize(effective_trial_stress, elasticityTensor);

  Real scalar;
  returnMappingSolve(effective_trial_stress, scalar, _console);

  // compute inelastic and elastic strain increments
  if (_legacy_return_mapping)
  {
    if (effective_trial_stress < 0.01)
      effective_trial_stress = 0.01;

    inelastic_strain_increment = dev_trial_stress;
    inelastic_strain_increment *= (1.5 * scalar / effective_trial_stress);
  }
  else
  {
    if (scalar != 0.0)
      inelastic_strain_increment = dev_trial_stress * (1.5 * scalar / effective_trial_stress);
    else
      inelastic_strain_increment = 0.0;
  }

  strain_increment -= inelastic_strain_increment;
  _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + scalar;

  // compute stress increment
  stress_new = elasticityTensor * strain_increment;

  // update stress
  stress_new += stress_old;

  computeStressFinalize(inelastic_strain_increment);
}
Пример #18
0
void
SymmIsotropicElasticityTensor::multiply( const SymmTensor & x, SymmTensor & b ) const
{
  const Real xx = x.xx();
  const Real yy = x.yy();
  const Real zz = x.zz();
  const Real xy = x.xy();
  const Real yz = x.yz();
  const Real zx = x.zx();

  b.xx() = _val[ 0]*xx + _val[ 1]*yy + _val[ 2]*zz;
  b.yy() = _val[ 1]*xx + _val[ 6]*yy + _val[ 7]*zz;
  b.zz() = _val[ 2]*xx + _val[ 7]*yy + _val[11]*zz;
  b.xy() = 2*_val[15]*xy;
  b.yz() = 2*_val[18]*yz;
  b.zx() = 2*_val[20]*zx;
}
Пример #19
0
bool FractureElasticityVoigt::evalStress (double lambda, double mu, double Gc,
                                          const SymmTensor& epsil, double* Phi,
                                          SymmTensor* sigma, Matrix* dSdE,
                                          bool postProc, bool printElm) const
{
  PROFILE3("FractureEl::evalStress");

  unsigned short int a = 0, b = 0;

  // Define a Lambda-function to set up the isotropic constitutive matrix
  auto&& setIsotropic = [this,a,b](Matrix& C, double lambda, double mu) mutable
  {
    for (a = 1; a <= C.rows(); a++)
      if (a > nsd)
        C(a,a) = mu;
      else
      {
        C(a,a) = 2.0*mu;
        for (b = 1; b <= nsd; b++)
          C(a,b) += lambda;
      }
  };

  // Define some material constants
  double trEps = epsil.trace();
  double C0 = trEps >= -epsZ ? Gc*lambda : lambda;
  double Cp = Gc*mu;

  if (trEps >= -epsZ && trEps <= epsZ)
  {
    // No strains, stress free configuration
    Phi[0] = 0.0;
    if (postProc)
      Phi[1] = Phi[2] = Phi[3] = 0.0;
    if (sigma)
      *sigma = 0.0;
    if (dSdE)
      setIsotropic(*dSdE,C0,Cp);
    return true;
  }

  // Calculate principal strains and the associated directions
  Vec3 eps;
  std::vector<SymmTensor> M(nsd,SymmTensor(nsd));
  {
    PROFILE4("Tensor::principal");
    if (!epsil.principal(eps,M.data()))
      return false;
  }

  // Split the strain tensor into positive and negative parts
  SymmTensor ePos(nsd), eNeg(nsd);
  for (a = 0; a < nsd; a++)
    if (eps[a] > 0.0)
      ePos += eps[a]*M[a];
    else if (eps[a] < 0.0)
      eNeg += eps[a]*M[a];

  if (sigma)
  {
    // Evaluate the stress tensor
    *sigma = C0*trEps;
    *sigma += 2.0*mu*(Gc*ePos + eNeg);
  }

  // Evaluate the tensile energy
  Phi[0] = mu*(ePos*ePos).trace();
  if (trEps > 0.0) Phi[0] += 0.5*lambda*trEps*trEps;
  if (postProc)
  {
    // Evaluate the compressive energy
    Phi[1] = mu*(eNeg*eNeg).trace();
    if (trEps < 0.0) Phi[1] += 0.5*lambda*trEps*trEps;
    // Evaluate the total strain energy
    Phi[2] = Gc*Phi[0] + Phi[1];
    // Evaluate the bulk energy
    Phi[3] = Gc*(Phi[0] + Phi[1]);
  }
  else if (sigmaC > 0.0) // Evaluate the crack driving function
    Phi[0] = this->MieheCrit56(eps,lambda,mu);

#if INT_DEBUG > 4
  std::cout <<"eps_p = "<< eps <<"\n";
  for (a = 0; a < nsd; a++)
    std::cout <<"M("<< 1+a <<") =\n"<< M[a];
  std::cout <<"ePos =\n"<< ePos <<"eNeg =\n"<< eNeg;
  if (sigma) std::cout <<"sigma =\n"<< *sigma;
  std::cout <<"Phi = "<< Phi[0];
  if (postProc) std::cout <<" "<< Phi[1] <<" "<< Phi[2] <<" "<< Phi[3];
  std::cout << std::endl;
#else
  if (printElm)
  {
    std::cout <<"g(c) = "<< Gc
              <<"\nepsilon =\n"<< epsil <<"eps_p = "<< eps
              <<"\nePos =\n"<< ePos <<"eNeg =\n"<< eNeg;
    if (sigma) std::cout <<"sigma =\n"<< *sigma;
    std::cout <<"Phi = "<< Phi[0];
    if (postProc) std::cout <<" "<< Phi[1] <<" "<< Phi[2] <<" "<< Phi[3];
    std::cout << std::endl;
  }
#endif

  if (!dSdE)
    return true;
  else if (eps[0] == eps[nsd-1])
  {
    // Hydrostatic pressure
    setIsotropic(*dSdE, C0, eps.x > 0.0 ? Cp : mu);
    return true;
  }

  typedef unsigned short int s_ind; // Convenience type definition

  // Define a Lambda-function to calculate (lower triangle of) the matrix Qa
  auto&& getQ = [this](Matrix& Q, const SymmTensor& Ma, double C)
  {
    if (C == 0.0) return;

    auto&& Mult = [Ma](s_ind i, s_ind j, s_ind k, s_ind l)
    {
      return Ma(i,j)*Ma(k,l);
    };

    s_ind i, j, k, l, is, js;

    // Normal stresses and strains
    for (i = 1; i <= nsd; i++)
      for (j = 1; j <= i; j++)
        Q(i,j) += C*Mult(i,i,j,j);

    is = nsd+1;
    for (i = 1; i < nsd; i++)
      for (j = i+1; j <= nsd; j++, is++)
      {
        // Shear stress coupled to normal strain
        for (k = 1; k <= nsd; k++)
          Q(is,k) += C*Mult(i,j,k,k);

        // Shear stress coupled to shear strain
        js = nsd+1;
        for (k = 1; k < nsd; k++)
          for (l = k+1; js <= is; l++, js++)
            Q(is,js) += C*Mult(i,j,k,l);
      }
  };

  // Define a Lambda-function to calculate (lower triangle of) the matrix Gab
  auto&& getG = [this](Matrix& G, const SymmTensor& Ma,
                       const SymmTensor& Mb, double C)
  {
    if (C == 0.0) return;

    auto&& Mult = [Ma,Mb](s_ind i, s_ind j, s_ind k, s_ind l)
    {
      return Ma(i,k)*Mb(j,l) + Ma(i,l)*Mb(j,k) +
             Mb(i,k)*Ma(j,l) + Mb(i,l)*Ma(j,k);
    };

    s_ind i, j, k, l, is, js;

    // Normal stresses and strains
    for (i = 1; i <= nsd; i++)
      for (j = 1; j <= i; j++)
        G(i,j) += C*Mult(i,i,j,j);

    is = nsd+1;
    for (i = 1; i < nsd; i++)
      for (j = i+1; j <= nsd; j++, is++)
      {
        // Shear stress coupled to normal strain
        for (k = 1; k <= nsd; k++)
          G(is,k) += C*Mult(i,j,k,k);

        // Shear stress coupled to shear strain
        js = nsd+1;
        for (k = 1; k < nsd; k++)
          for (l = k+1; js <= is; l++, js++)
            G(is,js) += C*Mult(i,j,k,l);
      }
  };

  // Evaluate the stress tangent assuming Voigt notation and symmetry
  for (a = 1; a <= nsd; a++)
    for (b = 1; b <= a; b++)
      (*dSdE)(a,b) = C0;

  for (a = 0; a < nsd; a++)
  {
    double C1 = eps[a] >= 0.0 ? Cp : mu;
    getQ(*dSdE, M[a], 2.0*C1);
    if (eps[a] != 0.0)
      for (b = 0; b < nsd; b++)
        if (a != b && eps[a] != eps[b])
          getG(*dSdE,M[a],M[b],C1/(1.0-eps[b]/eps[a]));
  }

  // Account for symmetry
  for (b = 2; b <= dSdE->rows(); b++)
    for (a = 1; a < b; a++)
      (*dSdE)(a,b) = (*dSdE)(b,a);

  return true;
}
Пример #20
0
Real
StressDivergence::computeQpOffDiagJacobian(unsigned int jvar)
{
  unsigned int coupled_component = 0;

  bool active = false;

  if (_xdisp_coupled && jvar == _xdisp_var)
  {
    coupled_component = 0;
    active = true;
  }
  else if (_ydisp_coupled && jvar == _ydisp_var)
  {
    coupled_component = 1;
    active = true;
  }
  else if (_zdisp_coupled && jvar == _zdisp_var)
  {
    coupled_component = 2;
    active = true;
  }

  if (active)
  {
    Real sum_C3x3 = _Jacobian_mult[_qp].sum_3x3();
    RealGradient sum_C3x1 = _Jacobian_mult[_qp].sum_3x1();
    Real jacobian = 0.0;
    jacobian += _Jacobian_mult[_qp].stiffness(
        _component, coupled_component, _grad_test[_i][_qp], _grad_phi[_j][_qp]); // B^T_i * C *B_j

    if (_volumetric_locking_correction)
    {
      // jacobian = Bbar^T_i * C * Bbar_j where Bbar = B + Bvol
      // jacobian = B^T_i * C * B_j + Bvol^T_i * C * Bvol_j +  Bvol^T_i * C * B_j + B^T_i * C *
      // Bvol_j

      // Bvol^T_i * C * Bvol_j
      jacobian += sum_C3x3 * (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) *
                  (_avg_grad_phi[_j][coupled_component] - _grad_phi[_j][_qp](coupled_component)) /
                  9.0;

      // B^T_i * C * Bvol_j
      jacobian += sum_C3x1(_component) * _grad_test[_i][_qp](_component) *
                  (_avg_grad_phi[_j][coupled_component] - _grad_phi[_j][_qp](coupled_component)) /
                  3.0;

      // Bvol^T_i * C * B_i
      SymmTensor phi;
      if (coupled_component == 0)
      {
        phi.xx() = _grad_phi[_j][_qp](0);
        phi.xy() = _grad_phi[_j][_qp](1);
        phi.xz() = _grad_phi[_j][_qp](2);
      }
      else if (coupled_component == 1)
      {
        phi.yy() = _grad_phi[_j][_qp](1);
        phi.xy() = _grad_phi[_j][_qp](0);
        phi.yz() = _grad_phi[_j][_qp](2);
      }
      else if (coupled_component == 2)
      {
        phi.zz() = _grad_phi[_j][_qp](2);
        phi.xz() = _grad_phi[_j][_qp](0);
        phi.yz() = _grad_phi[_j][_qp](1);
      }

      SymmTensor tmp(_Jacobian_mult[_qp] * phi);

      jacobian += (tmp.xx() + tmp.yy() + tmp.zz()) *
                  (_avg_grad_test[_i][_component] - _grad_test[_i][_qp](_component)) / 3.0;
    }

    if (_dt > 0)
      return jacobian * (1 + _alpha + _zeta / _dt);
    else
      return jacobian;
  }

  if (_temp_coupled && jvar == _temp_var)
    return _d_stress_dT[_qp].rowDot(_component, _grad_test[_i][_qp]) * _phi[_j][_qp];

  return 0;
}
Пример #21
0
Real
equivalentPlasticStrain(const SymmTensor & symm_strain)
{
    return std::sqrt(2.0 / 3.0 * symm_strain.doubleContraction(symm_strain));
}
Пример #22
0
void
PLC_LSH::computeLSH( const SymmTensor & strain_increment,
                     SymmTensor & plastic_strain_increment,
                     SymmTensor & stress_new )
{

  // compute deviatoric trial stress
  SymmTensor dev_trial_stress(stress_new);
  dev_trial_stress.addDiag( -stress_new.trace()/3 );

  // effective trial stress
  Real dts_squared = dev_trial_stress.doubleContraction(dev_trial_stress);
  Real effective_trial_stress = std::sqrt(1.5 * dts_squared);

  // determine if yield condition is satisfied
  Real yield_condition = effective_trial_stress - _hardening_variable_old[_qp] - _yield_stress;

  _hardening_variable[_qp] = _hardening_variable_old[_qp];
  _plastic_strain[_qp] = _plastic_strain_old[_qp];

  if (yield_condition > 0)  // then use newton iteration to determine effective plastic strain increment
  {
    unsigned int it = 0;
    Real plastic_residual = 0;
    Real norm_plas_residual = 10;
    Real first_norm_plas_residual = 10;
    Real scalar_plastic_strain_increment = 0;

    while (it < _max_its &&
          norm_plas_residual > _absolute_tolerance &&
          (norm_plas_residual/first_norm_plas_residual) > _relative_tolerance)
    {
      plastic_residual = effective_trial_stress - (3. * _shear_modulus * scalar_plastic_strain_increment) -
        _hardening_variable[_qp] - _yield_stress;
      norm_plas_residual = std::abs(plastic_residual);
      if (it == 0)
      {
        first_norm_plas_residual = norm_plas_residual;
      }

      scalar_plastic_strain_increment += plastic_residual / (3. * _shear_modulus + _hardening_constant);

      _hardening_variable[_qp] = _hardening_variable_old[_qp] + (_hardening_constant * scalar_plastic_strain_increment);

      if (_output_iteration_info == true)
      {
        _console
          << "pls_it="    << it
          << " trl_strs=" << effective_trial_stress
          << " del_p="    << scalar_plastic_strain_increment
          << " harden="   << _hardening_variable[_qp]
          << " rel_res="  << norm_plas_residual/first_norm_plas_residual
          << " rel_tol="  << _relative_tolerance
          << " abs_res="  << norm_plas_residual
          << " abs_tol="  << _absolute_tolerance
          << std::endl;
      }

      ++it;

    }

    if (it == _max_its &&
       norm_plas_residual > _absolute_tolerance &&
       (norm_plas_residual/first_norm_plas_residual) > _relative_tolerance)
    {
      mooseError("Max sub-newton iteration hit during plasticity increment solve!");
    }

    if (effective_trial_stress < 0.01)
    {
      effective_trial_stress = 0.01;
    }
    plastic_strain_increment = dev_trial_stress;
    plastic_strain_increment *= (1.5*scalar_plastic_strain_increment/effective_trial_stress);

    SymmTensor elastic_strain_increment(strain_increment);
    elastic_strain_increment -= plastic_strain_increment;

    // compute stress increment
    stress_new = *elasticityTensor() * elastic_strain_increment;

    // update stress and plastic strain
    stress_new += _stress_old;
    _plastic_strain[_qp] += plastic_strain_increment;

  } // end of if statement

}
Пример #23
0
Real
hydrostatic(const SymmTensor & symm_tensor)
{
    return symm_tensor.trace() / 3.0;
}
Пример #24
0
Real
firstInvariant(const SymmTensor & symm_tensor)
{
    return symm_tensor.trace();
}
Пример #25
0
Real
thirdInvariant(const SymmTensor & symm_tensor)
{
    Real val = 0.0;
    val = symm_tensor.xx() * symm_tensor.yy() * symm_tensor.zz() -
          symm_tensor.xx() * symm_tensor.yz() * symm_tensor.yz() +
          symm_tensor.xy() * symm_tensor.yz() * symm_tensor.zx() -
          symm_tensor.xy() * symm_tensor.xy() * symm_tensor.zz() +
          symm_tensor.zx() * symm_tensor.xy() * symm_tensor.yz() -
          symm_tensor.zx() * symm_tensor.yy() * symm_tensor.zx();

    return val;
}
Пример #26
0
Real
secondInvariant(const SymmTensor & symm_tensor)
{
    Real value = symm_tensor.xx() * symm_tensor.yy() +
                 symm_tensor.yy() * symm_tensor.zz() +
                 symm_tensor.zz() * symm_tensor.xx() -
                 symm_tensor.xy() * symm_tensor.xy() -
                 symm_tensor.yz() * symm_tensor.yz() -
                 symm_tensor.zx() * symm_tensor.zx();

    return value;
}
Пример #27
0
void
Element::unrotateSymmetricTensor( const ColumnMajorMatrix & R,
                                const SymmTensor & T,
                                SymmTensor & result )
{

  //     Rt           T         R
  //  00 10 20    00 01 02   00 01 02
  //  01 11 21  * 10 11 12 * 10 11 12
  //  02 12 22    20 21 22   20 21 22
  //
  const Real T00 = R(0,0)*T.xx() + R(1,0)*T.xy() + R(2,0)*T.zx();
  const Real T01 = R(0,0)*T.xy() + R(1,0)*T.yy() + R(2,0)*T.yz();
  const Real T02 = R(0,0)*T.zx() + R(1,0)*T.yz() + R(2,0)*T.zz();

  const Real T10 = R(0,1)*T.xx() + R(1,1)*T.xy() + R(2,1)*T.zx();
  const Real T11 = R(0,1)*T.xy() + R(1,1)*T.yy() + R(2,1)*T.yz();
  const Real T12 = R(0,1)*T.zx() + R(1,1)*T.yz() + R(2,1)*T.zz();

  const Real T20 = R(0,2)*T.xx() + R(1,2)*T.xy() + R(2,2)*T.zx();
  const Real T21 = R(0,2)*T.xy() + R(1,2)*T.yy() + R(2,2)*T.yz();
  const Real T22 = R(0,2)*T.zx() + R(1,2)*T.yz() + R(2,2)*T.zz();

  result.xx( T00 * R(0,0) + T01 * R(1,0) + T02 * R(2,0) );
  result.yy( T10 * R(0,1) + T11 * R(1,1) + T12 * R(2,1) );
  result.zz( T20 * R(0,2) + T21 * R(1,2) + T22 * R(2,2) );
  result.xy( T00 * R(0,1) + T01 * R(1,1) + T02 * R(2,1) );
  result.yz( T10 * R(0,2) + T11 * R(1,2) + T12 * R(2,2) );
  result.zx( T00 * R(0,2) + T01 * R(1,2) + T02 * R(2,2) );

}
Пример #28
0
void
SymmElasticityTensor::multiply(const SymmTensor & x, SymmTensor & b) const
{
  const Real xx = x.xx();
  const Real yy = x.yy();
  const Real zz = x.zz();
  const Real xy = x.xy();
  const Real yz = x.yz();
  const Real zx = x.zx();

  b.xx() =
      _val[0] * xx + _val[1] * yy + _val[2] * zz + 2 * (_val[3] * xy + _val[4] * yz + _val[5] * zx);
  b.yy() = _val[1] * xx + _val[6] * yy + _val[7] * zz +
           2 * (_val[8] * xy + _val[9] * yz + _val[10] * zx);
  b.zz() = _val[2] * xx + _val[7] * yy + _val[11] * zz +
           2 * (_val[12] * xy + _val[13] * yz + _val[14] * zx);
  b.xy() = _val[3] * xx + _val[8] * yy + _val[12] * zz +
           2 * (_val[15] * xy + _val[16] * yz + _val[17] * zx);
  b.yz() = _val[4] * xx + _val[9] * yy + _val[13] * zz +
           2 * (_val[16] * xy + _val[18] * yz + _val[19] * zx);
  b.zx() = _val[5] * xx + _val[10] * yy + _val[14] * zz +
           2 * (_val[17] * xy + _val[19] * yz + _val[20] * zx);
}
Пример #29
0
void
Linear::computeStrain( const unsigned qp,
                       const SymmTensor & total_strain_old,
                       SymmTensor & total_strain_new,
                       SymmTensor & strain_increment )
{
  strain_increment.xx( _grad_disp_x[qp](0) );
  strain_increment.yy( _grad_disp_y[qp](1) );
  strain_increment.zz( _grad_disp_z[qp](2) );
  strain_increment.xy( 0.5*(_grad_disp_x[qp](1)+_grad_disp_y[qp](0)) );
  strain_increment.yz( 0.5*(_grad_disp_y[qp](2)+_grad_disp_z[qp](1)) );
  strain_increment.zx( 0.5*(_grad_disp_z[qp](0)+_grad_disp_x[qp](2)) );
  if (_large_strain)
  {
    strain_increment.xx() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](0) +
                                  _grad_disp_y[qp](0)*_grad_disp_y[qp](0) +
                                  _grad_disp_z[qp](0)*_grad_disp_z[qp](0));
    strain_increment.yy() += 0.5*(_grad_disp_x[qp](1)*_grad_disp_x[qp](1) +
                                  _grad_disp_y[qp](1)*_grad_disp_y[qp](1) +
                                  _grad_disp_z[qp](1)*_grad_disp_z[qp](1));
    strain_increment.zz() += 0.5*(_grad_disp_x[qp](2)*_grad_disp_x[qp](2) +
                                  _grad_disp_y[qp](2)*_grad_disp_y[qp](2) +
                                  _grad_disp_z[qp](2)*_grad_disp_z[qp](2));
    strain_increment.xy() += 0.5*(_grad_disp_x[qp](0)*_grad_disp_x[qp](1) +
                                  _grad_disp_y[qp](0)*_grad_disp_y[qp](1) +
                                  _grad_disp_z[qp](0)*_grad_disp_z[qp](1));
    strain_increment.yz() += 0.5*(_grad_disp_x[qp](1)*_grad_disp_x[qp](2) +
                                  _grad_disp_y[qp](1)*_grad_disp_y[qp](2) +
                                  _grad_disp_z[qp](1)*_grad_disp_z[qp](2));
    strain_increment.zx() += 0.5*(_grad_disp_x[qp](2)*_grad_disp_x[qp](0) +
                                  _grad_disp_y[qp](2)*_grad_disp_y[qp](0) +
                                  _grad_disp_z[qp](2)*_grad_disp_z[qp](0));
  }

  if (_volumetric_locking_correction)
  {
    // volumetric locking correction - averaging the volumertic strain over the element
    Real volumetric_strain = 0.0;
    Real volume = 0.0;
    for (unsigned int qp_loop = 0; qp_loop < _solid_model.qrule()->n_points(); ++qp_loop)
    {
      volumetric_strain += (_grad_disp_x[qp_loop](0) + _grad_disp_y[qp_loop](1) + _grad_disp_z[qp_loop](2)) / 3.0 * _solid_model.JxW(qp_loop);

      volume += _solid_model.JxW(qp_loop);

      if (_large_strain)
      {
        volumetric_strain += 0.5 * (_grad_disp_x[qp](0) * _grad_disp_x[qp](0) +
                                    _grad_disp_y[qp](0) * _grad_disp_y[qp](0) +
                                    _grad_disp_z[qp](0) * _grad_disp_z[qp](0)) / 3.0 * _solid_model.JxW(qp_loop);
        volumetric_strain += 0.5 * (_grad_disp_x[qp](1) * _grad_disp_x[qp](1) +
                                    _grad_disp_y[qp](1) * _grad_disp_y[qp](1) +
                                    _grad_disp_z[qp](1) * _grad_disp_z[qp](1)) / 3.0 * _solid_model.JxW(qp_loop);
        volumetric_strain += 0.5 * (_grad_disp_x[qp](2) * _grad_disp_x[qp](2) +
                                    _grad_disp_y[qp](2) * _grad_disp_y[qp](2) +
                                    _grad_disp_z[qp](2) * _grad_disp_z[qp](2)) / 3.0 * _solid_model.JxW(qp_loop);
      }
    }

    volumetric_strain /= volume; // average volumetric strain

    // strain increment at _qp
    Real trace = strain_increment.trace();
    strain_increment.xx() += volumetric_strain - trace / 3.0;
    strain_increment.yy() += volumetric_strain - trace / 3.0;
    strain_increment.zz() += volumetric_strain - trace / 3.0;
  }

  total_strain_new = strain_increment;
  strain_increment -= total_strain_old;
}
Пример #30
0
Real
component(const SymmTensor & symm_tensor, unsigned int index)
{
    return symm_tensor.component(index);
}