21#ifndef B2ELEMENT_CONTACT_H_
22#define B2ELEMENT_CONTACT_H_
26#include "b2element_continuum_integrate.H"
27#include "elements/properties/b2contact_mechanics.H"
29#include "model/b2element.H"
31#include "model_imp/b2hnode.H"
32#include "utils/b2point_triangle_distance.H"
37typedef double darrar3[3];
41 static const int value = Pow3<N - 1>::value * 3;
46 static const int value = 1;
49template <
int NB_LEVEL>
50class TriangleOnePointCompositIntegration {
52 static int nb_point[NB_LEVEL];
53 static darrar3 weight[NB_LEVEL][Pow3<NB_LEVEL>::value];
55 TriangleOnePointCompositIntegration() {
56 const darrar3 w1 = {1, 0, 0};
57 const darrar3 w2 = {0, 1, 0};
58 const darrar3 w3 = {0, 0, 1};
59 for (
int i = 0; i < NB_LEVEL; ++i) {
60 const darrar3* ptr = init(i, w1, w2, w3, weight[i]);
61 nb_point[i] = ptr - weight[i];
67 int level,
const darrar3 w1,
const darrar3 w2,
const darrar3 w3, darrar3* ptr) {
69 (*ptr)[0] = (w1[0] + w2[0] + w3[0]) / 3;
70 (*ptr)[1] = (w1[1] + w2[1] + w3[1]) / 3;
71 (*ptr)[2] = (w1[2] + w2[2] + w3[2]) / 3;
75 (w1[0] + w2[0] + w3[0]) / 3, (w1[1] + w2[1] + w3[1]) / 3,
76 (w1[2] + w2[2] + w3[2]) / 3};
78 ptr = init(level, w1, w2, w4, ptr);
79 ptr = init(level, w2, w3, w4, ptr);
80 ptr = init(level, w3, w1, w4, ptr);
84 static TriangleOnePointCompositIntegration dumy;
87template <
int NB_LEVEL>
88TriangleOnePointCompositIntegration<NB_LEVEL> TriangleOnePointCompositIntegration<NB_LEVEL>::dumy;
90template <
int NB_LEVEL>
91darrar3 TriangleOnePointCompositIntegration<NB_LEVEL>::weight[NB_LEVEL][Pow3<NB_LEVEL>::value];
93template <
int NB_LEVEL>
94int TriangleOnePointCompositIntegration<NB_LEVEL>::nb_point[NB_LEVEL];
102#define USE_UNSYMMETRIC 1
105class ElementContactT3 :
public TypedElement<double> {
107 using node_type = node::HNode<
108 coordof::Coor<coordof::Trans<coordof::X, coordof::Y, coordof::Z>>,
109 coordof::Dof<coordof::DTrans<coordof::DX, coordof::DY, coordof::DZ>, coordof::Contact>>;
111 using type_t = ObjectTypeComplete<ElementContactT3, TypedElement<double>::type_t>;
114#ifdef USE_UNSYMMETRIC
115 : TypedElement{
false}
120 void set_nodes(std::pair<int, Node* const*> nodes_)
override {
121 if (nodes_.first != 3) { Exception() <<
"This element has 3 nodes." <<
THROW; }
122 for (
int i = 0; i != 3; ++i) {
123 nodes[i] = nodes_.second[i];
124 if (!node_type::is_dof_subset_s(nodes[i])) {
125 Exception() <<
"This element cannot accept node of type " <<
typeid(*nodes[i])
126 <<
". The only accepted node types are " <<
typeid(node_type) <<
"."
132 std::pair<int, Node* const*> get_nodes()
const override {
133 return std::pair<int, Node* const*>(3, nodes);
136 void set_property(ElementProperty* property_)
override {
143 const ElementProperty* get_property()
const override {
return property; }
145 void init(Model& model)
override {}
147 void get_dof_numbering(b2linalg::Index& dof_numbering)
override {
148 dof_numbering.resize(12);
149 size_t* ptr = &dof_numbering[0];
150 for (
int k = 0; k != 3; ++k) { ptr = node_type::get_global_dof_numbering_s(ptr, nodes[k]); }
153 const std::vector<VariableInfo> get_value_info()
const override {
159 Model& model,
const bool linear,
const EquilibriumSolution equilibrium_solution,
160 const double time,
const double delta_time,
161 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& dof,
162 GradientContainer* gradient_container, SolverHints* solver_hints,
163 b2linalg::Vector<double, b2linalg::Vdense>& value,
164 std::vector<b2linalg::Matrix<
166#ifdef USE_UNSYMMETRIC
172 b2linalg::Vector<double, b2linalg::Vdense>& d_value_d_time) {
174 typedef b2linalg::Matrix<
176#ifdef USE_UNSYMMETRIC
184 const double epsilon1 = 1e1;
185 const double epsilon2 = 1e2;
195 for (
int k = 0; k != 3; ++k) { node_type::get_coor_s(R[k], nodes[k]); }
196 std::fill_n(u[0], 9, 0);
197 std::fill_n(lambda, 3, 0);
199 const double* ptr = &dof(0, 0);
200 for (
int k = 0; k != 3; ++k) {
201 node_type::get_coor_s(R[k], nodes[k]);
209 double surface_initial;
213 for (
int i = 0; i != 3; ++i) {
214 J[0][i] = -R[0][i] + R[1][i];
215 J[1][i] = -R[0][i] + R[2][i];
219 surface_initial = 0.5 * std::sqrt(
dot_3(normal, normal));
230 if (!value.is_null()) {
235 bool comput_d_value_d_dof = !d_value_d_dof.empty() && !d_value_d_dof[0].is_null();
242 if (&matrix == &matrix_tmp) { comput_d_value_d_dof =
true; }
244 if (comput_d_value_d_dof) {
245#ifdef USE_UNSYMMETRIC
246 matrix.resize(12, 12);
248 matrix.resize(12, 12,
true);
287 integration.set_num(3);
288 for (
int p = 0; p != integration.get_num(); ++p) {
291 integration.get_point(p, ip_id, weight);
292 weight *= surface_initial;
293 const double shape[3] = {1 - ip_id[0] - ip_id[1], ip_id[0], ip_id[1]};
294 double x[3] = {0, 0, 0};
296 for (
int k = 0; k != 3; ++k) {
297 l += shape[k] * lambda[k];
298 for (
int i = 0; i != 3; ++i) { x[i] += shape[k] * (u[k][i] + R[k][i]); }
300 const double g = x[2];
301 const double gnormal[3] = {0, 0, -1};
302 double d_gnormal_d_u[3][3][3];
303 std::fill_n(d_gnormal_d_u[0][0], 27, 0);
304 const double d_g_d_u[3][3] = {
314 const double w = epsilon1 * ((g + l) / 2 - std::sqrt((g - l) * (g - l) / 4 + epsilon2));
317#ifdef WITHOUT_CONSTRAINT
318 if (g < 1e-4 && l > 1e-4) {
319 if (!value.is_null()) {
320 double* ptr = &value[0];
321 for (
int k = 0; k != 3; ++k, ++ptr) {
322 for (
int i = 0; i != 3; ++i, ++ptr) {
323 for (
int j = 0; j != 3; ++j) {
324 *ptr -= weight * shape[j] * d_g_d_u[i][k] * lambda[j];
327 *ptr -= weight * shape[k] * g;
330 if (comput_d_value_d_dof) {
331 double* ptr = &d_value_d_dof[0](0, 0);
332 for (
int ki = 0; ki != 3; ++ki) {
333 for (
int i = 0; i != 3; ++i) {
334 for (
int kj = 0; kj <= ki; ++kj) {
336 for (
int j = 0; j <= i; ++j) { ptr++; }
338 for (
int j = 0; j != 3; ++j) { ptr++; }
339 *ptr++ -= weight * shape[kj] * d_g_d_u[i][ki];
343 for (
int kj = 0; kj <= ki; ++kj) {
344 for (
int j = 0; j != 3; ++j) {
345 *ptr++ -= weight * shape[ki] * d_g_d_u[j][kj];
352 if (!value.is_null()) {
353 for (
int ki = 0; ki != 3; ++ki) {
354 value[ki * 4 + 3] += 1e-8 * weight * shape[ki] * l;
357 if (comput_d_value_d_dof) {
358 for (
int ki = 0; ki != 3; ++ki) {
359 d_value_d_dof[0](ki * 4 + 3, ki * 4 + 3) +=
360 1e-8 * weight * shape[ki] * shape[ki];
365 if (!value.is_null()) {
366 double* ptr = &value[0];
367 for (
int k = 0; k != 3; ++k, ++ptr) {
368 for (
int i = 0; i != 3; ++i, ++ptr) {
369 *ptr += weight * gnormal[i] * shape[k] * l;
371 *ptr += weight * shape[k] * w;
374 if (comput_d_value_d_dof) {
375 const double d_w_d_g =
376 epsilon1 * 0.5 * (1 - (g - l) / std::sqrt((g - l) * (g - l) + 4 * epsilon2));
377 const double d_w_d_l =
378 epsilon1 * 0.5 * (1 + (g - l) / std::sqrt((g - l) * (g - l) + 4 * epsilon2));
379 double* ptr = &matrix(0, 0);
380#ifdef USE_UNSYMMETRIC
381 for (
int kj = 0; kj != 3; ++kj) {
382 for (
int j = 0; j != 3; ++j) {
383 for (
int ki = 0; ki != 3; ++ki) {
384 for (
int i = 0; i != 3; ++i) {
385 *ptr++ += weight * l * d_gnormal_d_u[kj][i][j] * shape[ki];
387 *ptr++ += weight * shape[ki] * d_w_d_g * d_g_d_u[j][kj];
390 for (
int ki = 0; ki != 3; ++ki) {
391 for (
int i = 0; i != 3; ++i) {
392 *ptr++ += weight * shape[kj] * gnormal[i] * shape[ki];
394 *ptr++ += weight * shape[ki] * d_w_d_l * shape[kj];
405 for (
int ki = 0; ki != 3; ++ki) {
406 for (
int i = 0; i != 3; ++i) {
407 for (
int kj = 0; kj <= ki; ++kj) {
408 const int j_max = kj == ki ? i : 2;
409 for (
int j = 0; j <= j_max; ++j) {
410 *ptr++ += weight * l * 0.5
411 * (d_gnormal_d_u[kj][i][j] * shape[ki]
412 + d_gnormal_d_u[ki][j][i] * shape[kj]);
415 *ptr++ += weight * shape[kj] * 0.5
416 * (gnormal[i] * shape[ki] + d_w_d_g * d_g_d_u[i][ki]);
420 for (
int kj = 0; kj <= ki; ++kj) {
421 for (
int j = 0; j != 3; ++j) {
422 *ptr++ += weight * shape[ki] * 0.5
423 * (d_w_d_g * d_g_d_u[j][kj] + gnormal[j] * shape[kj]);
425 *ptr++ += weight * shape[ki] * d_w_d_l * shape[kj];
436 for (
int i = 1; i < d_value_d_dof.size(); ++i) {
437 if (!d_value_d_dof[i].is_null()) {
438#ifdef USE_UNSYMMETRIC
439 d_value_d_dof[i].resize(12, 12);
441 d_value_d_dof[i].resize(12, 12,
true);
443 d_value_d_dof[i].set_zero();
453 void get_axe_aligned_bounding_box(
454 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& dof,
int dim,
double* min,
455 double* max)
override {
456 for (
size_t i = 0; i != 3; ++i) {
457 min[i] = std::numeric_limits<double>::max();
458 max[i] = std::numeric_limits<double>::lowest();
460 for (
size_t p = 0; p != 3; ++p) {
462 node_type::get_coor_s(coor, nodes[p]);
464 node_type::get_global_dof_numbering_s(dn, nodes[p]);
466 for (
int i = 0; i != dim; ++i) {
467 coor[i] += dof(dn[i], 0);
468 min[i] = std::min(min[i], coor[i]);
469 max[i] = std::max(max[i], coor[i]);
475 Model& model,
const bool linear,
const EquilibriumSolution equilibrium_solution,
476 const double time,
const double delta_time,
477 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& dof,
478 GradientContainer* gradient_container, SolverHints* solver_hints,
479 b2linalg::Index& dof_numbering, b2linalg::Vector<double, b2linalg::Vdense>& value,
480 const std::vector<bool>& d_value_d_dof_flags,
481 std::vector<b2linalg::Matrix<
483#ifdef USE_UNSYMMETRIC
489 b2linalg::Vector<double, b2linalg::Vdense>& d_value_d_time)
override {
490 const double epsilon = 1e-0;
491 const double dist_box = 1;
492 const int integration_level = 1;
493 std::vector<Element*> element_list;
494 model.get_domain().get_elements_of_same_type_near(
this, dist_box, element_list);
499 if (element_list.empty()) {
500 get_dof_numbering(dof_numbering);
501 for (
int p = 0; p != 3; ++p) { node_type::get_coor_s(coor[p], nodes[p]); }
505 coor[1][0] - coor[0][0], coor[1][1] - coor[0][1], coor[1][2] - coor[0][2]};
507 coor[2][0] - coor[0][0], coor[2][1] - coor[0][1], coor[2][2] - coor[0][2]};
511 normalise_3(normal) / (6 * composit_integration.nb_point[integration_level]);
513 for (
int i = 0; i != 3; ++i) { dof_numbering[i] = dof_numbering[i * 4 + 3]; }
514 dof_numbering.resize(3);
515 if (!value.is_null()) {
517 for (
int i = 0; i != 3; ++i) { value[i] = area * dof(dof_numbering[i], 0); }
519 if (!d_value_d_dof_flags.empty() && d_value_d_dof_flags[0]) {
520 d_value_d_dof[0].resize(
522#ifndef USE_UNSYMMETRIC
527 d_value_d_dof[0].set_zero();
528 for (
int i = 0; i != 3; ++i) { d_value_d_dof[0](i, i) = area; }
530 for (
size_t i = 1; i < d_value_d_dof_flags.size(); ++i) {
531 if (d_value_d_dof_flags[i]) {
532 d_value_d_dof[i].resize(
533 dof_numbering.size(), dof_numbering.size()
534#ifndef USE_UNSYMMETRIC
539 d_value_d_dof[i].set_zero();
542 if (!d_value_d_time.is_null()) {
543 d_value_d_time.resize(dof_numbering.size());
544 d_value_d_time.set_zero();
549 std::vector<ElemCoor> element_list_coor(element_list.size());
550 for (
size_t e = 0; e != element_list_coor.size(); ++e) {
551 element_list[e]->get_dof_numbering(dof_numbering);
552 Node*
const* n = element_list[e]->get_nodes().second;
553 for (
int p = 0; p != 3; ++p) {
554 node_type::get_coor_s(element_list_coor[e].coor[p], n[p]);
555 for (
int i = 0; i != 3; ++i) {
556 element_list_coor[e].coor[p][i] += dof(dof_numbering[p * 4 + i], 0);
561 get_dof_numbering(dof_numbering);
563 for (
int p = 0; p != 3; ++p) { node_type::get_coor_s(coor[p], nodes[p]); }
566 coor[1][0] - coor[0][0], coor[1][1] - coor[0][1], coor[1][2] - coor[0][2]};
568 coor[2][0] - coor[0][0], coor[2][1] - coor[0][1], coor[2][2] - coor[0][2]};
572 normalise_3(normal) / (2 * composit_integration.nb_point[integration_level]);
574 for (
int p = 0; p != 3; ++p) {
575 for (
int i = 0; i != 3; ++i) { coor[p][i] += dof(dof_numbering[p * 4 + i], 0); }
579 coor[1][0] - coor[0][0], coor[1][1] - coor[0][1], coor[1][2] - coor[0][2]};
581 coor[2][0] - coor[0][0], coor[2][1] - coor[0][1], coor[2][2] - coor[0][2]};
584 const double inv_norme_normal = 1 /
normalise_3(normal);
587 if (!value.is_null()) {
593 double d_normal_d_u[3][3][3];
594 if (!d_value_d_dof_flags.empty() && d_value_d_dof_flags[0]) {
595 d_value_d_dof[0].resize(
597#ifndef USE_UNSYMMETRIC
602 d_value_d_dof[0].set_zero();
604 double d_n_d_u[3][3][3];
605 d_n_d_u[0][0][0] = 0;
606 d_n_d_u[0][0][1] = coor[1][2] - coor[2][2];
607 d_n_d_u[0][0][2] = coor[2][1] - coor[1][1];
608 d_n_d_u[0][1][0] = 0;
609 d_n_d_u[0][1][1] = coor[2][2] - coor[0][2];
610 d_n_d_u[0][1][2] = coor[0][1] - coor[2][1];
611 d_n_d_u[0][2][0] = 0;
612 d_n_d_u[0][2][1] = coor[0][2] - coor[1][2];
613 d_n_d_u[0][2][2] = coor[1][1] - coor[0][1];
615 d_n_d_u[1][0][0] = coor[2][2] - coor[1][2];
616 d_n_d_u[1][0][1] = 0;
617 d_n_d_u[1][0][2] = coor[1][0] - coor[2][0];
618 d_n_d_u[1][1][0] = coor[0][2] - coor[2][2];
619 d_n_d_u[1][1][1] = 0;
620 d_n_d_u[1][1][2] = coor[2][0] - coor[0][0];
621 d_n_d_u[1][2][0] = coor[1][2] - coor[0][2];
622 d_n_d_u[1][2][1] = 0;
623 d_n_d_u[1][2][2] = coor[0][0] - coor[1][0];
625 d_n_d_u[2][0][0] = coor[1][1] - coor[2][1];
626 d_n_d_u[2][0][1] = coor[2][0] - coor[1][0];
627 d_n_d_u[2][0][2] = 0;
628 d_n_d_u[2][1][0] = coor[2][1] - coor[0][1];
629 d_n_d_u[2][1][1] = coor[0][0] - coor[2][0];
630 d_n_d_u[2][1][2] = 0;
631 d_n_d_u[2][2][0] = coor[0][1] - coor[1][1];
632 d_n_d_u[2][2][1] = coor[1][0] - coor[0][0];
633 d_n_d_u[2][2][2] = 0;
635 for (
int i = 0; i != 3; ++i) {
636 for (
int j = 0; j != 3; ++j) {
638 for (
int l = 0; l != 3; ++l) { tmp += normal[l] * d_n_d_u[l][j][i]; }
639 for (
int k = 0; k != 3; ++k) {
640 d_normal_d_u[k][j][i] =
641 inv_norme_normal * (d_n_d_u[k][j][i] - normal[k] * tmp);
646#ifdef CHECK_DERIVATIVE
648 const long double h = 0.0000001;
649 for (
int j = 0; j != 3; ++j) {
650 for (
int i = 0; i != 3; ++i) {
651 long double coor_tmp[3][3];
652 std::copy(coor[0], coor[3], coor_tmp[0]);
654 long double a_tmp[3] = {
655 coor_tmp[1][0] - coor_tmp[0][0], coor_tmp[1][1] - coor_tmp[0][1],
656 coor_tmp[1][2] - coor_tmp[0][2]};
657 long double b_tmp[3] = {
658 coor_tmp[2][0] - coor_tmp[0][0], coor_tmp[2][1] - coor_tmp[0][1],
659 coor_tmp[2][2] - coor_tmp[0][2]};
660 long double normal_tmp[3];
663 for (
int k = 0; k != 3; ++k) {
664 long double v = (normal_tmp[k] - normal[k]) / h;
665 if (std::abs(d_normal_d_u[k][j][i] - v) > 1e-5) {
666 std::cout <<
"d_normal_d_u[" << k <<
"][" << j <<
"][" << i
667 <<
"]=" << d_normal_d_u[k][j][i] <<
", n=" << v
677 std::map<size_t, size_t> list_contact_element;
678 for (
int k = 0; k != composit_integration.nb_point[integration_level]; ++k) {
679 const double* weight = composit_integration.weight[integration_level][k];
680 double point[3] = {};
681 for (
int p = 0; p != 3; ++p) {
682 for (
int i = 0; i != 3; ++i) { point[i] += weight[p] * coor[p][i]; }
687 for (
size_t i = 0; i != element_list.size(); ++i) {
689 const double dist_tmp = point_triangle_distance3d(
690 point, element_list_coor[i].coor[0], element_list_coor[i].coor[1],
691 element_list_coor[i].coor[2], r_tmp, s_tmp);
692 if (dist_tmp < dist) {
699 if (dist > dist_box * dist_box) {
continue; }
701 size_t dof_numbering_idx = list_contact_element[elem];
702 if (dof_numbering_idx == 0) {
703 list_contact_element[elem] = dof_numbering_idx = dof_numbering.size();
704 b2linalg::Index dof_numbering_tmp;
705 element_list[elem]->get_dof_numbering(dof_numbering_tmp);
706 for (
int i = 0; i != 3; ++i) {
707 dof_numbering.insert(
708 dof_numbering.end(), dof_numbering_tmp.begin() + i * 4,
709 dof_numbering_tmp.begin() + i * 4 + 3);
711 if (!value.is_null()) { value.resize(dof_numbering.size()); }
712 if (!d_value_d_dof_flags.empty() && d_value_d_dof_flags[0]) {
713 d_value_d_dof[0].resize(
714 dof_numbering.size(), dof_numbering.size()
715#ifndef USE_UNSYMMETRIC
725 const double c_weight[3] = {1 - r - s, r, s};
726 for (
int p = 0; p != 3; ++p) {
727 lambda += weight[p] * dof(dof_numbering[p * 4 + 3], 0);
728 g += (element_list_coor[elem].coor[0][p] * c_weight[0]
729 + element_list_coor[elem].coor[1][p] * r
730 + element_list_coor[elem].coor[2][p] * s - point[p])
734 area * ((g + lambda) / 2 - std::sqrt((g - lambda) * (g - lambda) / 4 + epsilon));
735 const double lambda_area = area * lambda;
744 if (!value.is_null()) {
745 for (
int p = 0; p != 3; ++p) {
746 for (
int i = 0; i != 3; ++i) {
747 const double v = lambda_area * normal[i];
748 value[p * 4 + i] += v * weight[p];
749 value[dof_numbering_idx + p * 3 + i] -= v * c_weight[p];
751 value[p * 4 + 3] -= weight[p] * w;
755 if (!d_value_d_dof_flags.empty() && d_value_d_dof_flags[0]) {
758 point_triangle_distance3d(
759 point, element_list_coor[elem].coor[0], element_list_coor[elem].coor[1],
760 element_list_coor[elem].coor[2], r, s, d_r, d_s);
762#ifdef CHECK_DERIVATIVE
764 const double h = 0.000001;
765 for (
int i = 0; i != 3; ++i) {
766 double point_tmp[3] = {point[0], point[1], point[2]};
769 point_triangle_distance3d(
770 point_tmp, element_list_coor[elem].coor[0],
771 element_list_coor[elem].coor[1], element_list_coor[elem].coor[2], r1,
773 double rtmp = (r1 - r) / h;
774 double stmp = (s1 - s) / h;
775 if (std::abs(d_r[0][i] - rtmp) > 1e-5) {
776 std::cout <<
"d_r[0][" << i <<
"]=" << d_r[0][i] <<
", n=" << rtmp
779 if (std::abs(d_s[0][i] - stmp) > 1e-5) {
780 std::cout <<
"d_s[0][" << i <<
"]=" << d_s[0][i] <<
", n=" << stmp
784 for (
int i = 0; i != 3; ++i) {
785 for (
int j = 0; j != 3; ++j) {
786 double coor_tmp[3][3];
787 for (
int k = 0; k != 3; ++k) {
788 for (
int l = 0; l != 3; ++l) {
789 coor_tmp[k][l] = element_list_coor[elem].coor[k][l];
794 point_triangle_distance3d(
795 point, coor_tmp[0], coor_tmp[1], coor_tmp[2], r1, s1);
796 double rtmp = (r1 - r) / h;
797 double stmp = (s1 - s) / h;
798 if (std::abs(rtmp - d_r[i + 1][j]) > 1e-5) {
799 std::cout <<
"d_r[" << i + 1 <<
"][" << j <<
"]=" << d_r[i + 1][j]
800 <<
", n=" << rtmp << std::endl;
802 if (std::abs(stmp - d_s[i + 1][j]) > 1e-5) {
803 std::cout <<
"d_s[" << i + 1 <<
"][" << j <<
"]=" << d_s[i + 1][j]
804 <<
", n=" << stmp << std::endl;
811 double d_c_weight[3][6][3];
812 for (
int p = 0; p != 3; ++p) {
813 for (
int i = 0; i != 3; ++i) {
814 d_c_weight[0][p][i] = -weight[p] * (d_r[0][i] + d_s[0][i]);
815 d_c_weight[1][p][i] = weight[p] * d_r[0][i];
816 d_c_weight[2][p][i] = weight[p] * d_s[0][i];
817 d_c_weight[0][p + 3][i] = -d_r[p + 1][i] - d_s[p + 1][i];
818 d_c_weight[1][p + 3][i] = d_r[p + 1][i];
819 d_c_weight[2][p + 3][i] = d_s[p + 1][i];
823 const double tmp1 = std::sqrt((lambda - g) * (lambda - g) + 4 * epsilon);
824 const double d_w_d_g = area * (lambda - g + tmp1) / (2 * tmp1);
825 const double d_w_d_lambda = area * (g - lambda + tmp1) / (2 * tmp1);
828#ifdef CHECK_DERIVATIVE
830 const double h = 0.000001;
831 double g_tmp = g + h;
834 * ((g_tmp + lambda) / 2
835 - std::sqrt((g_tmp - lambda) * (g_tmp - lambda) / 4 + epsilon));
836 double d_w_d_g_tmp = (w_tmp - w) / h;
837 if (std::abs(d_w_d_g_tmp - d_w_d_g) > 1e-5) {
838 std::cout <<
"d_w_d_g=" << d_w_d_g <<
", n=" << d_w_d_g_tmp << std::endl;
840 double lambda_tmp = lambda + h;
842 * ((g + lambda_tmp) / 2
843 - std::sqrt((g - lambda_tmp) * (g - lambda_tmp) / 4 + epsilon));
844 double d_w_d_lambda_tmp = (w_tmp - w) / h;
845 if (std::abs(d_w_d_lambda_tmp - d_w_d_lambda) > 1e-5) {
846 std::cout <<
"d_w_d_lambda=" << d_w_d_lambda <<
", n=" << d_w_d_lambda_tmp
851 double d_g_d_u[6][3] = {};
852 for (
int i = 0; i != 3; ++i) {
853 const double tmp = element_list_coor[elem].coor[0][i] * c_weight[0]
854 + element_list_coor[elem].coor[1][i] * r
855 + element_list_coor[elem].coor[2][i] * s - point[i];
856 for (
int j = 0; j != 3; ++j) {
857 for (
int k = 0; k != 3; ++k) {
858 d_g_d_u[j][k] += tmp * d_normal_d_u[i][j][k];
860 d_g_d_u[j][i] -= normal[i] * weight[j];
861 d_g_d_u[j + 3][i] += normal[i] * c_weight[j];
863 const double tmp1 = element_list_coor[elem].coor[i][0] * normal[0]
864 + element_list_coor[elem].coor[i][1] * normal[1]
865 + element_list_coor[elem].coor[i][2] * normal[2];
866 for (
int j = 0; j != 6; ++j) {
867 for (
int k = 0; k != 3; ++k) {
868 d_g_d_u[j][k] += tmp1 * d_c_weight[i][j][k];
873#ifdef CHECK_DERIVATIVE
875 const double h = 0.0000001;
876 for (
int j = 0; j != 3; ++j) {
877 for (
int i = 0; i != 3; ++i) {
878 double coor_tmp[3][3];
879 for (
int k = 0; k != 3; ++k) {
880 for (
int l = 0; l != 3; ++l) { coor_tmp[k][l] = coor[k][l]; }
883 double point_tmp[3] = {};
884 for (
int k = 0; k != 3; ++k) {
885 for (
int l = 0; l != 3; ++l) {
886 point_tmp[l] += weight[k] * coor_tmp[k][l];
889 double normal_tmp[3];
892 coor_tmp[1][0] - coor_tmp[0][0],
893 coor_tmp[1][1] - coor_tmp[0][1],
894 coor_tmp[1][2] - coor_tmp[0][2]};
896 coor_tmp[2][0] - coor_tmp[0][0],
897 coor_tmp[2][1] - coor_tmp[0][1],
898 coor_tmp[2][2] - coor_tmp[0][2]};
904 point_triangle_distance3d(
905 point_tmp, element_list_coor[elem].coor[0],
906 element_list_coor[elem].coor[1], element_list_coor[elem].coor[2],
909 const double c_weight_tmp[3] = {1 - rtmp - stmp, rtmp, stmp};
910 for (
int p = 0; p != 3; ++p) {
911 gtmp += (element_list_coor[elem].coor[0][p] * c_weight_tmp[0]
912 + element_list_coor[elem].coor[1][p] * rtmp
913 + element_list_coor[elem].coor[2][p] * stmp - point_tmp[p])
916 double g1 = (gtmp - g) / h;
917 if (std::abs(g1 - d_g_d_u[j][i]) > 1e-5) {
918 std::cout <<
"d_g_d_u[" << j <<
"][" << i <<
"]=" << d_g_d_u[j][i]
919 <<
", n=" << g1 << std::endl;
923 for (
int j = 0; j != 3; ++j) {
924 for (
int i = 0; i != 3; ++i) {
925 double coor_tmp[3][3];
926 for (
int k = 0; k != 3; ++k) {
927 for (
int l = 0; l != 3; ++l) {
928 coor_tmp[k][l] = element_list_coor[elem].coor[k][l];
933 point_triangle_distance3d(
934 point, coor_tmp[0], coor_tmp[1], coor_tmp[2], rtmp, stmp);
936 const double c_weight[3] = {1 - rtmp - stmp, rtmp, stmp};
937 for (
int p = 0; p != 3; ++p) {
938 gtmp += (coor_tmp[0][p] * c_weight[0] + coor_tmp[1][p] * rtmp
939 + coor_tmp[2][p] * stmp - point[p])
942 double g1 = (gtmp - g) / h;
943 if (std::abs(g1 - d_g_d_u[j + 3][i]) > 1e-5) {
944 std::cout <<
"d_g_d_u[" << j + 3 <<
"][" << i
945 <<
"]=" << d_g_d_u[j + 3][i] <<
", n=" << g1 << std::endl;
952 for (
int pi = 0; pi != 3; ++pi) {
953 for (
int i = 0; i != 3; ++i) {
954 const int idx = pi * 4 + i;
955 for (
int pj = 0; pj != 3; ++pj) {
956 for (
int j = 0; j != 3; ++j) {
957 const int jdx = pj * 4 + j;
958 d_value_d_dof[0](idx, jdx) +=
959 lambda_area * d_normal_d_u[i][pj][j] * weight[pi];
960 d_value_d_dof[0](dof_numbering_idx + pi * 3 + i, jdx) +=
962 * (d_normal_d_u[i][pj][j] * c_weight[pi]
963 + normal[i] * d_c_weight[pi][pj][j]);
965 dof_numbering_idx + pi * 3 + i,
966 dof_numbering_idx + pj * 3 + j) +=
967 -lambda_area * normal[i] * d_c_weight[pi][pj + 3][j];
969 d_value_d_dof[0](idx, pj * 4 + 3) +=
970 area * normal[i] * weight[pj] * weight[pi];
971 d_value_d_dof[0](dof_numbering_idx + pi * 3 + i, pj * 4 + 3) +=
972 -area * normal[i] * weight[pj] * c_weight[pi];
975 for (
int pj = 0; pj != 3; ++pj) {
976 for (
int j = 0; j != 3; ++j) {
977 d_value_d_dof[0](pi * 4 + 3, pj * 4 + j) +=
978 -weight[pi] * d_w_d_g * d_g_d_u[pj][j];
979 d_value_d_dof[0](pi * 4 + 3, dof_numbering_idx + pj * 3 + j) +=
980 -weight[pi] * d_w_d_g * d_g_d_u[pj + 3][j];
982 d_value_d_dof[0](pi * 4 + 3, pj * 4 + 3) +=
983 -weight[pi] * d_w_d_lambda * weight[pj];
989 if (list_contact_element.empty()) {
991 for (
int i = 0; i != 3; ++i) { dof_numbering[i] = dof_numbering[i * 4 + 3]; }
992 const double warea = area * composit_integration.nb_point[integration_level] / 3;
993 dof_numbering.resize(3);
994 if (!value.is_null()) {
996 for (
int i = 0; i != 3; ++i) { value[i] = warea * dof(dof_numbering[i], 0); }
998 if (!d_value_d_dof_flags.empty() && d_value_d_dof_flags[0]) {
999 d_value_d_dof[0].resize(
1001#ifndef USE_UNSYMMETRIC
1006 d_value_d_dof[0].set_zero();
1007 for (
int i = 0; i != 3; ++i) { d_value_d_dof[0](i, i) = warea; }
1010#ifndef USE_UNSYMMETRIC
1011 else if (!d_value_d_dof_flags.empty() && d_value_d_dof_flags[0])
1012 for (
size_t i = 0; i != d_value_d_dof[0].size1(); ++i) {
1013 for (
int j = 0; j != i; ++j) { d_value_d_dof[0](i, j) *= 0.5; }
1017 for (
size_t i = 1; i < d_value_d_dof_flags.size(); ++i) {
1018 if (d_value_d_dof_flags[i]) {
1019 d_value_d_dof[i].resize(
1020 dof_numbering.size(), dof_numbering.size()
1021#ifndef USE_UNSYMMETRIC
1026 d_value_d_dof[i].set_zero();
1029 if (!d_value_d_time.is_null()) {
1030 d_value_d_time.resize(dof_numbering.size());
1031 d_value_d_time.set_zero();
1042 ContactMechanics*
property{};
1044 static TriangleOnePointCompositIntegration<5> composit_integration;
#define THROW
Definition b2exception.H:198
@ nonlinear
Definition b2element.H:619
@ linear
Definition b2element.H:615
virtual void get_value(Model &model, const bool linear, const EquilibriumSolution equilibrium_solution, const double time, const double delta_time, const b2linalg::Matrix< double, b2linalg::Mrectangle_constref > &dof, GradientContainer *gradient_container, SolverHints *solver_hints, b2linalg::Index &dof_numbering, b2linalg::Vector< double, b2linalg::Vdense > &value, const std::vector< bool > &d_value_d_dof_flags, std::vector< b2linalg::Matrix< double, b2linalg::Mpacked > > &d_value_d_dof, b2linalg::Vector< double, b2linalg::Vdense > &d_value_d_time)
Compute the internal forces and their derivatives of the element.
Definition b2element.H:1640
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
T normalise_3(T a[3])
Definition b2tensor_calculus.H:418
void outer_product_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:389
T dot_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:328