OOFEM 3.0
Loading...
Searching...
No Matches
shell7basexfem.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
38#include "constantsurfaceload.h"
43#include "feinterpol3d.h"
44#include "xfem/enrichmentitem.h"
45#include "xfem/xfemmanager.h"
46#include "dofmanager.h"
47#include "connectivitytable.h"
48#include "mathfem.h"
49#include "gausspoint.h"
50#include "spatiallocalizer.h"
51#include "parametermanager.h"
52#include "paramkey.h"
53
54namespace oofem {
55
56/* Scale factor fo the discontinuous dofs. Implies that the corresponding
57 must be scaled with 1/factor in the input file
58*/
59const double DISC_DOF_SCALE_FAC = 1.0;
60
62
63
64Shell7BaseXFEM :: Shell7BaseXFEM(int n, Domain *aDomain) : Shell7Base(n, aDomain), XfemElementInterface(this)
65{
66}
67
68int
69Shell7BaseXFEM :: checkConsistency()
70{
71 Shell7Base :: checkConsistency();
72 return 1;
73}
74
75void
76Shell7BaseXFEM :: postInitialize()
77{
78 Shell7Base :: postInitialize();
79 this->xMan = this->giveDomain()->giveXfemManager();
80
81 // Set up ordering arrays and arrays with the actived dofs
82 int numEI = xMan->giveNumberOfEnrichmentItems();
83 this->orderingArrays.resize(numEI);
84 this->activeDofsArrays.resize(numEI);
85 for ( int i = 1; i <= numEI; i++ ) {
86 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i);
87 if ( ei->isElementEnriched(this) ) {
88 this->computeOrderingArray( this->orderingArrays[i-1], activeDofsArrays[i-1], ei);
89 }
90 }
91
92}
93
94
95void
96Shell7BaseXFEM :: computeFailureCriteriaQuantities(FailureCriteriaStatus *fcStatus, TimeStep *tStep)
97{
98 // Compute necessary quantities for evaluation of failure criterias
100
101 if ( DamagedNeighborLayeredStatus * status = dynamic_cast< DamagedNeighborLayeredStatus * >(fcStatus) ) {
102 /*
103 Go through the neighbors of the element and check for each layer if the
104 corresponding cz is damaged (if applicable)
105 */
106 IntArray neighbors;
107 IntArray elements(1);
108 ConnectivityTable *conTable = this->giveDomain()->giveConnectivityTable();
109 elements.at(1) = fcStatus->el->giveNumber();
110 conTable->giveElementNeighbourList(neighbors, elements);
111 FloatArray damageArray(this->layeredCS->giveNumberOfLayers() - 1), damageArrayNeigh;
112 fcStatus->quantities.resize( neighbors.giveSize() );
113
114 for ( int i = 1; i <= neighbors.giveSize(); i++ ) {
115
116 Shell7BaseXFEM *neighbor =
117 dynamic_cast< Shell7BaseXFEM * > (this->giveDomain()->giveElement( neighbors.at(i) ));
118 if ( neighbor ) {
119 neighbor->giveMaxCZDamages(damageArrayNeigh, tStep); // damage parameter for each interface
120
121 // store maximum damage from neighbors
122 for ( int j = 1; j <= damageArray.giveSize(); j++ ) {
123 if (damageArrayNeigh.at(j) > damageArray.at(j) ) {
124 damageArray.at(j) = damageArrayNeigh.at(j);
125 }
126 }
127 }
128
129 }
130
131
132 // debugging
133 for ( int j = 1; j <= damageArray.giveSize(); j++ ) {
134 damageArray.at(j) = 1.0;
135 }
136
137 status->layerDamageValues = damageArray;
138 }
139 //case FC_DamagedNeighborCZ:
140 //std::vector < FloatArray > interLamStresses;
141 //int numInterfaces = this->layeredCS->giveNumberOfLayers() - 1;
142 //IntArray delaminatedInterfaceList;
143 //switch ( fc->giveType() ) {
144 //case FC_MaxShearStress:
145 //
146 // this->computeDelaminatedInterfaceList(delaminatedInterfaceList); ///@todo remove the need for this method - JB
147 //
148 // fc->quantities.resize(numInterfaces); // will overwrite this every time
149 // //fc->elQuantities[ this->giveNumber() - 1 ].
150 // for (int intface = 1; intface <= numInterfaces; intface++ ) {
151 //
152 // if ( ! delaminatedInterfaceList.contains(intface) ) { // interface is whole
153 // this->computeInterLaminarStressesAt(intface, tStep, interLamStresses); // all 6 components in each evaluation point (ip)
154 // int numEvalPoints = interLamStresses.size();
155 // fc->quantities[intface-1].resize(numEvalPoints); // most often = numIP
156 //
157 // for ( int evalPoint = 1; evalPoint <= numEvalPoints; evalPoint++) {
158 // FloatArray &values = fc->quantities[intface-1][evalPoint-1]; // one resulting shear stress
159 // FloatArray &vS = interLamStresses[evalPoint-1]; // Stress in eval point
160 // values.resize(1); // scalar measure in this case
161 // values.at(1) = sqrt( vS.at(2)*vS.at(2) + vS.at(3)*vS.at(3) ); // components can't be right here? shouldn't it be a traction vector?
162 // }
163 // }
164 // }
165 // break;
166}
167
168
169void Shell7BaseXFEM :: initializeFrom(InputRecord &ir, int priority)
170{
171 Shell7Base :: initializeFrom(ir, priority);
172
174 OOFEM_ERROR("'czmaterial' this keyword is not in use anymore! Instead define cz material for each interface in the cross secton, ex: interfacematerials 3 x x x ");
175 }
176}
177
178bool
179Shell7BaseXFEM :: hasCohesiveZone(int interfaceNum)
180{
181 if ( interfaceNum <= this->layeredCS->giveNumberOfLayers()-1 ) {
182 return this->layeredCS->giveInterfaceMaterialNum(interfaceNum) > 0;
183 } else {
184 return 0;
185 }
186}
187
189*Shell7BaseXFEM :: giveInterface(InterfaceType it)
190{
191 if ( it != XfemElementInterfaceType ) {
192 return Shell7Base :: giveInterface(it);
193 } else if ( it == XfemElementInterfaceType ) {
194 return static_cast< XfemElementInterface * >(this);
195 } else {
196 return Shell7Base :: giveInterface(it);
197 }
198}
199
200
201void
202Shell7BaseXFEM :: giveDofManDofIDMask(int inode, IntArray &answer) const
203{
204 // Returns the total id mask of the dof manager - regular id's + enriched id's
205
206 // Continuous part
207 Shell7Base :: giveDofManDofIDMask(inode, answer);
208 XfemManager *xMan = this->giveDomain()->giveXfemManager(); // xman not initialized on el. level when this is first called
209
210 // Discontinuous part
211 DofManager *dMan = this->giveDofManager(inode);
212 for ( int i = 1; i <= xMan->giveNumberOfEnrichmentItems(); i++ ) {
213 EnrichmentItem *ei = xMan->giveEnrichmentItem(i);
214 if ( ei->isDofManEnriched(*dMan) ) {
215 IntArray eiDofIdArray;
216 ei->giveEIDofIdArray(eiDofIdArray);
217 answer.followedBy(eiDofIdArray);
218 }
219 }
220}
221
222
224Shell7BaseXFEM :: evalCovarBaseVectorsAt(const FloatArrayF<3> &lCoords, FloatArray &genEpsC, TimeStep *tStep)
225{
226 // Continuous part g_c
227 auto gcov = Shell7Base :: evalCovarBaseVectorsAt(lCoords, genEpsC, tStep);
228
229 // Discontinuous part g_d
230 FloatArray dGenEps;
231 std :: vector< double > ef;
232 for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) {
233 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i);
234
235 if ( ei->isElementEnriched(this) ) {
236 computeDiscGeneralizedStrainVector(dGenEps, lCoords, ei, tStep);
237 auto gcovd = Shell7Base :: evalCovarBaseVectorsAt(lCoords, dGenEps, tStep);
238 gcov += gcovd;
239 }
240 }
241 return gcov;
242}
243
244
245void
246Shell7BaseXFEM :: computeDiscGeneralizedStrainVector(FloatArray &answer, const FloatArray &lCoords, EnrichmentItem *ei, TimeStep *tStep)
247{
248 FloatArray solVecD;
249 IntArray eiDofIdArray;
250 ei->giveEIDofIdArray(eiDofIdArray);
251 this->computeDiscSolutionVector(eiDofIdArray, tStep, solVecD);
252 FloatMatrix B;
253 this->computeEnrichedBmatrixAt(lCoords, B, ei);
254 answer.beProductOf(B, solVecD);
255}
256
257
258void
259Shell7BaseXFEM :: computeDiscSolutionVector(IntArray &dofIdArray , TimeStep *tStep, FloatArray &answer)
260{
261 FloatArray temp;
262 IntArray newIdArray = dofIdArray;
263 newIdArray.followedBy(0); // Extend it by one such that the length is 7 -> answer = size 42 for 6 noded triangle
264 this->computeVectorOf(newIdArray, VM_Total, tStep, temp, true);
265 answer.resize(temp.giveSize());
266 answer.zero();
267 answer.assemble( temp, this->giveOrderingNodes() );
268}
269
271Shell7BaseXFEM :: computeInterfaceJumpAt(int interf, const FloatArrayF<3> &lCoords, TimeStep *tStep)
272{
273 auto plus = lCoords;
274 plus.at(3) += 1.0e-9; // bottom position for plus side + num. perturbation
275 auto gplus = this->vtkEvalUpdatedGlobalCoordinateAt(plus, interf + 1, tStep); // position vector at + side
276
277 auto minus = lCoords;
278 minus.at(3) -= 2.0e-9; // top position for minus side - num. perturbation
279 auto gminus = this->vtkEvalUpdatedGlobalCoordinateAt(minus, interf, tStep); // position vector at - side
280
281 return gplus - gminus; // jump = x(+) - x(-)
282}
283
284int
285Shell7BaseXFEM :: giveNumberOfDofs()
286{
287 // Continuous part
288 int nDofs = Shell7Base :: giveNumberOfDofs();
289
290 // Discontinuous part
291 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
292 DofManager *dMan = this->giveDofManager(i);
293 for ( int j = 1; j <= this->xMan->giveNumberOfEnrichmentItems(); j++ ) {
294 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(j);
295 if ( ei->isDofManEnriched(*dMan) ) {
296 IntArray eiDofIdArray;
297 ei->giveEIDofIdArray(eiDofIdArray);
298 nDofs += eiDofIdArray.giveSize();
299 }
300 }
301 }
302 return nDofs;
303}
304
305
306void
307Shell7BaseXFEM :: edgeGiveUpdatedSolutionVector(FloatArray &answer, const int iedge, TimeStep *tStep)
308{
309 Shell7Base :: edgeGiveUpdatedSolutionVector(answer, iedge, tStep);
310 answer.times(DISC_DOF_SCALE_FAC);
311}
312
313
314void
315Shell7BaseXFEM :: computeOrderingArray( IntArray &orderingArray, IntArray &activeDofsArray, EnrichmentItem *ei)
316{
317 // Routine to extract vector given an array of dofid items
318 // If a certain dofId does not exist a zero is used as value
319
320 const IntArray &ordering_cont = this->giveOrderingDofTypes();
321 IntArray fieldDofId;
322 Shell7Base :: giveDofManDofIDMask(0, fieldDofId);
323
324
325 IntArray ordering_temp, activeDofsArrayTemp;
326 ordering_temp.resize(ordering_cont.giveSize());
327 activeDofsArrayTemp.resize(ordering_cont.giveSize());
328
329
330 int activeDofPos = 0, activeDofIndex = 0, orderingDofIndex = 0;
331
332 IntArray dofManDofIdMask, dofManDofIdMaskAll;
333 for ( int i = 1; i <= numberOfDofMans; i++ ) {
334 DofManager *dMan = this->giveDofManager(i);
335
336 if ( ei == nullptr ) { // return mask corresponding to the regular id's
337 Shell7Base :: giveDofManDofIDMask(i, dofManDofIdMask);
338 } else {
339 if ( ei->isDofManEnriched(*dMan) ) {
340 ei->giveEIDofIdArray(dofManDofIdMask);
341 }
342 }
343
344 for (int j = 1; j <= dofManDofIdMask.giveSize(); j++ ) {
345 int pos = dMan->findDofWithDofId( ( DofIDItem ) dofManDofIdMask.at(j) ) - dMan->begin() + 1;
346 activeDofPos++;
347 ordering_temp .at(activeDofPos) = orderingDofIndex + pos;
348 activeDofsArrayTemp.at(activeDofPos) = activeDofIndex + j;
349 }
350 this->giveDofManDofIDMask(i, dofManDofIdMaskAll);
351 orderingDofIndex += dofManDofIdMaskAll.giveSize();
352 activeDofIndex += fieldDofId.giveSize();
353
354 dofManDofIdMask.clear();
355 }
356
357 // Reduce arrays to actual size
358 int numActiveDofs = activeDofPos;
359 orderingArray.resize(numActiveDofs), activeDofsArray.resize(numActiveDofs);
360
361 for ( int i = 1; i <= numActiveDofs; i++ ) {
362 orderingArray.at(i) = ordering_temp.at(i);
363 activeDofsArray.at(i) = activeDofsArrayTemp.at(i);
364 }
365}
366
367
368void
369Shell7BaseXFEM :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord)
370{
371 // Computes internal forces as the array of: [f_c, f_d1, ..., f_dn]
372 answer.resize( this->giveNumberOfDofs() );
373 answer.zero();
374 FloatArray solVec, temp;
375
376 // Continuous part
377 this->giveUpdatedSolutionVector(solVec, tStep);
378 this->computeSectionalForces(temp, tStep, solVec, useUpdatedGpRecord);
379
380 IntArray activeDofs, ordering;
381 this->computeOrderingArray(ordering, activeDofs, NULL);
382 answer.assemble(temp, ordering);
383
384 // Disccontinuous part
385 IntArray eiDofIdArray;
386 FloatArray solVecD, tempRed, fCZ;
387 for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) {
388
389 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i);
390 if ( ei->isElementEnriched(this) ) {
391
392 ei->giveEIDofIdArray(eiDofIdArray);
393 this->computeDiscSolutionVector(eiDofIdArray, tStep, solVecD);
394
395 this->discComputeSectionalForces(temp, tStep, solVec, solVecD, ei);
396
397 tempRed.beSubArrayOf(temp, this->activeDofsArrays[i-1]);
398 answer.assemble(tempRed, this->orderingArrays[i-1]);
399
400 // Cohesive zone model
401 if ( this->hasCohesiveZone(i) ) {
402 // If there are only delaminations present the we only have one contribution per ei.
403 // If there are intralmainar cracks then we get several potential extra terms.
404 // Therefore we must go through them all and check.
405
406 for ( int j = 1; j <= this->xMan->giveNumberOfEnrichmentItems(); j++ ) {
407 if ( this->xMan->giveEnrichmentItem(j)->isElementEnriched(this) ) {
408 this->computeCohesiveForces( fCZ, tStep, solVec, solVecD, ei, this->xMan->giveEnrichmentItem(j));
409
410 tempRed.beSubArrayOf(fCZ, this->activeDofsArrays[j-1]);
411 answer.assemble(tempRed, this->orderingArrays[j-1]);
412 }
413 }
414 }
415 }
416 }
417}
418
419
420void
421Shell7BaseXFEM :: discComputeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, FloatArray &solVecD, EnrichmentItem *ei)
422//
423{
424 int ndofs = Shell7Base :: giveNumberOfDofs();
425 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
426 FloatArray f(ndofs), genEps, ftemp, lCoords, Nd;
427 FloatMatrix B, BEnr;
428 f.zero();
429
430 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
431 Material *mat = domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) );
432
433 for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) {
434 lCoords = gp->giveNaturalCoordinates();
435
436 this->computeEnrichedBmatrixAt(lCoords, B, NULL);
437 this->computeEnrichedBmatrixAt(lCoords, BEnr, ei);
438 genEps.beProductOf(B, solVec);
439 double zeta = giveGlobalZcoord(lCoords);
440 Nd = this->computeSectionalForcesAt(gp, mat, tStep, genEps, zeta);
441
442 // Computation of nodal forces: f = B^t*[N M T Ms Ts]^t
443 ftemp.beTProductOf( BEnr, Nd );
444 double dV = this->computeVolumeAroundLayer(gp, layer);
445 f.add( dV, ftemp );
446 }
447 }
448
449 answer.resize(ndofs); answer.zero();
450 answer.assemble(f, this->giveOrderingDofTypes());
451
452}
453
454
456Shell7BaseXFEM :: computeSectionalForcesAt(IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta)
457{
458 // New, in terms of PK1 stress
459 // f = \Lambda_i * P * G^I
460 auto P = this->computeStressMatrix(genEps, ip, mat, tStep);
461
462 const auto &lCoords = ip->giveNaturalCoordinates();
463 auto Gcon = this->evalInitialContravarBaseVectorsAt(lCoords);
464 auto PG = dot(P, Gcon);
465 auto PG1 = PG.column(0);
466 auto PG2 = PG.column(1);
467 auto PG3 = PG.column(2);
468
469 auto lambda = this->computeLambdaGMatricesDis(zeta); // associated with the variation of the test functions
470
471 // f = lambda_1^T * P*G^1 + lambda_2^T * P*G^2 + lambda_3^T * P*G^3
472 FloatArray sectionalForces;
473 sectionalForces.plusProduct(lambda[0], PG1, 1.0);
474 sectionalForces.plusProduct(lambda[1], PG2, 1.0);
475 sectionalForces.plusProduct(lambda[2], PG3, 1.0);
476 return sectionalForces;
477}
478
479
480double
481Shell7BaseXFEM :: evaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei)
482{
483 // Evaluates the corresponding level set depending on the type of enrichment
484 double levelSet = 0.0;
485 if ( dynamic_cast< Delamination * >( ei ) ) {
486 levelSet = lCoords.at(3) - dynamic_cast< Delamination * >( ei )->giveDelamXiCoord();
487 } else if ( dynamic_cast< Crack * >( ei ) ) {
488
489 Crack *crack = dynamic_cast< Crack * >( ei );
491 const IntArray &elNodes = this->giveDofManArray();
492 this->fei->evalN( N, lCoords, FEIElementGeometryWrapper(this) );
493 crack->interpLevelSet(levelSet, N, elNodes);
494 } else {
495 OOFEM_ERROR("error in evaluation of levelset");
496 }
497 return levelSet;
498}
499
500#if 0
501double
502Shell7BaseXFEM :: edgeEvaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei, const int edge)
503{
504 // Evaluates the corresponding level set depending on the type of enrichment
505 double levelSet = 0.0;
506 if ( dynamic_cast< Delamination * >( ei ) ) {
507 double xiLoad = 0.0;
508 levelSet = xiLoad - dynamic_cast< Delamination * >( ei )->giveDelamXiCoord();
509 } else if ( dynamic_cast< Crack * >( ei ) ) {
510 Crack *crack = dynamic_cast< Crack * >( ei );
511
512 FloatArray N;
513 //const IntArray &elNodes = this->giveDofManArray();
514 //const IntArray &elNodes = this->giveInterpolation()->givee
515
516 IntArray edgeNodes, globalNums;
517 static_cast< FEInterpolation3d* >(this->giveInterpolation())->computeLocalEdgeMapping(edgeNodes, edge);
518 globalNums.resize(edgeNodes.giveSize());
519 for ( int i = 1; i <= edgeNodes.giveSize(); i++ ) {
520 globalNums.at(i) = this->giveNode(edgeNodes.at(i))->giveGlobalNumber();
521 }
522 this->fei->edgeEvalN( N, edge, lCoords, FEIElementGeometryWrapper(this) );
523 crack->interpLevelSet(levelSet, N, globalNums);
524 } else {
525 OOFEM_ERROR("error in evaluation of levelset");
526 }
527 return levelSet;
528}
529#endif
530
531
532
533double
534Shell7BaseXFEM :: evaluateHeavisideXi(double xi, ShellCrack *ei)
535{
536 // Evaluates the "cut" Heaviside for a ShellCrack
537 double xiBottom = ei->xiBottom;
538 double xiTop = ei->xiTop;
539
540 return this->evaluateCutHeaviside(xi, xiBottom, xiTop);
541}
542
543double
544Shell7BaseXFEM :: evaluateHeavisideXi(double xi, Delamination *ei)
545{
546 // Evaluates the "cut" Heaviside for a Delamination
547 double xiBottom = ei->giveDelamXiCoord();
548 double xiTop = ei->giveBoundingDelamXiCoord();
549
550 return this->evaluateCutHeaviside(xi, xiBottom, xiTop);
551}
552
553double
554Shell7BaseXFEM :: evaluateCutHeaviside(const double xi, const double xiBottom, const double xiTop) const
555{
556 // Evaluates the "cut" Heaviside defined as:
557 // H(xi - xi1) - H(xi - xi2) or?
558 // H(xi - xi1) * ( 1 - H(xi - xi2) )
559
560 if ( ( xiBottom <= xi ) && ( xi <= xiTop ) ) {
561 return 1.0;
562 } else {
563 return 0.0;
564 }
565
566}
567
568void
569Shell7BaseXFEM :: giveMaxCZDamages(FloatArray &answer, TimeStep *tStep)
570{
571 // for each interface get maximum interface damage of all the ip's
572 int numZones = this->layeredCS->giveNumberOfLayers() - 1;
573 answer.resize(numZones);
575 FloatArray ipValues;
576 for ( int i = 0; i < numZones; i++ ) {
577 if ( hasCohesiveZone(i+1) ) {
578 double max = 0.0;
579 for ( GaussPoint *gp: *czIntegrationRulesArray [ i ] ) {
580
581 mat = static_cast < StructuralInterfaceMaterial * > (this->layeredCS->giveInterfaceMaterial(i+1) );
582 mat->giveIPValue(ipValues, gp, IST_DamageScalar, tStep);
583
584 double val = ipValues.at(1);
585 if ( val > max ) {
586 max = val;
587 }
588
589 }
590 answer(i) = max;
591 } else {
592 answer(i) = 0.0;
593 }
594 }
595}
596
597
598void
599Shell7BaseXFEM :: computeCohesiveForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVecC, FloatArray &solVecD, EnrichmentItem *ei, EnrichmentItem *coupledToEi)
600{
601 //Computes the cohesive nodal forces for a given delamination interface
602
603 Delamination *dei = dynamic_cast< Delamination * >( ei );
604 if ( dei ) { // For now only add cz for delaminations
605 FloatArray answerTemp, lCoords(3);
606 answerTemp.resize(Shell7Base :: giveNumberOfDofs() );
607 answerTemp.zero();
608
609 FloatMatrix B, Ncoh, NEnr, BEnr, F;
610 int delamNum = dei->giveDelamInterfaceNum();
611
613 (this->layeredCS->giveInterfaceMaterial(delamNum) );
614
615 FloatMatrix lambdaD, lambdaN, Q;
616 FloatArray Fcoh, T, nCov, jump, unknowns, genEpsC, genEpsD;
617
618 for ( auto &gp: *czIntegrationRulesArray [ delamNum - 1 ] ) {
619 double xi = dei->giveDelamXiCoord();
620 lCoords.at(1) = gp->giveNaturalCoordinate(1);
621 lCoords.at(2) = gp->giveNaturalCoordinate(2);
622 lCoords.at(3) = xi;
623
624 this->computeBmatrixAt(lCoords, B);
625 this->computeCohesiveNmatrixAt(lCoords, Ncoh, coupledToEi);
626
627 // Compute jump vector
628 jump = this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep); // -> numerical tol. issue -> normal jump = 1e-10
629
630 genEpsC.beProductOf(B, solVecC);
631 F = this->computeFAt(lCoords, genEpsC, tStep);
632
633 // Transform xd and F to a local coord system
634 nCov = this->evalInitialCovarNormalAt(lCoords);
635 Q.beLocalCoordSys(nCov);
636 jump.rotatedWith(Q,'n');
637 F.rotatedWith(Q,'n');
638
639 // Compute cohesive traction based on jump
640 T = intMat->giveFirstPKTraction_3d(jump, F, gp, tStep);
641
642 //zzjump.printYourself("spatial jump");
643 //T.printYourself("Traction");
644 T.rotatedWith(Q,'t'); // transform back to global coord system
645
646 double zeta = xi * this->layeredCS->computeIntegralThick() * 0.5;
647 lambdaD = this->computeLambdaNMatrixDis(zeta);
648 lambdaN.beProductOf(lambdaD, Ncoh);
649 Fcoh.beTProductOf(lambdaN, T);
650 double dA = this->computeAreaAround(gp,xi);
651 answerTemp.add(dA, Fcoh);
652 }
653
654 int ndofs = Shell7Base :: giveNumberOfDofs();
655 answer.resize(ndofs); answer.zero();
656 const IntArray &ordering = this->giveOrderingDofTypes();
657 answer.assemble(answerTemp, ordering);
658 }
659}
660
661
662void
663Shell7BaseXFEM :: updateYourself(TimeStep *tStep)
664{
665 Shell7Base :: updateYourself(tStep);
666
667 for ( int i = 0; i < this->layeredCS->giveNumberOfLayers() - 1; i++ ) {
668 if ( this->hasCohesiveZone(i+1) ) {
669 czIntegrationRulesArray [ i ]->updateYourself(tStep);
670 }
671 }
672}
673
674
675void
676Shell7BaseXFEM :: computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep)
677{
678 //Computes the cohesive tangent forces for a given interface
679
680 /* This tangent should be added for each delamination interface k
681 *
682 * Kcoh_k = [0 0 0 ... 0 0 ... 0
683 * 0 K_kk 0 ... 0 K_kc1 ... K_kcn
684 * 0 .
685 * 0 K_c1k 0 ... 0 K_c1c1 ... K_c1cn
686 * 0
687 * 0 K_cnk 0 ... 0 K_cnc1 ... K_cncn ]
688 *
689 */
690 FloatMatrix temp;
691 int ndofs = this->giveNumberOfDofs();
692 answer.resize(ndofs, ndofs);
693 answer.zero();
694
695 FloatMatrix tempRed, tempRedT;
696 for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) {
697
698 // dei is the current delamination where the material tangent d(trac)/d(jump) is evaluated
699 Delamination *dei = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(i) );
700 if ( dei && dei->isElementEnriched(this) && this->hasCohesiveZone(i) ) {
701
702 for ( int j = 1; j <= this->xMan->giveNumberOfEnrichmentItems(); j++ ) {
703 for ( int k = j; k <= this->xMan->giveNumberOfEnrichmentItems(); k++ ) { // upper triangular part
704 // Coupling enrichments
705 //EnrichmentItem *ei_j = this->xMan->giveEnrichmentItem(j);
706 Delamination *dei_j = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(j) );
707 //EnrichmentItem *ei_k = this->xMan->giveEnrichmentItem(k);
708 Delamination *dei_k = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(k) );
709 if ( dei_j && dei_j->isElementEnriched(this) && dei_k && dei_k->isElementEnriched(this) ) {
710
711 this->computeCohesiveTangentAt(temp, tStep, dei, dei_j, dei_k);
712
713 // Assemble part correpsonding to active dofs
714 tempRed.beSubMatrixOf(temp, this->activeDofsArrays[dei_j->giveNumber()-1], this->activeDofsArrays[dei_k->giveNumber()-1]);
715 answer.assemble(tempRed, this->orderingArrays[dei_j->giveNumber()-1], this->orderingArrays[dei_k->giveNumber()-1]);
716
717 if( j != k ) { // add off diagonal contributions
718 tempRedT.beTranspositionOf(tempRed);
719 answer.assemble(tempRedT, this->orderingArrays[dei_k->giveNumber()-1], this->orderingArrays[dei_j->giveNumber()-1]);
720 }
721 }
722 }
723 }
724 }
725 }
726}
727
728
729
730void
731Shell7BaseXFEM :: computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep, Delamination *dei, EnrichmentItem *ei_j, EnrichmentItem *ei_k)
732{
733 /* Computes the cohesive tangent contribution (block matrix) for a given interface given two
734 * enrichment items (j,k) it (potentially) couples to.
735 * K_cz = Ncoh_j^t*lambda*t * dT/dj * lambda * Ncoh_k
736 *
737 */
738 FloatMatrix answerTemp, Ncoh_j, Ncoh_k, temp, tangent;
739 int nDofs = Shell7Base :: giveNumberOfDofs();
740 answerTemp.resize(nDofs, nDofs);
741 answerTemp.zero();
742
743 int delamNum = dei->giveDelamInterfaceNum();
744 std :: unique_ptr< IntegrationRule > &iRuleL = czIntegrationRulesArray [ dei->giveDelamInterfaceNum() - 1 ];
746 (this->layeredCS->giveInterfaceMaterial(delamNum) );
747
748 double xi = dei->giveDelamXiCoord();
749
750 for ( auto &gp: *iRuleL ) {
751 FloatArrayF<3> lCoords = { gp->giveNaturalCoordinate(1), gp->giveNaturalCoordinate(2), xi};
752
753 auto D = intMat->give3dStiffnessMatrix_dTdj(TangentStiffness, gp, tStep);
754
755 //IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( intMat->giveStatus(gp) );
756 //double damage = status->giveTempDamage();
757 //if ( damage >= 1 ) { printf("Full damage in elt %i \n",damage,this->giveNumber()); }
758
759 auto nCov = this->evalInitialCovarNormalAt(lCoords);
760 auto Q = local_cs(nCov);
761 D = unrotate(D, Q); // rotate back to global coord system
762
763 double zeta = giveGlobalZcoord( lCoords);
764 auto lambda = this->computeLambdaNMatrixDis(zeta);
765 this->computeCohesiveNmatrixAt(lCoords, Ncoh_j, ei_j);
766 this->computeCohesiveNmatrixAt(lCoords, Ncoh_k, ei_k);
767
769 this->computeTripleProduct(temp, lambda, D, lambda);
770 this->computeTripleProduct(tangent, Ncoh_j, temp, Ncoh_k);
771 double dA = this->computeAreaAround(gp, xi);
772 answerTemp.add(dA,tangent);
773 }
774
775 answer.resize(nDofs, nDofs);
776 answer.zero();
777 const IntArray &ordering = this->giveOrderingDofTypes();
778 answer.assemble(answerTemp, ordering, ordering);
779}
780
781
782void
783Shell7BaseXFEM :: computeCohesiveNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei)
784{
785 /* Returns the N-matrix associated with the variation of the jump over a delamination interface.
786 * Evaluate \delta jump -> jump = phi(+)-phi(-) = N(+)*a - N(-)*a = [N(+)-N(-)]*a = Ncoh*a
787 * where a is the solution vector for a given dicontinuity (ei)
788 * This should be correct for delaminations (only) as well N(-)=0
789 */
790 FloatMatrix N_minus_side;
791 FloatArray perturbedCoords = lCoords;
792 perturbedCoords.at(3) = lCoords.at(3) + 1.0e-9; // make sure we are on the plus side
793 this->computeEnrichedNmatrixAt(perturbedCoords, answer, ei);
794
795 perturbedCoords.at(3) = lCoords.at(3) - 1.0e-9; // make sure we are on the minus side
796 this->computeEnrichedNmatrixAt(perturbedCoords, N_minus_side, ei);
797 answer.subtract(N_minus_side);
798
799}
800
801
802void
803Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
804{
805 this->OLDcomputeStiffnessMatrix(answer, rMode, tStep);
806 return;
807#if 0
808 int ndofs = this->giveNumberOfDofs();
809 answer.resize(ndofs, ndofs);
810 answer.zero();
811
812 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
813 FloatMatrix tempRed, tempRedT;
814 FloatMatrix KCC, KDC, KDD;
815 FloatMatrix LCC, LDD, LDC;
816 FloatMatrix B, BenrM, BenrK;
817
818 IntArray orderingC, activeDofsC;
819 this->computeOrderingArray(orderingC, activeDofsC, NULL);
820 FloatArray solVec;
821 this->giveUpdatedSolutionVector(solVec, tStep);
822
823 FloatMatrix A [ 3 ] [ 3 ], LB, KOrdered;
824 KOrdered.resize(ndofs,ndofs);
825
826 const IntArray &ordering = this->giveOrderingDofTypes();
827
828 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
829 StructuralMaterial *layerMaterial = static_cast< StructuralMaterial* >( domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ) );
830
831 for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) {
832 const FloatArray &lCoords = gp->giveNaturalCoordinates();
833 Shell7Base :: computeBmatrixAt(lCoords,B);
834 double dV = this->computeVolumeAroundLayer(gp, layer);
835
836 Shell7Base :: computeLinearizedStiffness(gp, layerMaterial, tStep, A); // called L in new formulation
837 this->discComputeStiffness(LCC, LDD, LDC, gp, layer, A, tStep); // called D in new formulation
838
839 LB.beProductOf(LCC, B);
840 KCC.clear();
841 KCC.plusProductSymmUpper(B, LB, dV);
842 KCC.symmetrized();
843 KOrdered.zero();
844 KOrdered.assemble(KCC, ordering, ordering); // from dof group to node ordering
845 tempRed.beSubMatrixOf(KOrdered, activeDofsC, activeDofsC);
846 answer.assemble(tempRed, orderingC, orderingC); // position in element stiffness matrix
847
848 // Discontinuous part
849 int numEI = this->xMan->giveNumberOfEnrichmentItems();
850 for ( int m = 1; m <= numEI; m++ ) {
851 EnrichmentItem *eiM = this->xMan->giveEnrichmentItem(m);
852 this->computeEnrichedBmatrixAt(lCoords, BenrM, eiM);
853
854 if ( eiM->isElementEnriched(this) ) {
855 LB.beProductOf(LDC, B);
856 KDC.clear();
857 KDC.plusProductUnsym(BenrM, LB, dV);
858 KOrdered.zero();
859 KOrdered.assemble(KDC, ordering, ordering);
860
861 tempRed.beSubMatrixOf(KOrdered, this->activeDofsArrays[m-1], activeDofsC);
862 tempRedT.beTranspositionOf(tempRed);
863 answer.assemble(tempRed, this->orderingArrays[m-1], orderingC);
864 answer.assemble(tempRedT, orderingC, this->orderingArrays[m-1]);
865
866 // K_{dk,dl}
867 for ( int k = 1; k <= numEI; k++ ) {
868 EnrichmentItem *eiK = this->xMan->giveEnrichmentItem(k);
869 this->computeEnrichedBmatrixAt(lCoords, BenrK, eiK);
870
871 if ( eiK->isElementEnriched(this) ) {
872 if ( this->activeDofsArrays[m-1].giveSize() != 0 && this->activeDofsArrays[k-1].giveSize() != 0 ) {
873 LB.beProductOf(LDD, BenrK);
874 KDD.clear();
875 KDD.plusProductSymmUpper(BenrM, LB, dV);
876 KDD.symmetrized();
877 KOrdered.zero();
878 KOrdered.assemble(KDD, ordering, ordering);
879 tempRed.beSubMatrixOf(KOrdered, this->activeDofsArrays[m-1], this->activeDofsArrays[k-1]);
880 answer.assemble(tempRed, this->orderingArrays[m-1], this->orderingArrays[k-1]);
881 }
882 }
883 }
884 }
885 }
886 }
887 }
888
889
890 // Cohesive zones
891#if 1
892 FloatMatrix Kcoh;
893 this->computeCohesiveTangent(Kcoh, tStep);
894 //Kcoh.times(DISC_DOF_SCALE_FAC*DISC_DOF_SCALE_FAC);
895 answer.add(Kcoh);
896
897#endif
898
899
900 // Add contribution due to pressure load
901#if 0
902
903 int nLoads = this->boundaryLoadArray.giveSize() / 2;
904
905 for ( int k = 1; k <= nLoads; k++ ) { // For each pressure load that is applied
906 int load_number = this->boundaryLoadArray.at(2 * k - 1);
907 int iSurf = this->boundaryLoadArray.at(2 * k); // load_id
908 Load *load = this->domain->giveLoad(load_number);
909 std :: vector< double > efM, efK;
910
911 if ( ConstantPressureLoad * pLoad = dynamic_cast< ConstantPressureLoad * >(load) ) {
912
913 IntegrationRule *iRule = specialIntegrationRulesArray [ 1 ];
914
915 for ( auto &gp: *iRule ) {
916 this->computePressureTangentMatrixDis(KCC, KCD, KDD, gp, load, iSurf, tStep);
917 KCD.times(DISC_DOF_SCALE_FAC);
919
920 // Continuous part
921 answer.assemble(KCC, orderingC, orderingC);
922
923 // Discontinuous part
924 int numEI = this->xMan->giveNumberOfEnrichmentItems();
925 for ( int m = 1; m <= numEI; m++ ) {
926 Delamination *deiM = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(m) );
927
928 if ( deiM !=NULL && deiM->isElementEnriched(this) ) {
929 double levelSetM = pLoad->giveLoadOffset() - deiM->giveDelamXiCoord();
930 deiM->evaluateEnrFuncAt(efM, lCoords, levelSetM);
931
932 IntArray &orderingJ = orderingArrays[m-1];
933 IntArray &activeDofsJ = activeDofsArrays[m-1];
934
935 // con-dis & dis-con
936 if ( efM[0] > 0.1 ) {
937 tempRed.beSubMatrixOf(KCD, activeDofsC, activeDofsJ);
938 answer.assemble(tempRed, orderingC, orderingJ);
939 tempRedT.beTranspositionOf(tempRed);
940 answer.assemble(tempRedT, orderingJ, orderingC);
941 }
942
943 // dis-dis
944 for ( int k = 1; k <= numEI; k++ ) {
945 Delamination *deiK = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(k) );
946 if ( deiK != NULL && deiK->isElementEnriched(this) ) {
947 double levelSetK = pLoad->giveLoadOffset() - deiK->giveDelamXiCoord();
948 deiK->evaluateEnrFuncAt(efK, lCoords, levelSetK);
949 if ( efM[0] > 0.1 && efK[0] > 0.1 ) {
950 IntArray &orderingK = orderingArrays[k-1];
951 IntArray &activeDofsK = activeDofsArrays[k-1];
952 tempRed.beSubMatrixOf(KDD, activeDofsJ, activeDofsK);
953 answer.assemble(tempRed, orderingJ, orderingK);
954 }
955 }
956 }
957 }
958 }
959 }
960 }
961 }
962#endif
963#endif
964}
965
966
967void
968Shell7BaseXFEM :: discComputeStiffness(FloatMatrix &LCC, FloatMatrix &LDD, FloatMatrix &LDC, IntegrationPoint *ip, int layer, FloatMatrix A [ 3 ] [ 3 ], TimeStep *tStep)
969{
970 // Should compute lambda_i * A_ij * lamda_j for the different combinations of lambda
971 // L_CC = lambdaC_i^T * A_ij * lambdaC_j
972 // L_DD = lambdaD_i^T * A_ij * lambdaD_j
973 // L_CD = lambdaC_i^T * A_ij * lambdaD_j
974 FloatMatrix B;
975
976 const auto &lCoords = ip->giveNaturalCoordinates();
977 FloatArray solVecC, genEpsC;
978 Shell7Base :: computeBmatrixAt(lCoords,B);
979
980 double zeta = giveGlobalZcoord( lCoords );
981 this->giveUpdatedSolutionVector(solVecC, tStep);
982 genEpsC.beProductOf(B,solVecC);
983 auto lambdaC = this->computeLambdaGMatrices(genEpsC, zeta);
984 auto lambdaD = this->computeLambdaGMatricesDis(zeta);
985
986 FloatMatrix A_lambdaC(3,18), A_lambdaD(3,18);
987 LCC.clear(); LDD.clear(); LDC.clear();
988
989 for (int i = 0; i < 3; i++) {
990 A_lambdaC.zero(); A_lambdaD.zero();
991 for (int j = 0; j < 3; j++) {
992 A_lambdaC.addProductOf(A[i][j], lambdaC[j]);
993 A_lambdaD.addProductOf(A[i][j], lambdaD[j]);
994 }
995 LCC.plusProductSymmUpper(lambdaC[i], A_lambdaC, 1.0);
996 LDD.plusProductSymmUpper(lambdaD[i], A_lambdaD, 1.0);
997 LDC.plusProductUnsym(lambdaD[i], A_lambdaC, 1.0);
998 }
999 LCC.symmetrized();
1000 LDD.symmetrized();
1001}
1002
1003
1004//remove
1005void
1006Shell7BaseXFEM :: OLDcomputeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
1007{
1008 // This is an old unoptimized version.
1009 // The new one doesn't work with all the coupling terms for shellcracks and delaminations.
1010 int ndofs = this->giveNumberOfDofs();
1011 answer.resize(ndofs, ndofs);
1012 answer.zero();
1013
1014 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
1015 FloatMatrix tempRed, tempRedT;
1016 FloatMatrix KCC, KCD, KDD, Bc;
1017 IntArray orderingC, activeDofsC;
1018 this->computeOrderingArray(orderingC, activeDofsC, NULL);
1019 FloatArray solVec;
1020 this->giveUpdatedSolutionVector(solVec, tStep);
1021
1022 FloatMatrix A [ 3 ] [ 3 ];
1023
1024 Shell7Base :: computeBulkTangentMatrix(KCC, solVec, tStep );
1025
1026 answer.assemble(KCC, orderingC, orderingC);
1027
1028
1029 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
1030 StructuralMaterial *layerMaterial = static_cast< StructuralMaterial* >( domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ) );
1031
1032 for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) {
1033 const FloatArray &lCoords = gp->giveNaturalCoordinates();
1034 this->computeEnrichedBmatrixAt(lCoords, Bc, NULL);
1035
1036 Shell7Base :: computeLinearizedStiffness(gp, layerMaterial, tStep, A);
1037
1038 // Continuous part K_{c,c}
1039 //this->discComputeBulkTangentMatrix(KCC, gp, NULL, NULL, layer, A, tStep);
1040 //answer.assemble(KCC, orderingC, orderingC);
1041
1042 // Discontinuous part
1043 int numEI = this->xMan->giveNumberOfEnrichmentItems();
1044 for ( int m = 1; m <= numEI; m++ ) {
1045 EnrichmentItem *eiM = this->xMan->giveEnrichmentItem(m);
1046
1047 if ( eiM->isElementEnriched(this) ) {
1048
1049 this->discComputeBulkTangentMatrix(KCD, gp, NULL, eiM, layer, A, tStep);
1050 tempRed.beSubMatrixOf(KCD, activeDofsC, this->activeDofsArrays[m-1]);
1051 answer.assemble(tempRed, orderingC, this->orderingArrays[m-1]);
1052
1053 tempRedT.beTranspositionOf(tempRed);
1054 answer.assemble(tempRedT, this->orderingArrays[m-1], orderingC);
1055
1056 // K_{dk,dl}
1057 for ( int k = 1; k <= numEI; k++ ) {
1058 EnrichmentItem *eiK = this->xMan->giveEnrichmentItem(k);
1059
1060 if ( eiK->isElementEnriched(this) ) {
1061 this->discComputeBulkTangentMatrix(KDD, gp, eiM, eiK, layer, A, tStep);
1062 if ( this->activeDofsArrays[m-1].giveSize() != 0 && this->activeDofsArrays[k-1].giveSize() != 0 ) {
1063 tempRed.beSubMatrixOf(KDD, this->activeDofsArrays[m-1], this->activeDofsArrays[k-1]);
1064 answer.assemble(tempRed, this->orderingArrays[m-1], this->orderingArrays[k-1]);
1065 }
1066
1067 }
1068
1069 }
1070 }
1071 }
1072
1073 }
1074 }
1075
1076// Cohesive zones
1077#if 1
1078FloatMatrix Kcoh;
1079this->computeCohesiveTangent(Kcoh, tStep);
1080//Kcoh.times(DISC_DOF_SCALE_FAC*DISC_DOF_SCALE_FAC);
1081answer.add(Kcoh);
1082
1083#endif
1084
1085
1086// Add contribution due to pressure load
1087#if 0
1088
1089int nLoads = this->boundaryLoadArray.giveSize() / 2;
1090
1091for ( int k = 1; k <= nLoads; k++ ) { // For each pressure load that is applied
1092 int load_number = this->boundaryLoadArray.at(2 * k - 1);
1093 int iSurf = this->boundaryLoadArray.at(2 * k); // load_id
1094 Load *load = this->domain->giveLoad(load_number);
1095 std :: vector< double > efM, efK;
1096
1097 if ( ConstantPressureLoad * pLoad = dynamic_cast< ConstantPressureLoad * >(load) ) {
1098
1099 IntegrationRule *iRule = specialIntegrationRulesArray [ 1 ];
1100
1101 for ( auto &gp: *iRule ) {
1102 this->computePressureTangentMatrixDis(KCC, KCD, KDD, gp, load, iSurf, tStep);
1105
1106 // Continuous part
1107 answer.assemble(KCC, orderingC, orderingC);
1108
1109 // Discontinuous part
1110 int numEI = this->xMan->giveNumberOfEnrichmentItems();
1111 for ( int m = 1; m <= numEI; m++ ) {
1112 Delamination *deiM = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(m) );
1113
1114 if ( deiM !=NULL && deiM->isElementEnriched(this) ) {
1115 double levelSetM = pLoad->giveLoadOffset() - deiM->giveDelamXiCoord();
1116 deiM->evaluateEnrFuncAt(efM, lCoords, levelSetM);
1117
1118 IntArray &orderingJ = orderingArrays[m-1];
1119 IntArray &activeDofsJ = activeDofsArrays[m-1];
1120
1121 // con-dis & dis-con
1122 if ( efM[0] > 0.1 ) {
1123 tempRed.beSubMatrixOf(KCD, activeDofsC, activeDofsJ);
1124 answer.assemble(tempRed, orderingC, orderingJ);
1125 tempRedT.beTranspositionOf(tempRed);
1126 answer.assemble(tempRedT, orderingJ, orderingC);
1127}
1128
1129// dis-dis
1130for ( int k = 1; k <= numEI; k++ ) {
1131 Delamination *deiK = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(k) );
1132 if ( deiK != NULL && deiK->isElementEnriched(this) ) {
1133 double levelSetK = pLoad->giveLoadOffset() - deiK->giveDelamXiCoord();
1134 deiK->evaluateEnrFuncAt(efK, lCoords, levelSetK);
1135 if ( efM[0] > 0.1 && efK[0] > 0.1 ) {
1136 IntArray &orderingK = orderingArrays[k-1];
1137 IntArray &activeDofsK = activeDofsArrays[k-1];
1138 tempRed.beSubMatrixOf(KDD, activeDofsJ, activeDofsK);
1139 answer.assemble(tempRed, orderingJ, orderingK);
1140}
1141}
1142
1143}
1144}
1145
1146}
1147
1148}
1149
1150}
1151}
1152#endif
1153
1154}
1155
1156//remove
1157void
1158Shell7BaseXFEM :: discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoint *ip, EnrichmentItem *ei1, EnrichmentItem *ei2, int layer, FloatMatrix A [ 3 ] [ 3 ], TimeStep *tStep)
1159{
1160
1161 FloatMatrix temp, B1, B2;
1162 std::array<FloatMatrixF<3,18>, 3> lambda1, lambda2;
1163
1164 const auto &lCoords = ip->giveNaturalCoordinates();
1165 this->computeEnrichedBmatrixAt(lCoords, B1, ei1);
1166 this->computeEnrichedBmatrixAt(lCoords, B2, ei2);
1167
1168 int eiNum1 = 0, eiNum2 = 0;
1169 double zeta = giveGlobalZcoord( lCoords );
1170 if ( ei1 ) {
1171 lambda1 = this->computeLambdaGMatricesDis(zeta);
1172 eiNum1 = ei1->giveNumber();
1173 } else {
1174 FloatArray solVecC, genEpsC;
1175 this->giveUpdatedSolutionVector(solVecC, tStep);
1176 genEpsC.beProductOf(B1,solVecC);
1177 lambda1 = this->computeLambdaGMatrices(genEpsC, zeta);
1178 }
1179 if ( ei2 ) {
1180 lambda2 = this->computeLambdaGMatricesDis(zeta);
1181 eiNum2 = ei2->giveNumber();
1182 } else {
1183 FloatArray solVecC, genEpsC;
1184 this->giveUpdatedSolutionVector(solVecC, tStep);
1185 genEpsC.beProductOf(B2,solVecC);
1186 lambda2 = this->computeLambdaGMatrices(genEpsC, zeta);
1187 }
1188
1189 double dV = this->computeVolumeAroundLayer(ip, layer);
1190
1191 int ndofs = Shell7Base :: giveNumberOfDofs();
1192 FloatMatrix KDDtemp(ndofs, ndofs);
1193 KDDtemp.zero();
1194 FloatMatrix L(18,18), A_lambda(3,18), LB;
1195 L.zero(); A_lambda.zero();
1196
1197 if ( eiNum1 == eiNum2 ) { // diagonal element
1198 //if (0 ) { // diagonal element
1199
1200 for (int i = 0; i < 3; i++) {
1201 A_lambda.zero();
1202 for (int j = 0; j < 3; j++) {
1203 A_lambda.addProductOf(A[i][j], lambda1[j]);
1204 }
1205 L.plusProductSymmUpper(lambda1[i], A_lambda, 1.0);
1206 //L.plusProductUnsym(lambda1[i], A_lambda, dV);
1207 }
1208 L.symmetrized();
1209 LB.beProductOf(L, B1);
1210 KDDtemp.plusProductSymmUpper(B1, LB, dV);
1211 KDDtemp.symmetrized();
1212 } else {
1213 for ( int j = 0; j < 3; j++ ) {
1214 for ( int k = 0; k < 3; k++ ) {
1215 this->computeTripleProduct(temp, lambda1 [ j ], A [ j ][ k ], lambda2 [ k ] );
1216 L.add(dV,temp);
1217 }
1218 }
1219 this->computeTripleProduct(KDDtemp, B1, L, B2 );
1220 }
1221
1222 KdIJ.resize(ndofs,ndofs);
1223 KdIJ.zero();
1224 const IntArray &ordering = this->giveOrderingDofTypes();
1225
1226 KdIJ.assemble(KDDtemp, ordering, ordering);
1227
1228}
1229
1230
1231std::array<FloatMatrixF<3,18>, 3>
1232Shell7BaseXFEM :: computeLambdaGMatricesDis(double zeta)
1233{
1234 // computes the lambda^g matrices associated with the variation and linearization
1235 // of the discontinuous base vectors gd_i.
1236
1237 // thickness coefficients
1238 double a = zeta ;
1239 double c = 1.0 ;
1240
1241 std::array<FloatMatrixF<3,18>, 3> lambda;
1242 // lambda1 = ( I, 0, a*I, 0 , 0, 0 , 0, 0 )
1243 lambda[ 0 ].at(1,1) = lambda[ 0 ].at(2,2) = lambda[ 0 ].at(3,3) = 1.;
1244 lambda[ 0 ].at(1,7) = lambda[ 0 ].at(2,8) = lambda[ 0 ].at(3,9) = a;
1245
1246 // lambda2 = ( 0, I, 0 , a*I, 0, 0 , 0, 0 )
1247 lambda[ 1 ].at(1,4) = lambda[ 1 ].at(2,5) = lambda[ 1 ].at(3,6) = 1.;
1248 lambda[ 1 ].at(1,10) = lambda[ 1 ].at(2,11) = lambda[ 1 ].at(3,12) = a;
1249
1250 // lambda3 = ( 0, 0, 0 , 0 , c*I , 0 , 0 , 0 )
1251 lambda[ 2 ].at(1,13) = lambda[ 2 ].at(2,14) = lambda[ 2 ].at(3,15) = c;
1252
1253 return lambda;
1254}
1255
1256
1258Shell7BaseXFEM :: computeLambdaNMatrixDis(double zeta)
1259{
1260 // computes the lambda_x matrix associated with the variation and linearization of the
1261 // discontinuous position vector x_di. (\delta x_{di} = lambda_{xd}*\delta n_x)
1262
1263 // lambda_x = ( I, a*I, 0 )
1264 FloatMatrixF<3,7> lambda_xd;
1265 lambda_xd.at(1,1) = lambda_xd.at(2,2) = lambda_xd.at(3,3) = 1.0;
1266 lambda_xd.at(1,4) = lambda_xd.at(2,5) = lambda_xd.at(3,6) = zeta;
1267 return lambda_xd;
1268}
1269
1270
1271void
1272Shell7BaseXFEM :: computePressureTangentMatrixDis(FloatMatrix &KCC, FloatMatrix &KCD, FloatMatrix &KDD, IntegrationPoint *ip, Load *load, const int iSurf, TimeStep *tStep)
1273{
1274 // Computes tangent matrix associated with the linearization of pressure loading. Assumes constant pressure.
1275 ConstantPressureLoad* pLoad = dynamic_cast< ConstantPressureLoad * >( load );
1276
1277 FloatMatrix N, B;
1278 FloatArray solVec, pressure;
1279 double xi = pLoad->giveLoadOffset();
1280 FloatArrayF<3> lCoords = ip->giveNaturalCoordinates();
1281 lCoords.at(3) = xi; // local coord where load is applied
1282 double zeta = this->giveGlobalZcoord( lCoords );
1283 this->giveUpdatedSolutionVector(solVec, tStep);
1284
1285 // compute w1,w2, KC
1286 this->computeNmatrixAt(lCoords, N);
1287 this->computeBmatrixAt(lCoords, B);
1288 FloatArray genEps;
1289 genEps.beProductOf(B, solVec);
1290
1291 //(xc+xd)*(g1xg2)=xc*g1xg2 + xd*g1xg2 -> xc*(W2*Dg1 - W1*Dg2) + xd*(W2*Dg1 - W1*Dg2)
1292 // Traction tangent, L = lambdaN * ( W2*lambdaG_1 - W1*lambdaG_2 )
1293 load->computeValueAt(pressure, tStep, ip->giveNaturalCoordinates(), VM_Total); // pressure component
1294 auto gcov = this->evalCovarBaseVectorsAt(lCoords, genEps, tStep);
1295 auto g1 = gcov.column(0);
1296 auto g2 = gcov.column(1);
1297 auto W1 = this->giveAxialMatrix(g1);
1298 auto W2 = this->giveAxialMatrix(g2);
1299
1300 auto lambdaGC = this->computeLambdaGMatrices(genEps, zeta);
1301 auto lambdaNC = this->computeLambdaNMatrix(genEps, zeta);
1302 auto lambdaGD = this->computeLambdaGMatricesDis(zeta);
1303 auto lambdaND = this->computeLambdaNMatrixDis(zeta);
1304
1305 auto W2L = dot(W2,lambdaGC[0]) - dot(W1,lambdaGC[1]);
1306 auto LCC =-pressure.at(1) * Tdot(lambdaNC, W2L);
1307
1308 W2L = dot(W2,lambdaGD[0]) - dot(W1,lambdaGD[1]);
1309 auto LCD = -pressure.at(1) * Tdot(lambdaNC, W2L);
1310
1311 W2L = dot(W2,lambdaGD[0]) - dot(W1,lambdaGD[1]);
1312 auto LDD = -pressure.at(1) * Tdot(lambdaND, W2L);
1313
1314 FloatMatrix KCCtemp, KCDtemp, KDDtemp;
1315 this->computeTripleProduct(KCCtemp, N, LCC, B );
1316 this->computeTripleProduct(KCDtemp, N, LCD, B );
1317 this->computeTripleProduct(KDDtemp, N, LDD, B );
1318
1319 int ndofs = Shell7Base :: giveNumberOfDofs();
1320 KCC.resize(ndofs,ndofs); KCD.resize(ndofs,ndofs); KDD.resize(ndofs,ndofs);
1321 KCC.zero(); KCD.zero(); KDD.zero();
1322 const IntArray &ordering = this->giveOrderingDofTypes();
1323 KCC.assemble(KCCtemp, ordering, ordering);
1324 KCD.assemble(KCDtemp, ordering, ordering);
1325 KDD.assemble(KDDtemp, ordering, ordering);
1326}
1327
1328void
1329Shell7BaseXFEM :: computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep)
1330{
1331 // Num refers in this case to numerical integration in both in-plane and through the thickness.
1332 // For analytically integrated throught he thickness, see computeMassMatrix
1334
1335#if 0
1336 FloatMatrix mass, temp;
1337 FloatArray solVec;
1338 this->giveUpdatedSolutionVector(solVec, tStep);
1339 int ndofs = this->giveNumberOfDofs();
1340
1341
1342 LayeredCrossSection *layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveCrossSection() );
1343 int numberOfLayers = layeredCS->giveNumberOfLayers(); // conversion of data
1344
1345 FloatMatrix M11(18, 18), M12(18, 18), M13(18, 6), M22(18, 18), M23(18, 6), M33(6, 6);
1346 M11.zero();
1347 M12.zero();
1348 M13.zero();
1349 M22.zero();
1350 M23.zero();
1351 M33.zero();
1352
1353 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
1354 IntegrationRule *iRuleL = integrationRulesArray [ layer - 1 ];
1355 Material *mat = domain->giveMaterial( layeredCS->giveLayerMaterial(layer) );
1356
1357 for ( GaussPoint *gp: *iRule ) {
1358
1359 FloatMatrix N11, N22, N33, N;
1360 //this->computeNmatricesAt(gp, N11, N22, N33);
1361 this->computeNmatrixAt(gp, N);
1362 FloatArray xbar, m;
1363 double gam = 0.;
1364 //this->computeSolutionFields(xbar, m, gam, solVec, N11, N22, N33);
1365 FloatArray localCoords = gp->giveNaturalCoordinates();
1366 this->giveUnknownsAt(localCoords, solVec, xbar, m, gam, tStep);
1367 //this->computeNmatrixAt(gp, N);
1368 //unknowns.beProductOf(N,a); // [xbar, m, gam]^T
1369 //m = {unknowns.at(4), unknowns.at(5), unknowns.at(6) };
1370 //double gam = unknowns.at(7);
1371
1372
1373 /* Consistent mass matrix M = int{N^t*mass*N}
1374 *
1375 * 3 3 1
1376 * 3 [a*I b*I c*m [A B C
1377 * mass = 3 d*I e*m = D E
1378 * 1 sym f*m.m] sym F]
1379 */
1380
1381
1382 double zeta = giveGlobalZcoord( gp->giveNaturalCoordinate(3) );
1383 double fac1 = 4;
1384 double fac2 = 2.0 * zeta * ( 2.0 + gam * zeta );
1385 double fac3 = 2.0 * zeta * zeta;
1386 double fac4 = zeta * zeta * ( 2.0 + gam * zeta ) * ( 2.0 + gam * zeta );
1387 double fac5 = zeta * zeta * zeta * ( 2.0 + gam * zeta );
1388 double fac6 = zeta * zeta * zeta * zeta;
1389 FloatMatrix mass11(3, 3), mass12(3, 3), mass13(3, 1), mass21(3, 3), mass22(3, 3), mass23(3, 1), mass31(1, 3), mass32(1, 3), mass33(1, 1);
1390 mass.resize(7, 7);
1391 mass11.at(1, 1) = mass11.at(2, 2) = mass11.at(3, 3) = fac1; // A
1392 mass12.at(1, 1) = mass12.at(2, 2) = mass12.at(3, 3) = fac2; // B
1393 mass13.at(1, 1) = fac3 * m.at(1);
1394 mass13.at(2, 1) = fac3 * m.at(2);
1395 mass13.at(3, 1) = fac3 * m.at(3); // C
1396 mass22.at(1, 1) = mass22.at(2, 2) = mass22.at(3, 3) = fac4; // D
1397 mass23.at(1, 1) = fac5 * m.at(1);
1398 mass23.at(2, 1) = fac5 * m.at(2);
1399 mass23.at(3, 1) = fac5 * m.at(3); // E
1400 mass33.at(1, 1) = fac6 * m.dotProduct(m); // F
1401 mass21.beTranspositionOf(mass12);
1402 mass31.beTranspositionOf(mass13);
1403 mass32.beTranspositionOf(mass23);
1404 //mass.symmetrized();
1405
1406 double dV = this->computeVolumeAroundLayer(gp, layer);
1407 double rho = mat->give('d', gp);
1408
1409 FloatMatrix M11temp, M12temp, M13temp, M22temp, M23temp, M33temp;
1410 this->computeTripleProduct(M11temp, N11, mass11, N11);
1411 this->computeTripleProduct(M12temp, N11, mass12, N22);
1412 this->computeTripleProduct(M13temp, N11, mass13, N33);
1413 this->computeTripleProduct(M22temp, N22, mass22, N22);
1414 this->computeTripleProduct(M23temp, N22, mass23, N33);
1415 this->computeTripleProduct(M33temp, N33, mass33, N33);
1416 M11.add(0.25 * rho * dV, M11temp);
1417 M12.add(0.25 * rho * dV, M12temp);
1418 M13.add(0.25 * rho * dV, M13temp);
1419 M22.add(0.25 * rho * dV, M22temp);
1420 M23.add(0.25 * rho * dV, M23temp);
1421 M33.add(0.25 * rho * dV, M33temp);
1422 }
1423
1424 answer.resize(ndofs, ndofs);
1425 answer.zero();
1426
1427 const IntArray &ordering_phibar = this->giveOrdering(Midplane);
1428 const IntArray &ordering_m = this->giveOrdering(Director);
1429 const IntArray &ordering_gam = this->giveOrdering(InhomStrain);
1430 answer.assemble(M11, ordering_phibar, ordering_phibar);
1431 answer.assemble(M12, ordering_phibar, ordering_m);
1432 answer.assemble(M13, ordering_phibar, ordering_gam);
1433 answer.assemble(M22, ordering_m, ordering_m);
1434 answer.assemble(M23, ordering_m, ordering_gam);
1435 answer.assemble(M33, ordering_gam, ordering_gam);
1436
1437 FloatMatrix M21, M31, M32;
1438 M21.beTranspositionOf(M12);
1439 M31.beTranspositionOf(M13);
1440 M32.beTranspositionOf(M23);
1441 answer.assemble(M21, ordering_m, ordering_phibar);
1442 answer.assemble(M31, ordering_gam, ordering_phibar);
1443 answer.assemble(M32, ordering_gam, ordering_m);
1444 answer.symmetrized();
1445
1446 }
1447#endif
1448}
1449
1450void Shell7BaseXFEM :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global)
1451{
1452 //@todo present formulation returns edge vector localized into element vector, efficient implementation can return only dofs related to edge (bp)
1453 answer.clear();
1454 if ( type != ExternalForcesVector ) {
1455 return;
1456 }
1457
1458 BoundaryLoad *edgeLoad = dynamic_cast< BoundaryLoad * >(load);
1459 if ( edgeLoad ) {
1460 answer.resize( this->computeNumberOfDofs() );
1461 answer.zero();
1462
1463 // Continuous part
1464 FloatArray fT;
1465 Shell7Base :: computeTractionForce(fT, boundary, edgeLoad, tStep, mode, true);
1466
1467 IntArray activeDofs, ordering;
1468 this->computeOrderingArray(ordering, activeDofs, NULL);
1469 answer.assemble(fT, ordering);
1470
1471 FloatArray componentsTemp, coordsTemp(1);
1472 coordsTemp.at(1) = 0.0;
1473 edgeLoad->computeValueAt(componentsTemp, tStep, coordsTemp, VM_Total);
1475 //double xi = 0.0; // defaults to geometric midplane
1476 //if ( componentsTemp.giveSize() == 8 ) {
1477 // xi = componentsTemp.at(8); // use the 8th component to store the-xi coord where the load acts
1478 //}
1479
1480 // Disccontinuous part
1481 FloatArray temp, tempRed;
1482 for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) { // Only one is supported at the moment
1483
1484 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i);
1485 if ( ei->isElementEnriched(this) ) {
1486 this->computeEnrTractionForce(temp, boundary, edgeLoad, tStep, mode, ei);
1487 this->computeOrderingArray(ordering, activeDofs, ei);
1488 tempRed.beSubArrayOf(temp, activeDofs);
1489 answer.assemble(tempRed, ordering);
1490 }
1491 }
1492 return;
1493 } else {
1494 OOFEM_ERROR("load type not supported");
1495 return;
1496 }
1497}
1498
1499
1500void
1501Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, EnrichmentItem *ei)
1502{
1503#if 0
1504 int approxOrder = edgeLoad->giveApproxOrder() + this->giveInterpolation()->giveInterpolationOrder();
1505 int numberOfGaussPoints = ( int ) ceil( ( approxOrder + 1. ) / 2. );
1506 GaussIntegrationRule iRule(1, this, 1, 1);
1507 iRule.SetUpPointsOnLine(numberOfGaussPoints, _Unknown);
1508
1509
1510 FloatMatrix N, Q;
1511 FloatArray fT(7), components, lCoords;
1512 Load :: CoordSystType coordSystType = edgeLoad->giveCoordSystMode();
1513
1514 FloatArray Nftemp(21), Nf(21);
1515 Nf.zero();
1516 for ( auto &gp : *iRule ) {
1517 const auto &lCoords = gp->giveNaturalCoordinates();
1518
1519 edgeLoad->computeValueAt(components, tStep, lCoords, mode);
1520 this->edgeComputeEnrichedNmatrixAt(lCoords, N, ei, iEdge);
1521
1522 if ( coordSystType == Load :: CST_UpdatedGlobal ) {
1523
1524 // Updated global coord system
1525 FloatMatrix gcov;
1526 this->edgeEvalEnrCovarBaseVectorsAt(lCoords, iEdge, gcov, tStep, ei);
1527 Q.beTranspositionOf(gcov);
1528
1529 FloatArray distrForces, distrMoments, t1, t2;
1530 distrForces = { components.at(1), components.at(2), components.at(3) };
1531 distrMoments = { components.at(4), components.at(5), components.at(6) };
1532 t1.beTProductOf(Q, distrForces);
1533 t2.beTProductOf(Q, distrMoments);
1534 fT.addSubVector(t1,1);
1535 fT.addSubVector(t2,4);
1536 fT.at(7) = components.at(7); // don't do anything with the 'gamma'-load
1537
1538 } else if( coordSystType == Load :: CST_Global ) {
1539 // Undeformed global coord system
1540 for ( int i = 1; i <= 7; i++) {
1541 fT.at(i) = components.at(i);
1542 }
1543 } else {
1544 OOFEM_ERROR("ModShell7Base :: computeTractionForce - does not support local coordinate system");
1545 }
1546
1547 double dL = this->edgeComputeLengthAround(gp, iEdge);
1548
1549 Nftemp.beTProductOf(N, fT*dL);
1550 Nf.add(Nftemp);
1551 }
1552
1553 IntArray mask;
1554 this->giveEdgeDofMapping(mask, iEdge);
1555 answer.resize( Shell7Base :: giveNumberOfDofs() );
1556 answer.zero();
1557 answer.assemble(Nf, mask);
1558
1559 answer.printYourself("f_ext old");
1560#else
1561
1562 int approxOrder = edgeLoad->giveApproxOrder() + this->giveInterpolation()->giveInterpolationOrder();
1563 int numberOfGaussPoints = ( int ) ceil( ( approxOrder + 1. ) / 2. );
1564 GaussIntegrationRule iRule(1, this, 1, 1);
1565 iRule.SetUpPointsOnLine(numberOfGaussPoints, _Unknown);
1566
1567 FloatMatrix N, Q;
1568 FloatArray fT(7), components, lCoords, gCoords, Nf;
1569 Load :: CoordSystType coordSystType = edgeLoad->giveCoordSystMode();
1570
1571 answer.resize( Shell7Base :: giveNumberOfDofs() );
1572 answer.zero();
1573 Nf.resize( Shell7Base :: giveNumberOfDofs() );
1574 Nf.zero();
1575 for ( auto &gp : iRule ) {
1576 const FloatArray &lCoordsEdge = gp->giveNaturalCoordinates();
1577
1578 this->fei->edgeLocal2global( gCoords, iEdge, lCoordsEdge, FEIElementGeometryWrapper(this) );
1579 this->fei->global2local( lCoords, gCoords, FEIElementGeometryWrapper(this) );
1580
1581
1582 edgeLoad->computeValueAt(components, tStep, lCoordsEdge, mode);
1583 if( components.giveSize() == 8 ) {
1584 lCoords.at(3) = components.at(8);
1585 }
1586 this->computeEnrichedNmatrixAt(lCoords, N, ei);
1587
1588 if ( coordSystType == Load :: CST_UpdatedGlobal ) {
1589
1590 // Updated global coord system
1591 auto gcov = this->edgeEvalEnrCovarBaseVectorsAt(lCoordsEdge, iEdge, tStep, ei);
1592 Q = transpose(gcov);
1593
1594 FloatArray distrForces, distrMoments, t1, t2;
1595 distrForces = { components.at(1), components.at(2), components.at(3) };
1596 distrMoments = { components.at(4), components.at(5), components.at(6) };
1597 t1.beTProductOf(Q, distrForces);
1598 t2.beTProductOf(Q, distrMoments);
1599 fT.addSubVector(t1,1);
1600 fT.addSubVector(t2,4);
1601 fT.at(7) = components.at(7); // don't do anything with the 'gamma'-load
1602
1603 } else if( coordSystType == Load :: CST_Global ) {
1604 // Undeformed global coord system
1605 for ( int i = 1; i <= 7; i++) {
1606 fT.at(i) = components.at(i);
1607 }
1608 } else {
1609 OOFEM_ERROR("ModShell7Base :: computeTractionForce - does not support local coordinate system");
1610 }
1611
1612 double dL = this->edgeComputeLengthAround(gp, iEdge);
1613
1614 //answer.plusProduct(N, fT, dL);
1615 Nf.plusProduct(N, fT, dL);
1616 }
1617 answer.assemble(Nf, this->giveOrderingDofTypes() );
1618#endif
1619}
1620
1622Shell7BaseXFEM :: edgeEvalEnrCovarBaseVectorsAt(const FloatArrayF<3> &lcoords, const int iedge, TimeStep *tStep, EnrichmentItem *ei)
1623{
1624 // Evaluates the covariant base vectors in the current configuration for an edge
1625 double zeta = lcoords.at(3);
1626
1627 FloatArray solVecEdge;
1628 FloatMatrix B;
1629 //const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iedge);
1630 this->edgeComputeEnrichedBmatrixAt(lcoords, B, ei, iedge);
1631 this->edgeGiveUpdatedSolutionVector(solVecEdge, iedge, tStep);
1632
1633 FloatArray genEpsEdge; // generalized strain
1634 genEpsEdge.beProductOf(B, solVecEdge); // [dxdxi, dmdxi, m, dgamdxi, gam]^T
1635
1636 FloatArrayF<3> dxdxi = { genEpsEdge.at(1), genEpsEdge.at(2), genEpsEdge.at(3) };
1637 FloatArrayF<3> dmdxi = { genEpsEdge.at(4), genEpsEdge.at(5), genEpsEdge.at(6) };
1638 FloatArrayF<3> m = { genEpsEdge.at(7), genEpsEdge.at(8), genEpsEdge.at(9) };
1639 double dgamdxi = genEpsEdge.at(10);
1640 double gam = genEpsEdge.at(11);
1641
1642 double fac1 = ( zeta + 0.5 * gam * zeta * zeta );
1643 double fac2 = ( 0.5 * zeta * zeta );
1644 double fac3 = ( 1.0 + zeta * gam );
1645
1646 const auto g2 = normalize(dxdxi + fac1*dmdxi + fac2*dgamdxi*m); // base vector along the edge
1647 const auto g3 = normalize(fac3*m); // director field
1648 const auto g1 = normalize(cross(g2, g3));
1649
1650 return FloatMatrixF<3,3>::fromColumns({g1, g2, g3});
1651}
1652
1653
1654// Surface
1655/*
1656void
1657Shell7BaseXFEM :: computeSurfaceLoadVectorAt(FloatArray &answer, Load *load,
1658 int iSurf, TimeStep *tStep, ValueModeType mode)
1659{
1660 BoundaryLoad *surfLoad = dynamic_cast< BoundaryLoad * >(load);
1661
1662 if ( surfLoad ) {
1663 answer.resize( this->giveNumberOfDofs() );
1664 answer.zero();
1665
1666 // Continuous part
1667 FloatArray solVec, force;
1668 this->giveUpdatedSolutionVector(solVec, tStep);
1669 this->computePressureForce(force, solVec, iSurf, surfLoad, tStep, mode);
1670
1671 IntArray activeDofs, ordering, eiDofIdArray;
1672 this->computeOrderingArray(ordering, activeDofs, NULL);
1673 answer.assemble(force, ordering);
1674
1675 // Disccontinuous part
1676#if 1
1677 FloatArray solVecD;
1678 double xi = 0.0; // defaults to geometric midplane
1679 if ( ConstantPressureLoad * pLoad = dynamic_cast< ConstantPressureLoad * >(load) ) {
1680 xi = pLoad->giveLoadOffset();
1681 }
1682 else if ( ConstantSurfaceLoad * sLoad = dynamic_cast< ConstantSurfaceLoad * >( load ) ) {
1683 xi = sLoad->giveLoadOffset();
1684 //printf("sLoad xi = %e \n",xi);
1685 }
1686 //xi = -1.0;
1687 std :: vector< double > ef;
1688 FloatArray temp, tempRed, lCoords(2);
1689 for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) {
1690 Delamination *dei = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(i) );
1691 if ( dei != NULL && dei->isElementEnriched(this) ) {
1692 double levelSet = xi - dei->giveDelamXiCoord();
1693 dei->evaluateEnrFuncAt(ef, lCoords, levelSet);
1694 //if (this->giveGlobalNumber() == 10) {printf("xi= %f, levelSet= %f, ef= %f \n",xi,levelSet,ef[0]); }
1695 if ( ef[0] > 0.1 ) {
1696 dei->giveEIDofIdArray(eiDofIdArray);
1697 this->computeDiscSolutionVector(eiDofIdArray, tStep, solVecD);
1698 this->computePressureForce(temp, solVecD, iSurf, surfLoad, tStep, mode);
1699 temp.times(DISC_DOF_SCALE_FAC);
1700 // Assemble
1701 this->computeOrderingArray(ordering, activeDofs, dei);
1702 tempRed.beSubArrayOf(temp, activeDofs);
1703// if (this->giveGlobalNumber() == 10) {
1704// ordering.printYourself("ordering");
1705// activeDofs.printYourself("activeDofs");
1706// }
1707 answer.assemble(tempRed, ordering);
1708 }
1709 }
1710 }
1711#endif
1712 return;
1713 } else {
1714 OOFEM_ERROR("load type not supported");
1715 return;
1716 }
1717}
1718*/
1719
1720
1721// Shifted N and B matrices
1722void
1723Shell7BaseXFEM :: computeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei)
1724{
1725 // Returns the enriched and shifted {B} matrix of the receiver, evaluated at gp. Such that
1726 // B*a = [dxbar_dxi, dwdxi, w, dgamdxi, gam]^T, where a is the vector of unknowns
1727
1728 if ( ei && dynamic_cast< ShellCrack*>(ei) ) {
1729
1730 int ndofs = Shell7Base :: giveNumberOfDofs();
1731 int ndofs_xm = 3 * this->giveNumberOfDofManagers();
1732 answer.resize(18, ndofs);
1733 answer.zero();
1734 FloatArray N;
1735 FloatMatrix dNdxi;
1736 this->fei->evalN( N, lCoords, FEIElementGeometryWrapper(this) );
1737 this->fei->evaldNdxi( dNdxi, lCoords, FEIElementGeometryWrapper(this) );
1738
1739 /* 18 18 6
1740 * 6 [B_u 0 0
1741 * 6 0 B_w 0
1742 * 3 0 N_w 0
1743 * 2 0 0 B_gam
1744 * 1 0 0 N_gam]
1745 */
1746
1747 // Evaluate enrichment function at point given by lcoords
1748// std :: vector< double > efGP;
1749// double levelSetGP = this->evaluateLevelSet(lCoords, ei);
1750// ///TODO : evaluateEnrFuncAt must have an input with only 3 values
1751// FloatArray lCoords2 = lCoords;
1752// lCoords2.resizeWithValues(2);
1753// ei->evaluateEnrFuncAt(efGP, lCoords2, levelSetGP);
1754 int ndofman = this->giveNumberOfDofManagers();
1755
1756 FloatArray gcoords;
1757 fei->local2global(gcoords, lCoords, FEIElementGeometryWrapper(this) );
1758 //computeGlobalCoordinates(gcoords, lCoords);
1759 gcoords.resizeWithValues(2);
1760
1761 for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
1762 if ( !ei->isDofManEnriched( *this->giveDofManager(i) ) ){
1763 continue;
1764 }
1765
1766 std :: vector< double > efGP;
1767 DofManager *dMan = this->giveDofManager(i);
1768 int nodeInd = dMan->giveGlobalNumber();
1769 ei->evaluateEnrFuncAt(efGP, gcoords, lCoords, nodeInd, *this, N, giveDofManArray());
1770
1771
1772 double factor = efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei);
1773
1774 // First column
1775 answer.at(1, 1 + j) = dNdxi.at(i, 1) * factor;
1776 answer.at(2, 2 + j) = dNdxi.at(i, 1) * factor;
1777 answer.at(3, 3 + j) = dNdxi.at(i, 1) * factor;
1778 answer.at(4, 1 + j) = dNdxi.at(i, 2) * factor;
1779 answer.at(5, 2 + j) = dNdxi.at(i, 2) * factor;
1780 answer.at(6, 3 + j) = dNdxi.at(i, 2) * factor;
1781
1782 // Second column
1783 answer.at(7, ndofs_xm + 1 + j) = dNdxi.at(i, 1) * factor;
1784 answer.at(8, ndofs_xm + 2 + j) = dNdxi.at(i, 1) * factor;
1785 answer.at(9, ndofs_xm + 3 + j) = dNdxi.at(i, 1) * factor;
1786 answer.at(10, ndofs_xm + 1 + j) = dNdxi.at(i, 2) * factor;
1787 answer.at(11, ndofs_xm + 2 + j) = dNdxi.at(i, 2) * factor;
1788 answer.at(12, ndofs_xm + 3 + j) = dNdxi.at(i, 2) * factor;
1789 answer.at(13, ndofs_xm + 1 + j) = N.at(i) * factor;
1790 answer.at(14, ndofs_xm + 2 + j) = N.at(i) * factor;
1791 answer.at(15, ndofs_xm + 3 + j) = N.at(i) * factor;
1792
1793 // Third column
1794 answer.at(16, ndofs_xm * 2 + 1 + i-1) = dNdxi.at(i, 1) * factor;
1795 answer.at(17, ndofs_xm * 2 + 1 + i-1) = dNdxi.at(i, 2) * factor;
1796 answer.at(18, ndofs_xm * 2 + 1 + i-1) = N.at(i) * factor;
1797 }
1798
1799 answer.times( this->evaluateHeavisideXi(lCoords.at(3), static_cast< ShellCrack* >(ei)) );
1800 answer.times(DISC_DOF_SCALE_FAC);
1801
1802 } else if ( ei && dynamic_cast< Delamination*>(ei) ){
1803 Shell7Base :: computeBmatrixAt(lCoords, answer);
1804 //std :: vector< double > efGP;
1805 //double levelSetGP = this->evaluateLevelSet(lCoords, ei);
1806 //ei->evaluateEnrFuncAt(efGP, lCoords, levelSetGP);
1807 double fac = this->evaluateHeavisideXi(lCoords.at(3), static_cast< Delamination* >(ei) );
1808 answer.times( fac * DISC_DOF_SCALE_FAC );
1809 } else {
1810 Shell7Base :: computeBmatrixAt(lCoords, answer);
1811 }
1812}
1813
1814
1815double
1816Shell7BaseXFEM :: EvaluateEnrFuncInDofMan(int dofManNum, EnrichmentItem *ei)
1817{
1818 DofManager *dMan = this->giveDofManager(dofManNum);
1819 if ( ei->isDofManEnriched(*dMan) ) {
1820 int globalNodeInd = dMan->giveGlobalNumber(); // global number in order to pick levelset value in that node
1821 double levelSetNode = 0.0;
1822 ei->evalLevelSetNormalInNode( levelSetNode, globalNodeInd, dMan->giveCoordinates() );
1823 std :: vector< double >efNode;
1824 //const FloatArray &nodePos = * ( dMan->giveCoordinates() );
1825 // evaluateEnrFuncAt requires coords to be size 2
1826 FloatArray nodePos = dMan->giveCoordinates();
1827 nodePos.resizeWithValues(2);
1828
1829 FloatArray localCoord;
1830 this->computeLocalCoordinates(localCoord, nodePos);
1831
1832 //ei->evaluateEnrFuncAt(efNode, nodePos, levelSetNode, globalNodeInd);
1833 ei->evaluateEnrFuncAt(efNode, nodePos, localCoord, globalNodeInd, *this);
1834
1835 return efNode [ 0 ];
1836 //if( efNode.size() ) {
1837 // return efNode [ 0 ];
1838 //} else {
1839 // return 0.0;
1840 //}
1841 } else {
1842 return 0.0;
1843 }
1844}
1845
1846
1847void
1848Shell7BaseXFEM :: computeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei)
1849{
1850 // Returns the displacement interpolation matrix {N} of the receiver,
1851 // evaluated at gp.
1852
1853 int ndofs = Shell7Base :: giveNumberOfDofs();
1854 int ndofs_xm = 3 * this->giveNumberOfDofManagers();
1855 answer.resize(7, ndofs);
1856 answer.zero();
1857 FloatArray N;
1858 this->fei->evalN( N, lCoords, FEIElementGeometryWrapper(this) );
1859
1860 /* nno*3 nno*3 nno
1861 * 3 [N_x 0 0
1862 * 3 0 N_m 0
1863 * 1 0 0 N_gmm ]
1864 */
1865
1866 if ( ei && dynamic_cast< Crack*>(ei) ) {
1867
1868 FloatArray gcoords;
1869 this->computeGlobalCoordinates(gcoords, lCoords);
1870
1871 for ( int i = 1, j = 0; i <= this->giveNumberOfDofManagers(); i++, j += 3 ) {
1872 if ( !ei->isDofManEnriched( *this->giveDofManager(i) ) ){
1873 continue;
1874 }
1875
1876 std :: vector< double > efGP;
1877 int nodeInd = giveDofManager(i)->giveGlobalNumber();
1878 ei->evaluateEnrFuncAt(efGP, gcoords, lCoords, nodeInd, *this, N, giveDofManArray());
1879
1880
1881 double factor = N.at(i) * ( efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei) );
1882
1883 answer.at(1, 1 + j) = factor;
1884 answer.at(2, 2 + j) = factor;
1885 answer.at(3, 3 + j) = factor;
1886 answer.at(4, ndofs_xm + 1 + j) = factor;
1887 answer.at(5, ndofs_xm + 2 + j) = factor;
1888 answer.at(6, ndofs_xm + 3 + j) = factor;
1889 answer.at(7, ndofs_xm * 2 + i) = factor;
1890 }
1891
1892 answer.times( this->evaluateHeavisideXi(lCoords.at(3), static_cast< ShellCrack* >(ei)) );
1893 answer.times(DISC_DOF_SCALE_FAC);
1894
1895 } else if ( ei && dynamic_cast< Delamination*>(ei) ) {
1896 Shell7Base :: computeNmatrixAt(lCoords, answer);
1897 //std :: vector< double > efGP;
1898 //double levelSetGP = this->evaluateLevelSet(lCoords, ei);
1899 //ei->evaluateEnrFuncAt(efGP, lCoords, levelSetGP);
1900 double fac = this->evaluateHeavisideXi(lCoords.at(3), static_cast< Delamination* >(ei) );
1901 answer.times( fac * DISC_DOF_SCALE_FAC );
1902 } else {
1903 Shell7Base :: computeNmatrixAt(lCoords, answer);
1904 }
1905}
1906
1907
1908void
1909Shell7BaseXFEM :: edgeComputeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei, const int edge)
1910{
1911 // Returns the displacement interpolation matrix {N} of the receiver
1912 // evaluated at gaussPoint along one edge.
1913 //TODO Add input for which edge!
1914
1915 answer.resize( 7, this->giveNumberOfEdgeDofs() );
1916 answer.zero();
1917
1918 FloatArray N;
1919 this->fei->edgeEvalN( N, 1, lCoords, FEIElementGeometryWrapper(this) );
1920
1921 /* 9 9 3
1922 * 3 [N_x 0 0
1923 * 3 0 N_m 0
1924 * 1 0 0 N_gmm ]
1925 */
1926 int ndofs_xm = this->giveNumberOfEdgeDofs() / 7 * 3; // numEdgeNodes * 3 dofs
1927
1928 if ( ei && dynamic_cast< Crack*>(ei) ) {
1929// std :: vector< double > efGP;
1930// double levelSetGP = this->evaluateLevelSet(lcoords, ei);
1931// ei->evaluateEnrFuncAt(efGP, lcoords, levelSetGP);
1932
1933 FloatArray gcoords;
1934// this->computeGlobalCoordinates(gcoords, lCoords);
1935 fei->edgeLocal2global(gcoords, 1, lCoords, FEIElementGeometryWrapper(this));
1936
1937 FloatArray elLocCoord;
1938 this->computeLocalCoordinates(elLocCoord, gcoords);
1939
1940 gcoords.resizeWithValues(2);
1941 elLocCoord.resizeWithValues(2);
1942
1943 for ( int i = 1, j = 0; i <= this->giveNumberOfEdgeDofManagers(); i++, j += 3 ) {
1944 //if ( !ei->isDofManEnriched(this->giveDofManager(i)) ){
1945 // continue;
1946 //}
1947
1948 std :: vector< double > efGP;
1949 int nodeInd = giveDofManager(i)->giveGlobalNumber();
1950 ei->evaluateEnrFuncAt(efGP, gcoords, elLocCoord, nodeInd, *this, N, giveDofManArray());
1951
1952 double factor = efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei);
1953 answer.at(1, 1 + j) = N.at(i) * factor;
1954 answer.at(2, 2 + j) = N.at(i) * factor;
1955 answer.at(3, 3 + j) = N.at(i) * factor;
1956 answer.at(4, ndofs_xm + 1 + j) = N.at(i) * factor;
1957 answer.at(5, ndofs_xm + 2 + j) = N.at(i) * factor;
1958 answer.at(6, ndofs_xm + 3 + j) = N.at(i) * factor;
1959 answer.at(7, ndofs_xm * 2 + i) = N.at(i) * factor;
1960 }
1961 answer.times( this->evaluateHeavisideXi(0.0, static_cast< ShellCrack* >(ei)) );
1962 answer.times(DISC_DOF_SCALE_FAC);
1963
1964 } else if ( ei && dynamic_cast< Delamination*>(ei) ) {
1965 Shell7Base :: edgeComputeNmatrixAt(lCoords, answer);
1966 //std :: vector< double > efGP;
1967 //double levelSetGP = this->edgeEvaluateLevelSet(lCoords, ei);
1968 //ei->evaluateEnrFuncAt(efGP, lCoords, levelSetGP);
1969 double fac = this->evaluateHeavisideXi(0.0, static_cast< Delamination* >(ei) );
1970 answer.times( fac * DISC_DOF_SCALE_FAC );
1971 } else {
1972 Shell7Base :: edgeComputeNmatrixAt(lCoords, answer);
1973 }
1974
1975}
1976
1977
1978void
1979Shell7BaseXFEM :: edgeComputeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei, const int edge)
1980{
1981/* Returns the matrix {B} of the receiver, evaluated at gp. Such that
1982 * B*a = [dxbar_dxi, dwdxi, w, dgamdxi, gam]^T, where a is the vector of unknowns
1983 */
1984
1985 answer.resize( 11, this->giveNumberOfEdgeDofs() );
1986 answer.zero();
1987 FloatArray N, dNdxi;
1988
1989 if ( ei && dynamic_cast< Crack*>(ei) ) {
1990
1991 this->fei->edgeEvalN( N, 1, lCoords, FEIElementGeometryWrapper(this) );
1992 int iedge = 0;
1993 this->fei->edgeEvaldNdxi( dNdxi, iedge, lCoords, FEIElementGeometryWrapper(this) );
1994
1995 /*
1996 * 3 [B_u 0 0
1997 * 3 0 B_w 0
1998 * 3 0 N_w 0
1999 * 1 0 0 B_gam
2000 * 1 0 0 N_gam]
2001 */
2002
2003 // Evaluate enrichment function at point given by lcoords
2004// std :: vector< double > efGP;
2005// double levelSetGP = this->evaluateLevelSet(lcoords, ei);
2006// ei->evaluateEnrFuncAt(efGP, lcoords, levelSetGP);
2007
2008 FloatArray gcoords;
2009 this->computeGlobalCoordinates(gcoords, lCoords);
2010
2011 int ndofs_xm = this->giveNumberOfEdgeDofs() / 7 * 3; // numEdgeNodes * 3 dofs
2012 int ndofman = this->giveNumberOfEdgeDofManagers();
2013 // First row
2014 for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
2015
2016 std :: vector< double > efGP;
2017 int nodeInd = giveDofManager(i)->giveGlobalNumber();
2018 ei->evaluateEnrFuncAt(efGP, gcoords, lCoords, nodeInd, *this, N, giveDofManArray());
2019
2020 double factor = efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei);
2021
2022 answer.at(1, 1 + j) = dNdxi.at(i) * factor;
2023 answer.at(2, 2 + j) = dNdxi.at(i) * factor;
2024 answer.at(3, 3 + j) = dNdxi.at(i) * factor;
2025// }
2026
2027 // Second row
2028// for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
2029
2030// std :: vector< double > efGP;
2031// int nodeInd = giveDofManager(i)->giveGlobalNumber();
2032// ei->evaluateEnrFuncAt(efGP, gcoords, lCoords, nodeInd, *this, N, giveDofManArray());
2033//
2034// double factor = efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei);
2035
2036 answer.at(4, ndofs_xm + 1 + j) = dNdxi.at(i) * factor;
2037 answer.at(5, ndofs_xm + 2 + j) = dNdxi.at(i) * factor;
2038 answer.at(6, ndofs_xm + 3 + j) = dNdxi.at(i) * factor;
2039 answer.at(7, ndofs_xm + 1 + j) = N.at(i) * factor;
2040 answer.at(8, ndofs_xm + 2 + j) = N.at(i) * factor;
2041 answer.at(9, ndofs_xm + 3 + j) = N.at(i) * factor;
2042// }
2043
2044 // Third row
2045// for ( int i = 1, j = 0; i <= ndofman; i++, j += 1 ) {
2046
2047// std :: vector< double > efGP;
2048// int nodeInd = giveDofManager(i)->giveGlobalNumber();
2049// ei->evaluateEnrFuncAt(efGP, gcoords, lCoords, nodeInd, *this, N, giveDofManArray());
2050//
2051// double factor = efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei);
2052
2053 answer.at(10, ndofs_xm * 2 + 1 + i-1) = dNdxi.at(i) * factor;
2054 answer.at(11, ndofs_xm * 2 + 1 + i-1) = N.at(i) * factor;
2055 }
2056
2057 answer.times( this->evaluateHeavisideXi(lCoords.at(3), static_cast< ShellCrack* >(ei)) );
2058 answer.times(DISC_DOF_SCALE_FAC);
2059
2060 } else if ( ei && dynamic_cast< Delamination*>(ei) ){
2061 Shell7Base :: edgeComputeBmatrixAt(lCoords, answer);
2062 //std :: vector< double > efGP;
2063 //double levelSetGP = this->evaluateLevelSet(lCoords, ei);
2064 //ei->evaluateEnrFuncAt(efGP, lCoords, levelSetGP);
2065 double fac = this->evaluateHeavisideXi(lCoords.at(3), static_cast< Delamination* >(ei) );
2066 answer.times( fac * DISC_DOF_SCALE_FAC );
2067 } else {
2068 Shell7Base :: edgeComputeBmatrixAt(lCoords, answer);
2069 }
2070
2071}
2072
2073
2074
2075// Delamination specific
2076
2077
2079Shell7BaseXFEM :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer, TimeStep *tStep)
2080{
2081 double zeta = this->giveGlobalZcoord( localCoords );
2082
2083 // Continuous part
2084 FloatArray solVec;
2085 this->giveUpdatedSolutionVector(solVec, tStep);
2086 FloatArrayF<3> xc, mc;
2087 double gamc = 0;
2088 Shell7Base :: giveUnknownsAt(localCoords, solVec, xc, mc, gamc, tStep);
2089 double fac_cont = ( zeta + 0.5 * gamc * zeta * zeta );
2090 auto globalCoords = xc + fac_cont * mc;
2091
2092#if 1
2093 // Discontinuous part
2094 FloatArray solVecD;
2095 double gamd = 0;
2096 for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) {
2097 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i);
2098
2099 if ( ei->isElementEnriched(this) ) {
2100 IntArray eiDofIdArray;
2101 ei->giveEIDofIdArray(eiDofIdArray);
2102 this->computeDiscSolutionVector(eiDofIdArray, tStep, solVecD);
2103 FloatArrayF<3> xd, md;
2104 this->giveDisUnknownsAt(localCoords, ei, solVecD, xd, md, gamd, tStep);
2105 double fac_disc = ( zeta + 0.5 * gamd * zeta * zeta );
2106 auto xtemp = xd + fac_disc * md;
2107 globalCoords += xtemp;
2108 }
2109 }
2110#endif
2111 return globalCoords;
2112}
2113
2114
2115void
2116Shell7BaseXFEM :: giveDisUnknownsAt(const FloatArrayF<3> &lcoords, EnrichmentItem *ei, const FloatArray &solVec, FloatArrayF<3> &x, FloatArrayF<3> &m, double &gam, TimeStep *tStep)
2117{
2118 // returns the unknowns evaluated at a point (xi1, xi2, xi3)
2119 FloatArray vec;
2120 FloatMatrix NEnr;
2121 this->computeEnrichedNmatrixAt(lcoords, NEnr, ei);
2122 vec.beProductOf(NEnr, solVec);
2123 x = {vec.at(1), vec.at(2), vec.at(3)};
2124 m = {vec.at(4), vec.at(5), vec.at(6)};
2125 gam = vec.at(7);
2126}
2127
2128
2129void
2130Shell7BaseXFEM :: giveCompositeExportData(std::vector< ExportRegion > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep )
2131{
2132 vtkPieces.resize(1);
2133 this->giveShellExportData(vtkPieces[0], primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep );
2134 //this->giveCZExportData(vtkPieces[1], primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep );
2135}
2136
2137
2138void
2139Shell7BaseXFEM :: giveCompositeExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep )
2140{
2141 this->giveCZExportData(vtkPiece, primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep );
2142 //this->giveShellExportData(vtkPiece, primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep );
2143}
2144
2145void
2146Shell7BaseXFEM :: giveShellExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep )
2147{
2148 int numSubCells = 1;
2149
2150 int numLayers = this->layeredCS->giveNumberOfLayers();
2151 //int numCells = numLayers * numSubCells;
2152 // Go through each layer and count the number of subcells
2153 int numCells = 0;
2154 for ( int i = 1; i <= numLayers; i++ ) {
2155 numCells += this->numSubDivisionsArray.at(i);
2156 }
2157
2158 int numCellNodes = 15; // quadratic wedge
2159
2160 int numTotalNodes = numCellNodes*numCells;
2161
2162 vtkPiece.setNumberOfCells(numCells);
2163 vtkPiece.setNumberOfNodes(numTotalNodes);
2164
2165 std::vector <FloatArray> nodeCoords;
2166 int val = 1;
2167 int offset = 0;
2168 int currentCell = 1;
2169 IntArray nodes(numCellNodes);
2170
2171 // Compute fictious node coords
2172 int nodeNum = 1;
2173 for ( int layer = 1; layer <= numLayers; layer++ ) {
2174
2175 numSubCells = (int)this->numSubDivisionsArray[layer - 1];
2176 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2177
2178 // Node coordinates
2179 if ( numSubCells == 1 ) {
2180 nodeCoords = Shell7Base :: giveFictiousNodeCoordsForExport(layer);
2181 } else {
2182 nodeCoords = this->giveFictiousNodeCoordsForExport(layer, subCell);
2183 }
2184
2185 for ( int node = 1; node <= numCellNodes; node++ ) {
2186 vtkPiece.setNodeCoords(nodeNum, nodeCoords[node-1] );
2187 nodeNum += 1;
2188 }
2189
2190 // Connectivity
2191 for ( int i = 1; i <= numCellNodes; i++ ) {
2192 nodes.at(i) = val++;
2193 }
2194 vtkPiece.setConnectivity(currentCell, nodes);
2195
2196 // Offset
2197 offset += numCellNodes;
2198 vtkPiece.setOffset(currentCell, offset);
2199
2200 // Cell types
2201
2202 vtkPiece.setCellType(currentCell, 26); // Quadratic wedge
2203
2204 currentCell++;
2205 }
2206 }
2207
2208 // Export nodal variables from primary fields
2209 vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes);
2210
2211 std::vector<FloatArray> updatedNodeCoords;
2212 FloatArray u(3);
2213 std::vector<FloatArray> values;
2214 for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) {
2215
2216// if ( recoverStress ) {
2217// // Recover shear stresses
2218// //printf("Shell7BaseXFEM: recover shear stress function \n");
2219// this->recoverShearStress(tStep);
2220// }
2221
2222 UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum);
2223 nodeNum = 1;
2224 currentCell = 1;
2225 for ( int layer = 1; layer <= numLayers; layer++ ) {
2226
2227 numSubCells = (int)this->numSubDivisionsArray[layer - 1];
2228 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2229
2230 if ( type == DisplacementVector ) { // compute displacement as u = x - X
2231 auto nodeCoords = numSubCells == 1 ?
2232 Shell7Base :: giveFictiousNodeCoordsForExport(layer) :
2233 this->giveFictiousNodeCoordsForExport(layer, subCell);
2234 auto updatedNodeCoords = this->giveFictiousUpdatedNodeCoordsForExport(layer, tStep, numSubCells == 1 ? 0 : subCell);
2235 for ( int j = 1; j <= numCellNodes; j++ ) {
2236 u = updatedNodeCoords[j-1];
2237 u.subtract(nodeCoords[j-1]);
2238 vtkPiece.setPrimaryVarInNode(type, nodeNum, u);
2239 nodeNum += 1;
2240 }
2241
2242 } else {
2243 NodalRecoveryMI_recoverValues(values, layer, ( InternalStateType ) 1, tStep); // does not work well - fix
2244 for ( int j = 1; j <= numCellNodes; j++ ) {
2245 vtkPiece.setPrimaryVarInNode(type, nodeNum, values[j-1]);
2246 nodeNum += 1;
2247 }
2248 }
2249 currentCell++;
2250 }
2251 }
2252 }
2253
2254
2255 // Export nodal variables from internal fields
2256
2257 vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes );
2258 for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) {
2259 InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum);
2260 nodeNum = 1;
2261
2262 //int currentCell = 1;
2263 for ( int layer = 1; layer <= numLayers; layer++ ) {
2264 numSubCells = (int)this->numSubDivisionsArray[layer - 1];
2265
2266 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2267 recoverValuesFromIP(values, layer, type, tStep);
2268
2269 for ( int j = 1; j <= numCellNodes; j++ ) {
2270 vtkPiece.setInternalVarInNode( type, nodeNum, values[j-1] );
2271 //ZZNodalRecoveryMI_recoverValues(el.nodeVars[fieldNum], layer, type, tStep);
2272 nodeNum += 1;
2273 }
2274 }
2275 }
2276 }
2277
2278 // Export cell variables
2279 FloatArray average;
2280 vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells);
2281 for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) {
2282 InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i);
2284 currentCell = 1;
2285 for ( int layer = 1; layer <= numLayers; layer++ ) {
2286 numSubCells = (int)this->numSubDivisionsArray[layer - 1];
2287 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2288 std :: unique_ptr< IntegrationRule > &iRuleL = integrationRulesArray [ layer - 1 ];
2289 VTKXMLExportModule :: computeIPAverage(average, iRuleL.get(), this, type, tStep);
2290 if ( valueType == ISVT_TENSOR_S3 ) {
2291 vtkPiece.setCellVar(type, currentCell, convV6ToV9Stress(average) );
2292 } else {
2293 vtkPiece.setCellVar(type, currentCell, average);
2294 }
2295 currentCell += 1;
2296 }
2297 }
2298
2299 }
2300
2301
2302#if 1
2303 // Export of XFEM related quantities
2304 XfemManager *xFemMan = this->xMan;
2305 int nEnrIt = xFemMan->giveNumberOfEnrichmentItems();
2306
2307 IntArray wedgeToTriMap;
2308 // For each node in the wedge take the value from the triangle node given by the map below
2309 wedgeToTriMap = { 1, 2, 3, 1, 2, 3, 4, 5, 6, 4, 5, 6, 1, 2, 3 };
2310
2311 vtkPiece.setNumberOfInternalXFEMVarsToExport(xFemMan->vtkExportFields.giveSize(), nEnrIt, numTotalNodes);
2312 for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) {
2313 XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ];
2314
2315 for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) {
2316 EnrichmentItem *ei = xFemMan->giveEnrichmentItem(enrItIndex);
2317 nodeNum = 1;
2318 for ( int layer = 1; layer <= numLayers; layer++ ) {
2319 FloatMatrix localNodeCoords;
2320
2321 numSubCells = (int)this->numSubDivisionsArray[layer - 1];
2322 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2323 FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, nodeLocalXi3CoordsMapped;
2324 if ( numSubCells == 1) {
2325 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, EGT_wedge_2);
2326 } else {
2327 giveLocalNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, layer, localNodeCoords);
2328 }
2329 mapXi3FromLocalToShell(nodeLocalXi3CoordsMapped, nodeLocalXi3Coords, layer);
2330 for ( int nodeIndx = 1; nodeIndx <= numCellNodes; nodeIndx++ ) {
2331
2332 FloatArray lCoords;
2333 //lCoords.setValues(3, nodeLocalXi1Coords.at(nodeIndx), nodeLocalXi2Coords.at(nodeIndx), nodeLocalXi3CoordsMapped.at(nodeIndx));
2334 lCoords.beColumnOf(localNodeCoords, nodeIndx);
2335 Node *node = this->giveNode( wedgeToTriMap.at(nodeIndx) );
2336 FloatArray valueArray;
2337 //const FloatArray *val = NULL;
2338 if ( xfemstype == XFEMST_LevelSetPhi ) {
2339 valueArray.resize(1);
2340 //val = & valueArray;
2341 //ei->evalLevelSetNormalInNode( valueArray.at(1), node->giveNumber() );
2342 valueArray.at(1) = this->evaluateLevelSet(lCoords, ei);
2343 } else if ( xfemstype == XFEMST_LevelSetGamma ) {
2344 valueArray.resize(1);
2345 //val = & valueArray;
2346 ei->evalLevelSetTangInNode( valueArray.at(1), node->giveNumber(), node->giveCoordinates() );
2347 } else if ( xfemstype == XFEMST_NodeEnrMarker ) {
2348 valueArray.resize(1);
2349 //val = & valueArray;
2350 ei->evalNodeEnrMarkerInNode( valueArray.at(1), node->giveNumber() );
2351 } else {
2352 //OOFEM_WARNING2("VTKXMLExportModule::getNodalVariableFromXFEMST: invalid data in node %d", inode);
2353 }
2354
2355 vtkPiece.setInternalXFEMVarInNode(field, enrItIndex, nodeNum, valueArray);
2356 nodeNum += 1;
2357 }
2358 }
2359 }
2360 }
2361 }
2362#endif
2363
2364}
2365
2366
2367std::vector<FloatArray>
2368Shell7BaseXFEM :: giveFictiousNodeCoordsForExport(int layer, int subCell)
2369{
2370
2371 // compute fictious node coords
2372 FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords;
2373 FloatMatrix localNodeCoords;
2374 // need to return local coordinates corresponding to the nodes of the sub triangles
2375 giveLocalNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, layer, localNodeCoords);
2376
2377 //this->interpolationForExport.giveLocalNodeCoords(localNodeCoords);
2378
2379 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
2380 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
2381 FloatArray localCoords(3);
2382 localCoords.at(1) = nodeLocalXi1Coords.at(i);
2383 localCoords.at(2) = nodeLocalXi2Coords.at(i);
2384 localCoords.at(3) = nodeLocalXi3Coords.at(i);
2386 localCoords.beColumnOf(localNodeCoords,i);
2387
2388 nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer);
2389 }
2390 return nodes;
2391}
2392
2393
2394std::vector<FloatArray>
2395Shell7BaseXFEM :: giveFictiousCZNodeCoordsForExport(int layer, int subCell)
2396{
2397 // compute fictious node coords
2398 FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords;
2399 FloatMatrix localNodeCoords;
2400 // need to return local coordinates corresponding to the nodes of the sub triangles
2401 giveLocalCZNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, localNodeCoords);
2402
2403 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
2404 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
2405 FloatArray localCoords(3);
2406 localCoords.beColumnOf(localNodeCoords,i);
2407
2408 nodes[i-1] = this->vtkEvalInitialGlobalCZCoordinateAt(localCoords, layer);
2409 }
2410 return nodes;
2411}
2412
2413
2414std::vector<FloatArray>
2415Shell7BaseXFEM :: giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep, int subCell)
2416{
2417 // compute fictious node coords
2418 FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords;
2419
2420 FloatMatrix localNodeCoords;
2421
2422
2423 if ( subCell == 0) {
2424 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, EGT_wedge_2);
2425 // must get local z-coord in terms of the total thickness not layerwise
2426 } else {
2427 giveLocalNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, layer, localNodeCoords);
2428 }
2429 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
2430 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
2431 FloatArray localCoords(3);
2432 localCoords.beColumnOf(localNodeCoords, i);
2433
2434 // Map local layer cs to local shell cs
2435 double scaleFactor = 0.9999; // Will be numerically unstable with xfem if the endpoints lie at +-1 - or will it?
2436 double totalThickness = this->layeredCS->computeIntegralThick();
2437 double zMid_i = this->layeredCS->giveLayerMidZ(layer); // global z-coord
2438 double xiMid_i = 1.0 - 2.0 * ( totalThickness - this->layeredCS->giveMidSurfaceZcoordFromBottom() - zMid_i ) / totalThickness; // local z-coord
2439 double deltaxi = localCoords.at(3) * this->layeredCS->giveLayerThickness(layer) / totalThickness; // distance from layer mid
2440 localCoords.at(3) = xiMid_i + deltaxi * scaleFactor;
2441
2442 nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, tStep);
2443 }
2444 return nodes;
2445}
2446
2447
2448std::vector<FloatArray>
2449Shell7BaseXFEM :: giveFictiousUpdatedCZNodeCoordsForExport(int interface, TimeStep *tStep, int subCell)
2450{
2451 // compute fictious node coords
2452 FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords;
2453
2454 FloatMatrix localNodeCoords;
2455
2456
2457 if ( subCell == 0) {
2458 this->interpolationForCZExport.giveLocalNodeCoords(localNodeCoords, EGT_triangle_2);
2459 // must get local z-coord in terms of the total thickness not layerwise
2460 } else {
2461 giveLocalCZNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, localNodeCoords);
2462 }
2463 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
2464 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
2465 FloatArray localCoords(3);
2466 localCoords.beColumnOf(localNodeCoords, i);
2467 localCoords.at(3) = 1.0;
2468 // Map local layer cs to local shell cs
2469 double scaleFactor = 0.9999; // Will be numerically unstable with xfem if the endpoints lie at +-1 - or will it?
2470 double totalThickness = this->layeredCS->computeIntegralThick();
2471 double zMid_i = this->layeredCS->giveLayerMidZ(interface); // global z-coord
2472 double xiMid_i = 1.0 - 2.0 * ( totalThickness - this->layeredCS->giveMidSurfaceZcoordFromBottom() - zMid_i ) / totalThickness; // local z-coord
2473 double deltaxi = localCoords.at(3) * this->layeredCS->giveLayerThickness(interface) / totalThickness; // distance from layer mid
2474 localCoords.at(3) = xiMid_i + deltaxi * scaleFactor;
2475
2476 nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, interface, tStep);
2477 }
2478 return nodes;
2479}
2480
2481
2482void
2483Shell7BaseXFEM :: mapXi3FromLocalToShell(FloatArray &answer, FloatArray &local, int layer)
2484{
2485 // Map local layer cs to local shell cs
2486 answer.resize(15);
2487 for ( int i = 1; i <= 15; i++ ){
2488 double scaleFactor = 0.9999; // Will be numerically unstable with xfem if the endpoints lie at +-1
2489 double totalThickness = this->layeredCS->computeIntegralThick();
2490 double zMid_i = this->layeredCS->giveLayerMidZ(layer); // global z-coord
2491 double xiMid_i = 1.0 - 2.0 * ( totalThickness - this->layeredCS->giveMidSurfaceZcoordFromBottom() - zMid_i ) / totalThickness; // local z-coord
2492 double deltaxi = local.at(i) * this->layeredCS->giveLayerThickness(layer) / totalThickness; // distance from layer mid
2493 local.at(i) = xiMid_i + deltaxi * scaleFactor;
2494
2495 answer.at(i) = local.at(i);
2496 }
2497}
2498
2499
2500void
2501Shell7BaseXFEM :: giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, int layer, FloatMatrix &localNodeCoords)
2502{
2503 // Local coords for a quadratic wedge element - coords for subtriangles
2504 double scale = 0.9999;
2505 double z = 1.0*scale;
2506
2507 // Triangle coordinates
2508 //g1 = this->allTri[subCell-1].giveVertex(1);
2509 //g2 = this->allTri[subCell-1].giveVertex(2);
2510 //g3 = this->allTri[subCell-1].giveVertex(3);
2511 auto g1 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(1);
2512 auto g2 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(2);
2513 auto g3 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(3);
2514
2515 // Move the triangle nodes slightly towards the center to avoid numerical problems - controlled by 'scale'
2516 double alpha1 = scale; double alpha2 = (1.0-alpha1)*0.5; double alpha3 = alpha2;
2517 g1.resizeWithValues(2); g2.resizeWithValues(2); g3.resizeWithValues(2);
2518 auto gs1 = alpha1*g1 + alpha2*g2 + alpha3*g3;
2519 auto gs2 = alpha2*g1 + alpha1*g2 + alpha3*g3;
2520 auto gs3 = alpha2*g1 + alpha3*g2 + alpha1*g3;
2521
2522 // Local coordinates for the (scaled) triangle coordinates
2523 FloatArray loc1, loc2, loc3;
2524 this->computeLocalCoordinates(loc1, gs1);
2525 this->computeLocalCoordinates(loc2, gs2);
2526 this->computeLocalCoordinates(loc3, gs3);
2527
2528 // Compute coordinates for the three mid nodes
2529 FloatArray loc12 = 0.5 * (loc1 + loc2);
2530 FloatArray loc23 = 0.5 * (loc2 + loc3);
2531 FloatArray loc31 = 0.5 * (loc3 + loc1);
2532 double a = loc1.at(1);
2533 double b = loc2.at(1);
2534 double c = loc3.at(1);
2535 double d = loc12.at(1);
2536 double e = loc23.at(1);
2537 double f = loc31.at(1);
2538 nodeLocalXi1Coords = { a, b, c, a, b, c, d, e, f, d, e, f, a, b, c };
2539
2540 a = loc1.at(2);
2541 b = loc2.at(2);
2542 c = loc3.at(2);
2543 d = loc12.at(2);
2544 e = loc23.at(2);
2545 f = loc31.at(2);
2546 nodeLocalXi2Coords = { a, b, c, a, b, c, d, e, f, d, e, f, a, b, c };
2547
2548 nodeLocalXi3Coords = { -z, -z, -z, z, z, z, -z, -z, -z, z, z, z, 0., 0., 0. };
2549
2550 FloatMatrix localNodeCoordsT = FloatMatrix::fromCols({nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords});
2551 localNodeCoords.beTranspositionOf(localNodeCoordsT);
2552}
2553
2554
2555void
2556Shell7BaseXFEM :: giveLocalCZNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, FloatMatrix &localNodeCoords)
2557{
2558 // Local coords for a quadratic triangle element - coords for subtriangles
2559 double scale = 0.999;
2560 //double z = 1.0*scale;
2561
2562 // Triangle coordinates
2563 auto g1 = this->allTri[subCell-1].giveVertex(1);
2564 auto g2 = this->allTri[subCell-1].giveVertex(2);
2565 auto g3 = this->allTri[subCell-1].giveVertex(3);
2566
2567 // Move the triangle nodes slightly towards the center to avoid numerical problems - controlled by 'scale'
2568 double alpha1 = scale; double alpha2 = (1.0-alpha1)*0.5; double alpha3 = alpha2;
2569 auto gs1 = alpha1*g1 + alpha2*g2 + alpha3*g3;
2570 auto gs2 = alpha2*g1 + alpha1*g2 + alpha3*g3;
2571 auto gs3 = alpha2*g1 + alpha3*g2 + alpha1*g3;
2572
2573 // Local coordinates for the (scaled) triangle coordinates
2574 FloatArray loc1, loc2, loc3;
2575 this->computeLocalCoordinates(loc1, gs1);
2576 this->computeLocalCoordinates(loc2, gs2);
2577 this->computeLocalCoordinates(loc3, gs3);
2578
2579 // Compute coordinates for the three mid nodes
2580 FloatArray loc12 = 0.5 * (loc1 + loc2);
2581 FloatArray loc23 = 0.5 * (loc2 + loc3);
2582 FloatArray loc31 = 0.5 * (loc3 + loc1);
2583 double a = loc1.at(1);
2584 double b = loc2.at(1);
2585 double c = loc3.at(1);
2586 double d = loc12.at(1);
2587 double e = loc23.at(1);
2588 double f = loc31.at(1);
2589 nodeLocalXi1Coords = { a, b, c, d, e, f };
2590
2591 a = loc1.at(2);
2592 b = loc2.at(2);
2593 c = loc3.at(2);
2594 d = loc12.at(2);
2595 e = loc23.at(2);
2596 f = loc31.at(2);
2597 nodeLocalXi2Coords = { a, b, c, d, e, f };
2598
2599 nodeLocalXi3Coords = { 0., 0., 0., 0., 0., 0. };
2600
2601 FloatMatrix localNodeCoordsT = FloatMatrix::fromCols({nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords});
2602 localNodeCoords.beTranspositionOf(localNodeCoordsT);
2603}
2604
2605void
2606Shell7BaseXFEM :: giveCZExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep )
2607{
2608
2609 int numSubCells = 1;
2610 if ( this->allTri.size() ) {
2611 numSubCells = (int)this->allTri.size();
2612 }
2613
2614 int numInterfaces = this->layeredCS->giveNumberOfLayers()-1;
2615 int numCells = numInterfaces * numSubCells;
2616
2617 int numCellNodes = 6; // quadratic triangle
2618
2619 int numTotalNodes = numCellNodes*numCells;
2620
2621 vtkPiece.setNumberOfCells(numCells);
2622 vtkPiece.setNumberOfNodes(numTotalNodes);
2623
2624 int val = 1;
2625 int offset = 0;
2626 int currentCell = 1;
2627 IntArray nodes(numCellNodes);
2628
2629 // Compute fictious node coords
2630 int nodeNum = 1;
2631 for ( int layer = 1; layer <= numInterfaces; layer++ ) {
2632
2633 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2634
2635 // Node coordinates
2636 auto nodeCoords = numSubCells == 1 ?
2637 Shell7Base :: giveFictiousCZNodeCoordsForExport(layer) :
2638 this->giveFictiousCZNodeCoordsForExport(layer, subCell);
2639
2640 for ( int node = 1; node <= numCellNodes; node++ ) {
2641 vtkPiece.setNodeCoords(nodeNum, nodeCoords[node-1] );
2642 nodeNum += 1;
2643 }
2644
2645 // Connectivity
2646 for ( int i = 1; i <= numCellNodes; i++ ) {
2647 nodes.at(i) = val++;
2648 }
2649 vtkPiece.setConnectivity(currentCell, nodes);
2650
2651 // Offset
2652 offset += numCellNodes;
2653 vtkPiece.setOffset(currentCell, offset);
2654
2655 // Cell types
2656 vtkPiece.setCellType(currentCell, 22); // Quadratic triangle
2657
2658 currentCell++;
2659 }
2660 }
2661
2662 // Export nodal variables from primary fields
2663 vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes);
2664
2665 std::vector<FloatArray> values;
2666 for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) {
2667 UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum);
2668 nodeNum = 1;
2669 currentCell = 1;
2670 for ( int layer = 1; layer <= numInterfaces; layer++ ) {
2671 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2672
2673 if ( type == DisplacementVector ) { // compute displacement as u = x - X
2674 auto nodeCoords = numSubCells == 1 ?
2675 Shell7Base :: giveFictiousCZNodeCoordsForExport(layer) :
2676 this->giveFictiousCZNodeCoordsForExport(layer, subCell);
2677
2678 auto updatedNodeCoords = this->giveFictiousUpdatedCZNodeCoordsForExport(layer, tStep, numSubCells == 1 ? 0 : subCell);
2679
2680 for ( int j = 1; j <= numCellNodes; j++ ) {
2681 auto u = updatedNodeCoords[j-1] - nodeCoords[j-1];
2682 vtkPiece.setPrimaryVarInNode(type, nodeNum, u);
2683 nodeNum += 1;
2684 }
2685
2686 } else {
2687 NodalRecoveryMI_recoverValues(values, layer, ( InternalStateType ) 1, tStep); // does not work well - fix
2688 for ( int j = 1; j <= numCellNodes; j++ ) {
2689 vtkPiece.setPrimaryVarInNode(type, nodeNum, values[j-1]);
2690 nodeNum += 1;
2691 }
2692 }
2693
2694 currentCell++;
2695 }
2696 }
2697 }
2698
2699 // Export nodal variables from internal fields
2700
2701 vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes );
2702 for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) {
2703 InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum);
2704 nodeNum = 1;
2705
2706 //int currentCell = 1;
2707 for ( int layer = 1; layer <= numInterfaces; layer++ ) {
2708 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2709 this->recoverValuesFromCZIP(values, layer, type, tStep);
2710
2711 for ( int j = 1; j <= numCellNodes; j++ ) {
2712 vtkPiece.setInternalVarInNode( type, nodeNum, values[j-1] );
2713 //ZZNodalRecoveryMI_recoverValues(el.nodeVars[fieldNum], layer, type, tStep);
2714 nodeNum += 1;
2715 }
2716 }
2717 }
2718 }
2719
2720
2721 // Export cell variables
2722 FloatArray average;
2723 vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells);
2724 for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) {
2725 InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i);
2727 currentCell = 1;
2728 for ( int layer = 1; layer <= numInterfaces; layer++ ) {
2729 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2730 if ( type == IST_CrossSectionNumber ) {
2731 average = FloatArray{ -double(layer) }; // Set a negative number for interfaces
2732 } else {
2733 std :: unique_ptr< IntegrationRule > &iRuleL = integrationRulesArray [ layer - 1 ];
2734 VTKXMLExportModule::computeIPAverage(average, iRuleL.get(), this, type, tStep);
2735 }
2736 if ( valueType == ISVT_TENSOR_S3 ) {
2737 vtkPiece.setCellVar(type, currentCell, convV6ToV9Stress(average) );
2738 } else {
2739 vtkPiece.setCellVar(type, currentCell, average);
2740 }
2741 currentCell += 1;
2742 }
2743 }
2744
2745 }
2746
2747
2748#if 0
2749
2750
2751 // Export of XFEM related quantities
2752 XfemManager *xFemMan = this->xMan;
2753 int nEnrIt = xFemMan->giveNumberOfEnrichmentItems();
2754
2755 IntArray wedgeToTriMap({15, 1, 2, 3, 1, 2, 3, 4, 5, 6, 4, 5, 6, 1, 2, 3} );
2756 // For each node in the wedge take the value from the triangle node given by the map below
2757 // wedgeToTriMap.setValues;
2758
2759 vtkPiece.setNumberOfInternalXFEMVarsToExport(xFemMan->vtkExportFields.giveSize(), nEnrIt, numTotalNodes);
2760 for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) {
2761 XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ];
2762
2763 for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) {
2764 EnrichmentItem *ei = xFemMan->giveEnrichmentItem(enrItIndex);
2765 int nodeNum = 1;
2766 for ( int layer = 1; layer <= numInterfaces; layer++ ) {
2767 FloatMatrix localNodeCoords;
2768
2769 for ( int subCell = 1; subCell <= numSubCells; subCell++ ) {
2770 FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, nodeLocalXi3CoordsMapped;
2771 if ( numSubCells == 1) {
2772 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords);
2773 } else {
2774 giveLocalNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, layer, localNodeCoords);
2775 }
2776 mapXi3FromLocalToShell(nodeLocalXi3CoordsMapped, nodeLocalXi3Coords, layer);
2777 for ( int nodeIndx = 1; nodeIndx <= numCellNodes; nodeIndx++ ) {
2778
2779 FloatArray lCoords;
2780 //lCoords.setValues(3, nodeLocalXi1Coords.at(nodeIndx), nodeLocalXi2Coords.at(nodeIndx), nodeLocalXi3CoordsMapped.at(nodeIndx));
2781 lCoords.beColumnOf(localNodeCoords, nodeIndx);
2782 //Node *node = this->giveNode( wedgeToTriMap.at(nodeIndx) );
2783 Node *node = this->giveNode( nodeIndx );
2784 FloatArray valueArray;
2785 const FloatArray *val = NULL;
2786 if ( xfemstype == XFEMST_LevelSetPhi ) {
2787 valueArray.resize(1);
2788 val = & valueArray;
2789 valueArray.at(1) = this->evaluateLevelSet(lCoords, ei);
2790 } else if ( xfemstype == XFEMST_LevelSetGamma ) {
2791 valueArray.resize(1);
2792 val = & valueArray;
2793 ei->evalLevelSetTangInNode( valueArray.at(1), node->giveNumber() , node->giveNodeCoordinates());
2794 } else if ( xfemstype == XFEMST_NodeEnrMarker ) {
2795 valueArray.resize(1);
2796 val = & valueArray;
2797 ei->evalNodeEnrMarkerInNode( valueArray.at(1), node->giveNumber() );
2798 } else {
2799 //OOFEM_WARNING2("VTKXMLExportModule::getNodalVariableFromXFEMST: invalid data in node %d", inode);
2800 }
2801
2802 vtkPiece.setInternalXFEMVarInNode(field, enrItIndex, nodeNum, valueArray);
2803 nodeNum += 1;
2804 }
2805 }
2806 }
2807 }
2808 }
2809#endif
2810}
2811
2812void
2813Shell7BaseXFEM :: recoverValuesFromCZIP(std::vector<FloatArray> &recoveredValues, int interfce, InternalStateType type, TimeStep *tStep)
2814{
2815 // recover nodal values by coosing the ip closest to the node
2816
2817 // composite element interpolator
2818 FloatMatrix localNodeCoords;
2819 //this->interpolationForExport.giveLocalNodeCoords(localNodeCoords);
2820 this->interpolationForCZExport.giveLocalNodeCoords(localNodeCoords, EGT_triangle_2);
2821 int numNodes = localNodeCoords.giveNumberOfColumns();
2822 recoveredValues.resize(numNodes);
2823
2824 std :: unique_ptr< IntegrationRule > &iRule = this->czIntegrationRulesArray [ interfce - 1 ];
2825
2826 // Find closest ip to the nodes
2827 IntArray closestIPArray(numNodes);
2828 FloatArray nodeCoords, ipValues;
2829
2830 for ( int i = 1; i <= numNodes; i++ ) {
2831 nodeCoords.beColumnOf(localNodeCoords, i);
2832 double distOld = 3.0; // should not be larger
2833 for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) {
2834 IntegrationPoint *ip = iRule->getIntegrationPoint(j);
2835 double dist = distance(nodeCoords, ip->giveNaturalCoordinates());
2836 if ( dist < distOld ) {
2837 closestIPArray.at(i) = j;
2838 distOld = dist;
2839 }
2840 }
2841 }
2842
2844
2845 // recover ip values
2846 for ( int i = 1; i <= numNodes; i++ ) {
2847 if ( this->layeredCS->giveInterfaceMaterial(interfce) ) {
2848 IntegrationPoint *ip = iRule->getIntegrationPoint( closestIPArray.at(i) );
2849 this->layeredCS->giveInterfaceMaterial(interfce)->giveIPValue(ipValues, ip, type, tStep);
2850 } else {
2851 ipValues.resize(0);
2852 }
2853
2854 if ( ipValues.giveSize() == 0 && type == IST_AbaqusStateVector) {
2855 recoveredValues[i-1].resize(23);
2856 recoveredValues[i-1].zero();
2857 } else if ( ipValues.giveSize() == 0 ) {
2858 recoveredValues[i-1].resize(giveInternalStateTypeSize(valueType));
2859 recoveredValues[i-1].zero();
2860 } else if ( valueType == ISVT_TENSOR_S3 ) {
2861 recoveredValues[i-1] = convV6ToV9Stress(ipValues);
2862
2863 } else {
2864 recoveredValues[i-1] = ipValues;
2865 }
2866 }
2867}
2868
2869
2870void
2871Shell7BaseXFEM :: computeTripleProduct(FloatMatrix &answer, const FloatMatrix &a, const FloatMatrix &b, const FloatMatrix &c)
2872{
2873 // Computes the product a^T*b*c
2874 FloatMatrix temp;
2875 temp.beTProductOf(a, b);
2876 answer.beProductOf(temp, c);
2877}
2878
2879
2880void
2881Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep)
2882{
2883 // Recover shear stresses at ip by numerical integration of the momentum balance through the thickness (overloaded from shell7base)
2884
2885 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
2886
2887 // Check if delamination/CZ is active. Then use hasCohesiveZone to decide whether the cohforces need to be calculated (otherwise traction BC need to be found)
2888 // Find (possible) layer/interface BC, starting from bottom
2889// IntArray layerHasBC(numberOfLayers+1); layerHasBC.zero();
2890 IntArray delaminationInterface; delaminationInterface.clear(); // interface (starting from 1) which contains delamination
2891 IntArray interfaceEI(numberOfLayers-1);
2892
2893 bool hasDelamination = false;
2894 int numEI = this->xMan->giveNumberOfEnrichmentItems();
2895 for ( int iEI = 1; iEI <= numEI; iEI++ ) {
2896
2897 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(iEI);
2898 if ( ei->isElementEnriched(this) ) {
2899 hasDelamination = true;
2900 // Find cohesive material (for delamination)
2901 Delamination *dei = dynamic_cast< Delamination * >( ei );
2902 int delaminationInterfaceNum = dei->giveDelamInterfaceNum();
2903// layerHasBC.at(delaminationInterfaceNum+1) = iEI;
2904 delaminationInterface.followedBy(delaminationInterfaceNum);
2905 interfaceEI.at(delaminationInterfaceNum) = iEI;
2906 }
2907 }
2908 delaminationInterface.sort();
2909
2910 if ( hasDelamination ) {
2911
2912 int numInPlaneIP = 6;
2913 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2914 if (numThicknessIP < 2) {
2915 // Polynomial fit involves linear z-component at the moment
2916 OOFEM_ERROR("To few thickness IP per layer to do polynomial fit");
2917 }
2918
2919 int numDel = delaminationInterface.giveSize();
2920
2921 // Find top and bottom BC NB: assumes constant over element surface.
2922 // traction BC added to vector of BC.
2923 std::vector <FloatMatrix> tractionBC; tractionBC.resize(numDel+2);
2924 tractionBC[numDel+1].resize(3,numInPlaneIP);
2925 tractionBC[0].resize(3,numInPlaneIP);
2926 giveTractionBC(tractionBC[numDel+1],tractionBC[0], tStep);
2927 //if (this->giveGlobalNumber() == 8 || this->giveGlobalNumber() == 50) {tractionBC[numDel+1].printYourself("tractionTop"); tractionBC[0].printYourself("tractionBtm");}
2928
2929#if 0
2930 FloatArray tractionTop, tractionBtm;
2931 giveTractionBC(tractionTop,tractionBtm, tStep);
2932 for ( int i = 1 ; i <= numInPlaneIP ; i++) {
2933 tractionBC[0].at(1,i) = tractionBtm.at(1);
2934 tractionBC[0].at(2,i) = tractionBtm.at(2);
2935 tractionBC[0].at(3,i) = tractionBtm.at(3);
2936 tractionBC[numDel+1].at(1,i) = tractionTop.at(1);
2937 tractionBC[numDel+1].at(2,i) = tractionTop.at(2);
2938 tractionBC[numDel+1].at(3,i) = tractionTop.at(3);
2939 }
2940#endif
2941 // Find delamination traction BC
2942 for (int iDel = 1 ; iDel <= numDel ; iDel++) {
2943
2944 tractionBC[iDel].resize(3,numInPlaneIP);
2945
2946 int interfaceNum = delaminationInterface.at(iDel);
2947 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(interfaceEI.at(interfaceNum));
2948 Delamination *dei = dynamic_cast< Delamination * >( ei );
2949
2950 if ( this->hasCohesiveZone( interfaceNum ) ) {
2951#if 1
2952 // CZ traction
2953 std :: unique_ptr< IntegrationRule > &iRuleI = this->czIntegrationRulesArray [ interfaceNum - 1 ];
2954 if (czIntegrationRulesArray [ interfaceNum - 1 ]->giveNumberOfIntegrationPoints() != numInPlaneIP ) {
2955 OOFEM_ERROR("Interface IPs doesn't match the element IPs");
2956 }
2957 StructuralInterfaceMaterial *intMat = dynamic_cast < StructuralInterfaceMaterial * > (this->layeredCS->giveInterfaceMaterial(interfaceNum) );
2958 if (intMat == 0) {
2959 OOFEM_ERROR("NULL pointer to material, shell element %i",this->giveGlobalNumber());
2960 }
2961
2962 FloatArray lCoords(3), nCov, CZPKtraction(3);
2963 FloatMatrix Q;
2964 int iIGP = 1;
2965 for ( GaussPoint *gp : *iRuleI ) {
2966 double xi = dei->giveDelamXiCoord();
2967 lCoords.at(1) = gp->giveNaturalCoordinate(1);
2968 lCoords.at(2) = gp->giveNaturalCoordinate(2);
2969 lCoords.at(3) = xi;
2970
2971 //FloatArray GPcoords = gp->giveGlobalCoordinates();
2972 //if (this->giveGlobalNumber() == 126) { GPcoords.printYourself("interface GPs"); }
2973// this->evalInitialCovarNormalAt(nCov, lCoords); // intial coords
2974
2975 // Find PK-traction in current coords.
2976 FloatArray solVecC;
2977 this->giveUpdatedSolutionVector(solVecC, tStep);
2978 FloatMatrix B;
2979 this->computeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei
2980 FloatArray genEpsC;
2981 genEpsC.beProductOf(B, solVecC);
2982 nCov = this->evalCovarNormalAt(lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen?
2983 Q.beLocalCoordSys(nCov);
2984
2985#if 0
2986 // Compute 1PK traction from jump vector
2988 this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep, jump); // -> numerical tol. issue -> normal jump = 1e-10
2989
2990 genEpsC.beProductOf(B, solVecC);
2991 FloatMatrix F;
2992 this->computeFAt(lCoords, F, genEpsC, tStep);
2993
2994 // Transform xd and F to a local coord system
2995 this->evalInitialCovarNormalAt(nCov, lCoords);
2996 Q.beLocalCoordSys(nCov);
2997 jump.rotatedWith(Q,'n');
2998 F.rotatedWith(Q,'n');
2999
3000 // Compute cohesive traction based on jump
3001 intMat->giveFirstPKTraction_3d(CZPKtraction, gp, jump, F, tStep);
3002#else
3003 // Get 1PK traction directly from interface material status.
3004 StructuralInterfaceMaterialStatus *intMatStatus = dynamic_cast < StructuralInterfaceMaterialStatus * >( intMat->giveStatus(gp) );
3005 if (intMatStatus == 0) {
3006 OOFEM_ERROR("NULL pointer to interface material, shell element %i",this->giveGlobalNumber());
3007 }
3008 CZPKtraction = intMatStatus->giveTempFirstPKTraction(); // 3 components in local coords
3009#endif
3010
3011 CZPKtraction.rotatedWith(Q,'t'); // transform back to global coord system
3012 //if (this->giveGlobalNumber() == 9 ) { CZPKtraction.printYourself("CZPKtraction");}
3013
3014 // Set BC stresses
3015 tractionBC[iDel].at(1,iIGP) = CZPKtraction.at(1);
3016 tractionBC[iDel].at(2,iIGP) = CZPKtraction.at(2);
3017 tractionBC[iDel].at(3,iIGP) = CZPKtraction.at(3);
3018 iIGP++;
3019 }
3020#endif
3021 } else {
3022 // Delamination zero traction
3023 tractionBC[iDel].zero();
3024 }
3025 //if (this->giveGlobalNumber() == 50) {tractionBC[iDel].printYourself("tractionDel");}
3026 }
3027
3028 FloatMatrix SmatOld(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
3029 double totalThickness = this->layeredCS->computeIntegralThick();
3030 double zeroThicknessLevel = - 0.5 * totalThickness; // assumes midplane is the geometric midplane of layered structure.
3031 FloatMatrix dSmat(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
3032 FloatMatrix dSmatLayerIP(3,numInPlaneIP*numThicknessIP); // 3 stress components (S_xz, S_yz, S_zz) * num of wedge ip
3033
3034 int layerOld = 0;
3035 int iInt = 0;
3036 delaminationInterface.followedBy(numberOfLayers); // creates an array of the layer index of the top layer in a delamination (NB: index = numberOfLayers will allways be the last)
3037 for ( int topLayer : delaminationInterface) {
3038 SmatOld = tractionBC[iInt]; // bottom traction BC of delamination
3039 int numDelLayers = topLayer-layerOld; // number of layers in delamination
3040 std::vector <FloatMatrix> dSmatIP; dSmatIP.resize(numDelLayers); //recovered stress values in wedge IPs
3041 std::vector <FloatMatrix> dSmat; dSmat.resize(numDelLayers); //recovered stress values at delamination top
3042 std::vector <FloatMatrix> dSmatIPupd; dSmatIPupd.resize(numDelLayers); //recovered stress values in wedge IPs adjusted for top and btm traction BC.
3043 std::vector <FloatMatrix> dSmatupd; dSmatupd.resize(numDelLayers); //recovered stress values at delamination top, adjusted for top and btm traction BC
3044
3045 // Recovered stresses in delaminated layers
3046 double dz = 0.0;
3047 for ( int delLayer = 1 ; delLayer <= numDelLayers; delLayer++ ) {
3048 this->giveLayerContributionToSR(dSmat[delLayer-1], dSmatIP[delLayer-1], delLayer+layerOld, zeroThicknessLevel + dz, tStep);
3049 SmatOld.add(dSmat[delLayer-1]); // Integrated stress over laminate
3050 dz += this->layeredCS->giveLayerThickness(delLayer+layerOld);
3051
3052 }
3053
3054 // Adjust recovered stresses to traction BC (divide integration error 50/50 at top and btm of delamination)
3055 this->fitRecoveredStress2BC(dSmatIPupd, dSmatupd, dSmat, dSmatIP, SmatOld, tractionBC[iInt], tractionBC[iInt+1], zeroThicknessLevel, {0.0,0.0,1.0}, layerOld+1, topLayer);
3056
3057 for ( int layer = 1 ; layer <= numDelLayers; layer++ ) {
3058 //if (this->giveGlobalNumber() == 48 ) { dSmatIPupd[layer-1].printYourself(); }
3059 this->updateLayerTransvStressesSR( dSmatIPupd[layer-1], layer+layerOld);
3060 }
3061 zeroThicknessLevel += dz;
3062 layerOld = topLayer;
3063 iInt++;
3064 }
3065#if 0
3066 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
3067
3068 // Bör det vara this här istället för Shell7Base?
3069// Shell7Base :: giveLayerContributionToSR(dSmat, dSmatLayerIP, layer, zeroThicknessLevel, tStep); // NB: performed in global system
3070 this->giveLayerContributionToSR(dSmat, dSmatLayerIP, layer, zeroThicknessLevel, tStep); // NB: performed in global system
3071
3072// Shell7Base :: updateLayerStressesSR(dSmatLayerIP, SmatOld, layer);
3073 this->updateLayerTransvStressesSR(dSmatLayerIP, SmatOld, layer);
3074 //dSmatLayerIP.printYourself();
3075 //printf("enr func in dofman %d = %e \n", layer, layer);
3076
3077 SmatOld.add(dSmat);
3078 if (this->giveGlobalNumber() == 126) {
3079 SmatOld.printYourself();
3080 }
3081 zeroThicknessLevel += this->layeredCS->giveLayerThickness(layer);
3082
3083 // Add traction from delamination CZ. NB: assumes same number order of GPs in interface and shell elements
3084 if ( layerHasBC.at(layer+1) ) {
3085
3086 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(layerHasBC.at(layer+1));
3087 Delamination *dei = dynamic_cast< Delamination * >( ei );
3088 int interfaceNum = dei->giveDelamInterfaceNum();
3089
3090 if ( this->hasCohesiveZone( interfaceNum ) ) {
3091#if 1
3092 // CZ traction
3093 std :: unique_ptr< IntegrationRule > &iRuleI = czIntegrationRulesArray [ interfaceNum - 1 ];
3094 if (iRuleI->giveNumberOfIntegrationPoints() != numInPlaneIP ) {
3095 OOFEM_ERROR("Interface IPs doesn't match the element IPs");
3096 }
3097
3098 FloatArray lCoords(3), nCov, CZPKtraction(3);
3099 CZPKtraction.zero();
3100 FloatMatrix Q;
3101 int iIGP = 1;
3102 for ( GaussPoint *gp: *iRuleI ) {
3103 double xi = dei->giveDelamXiCoord();
3104 lCoords.at(1) = gp->giveNaturalCoordinate(1);
3105 lCoords.at(2) = gp->giveNaturalCoordinate(2);
3106 lCoords.at(3) = xi;
3107 #if 0
3108 FloatArray GPcoords = gp->giveGlobalCoordinates();
3109 if (this->giveGlobalNumber() == 126) {
3110 GPcoords.printYourself("interface GPs");
3111 }
3112 #endif
3113// this->evalInitialCovarNormalAt(nCov, lCoords); // intial coords
3114
3115 // Find PK-traction in current coords.
3116 FloatArray solVecC;
3117 this->giveUpdatedSolutionVector(solVecC, tStep);
3118 FloatMatrix B;
3119 this->computeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei
3120 FloatArray genEpsC;
3121 genEpsC.beProductOf(B, solVecC);
3122 this->evalCovarNormalAt(nCov, lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen?
3123 Q.beLocalCoordSys(nCov);
3124
3125 StructuralInterfaceMaterialStatus* intMatStatus = static_cast < StructuralInterfaceMaterialStatus* > ( gp->giveMaterialStatus() );
3126 if (intMatStatus == 0) {
3127 OOFEM_ERROR("NULL pointer to material status");
3128 }
3129
3130 CZPKtraction = intMatStatus->giveFirstPKTraction(); // 3 components in local coords
3131
3132 CZPKtraction.rotatedWith(Q,'t'); // transform back to global coord system
3133 #if 0
3134 if (this->giveGlobalNumber() == 126) {
3135 CZPKtraction.printYourself();
3136 }
3137 #endif
3138 // Set BC stresses
3139 SmatOld.at(1,iIGP) = CZPKtraction.at(1);
3140 SmatOld.at(2,iIGP) = CZPKtraction.at(2);
3141 SmatOld.at(3,iIGP) = CZPKtraction.at(3);
3142 iIGP++;
3143#endif
3144 }
3145 } else {
3146 // Delamination zero traction
3147 SmatOld.zero();
3148 }
3149 # if 0
3150 if (this->giveGlobalNumber() == 126) {
3151 SmatOld.printYourself();
3152 }
3153 # endif
3154 }
3155 }
3156#endif
3157
3158 } else {
3159 Shell7Base :: recoverShearStress(tStep);
3160 }
3161
3162}
3163
3164
3165void
3166Shell7BaseXFEM :: giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArray &initiationFactors, TimeStep *tStep, bool recoverStresses)
3167{
3168 // Compares recovered interface stresses to initiation stress (atm just max stress criterion).
3169 // Assumes three stress components in initiationStress: (Sxz, Syz, Szz)
3170 // Returns any new interface that needs to be enriched.
3172
3173 failedInterfaces.clear();
3174 std :: vector < FloatMatrix > transverseInterfaceStresses;
3175 if (recoverStresses) {
3176 // Find interface stresses using stress recovery
3177 this->giveRecoveredTransverseInterfaceStress(transverseInterfaceStresses, tStep);
3178 } else {
3179 // Take average stresses of adjacent layers.
3180 this->giveAverageTransverseInterfaceStress(transverseInterfaceStresses, tStep);
3181 }
3182 int numSC = 3;
3183 //initiationFactors.resizeWithValues(this->layeredCS->giveNumberOfLayers());
3184 FloatArray interfaceXiCoords;
3185 this->giveLayeredCS()->giveInterfaceXiCoords(interfaceXiCoords);
3186 FloatMatrix failurestresses(2,this->layeredCS->giveNumberOfLayers());
3187
3188 for ( int iInterface = 1 ; iInterface < this->layeredCS->giveNumberOfLayers() ; iInterface++ ) {
3189
3190 bool initiateElt = false;
3191 int interfaceMatNumber(this->giveLayeredCS()->giveInterfaceMaterialNum(iInterface));
3192
3193 if (interfaceMatNumber && !this->DelaminatedInterfaceList.findSorted(iInterface)) {
3194
3195 std :: unique_ptr< IntegrationRule > &iRuleI = this->czIntegrationRulesArray [ iInterface - 1 ];
3196
3197 IntArray failedSC;
3198 StructuralInterfaceMaterial *intMat = dynamic_cast < StructuralInterfaceMaterial * > (this->layeredCS->giveInterfaceMaterial(iInterface) );
3199 if (intMat == 0) {
3200 OOFEM_ERROR("NULL pointer to material, shell %i interface %i",this->giveGlobalNumber(),iInterface);
3201 }
3202
3203 FloatArray sigF = {1,1,1};
3204 FloatArray temp = intMat->giveInterfaceStrength();
3205 if (temp.giveSize() == 1 && temp.at(1) > 0) {
3206 // Same strength in all directions
3207 //sigF.times(temp.at(1)*initiationFactors.at(iInterface));
3208 sigF.times(temp.at(1));
3209 } else if (temp.giveSize() == 3) {
3210 // Assume S1,S1,N
3211 // sigF.beScaled(initiationFactors.at(iInterface),temp);
3212 sigF = temp;
3213 } else {
3214 OOFEM_ERROR( "Intitiation stress for delaminations not found or incorrect on CZ-material" );
3215 }
3216
3217 //if (this->giveGlobalNumber() == 9) {transverseInterfaceStresses[iInterface-1].printYourself("Interface stresses elt 9"); initiationStress.printYourself("initiationStress");}
3218
3219 for ( int iGP = 1 ; iGP <= transverseInterfaceStresses[iInterface-1].giveNumberOfColumns() ; iGP++ ) {
3220 if ( transverseInterfaceStresses[iInterface-1].giveNumberOfRows() != numSC ) {
3221 OOFEM_ERROR( "Wrong number of stress components" );
3222 }
3223
3224 // Collect interface stresses
3225 FloatArray interfaceStresses;
3226 interfaceStresses.beColumnOf(transverseInterfaceStresses[iInterface-1],iGP); // global coords
3227
3228 //Rotate to element coord.
3229 FloatArray lCoords; lCoords.resize(3);
3230 GaussPoint *gp = iRuleI->getIntegrationPoint(iGP-1);
3231 lCoords.at(1) = gp->giveNaturalCoordinate(1);
3232 lCoords.at(2) = gp->giveNaturalCoordinate(2);
3233 lCoords.at(3) = interfaceXiCoords.at(iInterface);
3234
3235 FloatArray solVecC, nCov;
3236 this->giveUpdatedSolutionVector(solVecC, tStep);
3237 FloatMatrix Q,B;
3238 this->computeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei
3239 FloatArray genEpsC;
3240 genEpsC.beProductOf(B, solVecC);
3241 nCov = this->evalCovarNormalAt(lCoords, genEpsC, tStep);
3242 Q.beLocalCoordSys(nCov);
3243
3244 //if (this->giveGlobalNumber() == 61) {interfaceStresses.printYourself("interfaceStresses global"); lCoords.printYourself("lCoords"); }
3245
3246 interfaceStresses.rotatedWith(Q,'n'); // local coords
3247 double S1(interfaceStresses.at(1)); //Shear x
3248 double S2(interfaceStresses.at(2)); //Shear y
3249 double N(interfaceStresses.at(3)); //normal
3250 //if (this->giveGlobalNumber() == 61) {Q.printYourself("Q"); interfaceStresses.printYourself("interfaceStresses local");}
3251
3252 // polynom law
3253 double NM = 0.5*(N + fabs(N));
3254 double failCrit = NM*NM/(sigF.at(3)*sigF.at(3)) + (S1*S1 + S2*S2)/(sigF.at(1)*sigF.at(1));
3255 if (failCrit > (initiationFactors.at(iInterface)*initiationFactors.at(iInterface))) {
3256 initiateElt = true;
3257 failurestresses.at(1,iInterface) = NM;
3258 failurestresses.at(2,iInterface) = sqrt(S1*S1 + S2*S2);
3259 }
3260
3261 // Max stress criterion
3262// for ( int iSC = 1 ; iSC <= numSC ; iSC++ ) {
3263// if ( transverseInterfaceStresses[iInterface-1].at(iSC,iGP) > sigF.at(iSC) || (-transverseInterfaceStresses[iInterface-1].at(iSC,iGP)) > sigF.at(iSC)) {
3264// printf("SC%i = %1.0f, limit = %1.0f \n", iSC, transverseInterfaceStresses[iInterface-1].at(iSC,iGP), sigF.at(iSC));
3265// initiateElt = true;
3266// failedSC.followedBy(iSC);
3267// ///TODO: add break/continue;
3268// }
3269// }
3270 }
3271 if (initiateElt) {
3272 failedInterfaces.followedBy( iInterface );
3273// printf(" Element %i failed in interface %i. \n",this->giveGlobalNumber(),iInterface);
3274// for (auto iSC : failedSC) {
3275// printf(" %i ",iSC);
3276// }
3277// printf("\n");
3278 }
3279 }
3280 }
3281// if (!failedInterfaces.isEmpty()) {
3282// for ( int alreadyFailedInterface : this->DelaminatedInterfaceList ) {
3283// failedInterfaces.eraseSorted(alreadyFailedInterface);
3284// }
3285// }
3286 this->DelaminatedInterfaceList.followedBy(failedInterfaces);
3287 this->DelaminatedInterfaceList.sort();
3288 if (failedInterfaces.giveSize() > 0) {
3289 printf(" Delamination criterion was activated in element %i : \n",this->giveGlobalNumber() );//
3290 for (auto iInterface : failedInterfaces) {
3291 printf(" Interface %i - NM = %f, S = %f \n",iInterface,failurestresses.at(1,iInterface),failurestresses.at(2,iInterface));
3292 }
3293 printf("\n");
3294 }
3295}
3296
3297void
3298Shell7BaseXFEM::giveAverageTransverseInterfaceStress(std::vector< FloatMatrix >& transverseStress, TimeStep* tStep)
3299{
3300 transverseStress.clear();
3301 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
3302 transverseStress.resize(numberOfLayers-1);
3303 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
3304 int numInPlaneIP = 6;
3305
3306 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
3307 std :: unique_ptr< IntegrationRule > &iRule = this->integrationRulesArray[layer-1];
3308 if (layer < numberOfLayers) {
3309 transverseStress[layer-1].resize(3,numInPlaneIP);
3310 }
3311
3312 for ( int j = 0; j < numInPlaneIP; j++ ) {
3313
3314 // thickness GPs
3315 for ( int i = 0; i < numThicknessIP; i++ ) {
3316
3317 int point = i*numInPlaneIP + j; // wedge integration point number
3318 IntegrationPoint *ip = iRule->getIntegrationPoint(point);
3319 // Collect IP-value
3320 FloatArray tempIPvalues;
3321 this->giveIPValue(tempIPvalues, ip, IST_StressTensor, tStep);
3322
3323 for ( int iInt = layer-1 ; iInt <= layer ; iInt++ ) {
3324 if ( iInt > 0 && iInt < numberOfLayers ) {
3325 transverseStress[iInt-1].at(1,j+1) += (0.5/numThicknessIP)*tempIPvalues.at(5);
3326 transverseStress[iInt-1].at(2,j+1) += (0.5/numThicknessIP)*tempIPvalues.at(4);
3327 transverseStress[iInt-1].at(3,j+1) += (0.5/numThicknessIP)*tempIPvalues.at(3);
3328 }
3329 }
3330 }
3331 }
3332 }
3333}
3334
3335
3336void
3337Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vector<FloatMatrix> &transverseStress, TimeStep *tStep)
3338{
3339 transverseStress.clear();
3340 // Recover shear stresses at ip by numerical integration of the momentum balance through the thickness (overloaded from shell7base)
3341
3342 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
3343
3344 IntArray delaminationInterface; delaminationInterface.clear(); // interface (starting from 1) which contains delamination
3345 IntArray interfaceEI(numberOfLayers-1);
3346
3347 bool hasDelamination = false;
3348 int numEI = this->xMan->giveNumberOfEnrichmentItems();
3349 for ( int iEI = 1; iEI <= numEI; iEI++ ) {
3350
3351 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(iEI);
3352 if ( ei->isElementEnriched(this) ) {
3353 hasDelamination = true;
3354 // Find cohesive material (for delamination)
3355 Delamination *dei = dynamic_cast< Delamination * >( ei );
3356 int delaminationInterfaceNum = dei->giveDelamInterfaceNum();
3357 delaminationInterface.followedBy(delaminationInterfaceNum);
3358 interfaceEI.at(delaminationInterfaceNum) = iEI;
3359 }
3360 }
3361 delaminationInterface.sort();
3362
3363 if ( hasDelamination ) {
3364 transverseStress.resize(numberOfLayers-1);
3365
3366 int numInPlaneIP = 6;
3367 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
3368 if (numThicknessIP < 2) {
3369 // Polynomial fit involves linear z-component at the moment
3370 OOFEM_ERROR("To few thickness IP per layer to do polynomial fit");
3371 }
3372
3373 int numDel = delaminationInterface.giveSize();
3374
3375 // Find top and bottom BC NB: assumes constant over element surface.
3376 // traction BC added to vector of BC.
3377 std::vector <FloatMatrix> tractionBC; tractionBC.resize(numDel+2);
3378 tractionBC[numDel+1].resize(3,numInPlaneIP);
3379 tractionBC[0].resize(3,numInPlaneIP);
3380 giveTractionBC(tractionBC[numDel+1],tractionBC[0], tStep);
3381
3382 // Find delamination traction BC
3383 for (int iDel = 1 ; iDel <= numDel ; iDel++) {
3384
3385 tractionBC[iDel].resize(3,numInPlaneIP);
3386
3387 int interfaceNum = delaminationInterface.at(iDel);
3388 EnrichmentItem *ei = this->xMan->giveEnrichmentItem(interfaceEI.at(interfaceNum));
3389 Delamination *dei = dynamic_cast< Delamination * >( ei );
3390
3391 if ( this->hasCohesiveZone( interfaceNum ) ) {
3392 // CZ traction
3393 std :: unique_ptr< IntegrationRule > &iRuleI = this->czIntegrationRulesArray [ interfaceNum - 1 ];
3394 if (czIntegrationRulesArray [ interfaceNum - 1 ]->giveNumberOfIntegrationPoints() != numInPlaneIP ) {
3395 OOFEM_ERROR("Interface IPs doesn't match the element IPs");
3396 }
3397 StructuralInterfaceMaterial *intMat = dynamic_cast < StructuralInterfaceMaterial * >
3398 (this->layeredCS->giveInterfaceMaterial(interfaceNum) );
3399
3400 FloatArray lCoords(3), nCov, CZPKtraction(3);
3401 CZPKtraction.zero();
3402 FloatMatrix Q;
3403 int iIGP = 1;
3404 for ( auto &gp : *iRuleI ) {
3405 double xi = dei->giveDelamXiCoord();
3406 lCoords.at(1) = gp->giveNaturalCoordinate(1);
3407 lCoords.at(2) = gp->giveNaturalCoordinate(2);
3408 lCoords.at(3) = xi;
3409
3410 // Find PK-traction in current coords.
3411 FloatArray solVecC;
3412 this->giveUpdatedSolutionVector(solVecC, tStep);
3413 FloatMatrix B;
3414 this->computeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei
3415 FloatArray genEpsC;
3416 genEpsC.beProductOf(B, solVecC);
3417 nCov = this->evalCovarNormalAt(lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen?
3418 Q.beLocalCoordSys(nCov);
3419
3420#if 0
3421 // Compute 1PK traction from jump vector
3423 this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep, jump); // -> numerical tol. issue -> normal jump = 1e-10
3424
3425 genEpsC.beProductOf(B, solVecC);
3426 FloatMatrix F;
3427 this->computeFAt(lCoords, F, genEpsC, tStep);
3428
3429 // Transform xd and F to a local coord system
3430 this->evalInitialCovarNormalAt(nCov, lCoords);
3431 Q.beLocalCoordSys(nCov);
3432 jump.rotatedWith(Q,'n');
3433 F.rotatedWith(Q,'n');
3434
3435 // Compute cohesive traction based on jump
3436 intMat->giveFirstPKTraction_3d(CZPKtraction, gp, jump, F, tStep);
3437#else
3438 // Get 1PK traction directly from interface material status.
3439 StructuralInterfaceMaterialStatus *intMatStatus = dynamic_cast < StructuralInterfaceMaterialStatus * >( intMat->giveStatus(gp) );
3440 if (intMatStatus == 0) {
3441 OOFEM_ERROR("NULL pointer to interface material, shell element %i",this->giveGlobalNumber());
3442 }
3443 CZPKtraction = intMatStatus->giveTempFirstPKTraction(); // 3 components in local coords
3444#endif
3445
3446 CZPKtraction.rotatedWith(Q,'t'); // transform back to global coord system
3447
3448 // Set BC stresses
3449 tractionBC[iDel].at(1,iIGP) = CZPKtraction.at(1);
3450 tractionBC[iDel].at(2,iIGP) = CZPKtraction.at(2);
3451 tractionBC[iDel].at(3,iIGP) = CZPKtraction.at(3);
3452 iIGP++;
3453 }
3454 } else {
3455 // Delamination zero traction
3456 tractionBC[iDel].zero();
3457 }
3458 }
3459
3460 FloatMatrix SmatOld(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
3461 double totalThickness = this->layeredCS->computeIntegralThick();
3462 double zeroThicknessLevel = - 0.5 * totalThickness; // assumes midplane is the geometric midplane of layered structure.
3463 FloatMatrix dSmat(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
3464 FloatMatrix dSmatLayerIP(3,numInPlaneIP*numThicknessIP); // 3 stress components (S_xz, S_yz, S_zz) * num of wedge ip
3465
3466 int layerOld = 0;
3467 int iInt = 0;
3468 delaminationInterface.followedBy(numberOfLayers); // creates an array of the layer index of the top layer in a delamination (NB: index = numberOfLayers will allways be the last)
3469 for ( int topLayer : delaminationInterface) {
3470 SmatOld = tractionBC[iInt]; // bottom traction BC of delamination
3471 int numDelLayers = topLayer-layerOld; // number of layers in delamination
3472 std::vector <FloatMatrix> dSmatIP; dSmatIP.resize(numDelLayers); //recovered stress values in wedge IPs
3473 std::vector <FloatMatrix> dSmat; dSmat.resize(numDelLayers); //recovered stress values at delamination top
3474 std::vector <FloatMatrix> dSmatIPupd; dSmatIPupd.resize(numDelLayers); //recovered stress values in wedge IPs adjusted for top and btm traction BC.
3475 std::vector <FloatMatrix> dSmatupd; dSmatupd.resize(numDelLayers); //recovered stress values at delamination top, adjusted for top and btm traction BC
3476
3477 // Recovered stresses in delaminated layers
3478 double dz = 0.0;
3479 for ( int delLayer = 1 ; delLayer <= numDelLayers; delLayer++ ) {
3480 this->giveLayerContributionToSR(dSmat[delLayer-1], dSmatIP[delLayer-1], delLayer+layerOld, zeroThicknessLevel + dz, tStep);
3481 SmatOld.add(dSmat[delLayer-1]); // Integrated stress over laminate
3482 dz += this->layeredCS->giveLayerThickness(delLayer+layerOld);
3483 }
3484
3485 // Adjust recovered stresses to traction BC (divide integration error 50/50 at top and btm of delamination)
3486
3487 this->fitRecoveredStress2BC(dSmatIPupd, dSmatupd, dSmat, dSmatIP, SmatOld, tractionBC[iInt], tractionBC[iInt+1], zeroThicknessLevel, {0.0,0.0,1.0}, layerOld+1, topLayer);
3488
3489 for ( int delLayer = 1 ; delLayer <= numDelLayers; delLayer++ ) {
3490 if ( (delLayer + layerOld) < numberOfLayers ) {
3491 transverseStress[delLayer+layerOld-1] = dSmatupd[delLayer-1];
3492 }
3493 }
3494
3495 zeroThicknessLevel += dz;
3496 layerOld = topLayer;
3497 iInt++;
3498 }
3499
3500 } else {
3501 Shell7Base :: giveRecoveredTransverseInterfaceStress(transverseStress, tStep);
3502 }
3503}
3504
3505
3506} // end namespace oofem
#define N(a, b)
void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override
int giveApproxOrder() override=0
CoordSystType giveCoordSystMode() override
void giveElementNeighbourList(IntArray &answer, const IntArray &elemList)
int giveDelamInterfaceNum() const
double giveBoundingDelamXiCoord() const
double giveDelamXiCoord() const
void evaluateEnrFuncAt(std ::vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override
int giveGlobalNumber() const
Definition dofmanager.h:515
std::vector< Dof * >::const_iterator findDofWithDofId(DofIDItem dofID) const
Definition dofmanager.C:274
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
std::vector< Dof * >::iterator begin()
Definition dofmanager.h:161
int giveGlobalNumber() const
Definition element.h:1129
Node * giveNode(int i) const
Definition element.h:629
IntArray boundaryLoadArray
Definition element.h:147
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
const IntArray & giveDofManArray() const
Definition element.h:611
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
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 bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
Definition element.C:1240
bool evalNodeEnrMarkerInNode(double &oNodeEnrMarker, int iNodeInd) const
virtual void giveEIDofIdArray(IntArray &answer) const
bool evalLevelSetTangInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
bool isElementEnriched(const Element *element) const
bool isDofManEnriched(const DofManager &iDMan) const
virtual void evaluateEnrFuncAt(std ::vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const =0
bool evalLevelSetNormalInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
Stores all neccessary data (of a region) in a VTKPiece so it can be exported later.
void setCellVar(InternalStateType type, int cellNum, FloatArray valueArray)
void setInternalVarInNode(InternalStateType type, int nodeNum, FloatArray valueArray)
void setInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum, FloatArray valueArray)
void setCellType(int cellNum, int type)
void setNumberOfCellVarsToExport(const IntArray &cellVars, int numCells)
void setNumberOfInternalVarsToExport(const IntArray &ists, int numNodes)
void setNumberOfInternalXFEMVarsToExport(int numVars, int numEnrichmentItems, int numNodes)
void setNumberOfPrimaryVarsToExport(const IntArray &primVars, int numNodes)
void setConnectivity(int cellNum, IntArray &nodes)
void setPrimaryVarInNode(UnknownType type, int nodeNum, FloatArray valueArray)
void setOffset(int cellNum, int offset)
void setNumberOfCells(int numCells)
void setNodeCoords(int nodeNum, const FloatArray &coords)
void setNumberOfNodes(int numNodes)
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int giveNumber() const
Definition femcmpnn.h:104
std ::vector< std ::vector< FloatArray > > quantities
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
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void beColumnOf(const FloatMatrix &mat, int col)
virtual void printYourself() const
Definition floatarray.C:762
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:721
void add(const FloatArray &src)
Definition floatarray.C:218
void subtract(const FloatArray &src)
Definition floatarray.C:320
void beSubArrayOf(const FloatArray &src, const IntArray &indx)
Definition floatarray.C:440
void times(double s)
Definition floatarray.C:834
double at(std::size_t i, std::size_t j) const
static FloatMatrixF< N, M > fromColumns(FloatArrayF< N > const (&x)[M]) noexcept
void times(double f)
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
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
void beSubMatrixOf(const FloatMatrix &src, Index topRow, Index bottomRow, Index topCol, Index bottomCol)
void plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
int giveNumberOfColumns() const
Returns number of columns of receiver.
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void addProductOf(const FloatMatrix &a, const FloatMatrix &b)
void beTranspositionOf(const FloatMatrix &src)
void zero()
Zeroes all coefficient of receiver.
void beLocalCoordSys(const FloatArray &normal)
*Prints matrix to stdout Useful for debugging void printYourself() const
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
void subtract(const FloatMatrix &a)
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
static FloatMatrix fromCols(std ::initializer_list< FloatArray >mat)
int SetUpPointsOnLine(int nPoints, MaterialMode mode) override
double giveNaturalCoordinate(int i) const
Returns i-th natural element coordinate of receiver.
Definition gausspoint.h:136
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
void interpLevelSet(double &oLevelSet, const FloatArray &iN, const IntArray &iNodeInd) const
Definition hybridei.C:70
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
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
virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode)=0
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
virtual double give(int aProperty, GaussPoint *gp) const
Definition material.C:51
std::vector< IntArray > activeDofsArrays
FEI3dTrQuad interpolationForCZExport
void edgeGiveUpdatedSolutionVector(FloatArray &answer, const int iedge, TimeStep *tStep) override
virtual void discComputeStiffness(FloatMatrix &LCC, FloatMatrix &LDD, FloatMatrix &LDC, IntegrationPoint *ip, int layer, FloatMatrix A[3][3], TimeStep *tStep)
void computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep)
double evaluateCutHeaviside(const double xi, const double xiBottom, const double xiTop) const
void giveDisUnknownsAt(const FloatArrayF< 3 > &lCoords, EnrichmentItem *ei, const FloatArray &solVec, FloatArrayF< 3 > &x, FloatArrayF< 3 > &m, double &gam, TimeStep *tStep)
FloatMatrixF< 3, 7 > computeLambdaNMatrixDis(double zeta)
void mapXi3FromLocalToShell(FloatArray &answer, FloatArray &local, int layer)
void edgeComputeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei, const int edge)
FloatArray computeSectionalForcesAt(IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta)
static ParamKey IPK_Shell7BaseXFEM_CohesiveZoneMaterial
void computeDiscGeneralizedStrainVector(FloatArray &dGenEps, const FloatArray &lCoords, EnrichmentItem *ei, TimeStep *tStep)
std ::vector< Triangle > allTri
std::vector< FloatArray > giveFictiousCZNodeCoordsForExport(int layer, int subCell)
void computeEnrTractionForce(FloatArray &answer, const int iedge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, EnrichmentItem *ei)
int giveNumberOfDofs() override
std ::vector< std ::unique_ptr< IntegrationRule > > czIntegrationRulesArray
void discComputeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, FloatArray &solVecD, EnrichmentItem *ei)
void giveAverageTransverseInterfaceStress(std::vector< FloatMatrix > &transverseStress, TimeStep *tStep)
void computeCohesiveNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei)
Shell7BaseXFEM(int n, Domain *d)
FloatArrayF< 3 > computeInterfaceJumpAt(int interf, const FloatArrayF< 3 > &lCoords, TimeStep *tStep)
void recoverValuesFromCZIP(std::vector< FloatArray > &recoveredValues, int interfce, InternalStateType type, TimeStep *tStep)
void computeOrderingArray(IntArray &orderingArray, IntArray &activeDofsArray, EnrichmentItem *ei)
std ::vector< std ::vector< Triangle > > crackSubdivisions
std::vector< FloatArray > giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep, int subCell)
void computePressureTangentMatrixDis(FloatMatrix &KCC, FloatMatrix &KCD, FloatMatrix &KDD, IntegrationPoint *ip, Load *load, const int iSurf, TimeStep *tStep)
virtual void OLDcomputeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
double evaluateHeavisideXi(double xi, ShellCrack *ei)
void jump(FloatMatrix lambda, FloatArray deltaUnknowns)
std::vector< FloatArray > giveFictiousUpdatedCZNodeCoordsForExport(int layer, TimeStep *tStep, int subCell)
void giveCZExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep)
double evaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei)
void giveRecoveredTransverseInterfaceStress(std::vector< FloatMatrix > &transverseStress, TimeStep *tStep) override
void giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, int layer, FloatMatrix &localNodeCoords)
void computeDiscSolutionVector(IntArray &dofIdArray, TimeStep *tStep, FloatArray &solVecD)
void edgeComputeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei, const int edge)
bool hasCohesiveZone(int interfaceNum)
void computeCohesiveForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, FloatArray &solVecD, EnrichmentItem *ei, EnrichmentItem *coupledToEi)
double EvaluateEnrFuncInDofMan(int dofManNum, EnrichmentItem *ei)
std::vector< FloatArray > giveFictiousNodeCoordsForExport(int layer, int subCell)
std::array< FloatMatrixF< 3, 18 >, 3 > computeLambdaGMatricesDis(double zeta)
FloatArrayF< 3 > vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF< 3 > &localCoords, int layer, TimeStep *tStep) override
void giveShellExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) override
void giveMaxCZDamages(FloatArray &answer, TimeStep *tStep)
void giveDofManDofIDMask(int inode, IntArray &answer) const override
void giveLocalCZNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, FloatMatrix &localNodeCoords)
void computeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei)
void computeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei)
void computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep, Delamination *dei, EnrichmentItem *ei_j, EnrichmentItem *ei_k)
FloatMatrixF< 3, 3 > evalCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords, FloatArray &solVec, TimeStep *tStep) override
std::vector< IntArray > orderingArrays
virtual void discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoint *ip, EnrichmentItem *eiI, EnrichmentItem *eiJ, int layer, FloatMatrix A[3][3], TimeStep *tStep)
FEI3dWedgeQuad interpolationForExport
void computeTripleProduct(FloatMatrix &answer, const FloatMatrix &a, const FloatMatrix &b, const FloatMatrix &c)
FloatMatrixF< 3, 3 > edgeEvalEnrCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords, const int iedge, TimeStep *tStep, EnrichmentItem *ei)
FloatMatrixF< 3, 3 > computeStressMatrix(FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep)
Definition shell7base.C:701
virtual FloatArrayF< 3 > evalCovarNormalAt(const FloatArrayF< 3 > &lCoords, FloatArray &genEpsC, TimeStep *tStep)
void giveLayerContributionToSR(FloatMatrix &dSmat, FloatMatrix &dSmatLayerIP, int layer, double zeroThicknessLevel, TimeStep *tStep)
virtual double edgeComputeLengthAround(GaussPoint *gp, const int iedge)
FloatMatrixF< 3, 7 > computeLambdaNMatrix(FloatArray &genEps, double zeta)
Definition shell7base.C:492
std::array< FloatMatrixF< 3, 18 >, 3 > computeLambdaGMatrices(FloatArray &genEps, double zeta)
Definition shell7base.C:447
virtual double giveGlobalZcoord(const FloatArrayF< 3 > &lCoords)
Definition shell7base.C:201
void giveTractionBC(FloatMatrix &tractionTop, FloatMatrix &tractionBtm, TimeStep *tStep)
Shell7Base(int n, Domain *d)
Definition shell7base.C:63
void NodalRecoveryMI_recoverValues(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
virtual double computeVolumeAroundLayer(GaussPoint *mastergp, int layer)=0
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
Definition shell7base.C:737
virtual FloatArrayF< 3 > vtkEvalInitialGlobalCoordinateAt(const FloatArrayF< 3 > &localCoords, int layer)
LayeredCrossSection * giveLayeredCS()
Definition shell7base.h:100
void recoverValuesFromIP(std::vector< FloatArray > &nodes, int layer, InternalStateType type, TimeStep *tStep, stressRecoveryType SRtype=copyIPvalue)
virtual const IntArray & giveOrderingNodes() const =0
FloatMatrixF< 3, 3 > evalInitialContravarBaseVectorsAt(const FloatArrayF< 3 > &lCoords)
Definition shell7base.C:274
void computeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord=0)
Definition shell7base.C:773
LayeredCrossSection * layeredCS
Definition shell7base.h:113
FloatMatrixF< 3, 3 > computeFAt(const FloatArrayF< 3 > &lCoords, FloatArray &genEps, TimeStep *tStep)
Definition shell7base.C:691
static FloatArrayF< 9 > convV6ToV9Stress(const FloatArrayF< 6 > &V6)
virtual FloatArrayF< 3 > evalInitialCovarNormalAt(const FloatArrayF< 3 > &lCoords)
virtual int giveNumberOfEdgeDofs()=0
void updateLayerTransvStressesSR(FloatMatrix &dSmatLayerIP, int layer)
virtual double computeAreaAround(GaussPoint *gp, double xi)=0
int computeNumberOfDofs() override
Definition shell7base.h:80
void giveEdgeDofMapping(IntArray &answer, int iEdge) const override=0
void computeNmatrixAt(const FloatArray &iLocCoords, FloatMatrix &answer) override
FloatMatrixF< 3, 3 > giveAxialMatrix(const FloatArrayF< 3 > &vec)
Definition shell7base.C:664
virtual const IntArray & giveOrderingDofTypes() const =0
void giveUpdatedSolutionVector(FloatArray &answer, TimeStep *tStep)
void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li=1, int ui=ALL_STRAINS) override
Definition shell7base.h:269
void fitRecoveredStress2BC(std::vector< FloatMatrix > &answer1, std::vector< FloatMatrix > &answer2, std::vector< FloatMatrix > &dSmat, std::vector< FloatMatrix > &dSmatIP, FloatMatrix &SmatOld, FloatMatrix &tractionBtm, FloatMatrix &tractionTop, double zeroThicknessLevel, FloatArray fulfillBC, int startLayer, int endLayer)
int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override
Definition shell7base.C:159
FEInterpolation3d * fei
Definition shell7base.h:118
virtual int giveNumberOfEdgeDofManagers()=0
void giveUnknownsAt(const FloatArrayF< 3 > &lcoords, const FloatArray &solVec, FloatArrayF< 3 > &x, FloatArrayF< 3 > &m, double &gam, TimeStep *tStep)
virtual FloatArrayF< 3 > vtkEvalInitialGlobalCZCoordinateAt(const FloatArrayF< 3 > &localCoords, int interface)
const FloatArrayF< 3 > & giveTempFirstPKTraction() const
Returns the const pointer to receiver's temporary first Piola-Kirchhoff traction vector.
const FloatArrayF< 3 > & giveFirstPKTraction() const
Returns the const pointer to receiver's first Piola-Kirchhoff traction vector.
virtual FloatArrayF< 3 > giveFirstPKTraction_3d(const FloatArrayF< 3 > &jump, const FloatMatrixF< 3, 3 > &F, GaussPoint *gp, TimeStep *tStep) const
virtual FloatMatrixF< 3, 3 > give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
static void computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep)
XfemElementInterface(Element *e)
Constructor.
IntArray vtkExportFields
EnrichmentItem * giveEnrichmentItem(int n)
int giveNumberOfEnrichmentItems() const
#define OOFEM_ERROR(...)
Definition error.h:79
FloatMatrixF< M, N > transpose(const FloatMatrixF< N, M > &mat)
Constructs transposed matrix.
FloatMatrixF< N, P > Tdot(const FloatMatrixF< M, N > &a, const FloatMatrixF< M, P > &b)
Computes .
GaussPoint IntegrationPoint
Definition gausspoint.h:272
int giveInternalStateTypeSize(InternalStateValueType valType)
Definition cltypes.C:229
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
XFEMStateType
Definition xfemmanager.h:92
InternalStateValueType
Determines the type of internal variable.
@ ISVT_TENSOR_S3
Symmetric 3x3 tensor.
FloatArrayF< 3 > cross(const FloatArrayF< 3 > &x, const FloatArrayF< 3 > &y)
Computes $ x \cross y $.
const double DISC_DOF_SCALE_FAC
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< 2, 2 > local_cs(const FloatArrayF< 2 > &normal)
FloatMatrixF< M, M > unrotate(FloatMatrixF< N, N > &a, const FloatMatrixF< M, N > &r)
Computes .
@ XfemElementInterfaceType
InternalStateValueType giveInternalStateValueType(InternalStateType type)
Definition cltypes.C:75
FloatArrayF< N > normalize(const FloatArrayF< N > &x)
Normalizes vector (L2 norm).
double distance(const FloatArray &x, const FloatArray &y)
#define _IFT_Shell7BaseXFEM_CohesiveZoneMaterial

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