Real GluedContactConstraint::computeQpResidual(Moose::ConstraintType type) { switch (type) { case Moose::Slave: { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; Real distance = (*_current_node)(_component) - pinfo->_closest_point(_component); Real pen_force = _penalty * distance; Real resid = pen_force; pinfo->_contact_force(_component) = resid; pinfo->_mech_status=PenetrationInfo::MS_STICKING; return _test_slave[_i][_qp] * resid; } case Moose::Master: { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; long int dof_number = _current_node->dof_number(0, _vars(_component), 0); Real resid = _residual_copy(dof_number); pinfo->_contact_force(_component) = -resid; pinfo->_mech_status=PenetrationInfo::MS_STICKING; return _test_master[_i][_qp] * resid; } } return 0; }
void GluedContactConstraint::updateContactSet(bool beginning_of_step) { std::set<dof_id_type> & has_penetrated = _penetration_locator._has_penetrated; std::map<dof_id_type, PenetrationInfo *>::iterator it = _penetration_locator._penetration_info.begin(), end = _penetration_locator._penetration_info.end(); for (; it!=end; ++it) { 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; const dof_id_type slave_node_num = it->first; std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (beginning_of_step) { 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 (pinfo->_distance >= 0) if (hpit == has_penetrated.end()) has_penetrated.insert(slave_node_num); } }
void ContactMaster::addPoints() { _point_to_info.clear(); std::map<dof_id_type, PenetrationInfo *>::iterator it = _penetration_locator._penetration_info.begin(), end = _penetration_locator._penetration_info.end(); for (; it!=end; ++it) { 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 ( pinfo->isCaptured() ) { addPoint(pinfo->_elem, pinfo->_closest_point); _point_to_info[pinfo->_closest_point] = pinfo; computeContactForce(pinfo); } } }
inline expr MkAtMost(expr_vector vars, unsigned k) { array<Z3_ast> _vars(vars.size()); for (unsigned i = 0; i < vars.size(); ++i) { _vars[i] = vars[i]; } expr r{ vars.ctx(), Z3_mk_atmost(vars.ctx(), vars.size(), _vars.ptr(), k) }; vars.check_error(); return r; }
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; } }
bool MechanicalContactConstraint::getCoupledVarComponent(unsigned int var_num, unsigned int &component) { component = std::numeric_limits<unsigned int>::max(); bool coupled_var_is_disp_var = false; for (unsigned int i=0; i<_vars.size(); ++i) { if (var_num == _vars(i)) { coupled_var_is_disp_var = true; component = i; break; } } return coupled_var_is_disp_var; }
void SlaveConstraint::addPoints() { _point_to_info.clear(); std::map<dof_id_type, PenetrationInfo *>::iterator it = _penetration_locator._penetration_info.begin(), end = _penetration_locator._penetration_info.end(); for (; it!=end; ++it) { 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; dof_id_type slave_node_num = it->first; const Node * node = pinfo->_node; if (pinfo->isCaptured() && node->processor_id() == processor_id()) { // Find an element that is connected to this node that and that is also on this processor std::vector<dof_id_type> & connected_elems = _mesh.nodeToElemMap()[slave_node_num]; Elem * elem = NULL; for (unsigned int i=0; i<connected_elems.size() && !elem; ++i) { Elem * cur_elem = _mesh.elem(connected_elems[i]); if (cur_elem->processor_id() == processor_id()) elem = cur_elem; } mooseAssert(elem, "Couldn't find an element on this processor that is attached to the slave node!"); addPoint(elem, *node); _point_to_info[*node] = pinfo; } } }
Real GluedContactConstraint::computeQpOffDiagJacobian(Moose::ConstraintJacobianType type, unsigned int /*jvar*/) { Real retVal = 0; switch (type) { case Moose::SlaveSlave: break; case Moose::SlaveMaster: break; case Moose::MasterSlave: { double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); retVal = slave_jac*_test_master[_i][_qp]; break; } case Moose::MasterMaster: break; } return retVal; }
Real GluedContactConstraint::computeQpJacobian(Moose::ConstraintJacobianType type) { switch (type) { case Moose::SlaveSlave: { return _penalty*_phi_slave[_j][_qp]*_test_slave[_i][_qp]; } case Moose::SlaveMaster: { return _penalty*-_phi_master[_j][_qp]*_test_slave[_i][_qp]; } case Moose::MasterSlave: { double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return slave_jac*_test_master[_i][_qp]; } case Moose::MasterMaster: return 0; } 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"); } }
Real MechanicalContactConstraint::computeQpJacobian(Moose::ConstraintJacobianType type) { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; switch(type) { case Moose::SlaveSlave: switch(_model) { case CM_FRICTIONLESS: case CM_EXPERIMENTAL: switch (_formulation) { case CF_DEFAULT: { double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); //TODO: Need off-diagonal term/s return (-curr_jac + _phi_slave[_j][_qp] * _penalty * _test_slave[_i][_qp]) * pinfo->_normal(_component) * pinfo->_normal(_component); } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return _phi_slave[_j][_qp] * _penalty * _test_slave[_i][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: case CM_TIED: switch (_formulation) { case CF_DEFAULT: { double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return -curr_jac + _phi_slave[_j][_qp] * _penalty * _test_slave[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return _phi_slave[_j][_qp] * _penalty * _test_slave[_i][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::SlaveMaster: switch(_model) { case CM_FRICTIONLESS: case CM_EXPERIMENTAL: switch (_formulation) { case CF_DEFAULT: { Node * curr_master_node = _current_master->get_node(_j); double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), curr_master_node->dof_number(0, _vars(_component), 0)); //TODO: Need off-diagonal terms return (-curr_jac - _phi_master[_j][_qp] * _penalty * _test_slave[_i][_qp]) * pinfo->_normal(_component) * pinfo->_normal(_component); } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return -_phi_master[_j][_qp] * _penalty * _test_slave[_i][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: case CM_TIED: switch (_formulation) { case CF_DEFAULT: { Node * curr_master_node = _current_master->get_node(_j); double curr_jac = (*_jacobian)( _current_node->dof_number(0, _vars(_component), 0), curr_master_node->dof_number(0, _vars(_component), 0)); return -curr_jac - _phi_master[_j][_qp] * _penalty * _test_slave[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return -_phi_master[_j][_qp] * _penalty * _test_slave[_i][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::MasterSlave: switch(_model) { case CM_FRICTIONLESS: case CM_EXPERIMENTAL: switch (_formulation) { case CF_DEFAULT: { //TODO: Need off-diagonal terms double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); //TODO: To get off-diagonal terms correct using an approach like this, we would need to assemble in the rows for //all displacement components times their components of the normal vector. return slave_jac * _test_master[_i][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return -_test_master[_i][_qp] * _penalty * _phi_slave[_j][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: case CM_TIED: switch (_formulation) { case CF_DEFAULT: { double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return slave_jac * _test_master[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return -_test_master[_i][_qp] * _penalty * _phi_slave[_j][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::MasterMaster: switch(_model) { case CM_FRICTIONLESS: case CM_EXPERIMENTAL: switch (_formulation) { case CF_DEFAULT: return 0; case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return _test_master[_i][_qp] * _penalty * _phi_master[_j][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: case CM_TIED: switch (_formulation) { case CF_DEFAULT: return 0; case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return _test_master[_i][_qp] * _penalty * _phi_master[_j][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } } return 0; }
Real MechanicalContactConstraint::computeQpOffDiagJacobian(Moose::ConstraintJacobianType type, unsigned int jvar) { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; const Real penalty = getPenalty(*pinfo); unsigned int coupled_component; double normal_component_in_coupled_var_dir = 1.0; if (getCoupledVarComponent(jvar,coupled_component)) normal_component_in_coupled_var_dir = pinfo->_normal(coupled_component); switch (type) { case Moose::SlaveSlave: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_KINEMATIC: { RealVectorValue jac_vec; for (unsigned int i=0; i<_mesh_dimension; ++i) { dof_id_type dof_number = _current_node->dof_number(0, _vars(i), 0); jac_vec(i) = (*_jacobian)(dof_number, _connected_dof_indices[_j]); } return -pinfo->_normal(_component) * (pinfo->_normal*jac_vec) + (_phi_slave[_j][_qp] * penalty * _test_slave[_i][_qp]) * pinfo->_normal(_component) * normal_component_in_coupled_var_dir; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return _phi_slave[_j][_qp] * penalty * _test_slave[_i][_qp] * pinfo->_normal(_component) * normal_component_in_coupled_var_dir; default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: { double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return -curr_jac; } default: mooseError("Invalid or unavailable contact model"); } case Moose::SlaveMaster: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_KINEMATIC: { Node * curr_master_node = _current_master->get_node(_j); RealVectorValue jac_vec; for (unsigned int i=0; i<_mesh_dimension; ++i) { dof_id_type dof_number = _current_node->dof_number(0, _vars(i), 0); jac_vec(i) = (*_jacobian)(dof_number, curr_master_node->dof_number(0, _vars(_component), 0)); } return -pinfo->_normal(_component)*(pinfo->_normal*jac_vec) - (_phi_master[_j][_qp] * penalty * _test_slave[_i][_qp]) * pinfo->_normal(_component) * normal_component_in_coupled_var_dir; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return -_phi_master[_j][_qp] * penalty * _test_slave[_i][_qp] * pinfo->_normal(_component) * normal_component_in_coupled_var_dir; default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: return 0; default: mooseError("Invalid or unavailable contact model"); } case Moose::MasterSlave: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_KINEMATIC: { RealVectorValue jac_vec; for (unsigned int i=0; i<_mesh_dimension; ++i) { dof_id_type dof_number = _current_node->dof_number(0, _vars(i), 0); jac_vec(i) = (*_jacobian)(dof_number, _connected_dof_indices[_j]); } return pinfo->_normal(_component)*(pinfo->_normal*jac_vec) * _test_master[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return -_test_master[_i][_qp] * penalty * _phi_slave[_j][_qp] * pinfo->_normal(_component) * normal_component_in_coupled_var_dir; default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: switch (_formulation) { case CF_KINEMATIC: { double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return slave_jac * _test_master[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return 0; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::MasterMaster: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_KINEMATIC: return 0; case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return _test_master[_i][_qp] * penalty * _phi_master[_j][_qp] * pinfo->_normal(_component) * normal_component_in_coupled_var_dir; default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: return 0; default: mooseError("Invalid or unavailable contact model"); } } return 0; }
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; } }
void MultiDContactConstraint::updateContactSet() { std::set<dof_id_type> & has_penetrated = _penetration_locator._has_penetrated; std::map<dof_id_type, PenetrationInfo *>::iterator it = _penetration_locator._penetration_info.begin(), end = _penetration_locator._penetration_info.end(); for (; it!=end; ++it) { 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; const Node * node = pinfo->_node; dof_id_type slave_node_num = it->first; std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); 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); } // Real resid = 0; switch (_model) { case CM_FRICTIONLESS: // resid = pinfo->_normal * res_vec; break; case CM_GLUED: // resid = pinfo->_normal * res_vec; break; default: mooseError("Invalid or unavailable contact model"); break; } // if (hpit != has_penetrated.end() && resid < 0) // Moose::err<<resid<<std::endl; /* if (hpit != has_penetrated.end() && resid < -.15) { Moose::err<<std::endl<<"Unlocking node "<<node->id()<<" because resid: "<<resid<<std::endl<<std::endl; has_penetrated.erase(hpit); unlocked_this_step[slave_node_num] = true; } else*/ if (pinfo->_distance > 0 && hpit == has_penetrated.end())// && !unlocked_this_step[slave_node_num]) { // Moose::err<<std::endl<<"Locking node "<<node->id()<<" because distance: "<<pinfo->_distance<<std::endl<<std::endl; has_penetrated.insert(slave_node_num); } } }
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; }