8 #include <unordered_set> 
   11 #include "libmesh/libmesh.h" 
   12 #include "libmesh/mesh.h" 
   13 #include "libmesh/equation_systems.h" 
   14 #include "libmesh/fe.h" 
   15 #include "libmesh/quadrature_gauss.h" 
   16 #include "libmesh/dof_map.h" 
   17 #include "libmesh/sparse_matrix.h" 
   18 #include "libmesh/numeric_vector.h" 
   19 #include "libmesh/dense_matrix.h" 
   20 #include "libmesh/dense_vector.h" 
   21 #include "libmesh/elem.h" 
   22 #include "libmesh/fe_interface.h" 
   23 #include "libmesh/fe_compute_data.h" 
   24 #include "libmesh/petsc_matrix.h" 
   25 #include "libmesh/edge_edge2.h" 
   28 #include "libmesh/nonlinear_solver.h" 
   29 #include "libmesh/nonlinear_implicit_system.h" 
   34                                                           Real contact_penalty_in) :
 
   36   _contact_penalty(contact_penalty_in)
 
   53   return i == j ? 1. : 0.;
 
   64   const Real lambda_1 = (young_modulus*poisson_ratio)/((1.+poisson_ratio)*(1.-2.*poisson_ratio));
 
   65   const Real lambda_2 = young_modulus/(2.*(1.+poisson_ratio));
 
   75   std::unordered_set<dof_id_type> encountered_node_ids;
 
   79   std::unique_ptr<NumericVector<Number>> localized_input_solution =
 
   82   localized_input_solution->
init (input_solution.
size(), 
false, 
SERIAL);
 
   83   input_solution.
