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