OOFEM 3.0
Loading...
Searching...
No Matches
intelline1PF.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
37#include "node.h"
40#include "gausspoint.h"
42#include "floatmatrix.h"
43#include "floatarray.h"
44#include "intarray.h"
45#include "mathfem.h"
46#include "fei2dlinelin.h"
47#include "classfactory.h"
48
49
50namespace oofem {
52
53FEI2dLineLin IntElLine1PF :: interp(1, 1);
54
55
56IntElLine1PF :: IntElLine1PF(int n, Domain *aDomain) :
57 StructuralInterfaceElement(n, aDomain), PhaseFieldElement(n, aDomain)
58{
60 alpha.resize(2);
61 alpha.zero();
62 this->oldAlpha.resize(2);
63 this->oldAlpha.zero();
64 this->deltaAlpha.resize(2);
65 this->deltaAlpha.zero();
66 this->prescribed_damage = -1.0;
67}
68
69
70
71void
72IntElLine1PF :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer)
73{
74 // Returns the modified N-matrix which multiplied with u give the spatial jump.
75
79
80 answer.resize(2, 8);
81 answer.zero();
82 answer.at(1, 1) = answer.at(2, 2) = -N.at(1);
83 answer.at(1, 3) = answer.at(2, 4) = -N.at(2);
84
85 answer.at(1, 5) = answer.at(2, 6) = N.at(1);
86 answer.at(1, 7) = answer.at(2, 8) = N.at(2);
87}
88
89
90void
91IntElLine1PF :: computeGaussPoints()
92{
93 if ( integrationRulesArray.size() == 0 ) {
94 integrationRulesArray.resize( 1 );
95 //integrationRulesArray[ 0 ] = std::make_unique<LobattoIntegrationRule>(1,domain, 1, 2);
96 integrationRulesArray [ 0 ] = std::make_unique<GaussIntegrationRule>(1, this, 1, 2);
97 integrationRulesArray [ 0 ]->SetUpPointsOnLine(this->numberOfGaussPoints, _2dInterface);
98 }
99}
100
101
103IntElLine1PF :: computeCovarBaseVectorAt(IntegrationPoint *ip) const
104{
106 FloatMatrix dNdxi;
107 interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
109 int numNodes = this->giveNumberOfNodes();
110 for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) {
111 double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface
112 double X2_i = 0.5 * ( this->giveNode(i)->giveCoordinate(2) + this->giveNode(i + numNodes / 2)->giveCoordinate(2) );
113 G.at(1) += dNdxi.at(i, 1) * X1_i;
114 G.at(2) += dNdxi.at(i, 1) * X2_i;
115 }
116 return G;
117}
118
119
120double
121IntElLine1PF :: computeAreaAround(IntegrationPoint *ip)
122{
123 auto G = this->computeCovarBaseVectorAt(ip);
124 auto ds = norm(G) * ip->giveWeight();
125 return ds * this->giveCrossSection()->give(CS_Thickness, ip);
126}
127
128
129void
130IntElLine1PF :: initializeFrom(InputRecord &ir)
131{
132 StructuralInterfaceElement :: initializeFrom(ir);
133
136 //this->alpha.setValues(2, damage, damage);
137 }
138}
139
140
141void
142IntElLine1PF :: giveDofManDofIDMask(int inode, IntArray &answer) const
143{
144 answer = {D_u, D_v, T_f};
145}
146
147
148void
149IntElLine1PF :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer)
150{
151 // Transformation matrix to the local coordinate system
152 FloatArray G;
153 this->computeCovarBaseVectorAt(gp, G);
154 G.normalize();
155
156 answer.resize(2, 2);
157 answer.at(1, 1) = G.at(1);
158 answer.at(2, 1) = G.at(2);
159 answer.at(1, 2) = -G.at(2);
160 answer.at(2, 2) = G.at(1);
161
162}
163
164
166IntElLine1PF :: giveInterpolation() const
167{
168 return & interp;
169}
170
171
172void
173IntElLine1PF :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
174{
175 //set displacement and nonlocal location array
177 IntArray IdMask_u, IdMask_d;
178 this->giveDofManDofIDMask_u( IdMask_u );
179 this->giveDofManDofIDMask_d( IdMask_d );
180 this->computeLocationArrayOfDofIDs( IdMask_u, loc_u );
181 this->computeLocationArrayOfDofIDs( IdMask_d, loc_d );
182
183 int nDofs = this->computeNumberOfDofs();
184 answer.resize( nDofs, nDofs );
185 answer.zero();
186
187 // Set the solution vectors (a_u, a_d) for the element
188 this->computeDisplacementUnknowns( this->unknownVectorU, VM_Total, tStep );
189 this->computeDamageUnknowns( this->unknownVectorD, VM_Total, tStep );
190 this->computeDamageUnknowns( this->deltaUnknownVectorD, VM_Incremental, tStep );
191
192 FloatMatrix temp;
193 solveForLocalDamage(temp, tStep);
194
195 FloatMatrix answer1, answer2, answer3, answer4;
196 this->computeStiffnessMatrix_uu(answer1, rMode, tStep);
197 //this->computeStiffnessMatrix_ud(answer2, rMode, tStep);
198 //this->computeStiffnessMatrix_du(answer3, rMode, tStep); //symmetric
199 answer3.beTranspositionOf( answer2 );
200 this->computeStiffnessMatrix_dd(answer4, rMode, tStep);
201
202 answer.assemble( answer1, loc_u, loc_u );
203 //answer.assemble( answer2, loc_u, loc_d );
204 //answer.assemble( answer3, loc_d, loc_u );
205 answer.assemble( answer4, loc_d, loc_d );
206}
207
208
209void
210IntElLine1PF :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
211{
212 // Computes the stiffness matrix of the receiver K_cohesive = int_A ( N^t * dT/dj * N ) dA
213 FloatMatrix N, D, DN, GD, Gmat;
214 bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode);
215 answer.resize(0, 0);
216 FloatArray Nd;
217 //IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
218 FloatMatrix rotationMatGtoL;
219
220 //for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) {
221 //IntegrationPoint *ip = iRule->getIntegrationPoint(j);
222 for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) {
223
224 if ( this->nlGeometry == 0 ) {
225 this->giveStiffnessMatrix_Eng(D, rMode, ip, tStep);
226 } else if ( this->nlGeometry == 1 ) {
227 this->giveStiffnessMatrix_dTdj(D, rMode, ip, tStep);
228 } else {
229 OOFEM_ERROR("nlgeometry must be 0 or 1!")
230 }
231
232 this->computeNmatrixAt(ip, N);
233
234 this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd);
235 double d = Nd.dotProduct(this->alpha);
236 this->computeGMatrix(Gmat, d, ip, VM_Total, tStep);
237 GD.beProductOf(Gmat,D);
238
239 this->computeTransformationMatrixAt(ip, rotationMatGtoL);
240 GD.rotatedWith(rotationMatGtoL, 't'); // transform stiffness to global coord system
241
242 DN.beProductOf(GD, N);
243
244 double dA = this->computeAreaAround(ip);
245 if ( matStiffSymmFlag ) {
246 answer.plusProductSymmUpper(N, DN, dA);
247 } else {
248 answer.plusProductUnsym(N, DN, dA);
249 }
250 }
251
252 if ( matStiffSymmFlag ) {
253 answer.symmetrized();
254 }
255}
256
257
258void
259IntElLine1PF :: computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
260{
261 //IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
262
263 FloatMatrix N, rotationMatGtoL;
264 FloatArray a_u, traction, tractionTemp, jump, fu, fd(2), fd4(4);
265
266 fd.zero();
267 FloatArray a_d_temp, a_d, Bd, Nd;
268 a_u = this->unknownVectorU;
269 a_d_temp = this->unknownVectorD;
270 a_d = { a_d_temp.at(1), a_d_temp.at(2) };
271
272 FloatMatrix temp, Kud(8,2);
273 fu.zero();
274 Kud.zero();
275 //for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
276 for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) {
277 //IntegrationPoint *ip = iRule->getIntegrationPoint(i);
278 this->computeNmatrixAt(ip, N);
279 this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd);
280 jump.beProductOf(N, a_u);
281 this->computeTraction(traction, ip, jump, tStep);
282
283 // compute internal cohesive forces as f = N^T*traction dA
284 double Gprim = computeGPrim(ip, VM_Total, tStep);
285 double dA = this->computeAreaAround(ip);
286
287 fu.plusProduct(N, traction, dA*Gprim);
288 temp.beDyadicProductOf(fu,Nd);
289 Kud.add(temp);
290
291 }
292
293 IntArray indxu, indx1, indx2;
294 indxu = {1, 2, 3, 4, 5, 6, 7, 8};
295 indx1 = {1, 2};
296 indx2 = {3, 4};
297 answer.resize(8,4);
298 answer.zero();
299 answer.assemble(Kud, indxu, indx1);
300 answer.assemble(Kud, indxu, indx2);
301
302
303 // Numerical tangent
304 // Set the solution vectors (a_u, a_d) for the element
305 FloatArray a_u_ref, a_d_pert, a_d_ref, fu_ref, fd_ref, fu_pert, K_col, fd_temp, delta_a_d_ref, delta_a_d_pert;
306 FloatMatrix K_num(8,2), Kdd_num;
307 double eps = 1.0e-6;
308
309 a_u_ref = this->unknownVectorU;
310 a_d_ref = this->unknownVectorD;
311 delta_a_d_ref = this->deltaUnknownVectorD;
312 this->giveInternalForcesVectorUD(fu_ref, fd_ref, tStep, false);
313
314 for ( int i = 1; i <=2; i++ ) {
315 a_d_pert = a_d_ref;
316 a_d_pert.at(i) += eps;
317 this->unknownVectorD = a_d_pert;
318
319 delta_a_d_pert = delta_a_d_ref;
320 delta_a_d_pert.at(i) += eps;
321 this->deltaUnknownVectorD = delta_a_d_pert;
322
323 this->giveInternalForcesVectorUD(fu_pert, fd_temp, tStep, false);
324 K_col = ( 1.0/eps ) * ( fu_pert - fu_ref );
325 K_num.addSubVectorCol(K_col, 1, i);
326 }
327
328 answer.zero();
329 answer.assemble(K_num, indxu, indx1);
330 answer.assemble(K_num, indxu, indx2);
331
332 this->unknownVectorU = a_u_ref;
333 this->unknownVectorD = a_d_ref;
334 this->deltaUnknownVectorD = delta_a_d_ref;
335}
336
337
338void
339IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
340{
341 // Computation of tangent: K_dd = \int Nd^t * ( -kp*neg_Mac'(alpha_dot)/delta_t + g_c/l + G''*Psibar) * Nd +
342 // \int Bd^t * ( g_c * l * [G^1 G^2]^t * [G^1 G^2] ) * Bd
343 // = K_dd1 + K_dd2
344 int ndofs = 8 + 4;
345 int ndofs_u = 8;
346 int ndofs_d = 4;
347
348 double l = this->giveInternalLength();
349 double g_c = this->giveCriticalEnergy();
350 double kp = this->givePenaltyParameter();
351 double Delta_t = tStep->giveTimeIncrement();
352
353 answer.resize( ndofs_d, ndofs_d );
354 answer.zero();
355
356 //IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
357 FloatMatrix tempN(2,2), tempB(2,2), temp(2,2);
358 FloatArray Nd, Bd;
359 tempN.zero();
360 tempB.zero();
361 temp.zero();
362 //for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) {
363 // IntegrationPoint *ip = iRule->getIntegrationPoint(j);
364 for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) {
365 computeBd_vectorAt(ip, Bd);
366 computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd);
367 double dA = this->computeAreaAround(ip);
368
369 //double Gbis = this->computeGbis()
370 double Gbis = 2.0;
371 double Psibar = this->computeFreeEnergy( ip, tStep );
372
373 // K_dd1 = ( -kp*neg_Mac'(d_dot) / Delta_t + g_c/ l + G'' * Psibar ) * N^t*N;
374 double Delta_d = computeDamageAt(ip, VM_Incremental, tStep);
375 double factorN = -kp * neg_MaCauleyPrime(Delta_d/Delta_t)/Delta_t + g_c / l + Gbis * Psibar;
376 //double factorN = g_c / l + Gbis * Psibar;
377
378 //double Psibar0 = this->givePsiBar0();
379 //double factorN = g_c / l + Gbis * this->MaCauley(Psibar-Psibar0);
380
381 tempN.beDyadicProductOf(Nd, Nd);
382 temp.add(factorN * dA, tempN);
383
384 // K_dd2 = g_c * l * Bd^t * Bd;
385 double factorB = g_c * l;
386 tempB.beDyadicProductOf(Bd, Bd);
387 temp.add(factorB * dA, tempB);
388 }
389
390 IntArray indx1 = {1, 2}, indx2 = {3, 4};
391
392 answer.assemble(temp, indx1, indx1);
393 answer.assemble(temp, indx2, indx2);
394
395#if 0
396 // Numerical tangent
397 // Set the solution vectors (a_u, a_d) for the element
398 FloatArray a_u_ref, a_d_ref, a_d_pert, fu_ref, fd_ref, fd_pert, K_col, fu_temp;
399 FloatMatrix K(4,4), Kdd_num;
400 double eps = 1.0e-6;
401
402 a_u_ref = this->unknownVectorU;
403 a_d_ref = this->unknownVectorD;
404 this->giveInternalForcesVectorUD(fu_ref, fd_ref, tStep, false);
405
406 for ( int i = 1; i <=2; i++ ) {
407 a_d_pert = a_d_ref;
408 a_d_pert.at(i) += eps;
409 this->unknownVectorD = a_d_pert;
410
411 this->giveInternalForcesVectorUD(fu_temp, fd_pert, tStep, false);
412 K_col = ( 1.0/eps ) * ( fd_pert - fd_ref );
413 K.addSubVectorCol(K_col, 1, i);
414 }
415
416 Kdd_num.beSubMatrixOf(K,1,2,1,2);
417
418 answer.zero();
419 answer.assemble(Kdd_num, indx1, indx1);
420 answer.assemble(Kdd_num, indx2, indx2);
421
422 this->unknownVectorU = a_u_ref;
423 this->unknownVectorD = a_d_ref;
424#endif
425}
426
427
428void
429IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep)
430{
431 // approach with dame defined over the element only
432
433 if ( tStep->giveNumber() == 1 ) {
434 return;
435 }
436 if ( this->prescribed_damage >-1.0e-8 ){
437 return;
438 }
439
440 //IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
441
442 FloatArray a_u, a_d_temp, a_d(2), traction, jump, fd(2), fd_ref(2), Nd, Bd;
443 FloatMatrix Kdd(2,2), tempN, tempB;
444 FloatArray delta_a_d;
445
446 double kp = this->givePenaltyParameter();
447 double Delta_t = tStep->giveTimeIncrement();
448 double l = this->giveInternalLength();
449 double g_c = this->giveCriticalEnergy();
450
451 fd.zero();
452 Kdd.zero();
453 //a_d.zero();
454 a_d = this->alpha; // checked - evolves
455 this->oldAlpha = this->alpha;
456 for ( int nIter = 1; nIter <= 10; nIter++ ) {
457 fd.zero();
458 Kdd.zero();
459 fd_ref.zero();
460 //for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
461 // IntegrationPoint *ip = iRule->getIntegrationPoint(i);
462 for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) {
463
464 this->computeBd_vectorAt(ip, Bd);
465 this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd);
466 double dA = this->computeAreaAround(ip);
467
468 // Internal force
469 //double d = computeDamageAt( ip, VM_Total, tStep);
470 double d = Nd.dotProduct(a_d);
471 double gradd = Bd.dotProduct(a_d); // Dalpha/Ds
472 //double Delta_d = computeDamageAt( ip, VM_Incremental, tStep);
473 double Delta_d = Nd.dotProduct(a_d-oldAlpha);
474 //double Gprim = computeGPrim(ip, VM_Total, tStep);
475 double Gprim = -2.0 * (1.0 - d);
476 double Psibar = this->computeFreeEnergy( ip, tStep );
477
478 double sectionalForcesScal = -kp * neg_MaCauley(Delta_d/Delta_t) + g_c / l * d + Gprim * Psibar;
479 double sectionalForcesVec = g_c * l * gradd;
480 fd = fd + ( Nd*sectionalForcesScal + Bd*sectionalForcesVec ) * dA;
481 fd_ref = fd_ref + ( Nd * (Gprim * Psibar + 1.0e-8 ) ) * dA;
482
483 // Tangent
484 //double Gbis = this->computeGbis()
485 double Gbis = 2.0;
486
487 // K_dd1 = ( -kp*neg_Mac'(d_dot) / Delta_t + g_c/ l + G'' * Psibar ) * N^t*N;
488 double factorN = -kp * neg_MaCauleyPrime(Delta_d/Delta_t)/Delta_t + g_c / l + Gbis * Psibar;
489 //double factorN = g_c / l + Gbis * Psibar;
490
491 tempN.beDyadicProductOf(Nd, Nd);
492 Kdd.add(factorN * dA, tempN);
493
494 // K_dd2 = g_c * l * Bd^t * Bd;
495 double factorB = g_c * l;
496 tempB.beDyadicProductOf(Bd, Bd);
497 Kdd.add(factorB * dA, tempB);
498
499 }
500 //printf("norm %e \n", fd.computeNorm() );
501 //if( fd.computeNorm() < 1.0e-5 ) {
502 if ( fd.computeNorm()/fd_ref.computeNorm() < 1.0e-3 ) {
503 this->alpha = a_d;
504 return;
505 }
506 Kdd.solveForRhs(fd, delta_a_d);
507 a_d.subtract(delta_a_d);
508 this->deltaAlpha += delta_a_d;
509 //this->alpha = a_d;
510 //a_d.printYourself();
511 }
512 printf("norm %e \n", fd.computeNorm()/fd_ref.computeNorm() );
513 OOFEM_ERROR("No convergence in phase field iterations")
514}
515
516
517void
518IntElLine1PF :: computeGMatrix(FloatMatrix &answer, const double damage, GaussPoint *gp, ValueModeType valueMode, TimeStep *tStep)
519{
520 double d = damage;
521 if ( this->prescribed_damage > -1.0e-8 ) {
523 }
524
526 const auto &strain = matStat->giveTempJump();
527 double g2 = -1.0;
528 if ( strain.at(3) < 0.0 ) { // Damage does not affect compressive stresses
529 g2 = 1.0;
530 //printf("compression \n");
531 } else {
532 g2 = (1.0 - d) * (1.0 - d);
533 //printf("g %e \n", g2);
534 //g2 = 1;
535 }
536
537 double g1 = (1.0 - d) * (1.0 - d);
538
539 answer.resize(2,2);
540 answer.zero();
541 answer.at(1,1) = g1;
542 answer.at(2,2) = g2;
543}
544
545
546double
547IntElLine1PF :: computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN)
548{
549 // d = N_d * a_d
550 //NLStructuralElement *el = static_cast< NLStructuralElement* >(this->giveElement( ) );
552 FloatArray dVec;
553 if ( valueMode == VM_Total ) {
554 //dVec = this->unknownVectorD;
557 dVec = this->alpha;
558 } else if ( valueMode == VM_Incremental ) {
559 //dVec = this->deltaUnknownVectorD;
560 //dVec = this->deltaAlpha;
561 dVec = this->alpha - this->oldAlpha;
562 }
563 //dVec.resizeWithValues(2);
564 FloatArray Nvec;
566 return Nvec.dotProduct(dVec);
567}
568
569
570void
571IntElLine1PF :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord)
572{
573 // Set the solution vectors (a_u, a_d) for the element
574 this->computeDisplacementUnknowns( this->unknownVectorU, VM_Total, tStep );
575 this->computeDamageUnknowns( this->unknownVectorD, VM_Total, tStep );
576 this->computeDamageUnknowns( this->deltaUnknownVectorD, VM_Incremental, tStep );
577
578 FloatArray fu, fd;
579 this->giveInternalForcesVectorUD(fu, fd, tStep, useUpdatedGpRecord);
580
581 // total vec
582 IntArray IdMask_u, IdMask_d;
583 this->giveDofManDofIDMask_u( IdMask_u );
584 this->giveDofManDofIDMask_d( IdMask_d );
585 this->computeLocationArrayOfDofIDs( IdMask_u, loc_u );
586 this->computeLocationArrayOfDofIDs( IdMask_d, loc_d );
587
588 int nDofs = this->computeNumberOfDofs();
589 answer.resize( nDofs );
590 answer.zero();
591 answer.assemble(fu, loc_u);
592 //answer.assemble(fd, loc_d);
593}
594
595
596void
597IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, TimeStep *tStep, int useUpdatedGpRecord)
598{
599 // Computes internal forces
600 // if useGpRecnord == 1 then data stored in ip->giveStressVector() are used
601 // instead computing stressVector through this->ComputeStressVector();
602 // this must be done after you want internal forces after element->updateYourself()
603 // has been called for the same time step.
604
605 //IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
606
607 FloatMatrix Nu, rotationMatGtoL, Gmat;
608 FloatArray a_u, a_d_temp, a_d, traction, jump, fd(2), Nd, Bd, GTraction;
609
610 a_u = this->unknownVectorU;
611 a_d_temp = this->unknownVectorD;
612 a_d = { a_d_temp.at(1), a_d_temp.at(2) };
613
614 fu.zero();
615 fd.zero();
616
617 for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) {
618 //for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
619 // IntegrationPoint *ip = iRule->getIntegrationPoint(i);
620 this->computeNmatrixAt(ip, Nu);
621 this->computeBd_vectorAt(ip, Bd);
622 this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd);
623
624 // compute internal cohesive forces as f = N^T * g * traction dA
625 jump.beProductOf(Nu, a_u);
626 this->computeTraction(traction, ip, jump, tStep);
627
628 //FloatMatrix temp;
629 //solveForLocalDamage(temp, tStep);
630 //double g = this->computeG(ip, VM_Total, tStep);
631
632 this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd);
633 double d = Nd.dotProduct(this->alpha);
634 // g = (1.0 - d) * (1.0 - d);
635
636
637 this->computeGMatrix(Gmat, d, ip, VM_Total, tStep);
638 GTraction.beProductOf(Gmat,traction);
639 //double g = this->computeOldG(ip, VM_Total, tStep);
640 double dA = this->computeAreaAround(ip);
641
642 //fu.plusProduct(Nu, traction, dA*g);
643 fu.plusProduct(Nu, GTraction, dA);
644
645
646 // damage field
647
648 double kp = this->givePenaltyParameter();
649 double Delta_t = tStep->giveTimeIncrement();
650 //double d = computeDamageAt( ip, VM_Total, tStep);
651 double Delta_d = computeDamageAt(ip, VM_Incremental, tStep);
652 double l = this->giveInternalLength();
653 double g_c = this->giveCriticalEnergy();
654 double Gprim = computeGPrim(ip, VM_Total, tStep);
655
656 double Psibar = this->computeFreeEnergy( ip, tStep );
657 double gradd = Bd.dotProduct(a_d); // Dalpha/Ds
658
659 //double Psibar0 = this->givePsiBar0();
660 //double sectionalForcesScal = g_c / l * d + Gprim * this->MaCauley(Psibar-Psibar0);
661 double sectionalForcesScal = -kp * neg_MaCauley(Delta_d/Delta_t) + g_c / l * d + Gprim * Psibar;
662 //double sectionalForcesScal = g_c / l * d + Gprim * Psibar;
663 double sectionalForcesVec = g_c * l * gradd;
664 fd = fd + ( Nd*sectionalForcesScal + Bd*sectionalForcesVec ) * dA;
665 }
666 fd4.resize(4);
667 fd4.zero();
668 IntArray indx1, indx2;
669 indx1 = {1, 2};
670 indx2 = {3, 4};
671 fd4.assemble(fd, indx1);
672 fd4.assemble(fd, indx2);
673}
674
675
676double
677IntElLine1PF :: computeFreeEnergy(GaussPoint *gp, TimeStep *tStep)
678{
680 FloatArray strain, stress;
681 stress = matStat->giveTempFirstPKTraction();
682 strain = matStat->giveTempJump();
683 //stress = matStat->giveFirstPKTraction();
684 //strain = matStat->giveJump();
685 //stress.printYourself();
686 //strain.printYourself();
687
688 // Damage only for positive normal traction
689 if ( strain.at(3) < 0.0 ) {
690 return 0.5 * ( stress.at(1)*strain.at(1) + stress.at(2)*strain.at(2) );
691 } else {
692 return 0.5 * stress.dotProduct( strain );
693 }
694}
695
696double
697IntElLine1PF :: computeOldG(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN)
698{
699 // computes Dg/Dd = (1-d)^2 + r0
700 //double d = this->computeDamageAt(gp, VM_Total, stepN) - this->computeDamageAt(gp, VM_Incremental, stepN);
701 double d = this->computeDamageAt(gp, VM_Total, stepN);
702 double r0 = 1.0e-10;
703 return (1.0 - d) * (1.0 - d) + r0;
704}
705
706
707void
708IntElLine1PF :: giveDofManDofIDMask_u(IntArray &answer)
709{
710 //StructuralInterfaceElement :: giveDofManDofIDMask(-1, EID_MomentumBalance, answer);
711 //IntElLine1 :: giveDofManDofIDMask(-1, EID_MomentumBalance, answer);
712 answer = {D_u, D_v};
713}
714
715void
716IntElLine1PF :: giveDofManDofIDMask_d(IntArray &answer)
717{
718 answer = {T_f};
719}
720
721
722void
723IntElLine1PF :: computeLocationArrayOfDofIDs( const IntArray &dofIdArray, IntArray &answer )
724{
725 // Routine to extract compute the location array an element given an dofid array.
726 answer.resize( 0 );
727 //NLStructuralElement *el = this->giveElement();
729 int k = 0;
730 for(int i = 1; i <= el->giveNumberOfDofManagers(); i++) {
731 DofManager *dMan = el->giveDofManager( i );
732 for(int j = 1; j <= dofIdArray.giveSize( ); j++) {
733
734 if(dMan->hasDofID( (DofIDItem) dofIdArray.at( j ) )) {
735 Dof *d = dMan->giveDofWithID( dofIdArray.at( j ) );
736 //answer.followedBy( k + d->giveNumber( ) );
737 }
738 }
739 k += dMan->giveNumberOfDofs( );
740 }
741}
742
743void
744IntElLine1PF :: computeNd_vectorAt(const FloatArray &lCoords, FloatArray &N)
745{
747 FloatArray Nvec;
748 el->giveInterpolation( )->evalN( N, lCoords, FEIElementGeometryWrapper( el ) );
749
750}
751
752void
753IntElLine1PF :: computeBd_vectorAt(GaussPoint *aGaussPoint, FloatArray &answer)
754{
755 // Returns the [numSpaceDim x nDofs] gradient matrix {B_d} of the receiver,
756 // evaluated at gp.
757
758 StructuralInterfaceElement *el = dynamic_cast< StructuralInterfaceElement* > ( this->giveElement() );
759 FloatMatrix dNdxi;
760 this->giveInterpolation()->evaldNdxi( dNdxi, aGaussPoint->giveNaturalCoordinates( ), FEIElementGeometryWrapper( this ) );
761
762 answer.resize(2);
763 for (int i = 1; i <= dNdxi.giveNumberOfRows(); i++) {
764 answer.at(i) = dNdxi.at(i,1);
765 }
766 FloatArray G;
767 this->computeCovarBaseVectorAt(aGaussPoint, G);
768 answer.times( 1.0 / sqrt(G.dotProduct(G)) );
769}
770
771} // end namespace oofem
#define N(a, b)
#define REGISTER_Element(class)
bool hasDofID(DofIDItem id) const
Definition dofmanager.C:174
int giveNumberOfDofs() const
Definition dofmanager.C:287
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
Node * giveNode(int i) const
Definition element.h:629
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual int giveNumberOfNodes() const
Definition element.h:703
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
int numberOfGaussPoints
Definition element.h:175
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
CrossSection * giveCrossSection()
Definition element.C:534
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
double & at(std::size_t i)
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void plusProduct(const FloatMatrix &b, const FloatArray &s, double dV)
Definition floatarray.C:288
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void times(double s)
Definition floatarray.C:834
void rotatedWith(const FloatMatrix &r, char mode='n')
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
void add(const FloatMatrix &a)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void beSubMatrixOf(const FloatMatrix &src, Index topRow, Index bottomRow, Index topCol, Index bottomCol)
void plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void beTranspositionOf(const FloatMatrix &src)
void zero()
Zeroes all coefficient of receiver.
void beDyadicProductOf(const FloatArray &vec1, const FloatArray &vec2)
int giveNumberOfRows() const
Returns number of rows of receiver.
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
double giveWeight()
Returns integration weight of receiver.
Definition gausspoint.h:180
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override
double computeAreaAround(GaussPoint *gp) override
FloatArray deltaUnknownVectorD
virtual void computeStiffnessMatrix_dd(FloatMatrix &, MatResponseMode, TimeStep *)
void solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep)
StructuralInterfaceElement * giveElement() override
void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override
FloatArrayF< 2 > computeCovarBaseVectorAt(GaussPoint *gp) const
static FEI2dLineLin interp
virtual void giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd, TimeStep *tStep, int useUpdatedGpRecord=0)
virtual void computeNd_vectorAt(const FloatArray &lCoords, FloatArray &N)
virtual void computeLocationArrayOfDofIDs(const IntArray &dofIdArray, IntArray &answer)
FEInterpolation * giveInterpolation() const override
virtual void computeBd_vectorAt(GaussPoint *gp, FloatArray &B)
void giveDofManDofIDMask_d(IntArray &answer) override
virtual void computeStiffnessMatrix_uu(FloatMatrix &, MatResponseMode, TimeStep *)
int computeNumberOfDofs() override
virtual double computeFreeEnergy(GaussPoint *gp, TimeStep *tStep)
virtual double computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN)
double neg_MaCauleyPrime(double par) const
FloatArray unknownVectorD
void giveDofManDofIDMask_u(IntArray &answer) override
void computeGMatrix(FloatMatrix &answer, const double damage, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN)
FloatArray unknownVectorU
double neg_MaCauley(double par) const
void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override
void computeDisplacementUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *stepN)
void computeDamageUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *stepN)
double computeGPrim(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN)
PhaseFieldElement(int i, Domain *aDomain)
bool nlGeometry
Flag indicating if geometrical nonlinearities apply.
virtual void giveStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep)
virtual void computeTraction(FloatArray &traction, IntegrationPoint *ip, const FloatArray &jump, TimeStep *tStep)
const FloatArrayF< 3 > & giveTempFirstPKTraction() const
Returns the const pointer to receiver's temporary first Piola-Kirchhoff traction vector.
const FloatArrayF< 3 > & giveTempJump() const
Returns the const pointer to receiver's temporary jump.
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define _IFT_IntElLine1PF_prescribedDamage
double norm(const FloatArray &x)
@ CS_Thickness
Thickness.
GaussPoint IntegrationPoint
Definition gausspoint.h:272

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