Real SlaveConstraint::computeQpResidual() { PenetrationInfo * pinfo = _point_to_info[_current_point]; const Node * node = pinfo->_node; Real resid = pinfo->_contact_force(_component); const Real area = nodalArea(*pinfo); if (_formulation == CF_DEFAULT) { RealVectorValue distance_vec(_mesh.node(node->id()) - pinfo->_closest_point); RealVectorValue pen_force(_penalty * distance_vec); if (_normalize_penalty) pen_force *= area; if (_model == CM_FRICTIONLESS) resid += pinfo->_normal(_component) * pinfo->_normal * pen_force; else if (_model == CM_GLUED || _model == CM_COULOMB) resid += pen_force(_component); } return _test[_i][_qp] * resid; }
Real MechanicalContactConstraint::computeQpResidual(Moose::ConstraintType type) { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; computeContactForce(pinfo); Real resid = pinfo->_contact_force(_component); switch(type) { case Moose::Slave: if (_formulation == CF_DEFAULT) { //Real distance = (*_current_node)(_component) - pinfo->_closest_point(_component); //Real pen_force = _penalty * distance; RealVectorValue distance_vec(*_current_node - pinfo->_closest_point); RealVectorValue pen_force(_penalty * distance_vec); if (_model == CM_FRICTIONLESS || _model == CM_EXPERIMENTAL) resid += pinfo->_normal(_component) * pinfo->_normal * pen_force; else if (_model == CM_GLUED || _model == CM_TIED || _model == CM_COULOMB) resid += pen_force(_component); } return _test_slave[_i][_qp] * resid; case Moose::Master: return _test_master[_i][_qp] * -resid; } return 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"); } }
void MechanicalContactConstraint::computeContactForce(PenetrationInfo * pinfo) { const Node * node = pinfo->_node; RealVectorValue res_vec; // Build up residual vector for (unsigned int i=0; i<_mesh_dimension; ++i) { dof_id_type dof_number = node->dof_number(0, _vars(i), 0); res_vec(i) = _residual_copy(dof_number); } RealVectorValue distance_vec(_mesh.node(node->id()) - pinfo->_closest_point); const Real penalty = getPenalty(*pinfo); RealVectorValue pen_force(penalty * distance_vec); switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_KINEMATIC: 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 + pinfo->_lagrange_multiplier * pinfo->_normal))); break; default: mooseError("Invalid contact formulation"); break; } pinfo->_mech_status=PenetrationInfo::MS_SLIPPING; break; case CM_COULOMB: switch (_formulation) { case CF_KINEMATIC: pinfo->_contact_force = -res_vec; break; case CF_PENALTY: { distance_vec = pinfo->_incremental_slip + (pinfo->_normal * (_mesh.node(node->id()) - pinfo->_closest_point)) * pinfo->_normal; pen_force = penalty * distance_vec; // 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; break; } case CF_AUGMENTED_LAGRANGE: pinfo->_contact_force = pen_force + pinfo->_lagrange_multiplier*distance_vec/distance_vec.size(); break; default: mooseError("Invalid contact formulation"); break; } break; case CM_GLUED: switch (_formulation) { case CF_KINEMATIC: pinfo->_contact_force = -res_vec; break; case CF_PENALTY: pinfo->_contact_force = pen_force; break; case CF_AUGMENTED_LAGRANGE: pinfo->_contact_force = pen_force + pinfo->_lagrange_multiplier*distance_vec/distance_vec.size(); break; default: mooseError("Invalid contact formulation"); break; } pinfo->_mech_status=PenetrationInfo::MS_STICKING; break; default: mooseError("Invalid or unavailable contact model"); break; } }
Real MultiDContactConstraint::computeQpResidual(Moose::ConstraintType type) { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; const Node * node = pinfo->_node; RealVectorValue res_vec; // Build up residual vector for (unsigned int i=0; i<_mesh_dimension; ++i) { dof_id_type dof_number = node->dof_number(0, _vars(i), 0); res_vec(i) = _residual_copy(dof_number); } const RealVectorValue distance_vec(_mesh.node(node->id()) - pinfo->_closest_point); const RealVectorValue pen_force(_penalty * distance_vec); Real resid = 0; switch (type) { case Moose::Slave: switch (_model) { case CM_FRICTIONLESS: resid = pinfo->_normal(_component) * (pinfo->_normal * ( pen_force - res_vec )); break; case CM_GLUED: resid = pen_force(_component) - res_vec(_component) ; break; default: mooseError("Invalid or unavailable contact model"); break; } return _test_slave[_i][_qp] * resid; case Moose::Master: switch (_model) { case CM_FRICTIONLESS: resid = pinfo->_normal(_component) * (pinfo->_normal * res_vec); break; case CM_GLUED: resid = res_vec(_component); break; default: mooseError("Invalid or unavailable contact model"); break; } return _test_master[_i][_qp] * resid; } return 0; }