Esempio n. 1
0
void
ContactMaster::updateContactSet(bool beginning_of_step)
{
  std::map<dof_id_type, PenetrationInfo *>::iterator
    it  = _penetration_locator._penetration_info.begin(),
    end = _penetration_locator._penetration_info.end();
  for (; it!=end; ++it)
  {
    const dof_id_type slave_node_num = it->first;
    PenetrationInfo * pinfo = it->second;

    // Skip this pinfo if there are no DOFs on this node.
    if ( ! pinfo || pinfo->_node->n_comp(_sys.number(), _vars(_component)) < 1 )
      continue;

    if (beginning_of_step)
    {
      pinfo->_locked_this_step = 0;
      pinfo->_starting_elem = it->second->_elem;
      pinfo->_starting_side_num = it->second->_side_num;
      pinfo->_starting_closest_point_ref = it->second->_closest_point_ref;
      pinfo->_contact_force_old = pinfo->_contact_force;
      pinfo->_accumulated_slip_old = pinfo->_accumulated_slip;
      pinfo->_frictional_energy_old = pinfo->_frictional_energy;
    }

    const Real contact_pressure = -(pinfo->_normal * pinfo->_contact_force) / nodalArea(*pinfo);
    const Real distance = pinfo->_normal * (pinfo->_closest_point - _mesh.node(slave_node_num));

    // Capture
    if ( ! pinfo->isCaptured() && MooseUtils::absoluteFuzzyGreaterEqual(distance, 0, _capture_tolerance))
    {
      pinfo->capture();

      // Increment the lock count every time the node comes back into contact from not being in contact.
      if (_formulation == CF_KINEMATIC)
        ++pinfo->_locked_this_step;
    }
    // Release
    else if (_model != CM_GLUED &&
             pinfo->isCaptured() &&
             _tension_release >= 0 &&
             -contact_pressure >= _tension_release &&
             pinfo->_locked_this_step < 2)
    {
      pinfo->release();
      pinfo->_contact_force.zero();
    }

    if (_formulation == CF_AUGMENTED_LAGRANGE && pinfo->isCaptured())
      pinfo->_lagrange_multiplier -= getPenalty(*pinfo) * distance;
  }
}
Esempio n. 2
0
Real
SlaveConstraint::computeQpJacobian()
{

  // TODO: for the default formulation,
  //   we should subtract off the existing Jacobian weighted by the effect of the normal


  PenetrationInfo * pinfo = _point_to_info[_current_point];
  const Node * node = pinfo->_node;
//   long int dof_number = node->dof_number(0, _var.number(), 0);


//  RealVectorValue jac_vec;

  // Build up jac vector
//  for (unsigned int i=0; i<_dim; i++)
//  {
//    unsigned int dof_row = _dof_data._var_dof_indices[_var_num][_i];
//    unsigned int dof_col = _dof_data._var_dof_indices[_var_num][_j];

//    Real jac_value = _jacobian_copy(dof_row, dof_col);
//  }

//    Real jac_mag = pinfo->_normal(_component) * jac_value;
/*
   return _test[_i][_qp] * (
     (1e8*-_phi[_j][_qp])
     -_jacobian_copy(dof_number, dof_number)
     );
   */

  RealVectorValue normal(pinfo->_normal);

  Real penalty = _penalty;
  if (_normalize_penalty)
    penalty *= nodalArea(*pinfo);

  Real term(0);

  if ( CM_FRICTIONLESS == _model )
  {

    const Real nnTDiag = normal(_component) * normal(_component);
    term =  penalty * nnTDiag;

    const RealGradient & A1( pinfo->_dxyzdxi [0] );
    RealGradient A2;
    RealGradient d2;
    if ( _mesh_dimension == 3 )
    {
      A2 = pinfo->_dxyzdeta[0];
      d2 = pinfo->_d2xyzdxideta[0];
    }
    else
    {
      A2.zero();
      d2.zero();
    }

    const RealVectorValue distance_vec(_mesh.node(node->id()) - pinfo->_closest_point);
    const Real ATA11( A1 * A1 );
    const Real ATA12( A1 * A2 );
    const Real ATA22( A2 * A2 );
    const Real D11( -ATA11 );
    const Real D12( -ATA12 + d2 * distance_vec );
    const Real D22( -ATA22 );

    Real invD11(0);
    Real invD12(0);
    Real invD22(0);
    if ( _mesh_dimension == 3)
    {
      const Real detD( D11*D22 - D12*D12 );
      invD11 =  D22/detD;
      invD12 = -D12/detD;
      invD22 =  D11/detD;
    }
    else if ( _mesh_dimension == 2 )
    {
      invD11 = 1 / D11;
    }

    const Real AinvD11( A1(0)*invD11 + A2(0)*invD12 );
    const Real AinvD12( A1(0)*invD12 + A2(0)*invD22 );
    const Real AinvD21( A1(1)*invD11 + A2(1)*invD12 );
    const Real AinvD22( A1(1)*invD12 + A2(1)*invD22 );
    const Real AinvD31( A1(2)*invD11 + A2(2)*invD12 );
    const Real AinvD32( A1(2)*invD12 + A2(2)*invD22 );

    const Real AinvDAT11( AinvD11*A1(0) + AinvD12*A2(0) );
//     const Real AinvDAT12( AinvD11*A1(1) + AinvD12*A2(1) );
//     const Real AinvDAT13( AinvD11*A1(2) + AinvD12*A2(2) );
//     const Real AinvDAT21( AinvD21*A1(0) + AinvD22*A2(0) );
    const Real AinvDAT22( AinvD21*A1(1) + AinvD22*A2(1) );
//     const Real AinvDAT23( AinvD21*A1(2) + AinvD22*A2(2) );
//     const Real AinvDAT31( AinvD31*A1(0) + AinvD32*A2(0) );
//     const Real AinvDAT32( AinvD31*A1(1) + AinvD32*A2(1) );
    const Real AinvDAT33( AinvD31*A1(2) + AinvD32*A2(2) );

    if ( _component == 0 )
      term += penalty * ( 1 - nnTDiag + AinvDAT11 );

    else if ( _component == 1 )
      term += penalty * ( 1 - nnTDiag + AinvDAT22 );

    else
      term += penalty * ( 1 - nnTDiag + AinvDAT33 );

  }
  else if ( CM_GLUED == _model ||
            CM_COULOMB == _model )
  {
    normal.zero();
    normal(_component) = 1;
    term = penalty;
  }
  else
  {
    mooseError("Invalid or unavailable contact model");
  }

  return _test[_i][_qp] * term * _phi[_j][_qp];
}
Esempio n. 3
0
Real
ContactMaster::computeQpJacobian()
{

  PenetrationInfo * pinfo = _point_to_info[_current_point];
  Real penalty = _penalty;
  if (_normalize_penalty)
    penalty *= nodalArea(*pinfo);


  switch (_model)
  {
  case CM_FRICTIONLESS:
    switch (_formulation)
    {
    case CF_DEFAULT:
      return 0;
      break;
    case CF_PENALTY:
    case CF_AUGMENTED_LAGRANGE:
      return _test[_i][_qp] * penalty * _phi[_j][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component);
      break;
    default:
      mooseError("Invalid contact formulation");
      break;
    }
    break;
  case CM_GLUED:
  case CM_COULOMB:
    switch (_formulation)
    {
    case CF_DEFAULT:
      return 0;
      break;
    case CF_PENALTY:
    case CF_AUGMENTED_LAGRANGE:
      return _test[_i][_qp] * penalty * _phi[_j][_qp];
      break;
    default:
      mooseError("Invalid contact formulation");
      break;
    }
    break;
  default:
    mooseError("Invalid or unavailable contact model");
    break;
  }

  return 0;
/*
  if (_i != _j)
    return 0;

  Node * node = pinfo->_node;

  RealVectorValue jac_vec;

  // Build up jac vector
  for (unsigned int i=0; i<_dim; i++)
  {
    long int dof_number = node->dof_number(0, _vars(i), 0);
    jac_vec(i) = _jacobian_copy(dof_number, dof_number);
  }

  Real jac_mag = pinfo->_normal * jac_vec;

  return _test[_i][_qp]*pinfo->_normal(_component)*jac_mag;
*/
}
Esempio n. 4
0
void
ContactMaster::computeContactForce(PenetrationInfo * pinfo)
{
  std::map<unsigned int, Real> & lagrange_multiplier = _penetration_locator._lagrange_multiplier;
  const Node * node = pinfo->_node;

  RealVectorValue res_vec;
  // Build up residual vector
  for (unsigned int i=0; i<_mesh_dimension; ++i)
  {
    long int dof_number = node->dof_number(0, _vars(i), 0);
    res_vec(i) = _residual_copy(dof_number);
  }

  const Real area = nodalArea(*pinfo);

  RealVectorValue distance_vec(_mesh.node(node->id()) - pinfo->_closest_point);
  RealVectorValue pen_force(_penalty * distance_vec);
  if (_normalize_penalty)
    pen_force *= area;

  RealVectorValue tan_residual(0,0,0);

  if (_model == CM_FRICTIONLESS)
  {
    switch (_formulation)
    {
    case CF_DEFAULT:
      pinfo->_contact_force = -pinfo->_normal * (pinfo->_normal * res_vec);
      break;
    case CF_PENALTY:
      pinfo->_contact_force = pinfo->_normal * (pinfo->_normal * pen_force);
      break;
    case CF_AUGMENTED_LAGRANGE:
      pinfo->_contact_force = (pinfo->_normal * (pinfo->_normal *
          //( pen_force + (lagrange_multiplier[node->id()]/distance_vec.size())*distance_vec)));
          ( pen_force + lagrange_multiplier[node->id()] * pinfo->_normal)));
      break;
    default:
      mooseError("Invalid contact formulation");
      break;
    }
    pinfo->_mech_status=PenetrationInfo::MS_SLIPPING;
  }
  else if (_model == CM_COULOMB && _formulation == CF_PENALTY)
  {
    distance_vec = pinfo->_incremental_slip + (pinfo->_normal * (_mesh.node(node->id()) - pinfo->_closest_point)) * pinfo->_normal;
    pen_force = _penalty * distance_vec;
    if (_normalize_penalty)
      pen_force *= area;


    // Frictional capacity
    // const Real capacity( _friction_coefficient * (pen_force * pinfo->_normal < 0 ? -pen_force * pinfo->_normal : 0) );
    const Real capacity( _friction_coefficient * (res_vec * pinfo->_normal > 0 ? res_vec * pinfo->_normal : 0) );

    // Elastic predictor
    pinfo->_contact_force = pen_force + (pinfo->_contact_force_old - pinfo->_normal*(pinfo->_normal*pinfo->_contact_force_old));
    RealVectorValue contact_force_normal( (pinfo->_contact_force*pinfo->_normal) * pinfo->_normal );
    RealVectorValue contact_force_tangential( pinfo->_contact_force - contact_force_normal );

    // Tangential magnitude of elastic predictor
    const Real tan_mag( contact_force_tangential.size() );

    if ( tan_mag > capacity )
    {
      pinfo->_contact_force = contact_force_normal + capacity * contact_force_tangential / tan_mag;
      pinfo->_mech_status=PenetrationInfo::MS_SLIPPING;
    }
    else
    {
      pinfo->_mech_status=PenetrationInfo::MS_STICKING;
    }
  }
  else if (_model == CM_GLUED ||
           (_model == CM_COULOMB && _formulation == CF_DEFAULT))
  {
    switch (_formulation)
    {
    case CF_DEFAULT:
      pinfo->_contact_force =  -res_vec;
      break;
    case CF_PENALTY:
      pinfo->_contact_force = pen_force;
      break;
    case CF_AUGMENTED_LAGRANGE:
      pinfo->_contact_force = pen_force +
                              lagrange_multiplier[node->id()]*distance_vec/distance_vec.size();
      break;
    default:
      mooseError("Invalid contact formulation");
      break;
    }
    pinfo->_mech_status=PenetrationInfo::MS_STICKING;
  }
  else
  {
    mooseError("Invalid or unavailable contact model");
  }
}
Esempio n. 5
0
void
ContactMaster::updateContactSet(bool beginning_of_step)
{
  std::set<unsigned int> & has_penetrated = _penetration_locator._has_penetrated;
  std::map<unsigned int, unsigned> & unlocked_this_step = _penetration_locator._unlocked_this_step;
  std::map<unsigned int, unsigned> & locked_this_step = _penetration_locator._locked_this_step;
  std::map<unsigned int, Real> & lagrange_multiplier = _penetration_locator._lagrange_multiplier;

  std::map<unsigned int, PenetrationInfo *>::iterator it = _penetration_locator._penetration_info.begin();
  std::map<unsigned int, PenetrationInfo *>::iterator end = _penetration_locator._penetration_info.end();

  for (; it!=end; ++it)
  {
    PenetrationInfo * pinfo = it->second;

    if (!pinfo)
    {
      continue;
    }

    Real area = nodalArea(*pinfo);

    const unsigned int slave_node_num = it->first;
    std::set<unsigned int>::iterator hpit = has_penetrated.find(slave_node_num);

    if (beginning_of_step)
    {
      if (hpit != has_penetrated.end())
        pinfo->_penetrated_at_beginning_of_step = true;
      else
        pinfo->_penetrated_at_beginning_of_step = false;

      pinfo->_starting_elem = it->second->_elem;
      pinfo->_starting_side_num = it->second->_side_num;
      pinfo->_starting_closest_point_ref = it->second->_closest_point_ref;
    }

    if ((_model == CM_FRICTIONLESS && _formulation == CF_DEFAULT) ||
        (_model == CM_COULOMB && _formulation == CF_DEFAULT))
    {
      const Node * node = pinfo->_node;

      Real resid( -(pinfo->_normal * pinfo->_contact_force) / area );

      // _console << locked_this_step[slave_node_num] << " " << pinfo->_distance << std::endl;
      const Real distance( pinfo->_normal * (pinfo->_closest_point - _mesh.node(node->id())));

      if (hpit != has_penetrated.end() &&
          _tension_release >= 0 &&
          resid < -_tension_release &&
          locked_this_step[slave_node_num] < 2)
      {
        _console << "Releasing node " << node->id() << " " << resid << " < " << -_tension_release << std::endl;
        has_penetrated.erase(hpit);
        pinfo->_contact_force.zero();
        pinfo->_mech_status=PenetrationInfo::MS_NO_CONTACT;
        ++unlocked_this_step[slave_node_num];
      }
      else if (distance > 0)
      {
        if (hpit == has_penetrated.end())
        {
          _console << "Capturing node " << node->id() << " " << distance << " " << unlocked_this_step[slave_node_num] <<  std::endl;
          ++locked_this_step[slave_node_num];
          has_penetrated.insert(slave_node_num);
        }
      }
    }
    else
    {
      if (_formulation == CF_PENALTY)
      {
        if (pinfo->_distance >= 0)
        {
          if (hpit == has_penetrated.end())
            has_penetrated.insert(slave_node_num);

        }
        else if (_tension_release < 0 ||
                 (pinfo->_contact_force * pinfo->_normal) / area < _tension_release)
        {
          // Do nothing.
        }
        else
        {
          if (hpit != has_penetrated.end())
          {
            has_penetrated.erase(hpit);
          }
          pinfo->_contact_force.zero();
          pinfo->_mech_status=PenetrationInfo::MS_NO_CONTACT;
        }
      }
      else
      {
        if (pinfo->_distance >= 0)
        {
          if (hpit == has_penetrated.end())
          {
            has_penetrated.insert(slave_node_num);
          }
        }
      }
    }
    if (_formulation == CF_AUGMENTED_LAGRANGE && hpit != has_penetrated.end())
    {
      const RealVectorValue distance_vec(_mesh.node(slave_node_num) - pinfo->_closest_point);
      Real penalty = _penalty;
      if (_normalize_penalty)
        penalty *= area;

      lagrange_multiplier[slave_node_num] += penalty * pinfo->_normal * distance_vec;
    }
  }
}