OOFEM 3.0
Loading...
Searching...
No Matches
structuralpenaltycontactbc.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35
37#include "domain.h"
38#include "floatarray.h"
39#include "floatmatrix.h"
40#include "classfactory.h"
41#include "mathfem.h"
42#include <ranges>
43#include <vector>
44#include "floatarray.h"
47#include "timestep.h"
48namespace oofem {
50
51
53bool frictionShouldBeConsidered(double friction, TimeStep *tStep) {
54 return friction > 0 && tStep->giveNumber() > 1;
55}
56
57
58
60{
61 answer.zero();
62 auto normal_gap = contactPair->giveNormalGap();
63 if ( normal_gap <= 1.e-15 ) {
64 contactPair->initContactPoint();
65 auto normal = contactPair->giveNormalVector();
66 auto area = normal.computeNorm();
67 normal /= area;
68 // get the contact element shape function values at this node
70 contactPair->computeNmatrix(N);
71 //
72 double normal_traction;
73 FloatArray tangential_traction, tangential_traction_trial;
75 this->computeTractions(normal_traction, tangential_traction, tangential_traction_trial, mode, contactPair, tStep);
76 double abs_normal_traction = std::abs(normal_traction);
77 /****************** Normal part of the stiffness matrix ******************************/
78 //@todo: update
79 double dA = 1;//area;
80 //auto dA = contactPair->giveArea();
81 // Equation(7.17) page 189
82 answer.plus_Nt_a_otimes_b_B(N, normal, normal, N, penalty_normal * dA);
83 //
84 auto tangent_vectors = contactPair->giveTangentVectors();
85 auto contravariant_metric = this->computeContravariantMetric(tangent_vectors);
86 // calculate curvature tensor kappa
87 FloatMatrix curvature;
88 contactPair->computeCurvature(curvature, tStep);
89 std::vector<FloatMatrix> dNs;
90 contactPair->compute_dNdxi_matrices(dNs);
91 FloatMatrix k_rot, k_curv;
92 for(int i = 0; i < surface_dimension; i++) {
93 auto tangent_i = tangent_vectors[i];
94 auto dNi = dNs[i];
95 //for (auto && [i, tangent_i] : std::views::enumerate(tangent_vectors)) {
96 for(int j = 0; j < surface_dimension; j++) {
97 auto dNj = dNs[j];
98 //for (auto && [j, dNj] : std::ranges::views::enumerate(Bs)) {
99 auto tangent_j = tangent_vectors[j];
100 double a_ij = contravariant_metric(i, j);
101 double h_ij = curvature(i, j);
102 // Equation(7.18)a page 189
103 k_rot.plus_Nt_a_otimes_b_B(dNj, normal, tangent_i, N, a_ij * normal_traction * dA);
104 // Equation(7.18)b page 189
105 k_rot.plus_Nt_a_otimes_b_B(N, tangent_j, normal, dNi, a_ij * normal_traction * dA);
106 // Equation(7.19) page 189
107 k_curv.plus_Nt_a_otimes_b_B(N, tangent_i, tangent_j, N, h_ij * normal_traction * dA);
108 }
109 }
110 answer += k_rot + k_curv;
111 /****************** End of the Normal part of the stiffness matrix ******************************/
113 /****************** Frictional part of the stiffness matrix ******************************/
114 tangential_traction = tangential_traction_trial;
115 if(mode == ContactProcess::Sticking) {
116 /**** STICK ****/
117 FloatMatrix k_st_m, k_st_r, k_st_c;
118 double factor;
119 /*for (auto && [i, rho_i] : std::ranges::views::enumerate(tangent_vectors)) {
120 for (auto && [j, rho_j] : std::ranges::views::enumerate(tangent_vectors)) {*/
121 for (int i = 0; i < this->surface_dimension; i++) {
122 auto rho_i = tangent_vectors[i];
123 double t_i = tangential_traction(i);
124 for (int j = 0; j < this->surface_dimension; j++) {
125 auto rho_j = tangent_vectors[j];
126 double a_ij = contravariant_metric(i, j);
127 const auto& dNj = dNs[j];
128 double h_ij = curvature(i, j);
129 // Equation(7.26), page 192
130 factor = - penalty_tangential * a_ij;
131 k_st_m.plus_Nt_a_otimes_b_B(N, rho_i, rho_j, N, factor);
132 // Equation (7.28), page 192
133 factor = + t_i * h_ij;
134 k_st_c.plus_Nt_a_otimes_b_B( N, rho_j, normal, N, factor);
135 k_st_c.plus_Nt_a_otimes_b_B( N, normal, rho_j, N, factor);
136 //for (auto && [k, tangent_k] : std::ranges::views::enumerate(tangent_vectors)) {
137 for (int k = 0; k < surface_dimension; k++) {
138 auto rho_k = tangent_vectors[k];
139 double a_ik = contravariant_metric(i, k);
140 double a_jk = contravariant_metric(j, k);
141 //for (auto && [l, tangent_l] : std::ranges::views::enumerate(tangent_vectors)) {
142 for (int l = 0; l < surface_dimension; l++) {
143 auto rho_l = tangent_vectors[l];
144 double a_il = contravariant_metric(i, l);
145 double a_jl = contravariant_metric(j, l);
146 // Equation (7.27), page 192
147 factor = - t_i * a_il * a_jk;
148 k_st_r.plus_Nt_a_otimes_b_B( N, rho_k, rho_l, dNj, factor);
149 factor = - t_i * a_ik * a_jl;
150 k_st_r.plus_Nt_a_otimes_b_B( dNj, rho_k, rho_l, N, factor);
151 }
152 }
153 }
154 }
155 FloatMatrix k_stick;
156 k_stick += k_st_m;
157 k_stick += k_st_r;
158 k_stick += k_st_c;
159 k_stick.times(dA);
160 answer += k_stick;
161 /**** END OF STICK ****/
162 } else {
163 /**** SLIP ****/
164 // see table 8.13 on the papge 252
165 // Equation (7.35), page 194
166 FloatMatrix k_sl_constitutive_non_symmetric; // (7.35a), page 194
167 FloatMatrix k_sl_constitutive_symmetric_1; // (7.35b), page 194
168 FloatMatrix k_sl_constitutive_symmetric_2; // (7.35c), page 194
169 FloatMatrix k_sl_rotational_symmetric; // (7.35d), page 194
170 FloatMatrix k_sl_curvature_symmetric; // (7.35e), page 194
171 FloatMatrix k_sl_curvature_non_symmetric; // (7.35f), page 194
172 // Equation (7.35a), page 194
173 double t_norm_squared = 0.0;
174 for (int i = 0; i < surface_dimension; i++) {
175 double t_i = tangential_traction(i);
176 for (int j = 0; j < surface_dimension; j++) {
177 double t_j = tangential_traction(j);
178 double a_ij = contravariant_metric(i, j);
179 t_norm_squared += t_i * t_j * a_ij;
180 }
181 }
182 const double t_norm = std::sqrt(t_norm_squared);
183 const double t_norm3 = std::pow(t_norm,3);
184 double factor;
185 for (int i = 0; i < surface_dimension; i++) {
186 const auto& rho_i = tangent_vectors[i];
187 const double t_i = tangential_traction(i);
188 for (int j = 0; j < surface_dimension; j++) {
189 const auto& rho_j = tangent_vectors[j];
190 const double t_j = tangential_traction(j);
191 const double a_ij = contravariant_metric(i, j);
192 const auto& dNj = dNs[j];
193 const double h_ij = curvature(i,j);
194 // Equation (7.35a), page 194
195 factor = -penalty_normal * friction * t_i / t_norm * a_ij;
196 k_sl_constitutive_non_symmetric.plus_Nt_a_otimes_b_B(N, rho_j, normal, N, factor);
197 // Equation (7.35b), page 194
198 factor = -penalty_tangential * friction * abs_normal_traction / t_norm * a_ij;
199 k_sl_constitutive_symmetric_1.plus_Nt_a_otimes_b_B(N, rho_i, rho_j, N, factor);
200 // Equation (7.35e), page 194
201 factor = +friction * abs_normal_traction * t_i / t_norm * h_ij;
202 k_sl_curvature_symmetric.plus_Nt_a_otimes_b_B(N, rho_j, normal, N, factor);
203 k_sl_curvature_symmetric.plus_Nt_a_otimes_b_B(N, normal, rho_j, N, factor);
204 for (int k = 0; k < surface_dimension; k++) {
205 const auto& rho_k = tangent_vectors[k];
206 const double a_ik = contravariant_metric(i, k);
207 const double a_jk = contravariant_metric(j, k);
208 for (int l = 0; l < surface_dimension; l++) {
209 const auto& rho_l = tangent_vectors[l];
210 const double a_il = contravariant_metric(i, l);
211 const double a_jl = contravariant_metric(j, l);
212 // Equation (7.35c), page 194
213 factor = +penalty_tangential * friction * abs_normal_traction * t_i * t_j / t_norm3 * a_ik * a_jl;
214 k_sl_constitutive_symmetric_2.plus_Nt_a_otimes_b_B(N, rho_k, rho_l, N, factor);
215 // Equation (7.35d), page 194
216 const double factorCommon = -friction * abs_normal_traction * t_i / t_norm;
217 factor = factorCommon * a_il * a_jk;
218 k_sl_rotational_symmetric.plus_Nt_a_otimes_b_B(N, rho_k, rho_l, dNj, factor);
219 factor = factorCommon * a_ik * a_jl;
220 k_sl_rotational_symmetric.plus_Nt_a_otimes_b_B(dNj, rho_k, rho_l, N, factor);
221 for (int m = 0; m <= surface_dimension; m++) {
222 // Equation (7.35f), page 194
223 // @todo
224 }
225 }
226 }
227 }
228 }
229 FloatMatrix k_slip;
230 k_slip += k_sl_constitutive_non_symmetric;
231 k_slip += k_sl_constitutive_symmetric_1;
232 k_slip += k_sl_constitutive_symmetric_2;
233 k_slip += k_sl_rotational_symmetric;
234 k_slip += k_sl_curvature_symmetric;
235 k_slip += k_sl_curvature_non_symmetric;
236 k_slip.times(dA);
237 answer += k_slip;
238 }
239 }
240 }
241}
242
243
245StructuralPenaltyContactBoundaryCondition ::computeCovariantMetric(const std::vector<FloatArray> &tangent_vectors)
246{
247 FloatMatrix covariantMatrix;
248 // double n = tangent_vectors.size();
249 double n = surface_dimension;
250 const FloatArray& rho_1 = tangent_vectors[0];
251 if(n == 1) {
252 covariantMatrix = {{rho_1.dotProduct(rho_1)}};
253 } else if(n == 2) {
254 const FloatArray& rho_2 = tangent_vectors[1];
255 covariantMatrix = {
256 {rho_1.dotProduct(rho_1), rho_1.dotProduct(rho_2)},
257 {rho_2.dotProduct(rho_1), rho_2.dotProduct(rho_2)}
258 };
259 } else {
260 OOFEM_WARNING("Incorect size of tangent_vectors");
261 }
262 return covariantMatrix;
263
264}
265
267StructuralPenaltyContactBoundaryCondition ::computeContravariantMetric(const std::vector<FloatArray> &tangent_vectors)
268{
269 FloatMatrix covariantMetric = this->computeCovariantMetric(tangent_vectors);
270 FloatMatrix contravariantMetric;
271 contravariantMetric.beInverseOf(covariantMetric);
272 return contravariantMetric;
273}
274
275void
276StructuralPenaltyContactBoundaryCondition :: setupContactSearchAlgorithm()
277{
278 if(this->surface_dimension == 2) {
279 if (algo == 1) {
281 this->contactSearchAlgorithm = std::make_unique<T>(this->slaveContactSurface, this->masterContactSurface, domain);
282 } else {
284 this->contactSearchAlgorithm = std::make_unique<T>(this->slaveContactSurface, this->masterContactSurface, domain);
285 }
286 } else if(surface_dimension == 1) {
287 this->contactSearchAlgorithm = std::make_unique<ContactSearchAlgorithm_Surface2FESurface_2d>(this->slaveContactSurface, this->masterContactSurface, domain);
288 } else {
289 OOFEM_ERROR("StructuralPenaltyContactBoundaryCondition ::Unknown number of spatial dimensions");
290 }
291}
292
293
294
295void
297{
298 answer.zero();
299 auto normal_gap = contactPair->giveNormalGap();
300 if ( normal_gap <= 1.e-15 ) {
301 contactPair->initContactPoint();
302 auto normal = contactPair->giveNormalVector();
303 auto area = normal.computeNorm();
304 normal /= area;
306 contactPair->computeNmatrix(N);
307 // tractions in local coordinate system
308 double normalTraction;
309 FloatArray tangentialTraction, tangentialTractionTrial;
311 this->computeTractions(normalTraction, tangentialTraction, tangentialTractionTrial, mode, contactPair, tStep);
312 // traction in global coordinate system
313 FloatArray tractionVector = normalTraction * normal;
315 const auto tangentVectors = contactPair->giveTangentVectors();
316 FloatMatrix contravariant_metric = this->computeContravariantMetric(tangentVectors);
317 for (int i = 0; i < surface_dimension; i++){
318 FloatArray rho_i = tangentVectors[i];
319 for (int j = 0; j < surface_dimension; j++){
320 double t_j = tangentialTraction(j);
321 double a_ij = contravariant_metric(i, j);
322 tractionVector += t_j * rho_i * a_ij;
323 }
324 }
325 }
326 answer.beTProductOf(N, tractionVector);
327 contactPair->setTempTractionVector(tangentialTraction);
328 //answer.times(area);
329 } else {
330 answer.clear();
331 }
332}
333
334
335void
336StructuralPenaltyContactBoundaryCondition :: computeTractions(double& normalTraction, FloatArray &tangentialTraction, FloatArray &tangentialTractionTrial, ContactProcess& mode, ContactPair* contactPair, TimeStep *tStep)
337{
338 // Algorithm from page 141
339 // Computes normal and tangential tractions in local coordinate system
340 tangentialTraction.zero();
341 tangentialTraction.resize(surface_dimension);
342 double normal_gap = contactPair->giveNormalGap();
343 normalTraction = 0.0;
344 if ( normal_gap > 0.0 ) {
345 return;
346 }
347 // compute normal traction
348 normalTraction = penalty_normal * normal_gap;
350 // auxiliary values
351 auto prevTangentialTractions = contactPair->giveTractionVector();
352 const auto prevTangentVectors = contactPair->givePreviousTangentVectors();
353 const auto tangentVectors = contactPair->giveTangentVectors();
354 FloatMatrix prev_contravariant_metric = this->computeContravariantMetric(prevTangentVectors);
355 FloatMatrix contravariant_metric = this->computeContravariantMetric(tangentVectors);
356 FloatMatrix covariant_metric = this->computeCovariantMetric(tangentVectors);
357 //
358 FloatArray delta_rho = contactPair->computeContactPointDisplacement();
359 //
360 for(int i = 0; i < surface_dimension; i++) {
361 const auto& rho_i = tangentVectors[i];
362 for(int j = 0; j < surface_dimension; j++) {
363 const double a_ij = covariant_metric(i, j);
364 const auto& prev_rho_j = prevTangentVectors[j];
365 double prev_rho_j_dot_rho_i = prev_rho_j.dotProduct(rho_i);
366 for(int k = 0; k < surface_dimension; k++) {
367 const double prev_a_kj = prev_contravariant_metric(k, j);
368 const double prev_t_k = prevTangentialTractions(k);
369 tangentialTraction(i) += prev_t_k * prev_a_kj * prev_rho_j_dot_rho_i;
370 }
371 double delta_xi_j = 0.0;
372 for (int k = 0; k < surface_dimension; k++) {
373 const double a_jk = contravariant_metric(j, k);
374 const FloatArray& rho_k = tangentVectors[k];
375 delta_xi_j += delta_rho.dotProduct(rho_k) * a_jk;
376 }
377 tangentialTraction(i) -= penalty_tangential * delta_xi_j * a_ij;
378 }
379 }
380 // return mapping
381 double tNorm2 = 0.0;
382 for(int i = 0; i < surface_dimension; i++) {
383 double t_i = tangentialTraction(i);
384 for(int j = 0; j < surface_dimension; j++) {
385 double a_ij = contravariant_metric(i, j);
386 double t_j = tangentialTraction(j);
387 tNorm2 += t_i * t_j * a_ij;
388 }
389 }
390 double tNorm = std::sqrt(tNorm2);
391 double absNormalTraction = std::abs(normalTraction);
392 double f = tNorm - friction * absNormalTraction;
393 tangentialTractionTrial = tangentialTraction;
394 if (f > 0) {
395 tangentialTractionTrial.times(-1);
396 tangentialTraction.times(-1);
397 double factor = friction * absNormalTraction / tNorm;
398 tangentialTraction *= factor;
400 } else {
402 }
403 }
404}
405
406
407
408void
430
431
432void
433StructuralPenaltyContactBoundaryCondition :: postInitialize()
434{
435 // take nodes of node set after everything is initialized
436 this->masterSurfaceElements = domain->giveSet(this->masterSurfaceNumber)->giveElementList();
437 this->slaveSurfaceElements = domain->giveSet(this->slaveSurfaceNumber)->giveElementList();
438 ContactBoundaryCondition :: postInitialize();
439}
440
441
442
443void
444StructuralPenaltyContactBoundaryCondition :: giveLocationArrays(std::vector< IntArray > &rows, std::vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)
445{
446 //returns all possible combinations of dof that can theoretically be triggered by contact
447 //of any segment with any node. There is a plenty room for optimization of this
448 IntArray m_loc, s_loc;
449
450 rows.resize(0);
451 cols.resize(0);
452
453 const auto& contactPairs = getContactPairs();
454 for(auto const &cp : contactPairs) {
455 if(cp->inContact()) {
456 cp->giveSlaveContactPoint()->giveLocationArray( s_loc, dofs, c_s);
457 cp->giveMasterContactPoint()->giveLocationArray( m_loc, dofs, r_s);
458 // insert location arrays into the answer arrays
459 rows.push_back(s_loc);
460 cols.push_back(m_loc);
461 rows.push_back(m_loc);
462 cols.push_back(s_loc);
463 }
464 }
465}
466
467
468
469
470} // namespace oofem
#define N(a, b)
#define REGISTER_BoundaryCondition(class)
void initializeFrom(InputRecord &ir) override
Definition activebc.h:75
std::vector< std::unique_ptr< ContactPair > > & getContactPairs()
Returns the current list of detected contact pairs (modifiable).
Definition contactbc.h:99
std::unique_ptr< ContactSearchAlgorithm > contactSearchAlgorithm
contactSearchAlgorithm
Definition contactbc.h:82
Represents a contact interaction between a master and a slave contact point.
Definition contactpair.h:68
void setTempTractionVector(const FloatArray &tv)
Sets a temporary traction vector (e.g., predictor or iteration-local value).
virtual void computeNmatrix(FloatMatrix &answer)
Computes the contact interpolation matrix (N-matrix) for this pair.
Definition contactpair.C:97
std::vector< FloatArray > giveTangentVectors() const
Returns all current tangent vectors (typically one or two, depending on surface dimension).
Definition contactpair.C:79
const FloatArray & giveNormalVector() const
Returns the current unit normal vector associated with the contact configuration.
double giveNormalGap()
Returns the current normal gap (signed separation) of the pair.
virtual void computeCurvature(FloatMatrix &G, TimeStep *tStep)
Computes curvature-related quantities of the contact surface at the contact point.
FloatArray computeContactPointDisplacement() const
Computes displacement at the contact point.
void initContactPoint()
Initializes contact-point related quantities for the pair.
std::vector< FloatArray > givePreviousTangentVectors() const
Returns the slave local coordinates used to parameterize the contact point.
Definition contactpair.C:88
const FloatArray & giveTractionVector() const
Returns the current traction vector associated with the contact constraint.
virtual void compute_dNdxi_matrices(std::vector< FloatMatrix > &answer)
Computes derivatives of shape functions w.r.t. local surface parameters.
Contact search algorithm based on the sweep-and-prune strategy.
ContactSurface * giveContactSurface(int n)
Definition domain.C:432
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
double computeNorm() const
Definition floatarray.C:861
void resize(Index s)
Definition floatarray.C:94
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:721
void times(double s)
Definition floatarray.C:834
void plus_Nt_a_otimes_b_B(const FloatMatrix &N, const FloatArray &a, const FloatArray &b, const FloatMatrix &B, double dV=1)
void times(double f)
void zero()
Zeroes all coefficient of receiver.
bool beInverseOf(const FloatMatrix &src)
IntArray dofs
Dofs that b.c. is applied to (relevant for Dirichlet type b.c.s).
void resize(int n)
Definition intarray.C:73
void computeTangentFromContact(FloatMatrix &answer, ContactPair *cp, TimeStep *tStep) override
Computes a consistent tangent contribution for one contact pair (pure virtual).
int surface_dimension
dimension of the surface, i.e., nsd - 1
FloatMatrix computeContravariantMetric(const std::vector< FloatArray > &tangent_vectors)
FloatMatrix computeCovariantMetric(const std::vector< FloatArray > &tangent_vectors)
void computeTractions(double &normalTraction, FloatArray &tangentialTraction, FloatArray &tangentialTractionTrial, ContactProcess &mode, ContactPair *contactPair, TimeStep *tStep)
double penalty_tangential
penalty in the tangent directions.
void computeInternalForcesFromContact(FloatArray &answer, ContactPair *cp, TimeStep *tStep) override
Computes internal force contribution for one contact pair (pure virtual).
double penalty_normal
penalty in the normal direction.
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
bool frictionShouldBeConsidered(double friction, TimeStep *tStep)
#define _IFT_StructuralPenaltyContactBoundaryCondition_penaltyTangential
#define _IFT_StructuralPenaltyContactBoundaryCondition_masterSurfaceNum
#define _IFT_StructuralPenaltyContactBoundaryCondition_nsd
#define _IFT_StructuralPenaltyContactBoundaryCondition_algo
#define _IFT_StructuralPenaltyContactBoundaryCondition_slaveSurfaceNum
#define _IFT_StructuralPenaltyContactBoundaryCondition_friction
#define _IFT_StructuralPenaltyContactBoundaryCondition_penaltyNormal

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011