localize(*localized_input_solution);
 
   89       for (
auto node_id : elem->node_index_range())
 
   91           Node & node = elem->node_ref(node_id);
 
   93           if (encountered_node_ids.find(node.
id()) != encountered_node_ids.end())
 
   96           encountered_node_ids.insert(node.
id());
 
   98           std::vector<std::string> uvw_names(3);
 
  104             const Point master_point = elem->master_point(node_id);
 
  107             for (std::size_t index=0; index<uvw_names.size(); index++)
 
  114                 FEInterface::compute_data(elem->dim(),
 
  119                 std::vector<dof_id_type> dof_indices_var;
 
  122                 for (std::size_t i=0; i<dof_indices_var.size(); i++)
 
  124                     Number value = (*localized_input_solution)(dof_indices_var[i]) * 
data.shape[i];
 
  126 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
 
  128                     uvw(index) += 
value.real();
 
  146   std::vector<dof_id_type> nodes_on_lower_surface;
 
  147   std::vector<dof_id_type> nodes_on_upper_surface;
 
  151     for (
auto side : elem->side_index_range())
 
  152       if (elem->neighbor_ptr(side) == 
nullptr)
 
  154           bool on_lower_contact_surface =
 
  157           bool on_upper_contact_surface =
 
  160           if (on_lower_contact_surface && on_upper_contact_surface)
 
  161             libmesh_error_msg(
"Should not be on both surfaces at the same time");
 
  163           if (on_lower_contact_surface || on_upper_contact_surface)
 
  165               for (
auto node_index : elem->node_index_range())
 
  166                 if (elem->is_node_on_side(node_index, side))
 
  168                     if (on_lower_contact_surface)
 
  169                       nodes_on_lower_surface.push_back(elem->node_id(node_index));
 
  172                         _lambdas[elem->node_id(node_index)] = 0.;
 
  173                         nodes_on_upper_surface.push_back(elem->node_id(node_index));
 
  180   libmesh_assert(nodes_on_lower_surface.size() == nodes_on_upper_surface.size());
 
  184   for (std::size_t i=0; i<nodes_on_lower_surface.size(); i++)
 
  186       dof_id_type lower_node_id = nodes_on_lower_surface[i];
 
  189       Real min_distance = std::numeric_limits<Real>::max();
 
  191       for (std::size_t j=0; j<nodes_on_upper_surface.size(); j++)
 
  193           dof_id_type upper_node_id = nodes_on_upper_surface[j];
 
  213   for( ; it != it_end ; ++it )
 
  222       connector_elem->
set_node(0) = &master_node;
 
  223       connector_elem->
set_node(1) = &slave_node;
 
  248   std::unique_ptr<FEBase> fe (FEBase::build(
dim, fe_type));
 
  250   fe->attach_quadrature_rule (&qrule);
 
  252   std::unique_ptr<FEBase> fe_face (FEBase::build(
dim, fe_type));
 
  254   fe_face->attach_quadrature_rule (&qface);
 
  256   std::unique_ptr<FEBase> fe_neighbor_face (FEBase::build(
dim, fe_type));
 
  257   fe_neighbor_face->attach_quadrature_rule (&qface);
 
  259   const std::vector<Real> & JxW = fe->get_JxW();
 
  260   const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
 
  284   std::vector<dof_id_type> dof_indices;
 
  285   std::vector<std::vector<dof_id_type>> dof_indices_var(3);
 
  289       if( elem->type() == 
EDGE2 )
 
  297       for (
unsigned int var=0; var<3; var++)
 
  298         dof_map.
dof_indices (elem, dof_indices_var[var], var);
 
  300       const unsigned int n_dofs   = dof_indices.size();
 
  301       const unsigned int n_var_dofs = dof_indices_var[0].size();
 
  306       for (
unsigned int var=0; var<3; var++)
 
  307         Re_var[var].reposition (var*n_var_dofs, n_var_dofs);
 
  309       Ke.
resize (n_dofs, n_dofs);
 
  310       for (
unsigned int var_i=0; var_i<3; var_i++)
 
  311         for (
unsigned int var_j=0; var_j<3; var_j++)
 
  312           Ke_var[var_i][var_j].reposition (var_i*n_var_dofs, var_j*n_var_dofs, n_var_dofs, n_var_dofs);
 
  314       for (
unsigned int qp=0; qp<qrule.n_points(); qp++)
 
  318           for (
unsigned int var_i=0; var_i<3; var_i++)
 
  319             for (
unsigned int var_j=0; var_j<3; var_j++)
 
  320               for (
unsigned int j=0; j<n_var_dofs; j++)
 
  321                 grad_u(var_i, var_j) += dphi[j][qp](var_j)*soln(dof_indices_var[var_i][j]);
 
  324           for (
unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++)
 
  325             for (
unsigned int i=0; i<3; i++)
 
  326               for (
unsigned int j=0; j<3; j++)
 
  327                 for (
unsigned int k=0; k<3; k++)
 
  328                   for (
unsigned int l=0; l<3; l++)
 
  329                     Re_var[i](dof_i) -= JxW[qp] *
 
  330                       elasticity_tensor(young_modulus, poisson_ratio, i, j, k, l) * grad_u(k,l) * dphi[dof_i][qp](j);
 
  333           for (
unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++)
 
  334             for (
unsigned int dof_j=0; dof_j<n_var_dofs; dof_j++)
 
  335               for (
unsigned int i=0; i<3; i++)
 
  336                 for (
unsigned int j=0; j<3; j++)
 
  337                   for (
unsigned int k=0; k<3; k++)
 
  338                     for (
unsigned int l=0; l<3; l++)
 
  339                       Ke_var[i][k](dof_i, dof_j) -= JxW[qp] *
 
  340                         elasticity_tensor(young_modulus, poisson_ratio, i, j, k, l) * dphi[dof_j][qp](l) * dphi[dof_i][qp](j);
 
  358   std::unique_ptr<MeshBase> mesh_clone = 
mesh.
clone();
 
  368   for ( ; it != it_end; ++it)
 
  373       Point upper_to_lower;
 
  375         Point lower_node_moved = mesh_clone->point(lower_point_id);
 
  376         Point upper_node_moved = mesh_clone->point(upper_point_id);
 
  378         upper_to_lower = (lower_node_moved - upper_node_moved);
 
  384       Point contact_force_direction(0., 0., 1.);
 
  389       Real gap_function = upper_to_lower * contact_force_direction;
 
  393       Real lambda_plus_penalty =
 
  396       if (lambda_plus_penalty < 0.)
 
  397         lambda_plus_penalty = 0.;
 
  405       std::vector<dof_id_type> dof_indices_on_lower_node(3);
 
  406       std::vector<dof_id_type> dof_indices_on_upper_node(3);
 
  410       for (
unsigned int var=0; var<3; var++)
 
  413           lower_contact_force_vec(var) = -lambda_plus_penalty * contact_force_direction(var);
 
  416           upper_contact_force_vec(var) = lambda_plus_penalty * contact_force_direction(var);
 
  419       if (lambda_plus_penalty > 0.)
 
  421           if (residual && (
_sys.
comm().rank() == 0))
 
  423               residual->
add_vector (lower_contact_force_vec, dof_indices_on_lower_node);
 
  424               residual->
add_vector (upper_contact_force_vec, dof_indices_on_upper_node);
 
  429           if (jacobian && (
_sys.
comm().rank() == 0))
 
  430             for (
unsigned int var=0; var<3; var++)
 
  431               for (
unsigned int j=0; j<3; j++)
 
  433                   jacobian->
add(dof_indices_on_lower_node[var],
 
  434                                 dof_indices_on_upper_node[j],
 
  435                                 _contact_penalty * contact_force_direction(j) * contact_force_direction(var));
 
  437                   jacobian->
add(dof_indices_on_lower_node[var],
 
  438                                 dof_indices_on_lower_node[j],
 
  439                                 -
_contact_penalty * contact_force_direction(j) * contact_force_direction(var));
 
  441                   jacobian->
add(dof_indices_on_upper_node[var],
 
  442                                 dof_indices_on_lower_node[j],
 
  443                                 _contact_penalty * contact_force_direction(j) * contact_force_direction(var));
 
  445                   jacobian->
add(dof_indices_on_upper_node[var],
 
  446                                 dof_indices_on_upper_node[j],
 
  447                                 -
_contact_penalty * contact_force_direction(j) * contact_force_direction(var));
 
  457           if (jacobian && (
_sys.
comm().rank() == 0))
 
  458             for (
unsigned int var=0; var<3; var++)
 
  459               for (
unsigned int j=0; j<3; j++)
 
  461                   jacobian->
add(dof_indices_on_lower_node[var],
 
  462                                 dof_indices_on_upper_node[j],
 
  465                   jacobian->
add(dof_indices_on_lower_node[var],
 
  466                                 dof_indices_on_lower_node[j],
 
  469                   jacobian->
add(dof_indices_on_upper_node[var],
 
  470                                 dof_indices_on_lower_node[j],
 
  473                   jacobian->
add(dof_indices_on_upper_node[var],
 
  474                                 dof_indices_on_upper_node[j],
 
  490   unsigned int displacement_vars[3];
 
  498   std::unique_ptr<FEBase> fe (FEBase::build(
dim, fe_type));
 
  500   fe->attach_quadrature_rule (&qrule);
 
  502   const std::vector<Real> & JxW = fe->get_JxW();
 
  503   const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
 
  508   unsigned int sigma_vars[6];
 
  515   unsigned int vonMises_var = stress_system.
variable_number (
"vonMises");
 
  518   std::vector<std::vector<dof_id_type>> dof_indices_var(
_sys.
n_vars());
 
  519   std::vector<dof_id_type> stress_dof_indices_var;
 
  526       if( elem->type() == 
EDGE2 )
 
  532       for (
unsigned int var=0; var<3; var++)
 
  533         dof_map.
dof_indices (elem, dof_indices_var[var], displacement_vars[var]);
 
  535       const unsigned int n_var_dofs = dof_indices_var[0].size();
 
  540       elem_avg_stress_tensor.
resize(3, 3);
 
  542       for (
unsigned int qp=0; qp<qrule.n_points(); qp++)
 
  546           for (
unsigned int var_i=0; var_i<3; var_i++)
 
  547             for (
unsigned int var_j=0; var_j<3; var_j++)
 
  548               for (
unsigned int j=0; j<n_var_dofs; j++)
 
  549                 grad_u(var_i, var_j) +=
 
  553           for (
unsigned int i=0; i<3; i++)
 
  554             for (
unsigned int j=0; j<3; j++)
 
  555               for (
unsigned int k=0; k<3; k++)
 
  556                 for (
unsigned int l=0; l<3; l++)
 
  557                   stress_tensor(i,j) +=
 
  562           elem_avg_stress_tensor.
add(JxW[qp], stress_tensor);
 
  566       elem_avg_stress_tensor.
scale(1./elem->volume());
 
  569       unsigned int stress_var_index = 0;
 
  570       for (
unsigned int i=0; i<3; i++)
 
  571         for (
unsigned int j=i; j<3; j++)
 
  573             stress_dof_map.dof_indices (elem, stress_dof_indices_var, sigma_vars[stress_var_index]);
 
  579             if ((stress_system.
solution->first_local_index() <= dof_index) &&
 
  580                 (dof_index < stress_system.solution->last_local_index()))
 
  581               stress_system.
solution->set(dof_index, elem_avg_stress_tensor(i,j));
 
  587       Number vonMises_value = 
std::sqrt(0.5*(
pow(elem_avg_stress_tensor(0,0) - elem_avg_stress_tensor(1,1), 2.) +
 
  588                                              pow(elem_avg_stress_tensor(1,1) - elem_avg_stress_tensor(2,2), 2.) +
 
  589                                              pow(elem_avg_stress_tensor(2,2) - elem_avg_stress_tensor(0,0), 2.) +
 
  590                                              6.*(
pow(elem_avg_stress_tensor(0,1), 2.) +
 
  591                                                  pow(elem_avg_stress_tensor(1,2), 2.) +
 
  592                                                  pow(elem_avg_stress_tensor(2,0), 2.))));
 
  594       stress_dof_map.dof_indices (elem, stress_dof_indices_var, vonMises_var);
 
  597       if ((stress_system.
solution->first_local_index() <= dof_index) &&
 
  598           (dof_index < stress_system.solution->last_local_index()))
 
  599         stress_system.
solution->set(dof_index, vonMises_value);
 
  609   Real max_delta_lambda = 0.;
 
  610   Real max_new_lambda = 0.;
 
  612   std::map<dof_id_type, Real>::iterator it = 
_lambdas.begin();
 
  613   std::map<dof_id_type, Real>::iterator it_end = 
_lambdas.end();
 
  614   for ( ; it != it_end; ++it)
 
  620         libmesh_error_msg(
"New lambda value not found");
 
  622       Real new_lambda = new_lambda_it->second;
 
  623       Real old_lambda = it->second;
 
  625       it->second = new_lambda;
 
  628       if (delta_lambda > max_delta_lambda)
 
  629         max_delta_lambda = delta_lambda;
 
  631       if (
std::abs(new_lambda) > max_new_lambda)
 
  632         max_new_lambda = 
std::abs(new_lambda);
 
  635   return std::make_pair(max_delta_lambda, max_new_lambda);
 
  643   Real least_value = std::numeric_limits<Real>::max();
 
  644   Real max_value = std::numeric_limits<Real>::min();
 
  648   for ( ; it != it_end; ++it)
 
  653       Point upper_to_lower;
 
  655         Point lower_node_moved = mesh_clone->point(lower_point_id);
 
  656         Point upper_node_moved = mesh_clone->point(upper_point_id);
 
  658         upper_to_lower = (lower_node_moved - upper_node_moved);
 
  664       Point contact_force_direction(0., 0., 1.);
 
  669       Real gap_function = upper_to_lower * contact_force_direction;
 
  671       if (gap_function < least_value)
 
  672         least_value = gap_function;
 
  674       if (gap_function > max_value)
 
  675         max_value = gap_function;
 
  678   return std::make_pair(least_value, max_value);