ContactSlipDamper::ContactSlipDamper(const InputParameters & parameters) : GeneralDamper(parameters), _aux_sys(parameters.get<FEProblem *>("_fe_problem")->getAuxiliarySystem()), _displaced_problem(parameters.get<FEProblem *>("_fe_problem")->getDisplacedProblem()), _num_contact_nodes(0), _num_sticking(0), _num_slipping(0), _num_slipping_friction(0), _num_stick_locked(0), _num_slip_reversed(0), _max_iterative_slip(parameters.get<Real>("max_iterative_slip")), _min_damping_factor(parameters.get<Real>("min_damping_factor")), _damping_threshold_factor(parameters.get<Real>("damping_threshold_factor")), _debug_output(parameters.get<bool>("debug_output")) { if (!_displaced_problem) mooseError("Must have displaced problem to use ContactSlipDamper"); std::vector<int> master = parameters.get<std::vector<int> >("master"); std::vector<int> slave = parameters.get<std::vector<int> >("slave"); unsigned int num_interactions = master.size(); if (num_interactions != slave.size()) mooseError("Sizes of master surface and slave surface lists must match in ContactSlipDamper"); if (num_interactions == 0) mooseError("Must define at least one master/slave pair in ContactSlipDamper"); for (unsigned int i = 0; i < master.size(); ++i) { std::pair<int, int> ms_pair(master[i], slave[i]); _interactions.insert(ms_pair); } }
void FrictionalContactProblem::updateIncrementalSlip() { AuxiliarySystem & aux_sys = getAuxiliarySystem(); NumericVector<Number> & aux_solution = aux_sys.solution(); MooseVariable * inc_slip_x_var = &getVariable(0,_inc_slip_x); MooseVariable * inc_slip_y_var = &getVariable(0,_inc_slip_y); MooseVariable * inc_slip_z_var = nullptr; unsigned int dim = getNonlinearSystem().subproblem().mesh().dimension(); if (dim == 3) inc_slip_z_var = &getVariable(0,_inc_slip_z); GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; for (PLIterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; if (info.isCaptured()) { const Node * node = info._node; VectorValue<dof_id_type> inc_slip_dofs(node->dof_number(aux_sys.number(), inc_slip_x_var->number(), 0), node->dof_number(aux_sys.number(), inc_slip_y_var->number(), 0), (inc_slip_z_var ? node->dof_number(aux_sys.number(), inc_slip_z_var->number(), 0) : 0)); RealVectorValue inc_slip = info._incremental_slip; for (unsigned int i=0; i<dim; ++i) aux_solution.set(inc_slip_dofs(i), inc_slip(i)); } } } } } aux_solution.close(); }
bool ContactSlipDamper::operateOnThisInteraction(const PenetrationLocator & pen_loc) { bool operate_on_this_interaction = false; std::set<std::pair<int, int> >::iterator ipit; std::pair<int, int> ms_pair(pen_loc._master_boundary, pen_loc._slave_boundary); ipit = _interactions.find(ms_pair); if (ipit != _interactions.end()) operate_on_this_interaction = true; return operate_on_this_interaction; }
unsigned int FrictionalContactProblem::numLocalFrictionalConstraints() { GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; unsigned int num_constraints(0); for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { std::set<dof_id_type> & has_penetrated = pen_loc._has_penetrated; std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (hpit != has_penetrated.end()) { ++num_constraints; } } } } } return num_constraints; }
FrictionalContactProblem::FrictionalContactProblem(const std::string & name, InputParameters params) : ReferenceResidualProblem(name, params), _refResidContact(0.0), _slip_residual(0.0), _do_slip_update(false), _num_slip_iterations(0), _target_contact_residual(0.0), _target_relative_contact_residual(0.0), _num_nl_its_since_contact_update(0), _num_contact_nodes(0), _num_slipping(0), _num_slipped_too_far(0), _inc_slip_norm(0.0), _it_slip_norm(0.0) { std::vector<int> master = params.get<std::vector<int> >("master"); std::vector<int> slave = params.get<std::vector<int> >("slave"); std::vector<Real> friction_coefficient = params.get<std::vector<Real> >("friction_coefficient"); std::vector<Real> slip_factor = params.get<std::vector<Real> >("slip_factor"); std::vector<Real> slip_too_far_factor = params.get<std::vector<Real> >("slip_too_far_factor"); unsigned int dim = getNonlinearSystem().subproblem().mesh().dimension(); _disp_x = params.get<NonlinearVariableName>("disp_x"); _residual_x = params.get<AuxVariableName>("residual_x"); _diag_stiff_x = params.get<AuxVariableName>("diag_stiff_x"); _inc_slip_x = params.get<AuxVariableName>("inc_slip_x"); _disp_y = params.get<NonlinearVariableName>("disp_y"); _residual_y = params.get<AuxVariableName>("residual_y"); _diag_stiff_y = params.get<AuxVariableName>("diag_stiff_y"); _inc_slip_y = params.get<AuxVariableName>("inc_slip_y"); if (dim == 3) { if (!params.isParamValid("disp_z")) mooseError("Missing disp_z in FrictionalContactProblem"); if (!params.isParamValid("residual_z")) mooseError("Missing residual_z in FrictionalContactProblem"); if (!params.isParamValid("diag_stiff_z")) mooseError("Missing diag_stiff_z in FrictionalContactProblem"); if (!params.isParamValid("inc_slip_z")) mooseError("Missing inc_slip_z in FrictionalContactProblem"); _disp_z = params.get<NonlinearVariableName>("disp_z"); _residual_z = params.get<AuxVariableName>("residual_z"); _diag_stiff_z = params.get<AuxVariableName>("diag_stiff_z"); _inc_slip_z = params.get<AuxVariableName>("inc_slip_z"); } unsigned int num_interactions = master.size(); if (num_interactions != slave.size()) mooseError("Sizes of master surface and slave surface lists must match in FrictionalContactProblem"); if (num_interactions != friction_coefficient.size()) mooseError("Must have friction coefficient defined for every interaction in FrictionalContactProblem"); if (num_interactions != slip_factor.size()) mooseError("Must have slip factor defined for every interaction in FrictionalContactProblem"); if (num_interactions != slip_too_far_factor.size()) mooseError("Must have slip too far factor defined for every interaction in FrictionalContactProblem"); for (unsigned int i=0; i<master.size(); ++i) { std::pair<int,int> ms_pair(master[i],slave[i]); InteractionParams ip; ip._friction_coefficient = friction_coefficient[i]; ip._slip_factor = slip_factor[i]; ip._slip_too_far_factor = slip_too_far_factor[i]; _interaction_params[ms_pair] = ip; } _min_slip_iters = params.get<int>("minimum_slip_iterations"); _max_slip_iters = params.get<int>("maximum_slip_iterations"); _slip_updates_per_iter = params.get<int>("slip_updates_per_iteration"); bool have_target = false; bool have_target_relative = false; if (params.isParamValid("target_contact_residual")) { _target_contact_residual = params.get<Real>("target_contact_residual"); have_target = true; } if (params.isParamValid("target_relative_contact_residual")) { _target_relative_contact_residual = params.get<Real>("target_relative_contact_residual"); have_target_relative = true; } if (!(have_target || have_target_relative)) mooseError("Must specify either target_contact_residual or target_relative_contact_residual"); _contact_slip_tol_factor = params.get<Real>("contact_slip_tolerance_factor"); if (params.isParamValid("contact_reference_residual_variables")) _contactRefResidVarNames = params.get<std::vector<std::string> >("contact_reference_residual_variables"); }
bool FrictionalContactProblem::calculateSlip(const NumericVector<Number>& ghosted_solution, std::vector<SlipData> * iterative_slip) { NonlinearSystem & nonlinear_sys = getNonlinearSystem(); unsigned int dim = nonlinear_sys.subproblem().mesh().dimension(); MooseVariable * residual_x_var = &getVariable(0,_residual_x); MooseVariable * residual_y_var = &getVariable(0,_residual_y); MooseVariable * residual_z_var = NULL; MooseVariable * diag_stiff_x_var = &getVariable(0,_diag_stiff_x); MooseVariable * diag_stiff_y_var = &getVariable(0,_diag_stiff_y); MooseVariable * diag_stiff_z_var = NULL; MooseVariable * inc_slip_x_var = &getVariable(0,_inc_slip_x); MooseVariable * inc_slip_y_var = &getVariable(0,_inc_slip_y); MooseVariable * inc_slip_z_var = NULL; if (dim == 3) { residual_z_var = &getVariable(0,_residual_z); diag_stiff_z_var = &getVariable(0,_diag_stiff_z); inc_slip_z_var = &getVariable(0,_inc_slip_z); } bool updatedSolution = false; _slip_residual = 0.0; _it_slip_norm = 0.0; _inc_slip_norm = 0.0; TransientNonlinearImplicitSystem & system = getNonlinearSystem().sys(); if (iterative_slip) iterative_slip->clear(); if (getDisplacedProblem() && _interaction_params.size() > 0) { computeResidual(system, ghosted_solution, *system.rhs); _num_contact_nodes = 0; _num_slipping = 0; _num_slipped_too_far = 0; GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; AuxiliarySystem & aux_sys = getAuxiliarySystem(); const NumericVector<Number> & aux_solution = *aux_sys.currentSolution(); for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; std::set<dof_id_type> & has_penetrated = pen_loc._has_penetrated; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { InteractionParams & interaction_params = ipit->second; Real slip_factor = interaction_params._slip_factor; Real slip_too_far_factor = interaction_params._slip_too_far_factor; Real friction_coefficient = interaction_params._friction_coefficient; std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; const Node * node = info._node; if (node->processor_id() == processor_id()) { std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (hpit != has_penetrated.end()) { _num_contact_nodes++; VectorValue<dof_id_type> residual_dofs(node->dof_number(aux_sys.number(), residual_x_var->number(), 0), node->dof_number(aux_sys.number(), residual_y_var->number(), 0), (residual_z_var ? node->dof_number(aux_sys.number(), residual_z_var->number(), 0) : 0)); VectorValue<dof_id_type> diag_stiff_dofs(node->dof_number(aux_sys.number(), diag_stiff_x_var->number(), 0), node->dof_number(aux_sys.number(), diag_stiff_y_var->number(), 0), (diag_stiff_z_var ? node->dof_number(aux_sys.number(), diag_stiff_z_var->number(), 0) : 0)); VectorValue<dof_id_type> inc_slip_dofs(node->dof_number(aux_sys.number(), inc_slip_x_var->number(), 0), node->dof_number(aux_sys.number(), inc_slip_y_var->number(), 0), (inc_slip_z_var ? node->dof_number(aux_sys.number(), inc_slip_z_var->number(), 0) : 0)); RealVectorValue res_vec; RealVectorValue stiff_vec; RealVectorValue slip_inc_vec; for (unsigned int i=0; i<dim; ++i) { res_vec(i) = aux_solution(residual_dofs(i)); stiff_vec(i) = aux_solution(diag_stiff_dofs(i)); slip_inc_vec(i) = aux_solution(inc_slip_dofs(i)); } RealVectorValue slip_iterative(0.0,0.0,0.0); Real interaction_slip_residual = 0.0; // _console<<"inc slip: "<<slip_inc_vec<<std::endl; // _console<<"info slip: "<<info._incremental_slip<<std::endl; // ContactState state = calculateInteractionSlip(slip_iterative, interaction_slip_residual, info._normal, res_vec, info._incremental_slip, stiff_vec, friction_coefficient, slip_factor, slip_too_far_factor, dim); ContactState state = calculateInteractionSlip(slip_iterative, interaction_slip_residual, info._normal, res_vec, slip_inc_vec, stiff_vec, friction_coefficient, slip_factor, slip_too_far_factor, dim); // _console<<"iter slip: "<<slip_iterative<<std::endl; _slip_residual += interaction_slip_residual*interaction_slip_residual; if (state == SLIPPING || state == SLIPPED_TOO_FAR) { _num_slipping++; if (state == SLIPPED_TOO_FAR) _num_slipped_too_far++; for (unsigned int i=0; i<dim; ++i) { SlipData sd(node,i,slip_iterative(i)); if (iterative_slip) iterative_slip->push_back(sd); _it_slip_norm += slip_iterative(i)*slip_iterative(i); _inc_slip_norm += (slip_inc_vec(i)+slip_iterative(i))*(slip_inc_vec(i)+slip_iterative(i)); } } } } } } } } _communicator.sum(_num_contact_nodes); _communicator.sum(_num_slipping); _communicator.sum(_num_slipped_too_far); _communicator.sum(_slip_residual); _slip_residual = std::sqrt(_slip_residual); _communicator.sum(_it_slip_norm); _it_slip_norm = std::sqrt(_it_slip_norm); _communicator.sum(_inc_slip_norm); _inc_slip_norm = std::sqrt(_inc_slip_norm); if (_num_slipping > 0) updatedSolution = true; } return updatedSolution; }
bool FrictionalContactProblem::enforceRateConstraint(NumericVector<Number>& vec_solution, NumericVector<Number>& ghosted_solution) { NonlinearSystem & nonlinear_sys = getNonlinearSystem(); unsigned int dim = nonlinear_sys.subproblem().mesh().dimension(); _displaced_problem->updateMesh(ghosted_solution, *_aux.currentSolution()); MooseVariable * disp_x_var = &getVariable(0,_disp_x); MooseVariable * disp_y_var = &getVariable(0,_disp_y); MooseVariable * disp_z_var = NULL; if (dim == 3) disp_z_var = &getVariable(0,_disp_z); bool updatedSolution = false; if (getDisplacedProblem() && _interaction_params.size() > 0) { GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; std::set<dof_id_type> & has_penetrated = pen_loc._has_penetrated; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (hpit != has_penetrated.end()) { // _console<<"Slave node: "<<slave_node_num<<std::endl; const Node * node = info._node; VectorValue<dof_id_type> solution_dofs(node->dof_number(nonlinear_sys.number(), disp_x_var->number(), 0), node->dof_number(nonlinear_sys.number(), disp_y_var->number(), 0), (disp_z_var ? node->dof_number(nonlinear_sys.number(), disp_z_var->number(), 0) : 0)); //Get old parametric coords from info //get old element from info //Apply current configuration to that element and find xyz coords of that point //find xyz coords of current point from original coords and displacement vector //calculate difference between those two point coordinates to get correction // std::vector<Point>points(1); // points[0] = info._starting_closest_point_ref; // Elem *side = (info._starting_elem->build_side(info._starting_side_num,false)).release(); // FEBase &fe = *(pen_loc._fe[0]); // fe.reinit(side, &points); // RealVectorValue correction = starting_point[0] - current_coords; // RealVectorValue current_coords = *node; // RealVectorValue correction = info._closest_point - current_coords; const Node & undisp_node = _mesh.node(node->id()); RealVectorValue solution = info._closest_point - undisp_node; for (unsigned int i=0; i<dim; ++i) { // vec_solution.add(solution_dofs(i), correction(i)); vec_solution.set(solution_dofs(i), solution(i)); } info._distance = 0.0; } } } } updatedSolution = true; } vec_solution.close(); _communicator.max(updatedSolution); if (updatedSolution) { ghosted_solution = vec_solution; ghosted_solution.close(); } } return updatedSolution; }