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);