OOFEM 3.0
Loading...
Searching...
No Matches
shell7base.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 "node.h"
39#include "load.h"
40#include "mathfem.h"
41#include "domain.h"
43#include "gausspoint.h"
44#include "boundaryload.h"
45#include "constantsurfaceload.h"
46#include "vtkxmlexportmodule.h"
47#include "fracturemanager.h"
48#include "dof.h"
49#include "floatarrayf.h"
50#include "floatmatrixf.h"
51#include "connectivitytable.h"
52#include "parametermanager.h"
53#include "paramkey.h"
54#include <fstream>
55
56namespace oofem {
57
58FEI3dTrQuad Shell7Base :: interpolationForCZExport;
59FEI3dWedgeQuad Shell7Base :: interpolationForExport;
60ParamKey Shell7Base :: IPK_Shell7Base_recoverStress("recoverstress");
61
62
67
68void Shell7Base :: initializeFrom(InputRecord &ir, int priority)
69{
70 ParameterManager & pm = this->giveDomain()->elementPPM;
71 NLStructuralElement :: initializeFrom(ir, priority);
73}
74
75int
76Shell7Base :: checkConsistency()
77{
78 NLStructuralElement :: checkConsistency();
79
80 if ( this->layeredCS == NULL ) {
81 OOFEM_ERROR("Elements derived from Shell7Base only supports layered cross section");
82 }
83 return ( this->layeredCS != NULL && this->fei != NULL);
84}
85
86
87void
88Shell7Base :: postInitialize()
89{
90 this->layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveCrossSection() );
91 if ( this->layeredCS == NULL ) {
92 OOFEM_ERROR("Shell7Base derived elements only supports layered cross section");
93 }
94 this->fei = dynamic_cast< FEInterpolation3d * >( this->giveInterpolation() );
98 Element :: postInitialize();
99
100 this->voigtIndices = {
101 { 1, 6, 5 },
102 { 9, 2, 4 },
103 { 8, 7, 3 }
104 };
105 this->nlGeometry = 1;
106}
107
108void
110{
111 if ( recoverStress ) {
112 // Recover shear stresses
113 this->recoverShearStress(tStep);
114 }
116}
117
118
119
120Interface *Shell7Base :: giveInterface(InterfaceType it)
121{
122 switch ( it ) {
124 return static_cast< NodalAveragingRecoveryModelInterface * >( this );
125
127 return static_cast< LayeredCrossSectionInterface * >( this );
128
130 return static_cast< VTKXMLExportModuleElementInterface * >( this );
131
133 return static_cast< ZZNodalRecoveryModelInterface * >( this );
134
136 return static_cast< FailureModuleElementInterface * >( this );
137
138 default:
139 return NLStructuralElement :: giveInterface(it);
140 }
141}
142
143
144void
145Shell7Base :: giveDofManDofIDMask(int inode, IntArray &answer) const
146{
147 answer = { D_u, D_v, D_w, W_u, W_v, W_w, Gamma };
148}
149
150
151int
152Shell7Base :: giveNumberOfDofs()
153{
154 return 7 * this->giveNumberOfDofManagers();
155}
156
157
158int
159Shell7Base :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords)
160{
161 // should it return coord in reference or updated config? -- Let it be initial so small def code remains the same
162 //@todo move VTK method into this
163 //int layer = 1;
164 //vtkEvalInitialGlobalCoordinateAt(lcoords, layer, answer);
165
166
167 double zeta = giveGlobalZcoord(lcoords);
169 this->fei->evalN( N, lcoords, FEIElementGeometryWrapper(this) );
170
171 answer.clear();
172 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
173 const auto &xbar = this->giveNode(i)->giveCoordinates();
174 const auto &M = this->giveInitialNodeDirector(i);
175 answer.add(N.at(i), ( xbar + FloatArray(zeta * M)));
176 }
177
178 return 1;
179}
180
181
182int
183Shell7Base :: computeGlobalCoordinatesOnEdge(FloatArray &answer, const FloatArray &lcoords, const int iEdge)
184{
185 // should it return coord in reference or updated config? -- Let it be initial so small def code remains the same
186// double zeta = giveGlobalZcoordInLayer(lcoords.at(3), layer);
187// FloatArray N;
188// this->fei->evalN( N, lcoords, FEIElementGeometryWrapper(this) );
189//
190// globalCoords.clear();
191// for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
192// FloatArray &xbar = *this->giveNode(i)->giveCoordinates();
193// const FloatArray &M = this->giveInitialNodeDirector(i);
194// globalCoords.add(N.at(i), ( xbar + zeta * M ));
195// }
196 return 1;
197}
198
199
200double
202{
203 return lCoords.at(3) * this->layeredCS->give( CS_Thickness, lCoords, this, false ) * 0.5;
204}
205
206
207double
208Shell7Base :: giveGlobalZcoordInLayer(double xi, int layer)
209{
210 // Mid position + part of the layer thickness
211 return this->layeredCS->giveLayerMidZ(layer) + xi*this->layeredCS->giveLayerThickness(layer)*0.5 ;
212}
213
214
215// Base vectors
216
217#if 1
218
220Shell7Base :: evalInitialCovarBaseVectorsAt(const FloatArrayF<3> &lcoords)
221{
222 double zeta = giveGlobalZcoord( lcoords );
223 FloatMatrix dNdxi;
224
225 // In plane base vectors
226 this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) );
227
228 FloatArrayF<3> G1, G2;
229 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
230 const auto &xbar = FloatArrayF<3>(this->giveNode(i)->giveCoordinates());
231 const auto &M = this->giveInitialNodeDirector(i);
232 const auto &nodeCoords = (xbar + zeta*M);
233 G1 += dNdxi.at(i, 1) * nodeCoords;
234 G2 += dNdxi.at(i, 2) * nodeCoords;
235 }
236
237 // Out of plane base vector = director
238 auto G3 = this->evalInitialDirectorAt(lcoords); // G3=M
239
241 gcov.setColumn(G1, 0);
242 gcov.setColumn(G2, 1);
243 gcov.setColumn(G3, 2);
244 return gcov;
245}
246
247
248std::pair<FloatArrayF<3>, FloatArrayF<3>>
249Shell7Base :: edgeEvalInitialCovarBaseVectorsAt(const FloatArrayF<1> &lcoords, const int iedge)
250{
251 double zeta = 0.0; // no variation i z (yet)
252
253 const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iedge);
254 FloatArray dNdxi;
255 this->fei->edgeEvaldNdxi( dNdxi, iedge, lcoords, FEIElementGeometryWrapper(this) );
256
257 // Base vector along edge
259 for ( int i = 1; i <= edgeNodes.giveSize(); i++ ) {
260 const auto &xbar = FloatArrayF<3>(this->giveNode(edgeNodes.at(i))->giveCoordinates());
261 auto M = this->giveInitialNodeDirector(edgeNodes.at(i));
262 auto nodeCoords = (xbar + zeta*M);
263 G1 += dNdxi.at(i) * nodeCoords;
264 }
265
266 // Director will be the second base vector
267 auto G3 = this->edgeEvalInitialDirectorAt(lcoords, iedge);
268
269 return {G1, G3};
270}
271
272
274Shell7Base :: evalInitialContravarBaseVectorsAt(const FloatArrayF<3> &lCoords)
275{
276 auto Gcov = this->evalInitialCovarBaseVectorsAt(lCoords);
277 return this->giveDualBase(Gcov);
278}
279
280
282Shell7Base :: giveDualBase( FloatMatrixF<3,3> &base1)
283{
284 // Computes the dual base through thte inversion of the metric tensor
285 auto gMetric = Tdot(base1,base1); // Metric tensor
286 auto ginv = inv(gMetric);
287 return dotT(base1, ginv);
288}
289
290
292Shell7Base :: evalInitialDirectorAt(const FloatArrayF<3> &lcoords)
293{
294 // Interpolates between the node directors
296 this->fei->evalN( N, lcoords, FEIElementGeometryWrapper(this) );
298 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
299 g3 += N.at(i) * this->giveInitialNodeDirector(i);
300 }
301 return g3;
302}
303
304
306Shell7Base :: edgeEvalInitialDirectorAt(const FloatArrayF<1> &lcoords, const int iEdge)
307{
308 // Interpolates between the node directors along an edge
309
311 const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iEdge);
312 this->fei->edgeEvalN( N, iEdge, lcoords, FEIElementGeometryWrapper(this) );
313
314 FloatArrayF<3> answer;
315 for ( int i = 1; i <= edgeNodes.giveSize(); i++ ) {
316 answer += N.at(i) * this->giveInitialNodeDirector( edgeNodes.at(i) );
317 }
318 return answer;
319}
320
321
322void
323Shell7Base :: setupInitialNodeDirectors()
324{
325 // Compute directors as normals to the surface
326 FloatArray lcoords;
327 FloatMatrix localNodeCoords;
328 this->giveInterpolation()->giveLocalNodeCoords(localNodeCoords, this->giveGeometryType());
329
330 int nDofMan = this->giveNumberOfDofManagers();
331 this->initialNodeDirectors.resize(nDofMan);
332 FloatMatrix dNdxi;
333 for ( int node = 1; node <= nDofMan; node++ ) {
334 lcoords.beColumnOf(localNodeCoords,node);
335 this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) );
336
337 FloatArrayF<3> G1, G2;
338 // base vectors of the initial surface
339 for ( int i = 1; i <= nDofMan; i++ ) {
340 const auto &nodeI = FloatArrayF<3>(this->giveNode(i)->giveCoordinates());
341 G1 += dNdxi.at(i, 1) * nodeI;
342 G2 += dNdxi.at(i, 2) * nodeI;
343 }
344 this->initialNodeDirectors [ node - 1 ] = normalize(cross(G1, G2));
345 }
346}
347
348
350Shell7Base :: evalCovarBaseVectorsAt(const FloatArrayF<3> &lcoords, FloatArray &genEps, TimeStep *tStep)
351{
352 // Evaluates the covariant base vectors in the current configuration
353 double zeta = giveGlobalZcoord( lcoords );
354
355 FloatArrayF<3> dxdxi1, dxdxi2, m, dmdxi1, dmdxi2;
356 double dgamdxi1, dgamdxi2, gam;
357 this->giveGeneralizedStrainComponents(genEps, dxdxi1, dxdxi2, dmdxi1, dmdxi2, m, dgamdxi1, dgamdxi2, gam);
358
359 double fac1 = ( zeta + 0.5 * gam * zeta * zeta );
360 double fac2 = ( 0.5 * zeta * zeta );
361 double fac3 = ( 1.0 + zeta * gam );
362
363 auto g1 = dxdxi1 + fac1*dmdxi1 + fac2*dgamdxi1*m;
364 auto g2 = dxdxi2 + fac1*dmdxi2 + fac2*dgamdxi2*m;
365 auto g3 = fac3*m;
366
368 gcov.setColumn(g1,0); gcov.setColumn(g2,1); gcov.setColumn(g3,2);
369 return gcov;
370
371}
372
373
375Shell7Base :: edgeEvalCovarBaseVectorsAt(const FloatArrayF<3> &lcoords, const int iedge, TimeStep *tStep)
376{
377 // Evaluates the covariant base vectors in the current configuration for an edge
378 double zeta = lcoords.at(3);
379
380 FloatArray solVecEdge;
381 FloatMatrix B;
382 //const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iedge);
383 this->edgeComputeBmatrixAt(lcoords, B, 1, ALL_STRAINS);
384 this->edgeGiveUpdatedSolutionVector(solVecEdge, iedge, tStep);
385
386 FloatArray genEpsEdge; // generalized strain
387 genEpsEdge.beProductOf(B, solVecEdge); // [dxdxi, dmdxi, m, dgamdxi, gam]^T
388
389 FloatArrayF<3> dxdxi = { genEpsEdge.at(1), genEpsEdge.at(2), genEpsEdge.at(3) };
390 FloatArrayF<3> dmdxi = { genEpsEdge.at(4), genEpsEdge.at(5), genEpsEdge.at(6) };
391 FloatArrayF<3> m = { genEpsEdge.at(7), genEpsEdge.at(8), genEpsEdge.at(9) };
392 double dgamdxi = genEpsEdge.at(10);
393 double gam = genEpsEdge.at(11);
394
395 double fac1 = ( zeta + 0.5 * gam * zeta * zeta );
396 double fac2 = ( 0.5 * zeta * zeta );
397 double fac3 = ( 1.0 + zeta * gam );
398
399 auto g2 = normalize(dxdxi + fac1*dmdxi + fac2*dgamdxi*m); // base vector along the edge
400 auto g3 = normalize(fac3*m); // director field
401 auto g1 = normalize(cross(g2, g3));
402
404 gcov.setColumn(g1, 0);
405 gcov.setColumn(g2, 1);
406 gcov.setColumn(g3, 2);
407 return gcov;
408}
409
410
411#endif
412
413
414
415
416// Tangent matrices
417
418#if 1
419
420void
421Shell7Base :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
422{
423 FloatArray solVec;
424 this->giveUpdatedSolutionVector(solVec, tStep); // a
425
426 this->computeBulkTangentMatrix(answer, solVec, tStep);
427
428
429 // Add contribution due to pressure load ///@todo should later be compted by the load
430 int nLoads = this->boundaryLoadArray.giveSize() / 2;
431
432 for ( int i = 1; i <= nLoads; i++ ) { // For each pressure load that is applied
433 int load_number = this->boundaryLoadArray.at(2 * i - 1);
434 int iSurf = this->boundaryLoadArray.at(2 * i); // load_id
435 Load *load = this->domain->giveLoad(load_number);
436
437 if ( dynamic_cast< ConstantPressureLoad * >( load ) ) {
438 FloatMatrix K_pressure;
439 this->computePressureTangentMatrix(K_pressure, load, iSurf, tStep);
440 answer.add(K_pressure); // Should assemble with ordering
441 }
442 }
443
444}
445
446std::array<FloatMatrixF<3,18>, 3>
447Shell7Base :: computeLambdaGMatrices(FloatArray &genEps, double zeta)
448{
449 // computes the lambda^g matrices associated with the variation and linearization of the base vectors g_i.
450 // \delta g_i = lambda_i * \delta n and \Delta g_i = lambda_i * \Delta n
451 // \delta n = B * \delta a and \Delta n = B * \Delta a
452 // @todo optimize method
453 FloatArrayF<3> m, dm1, dm2, temp1;
454 double dgam1, dgam2, gam;
455 this->giveGeneralizedStrainComponents(genEps, temp1, temp1, dm1, dm2, m, dgam1, dgam2, gam);
456
457 // thickness coefficients
458 double a = zeta + 0.5 * gam * zeta * zeta;
459 double b = 0.5 * zeta * zeta;
460 double c = 1.0 + gam * zeta;
461
462 auto bm = b * m;
463 auto bdm1 = b * dm1;
464 auto bdm2 = b * dm2;
465
466 std::array<FloatMatrixF<3,18>, 3> lambda;
467
468 // lambda1 = ( I, 0, a*I, 0 , b*dgam1*I, b*m, 0 , b*dm1 )
469 lambda[ 0 ](0,0) = lambda[ 0 ](1,1) = lambda[ 0 ](2,2) = 1.;
470 lambda[ 0 ](0,6) = lambda[ 0 ](1,7) = lambda[ 0 ](2,8) = a;
471 lambda[ 0 ](0,12) = lambda[ 0 ](1,13) = lambda[ 0 ](2,14) = b * dgam1;
472 lambda[ 0 ].setColumn(bm, 15);
473 lambda[ 0 ].setColumn(bdm1, 17);
474
475 // lambda2 = ( 0, I, 0 , a*I, b*dgam2*I, 0 , b*m, b*dm2 )
476 lambda[ 1 ](0,3) = lambda[ 1 ](1,4) = lambda[ 1 ](2,5) = 1.;
477 lambda[ 1 ](0,9) = lambda[ 1 ](1,10) = lambda[ 1 ](2,11) = a;
478 lambda[ 1 ](0,12) = lambda[ 1 ](1,13) = lambda[ 1 ](2,14) = b * dgam2;
479 lambda[ 1 ].setColumn(bm, 16);
480 lambda[ 1 ].setColumn(bdm2, 17);
481
482 // lambda3 = ( 0, 0, 0 , 0 , c*I , 0 , 0 , xi*m )
483 lambda[ 2 ](0,12) = lambda[ 2 ](1,13) = lambda[ 2 ](2,14) = c;
484 auto zm = zeta * m;
485 lambda[ 2 ].setColumn(zm, 17);
486
487 return lambda;
488}
489
490
492Shell7Base :: computeLambdaNMatrix(FloatArray &genEps, double zeta)
493{
494 // computes the lambda^n matrix associated with the variation and linearization of the position vector x.
495 // \delta x = lambda * \delta \hat{x} with \hat{x} = [\bar{x}, m, \gamma]
496
497 FloatArrayF<3> m = { genEps.at(13), genEps.at(14), genEps.at(15) };
498 double gam = genEps.at(18);
499
500 // thickness coefficients
501 double a = zeta + 0.5 * gam * zeta * zeta;
502 double b = 0.5 * zeta * zeta;
503
504 // lambda = ( I, a*I, b*m )
505 FloatMatrixF<3,7> lambda;
506 lambda.at(1,1) = lambda.at(2,2) = lambda.at(3,3) = 1.0;
507 lambda.at(1,4) = lambda.at(2,5) = lambda.at(3,6) = a;
508 lambda.setColumn(b*m, 6);
509 return lambda;
510}
511
512
513void
514Shell7Base :: computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, TimeStep *tStep)
515{
516 FloatMatrix A [ 3 ] [ 3 ], A_lambda(3,18), LB;
517 FloatMatrix L(18,18), B;
518 FloatMatrix tempAnswer;
519
520 int ndofs = Shell7Base :: giveNumberOfDofs();
521 answer.resize(ndofs, ndofs); tempAnswer.resize(ndofs, ndofs);
522 answer.zero(); tempAnswer.zero();
523
524 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
525 FloatArray genEps;
526
527 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
528 StructuralMaterial *mat = static_cast< StructuralMaterial* >( domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ) );
529
530 for ( GaussPoint *gp : *integrationRulesArray [ layer - 1 ] ) {
531 const auto &lCoords = gp->giveNaturalCoordinates();
532
533 this->computeBmatrixAt(lCoords, B);
534 genEps.beProductOf(B, solVec);
535 // Material stiffness
536 Shell7Base :: computeLinearizedStiffness(gp, mat, tStep, A);
537
538 double zeta = giveGlobalZcoord(lCoords);
539 auto lambda = this->computeLambdaGMatrices(genEps, zeta);
540
541 // L = sum_{i,j} (lambdaI_i)^T * A^ij * lambdaJ_j
542 // note: L will only be symmetric if lambdaI = lambdaJ (not the case for xfem)
543 L.zero();
544 for (int i = 0; i < 3; i++) {
545 A_lambda.zero();
546 for (int j = 0; j < 3; j++) {
547 A_lambda.addProductOf(A[i][j], lambda[j]);
548 }
549 L.plusProductSymmUpper(lambda[i], A_lambda, 1.0);
550 }
551 L.symmetrized();
552 LB.beProductOf(L, B);
553 double dV = this->computeVolumeAroundLayer(gp, layer);
554 tempAnswer.plusProductSymmUpper(B, LB, dV);
555
556 }
557 }
558 tempAnswer.symmetrized();
559
560 const auto &ordering = this->giveOrderingDofTypes();
561 answer.assemble(tempAnswer, ordering, ordering);
562
563}
564
565
566void
567Shell7Base :: computeLinearizedStiffness(GaussPoint *gp, StructuralMaterial *mat, TimeStep *tStep, FloatMatrix A [ 3 ] [ 3 ])
568{
569 const auto &lcoords = gp->giveNaturalCoordinates();
570
571 // Material stiffness when internal work is formulated in terms of P and F:
572 // \Delta(P*G^I) = L^IJ * \Delta g_J
573 // A[I][J] = L^IJ = L_klmn * [G^I]_l * [G^J]_n
574 auto D = mat->give3dMaterialStiffnessMatrix_dPdF(TangentStiffness, gp, tStep); // D_ijkl - cartesian system (Voigt)
575 auto G = this->evalInitialContravarBaseVectorsAt(lcoords);
576 for (int I = 1; I <= 3; I++) {
577 for (int J = I; J <= 3; J++) {
578 A[I - 1][J - 1].resize(3, 3);
579 A[I - 1][J - 1].zero();
580
581 for (int k = 1; k <= 3; k++) {
582 for (int l = 1; l <= 3; l++) {
583 for (int m = 1; m <= 3; m++) {
584 for (int n = 1; n <= 3; n++) {
585
586 A[I-1][J-1].at(k, m) += D.at( giveVoigtIndex(k, l), giveVoigtIndex(m, n) ) * G.at(l, I) * G.at(n, J);
587
588 }
589 }
590 }
591 }
592 }
593 }
594
595 // position 21
596 A [ 1 ] [ 0 ].beTranspositionOf( A [ 0 ] [ 1 ] );
597
598 // position 31
599 A [ 2 ] [ 0 ].beTranspositionOf( A [ 0 ] [ 2 ] );
600
601 // position 32
602 A [ 2 ] [ 1 ].beTranspositionOf( A [ 1 ] [ 2 ] );
603}
604
605
606void
607Shell7Base :: computePressureTangentMatrix(FloatMatrix &answer, Load *load, const int iSurf, TimeStep *tStep)
608{
609 // Computes tangent matrix associated with the linearization of pressure loading. Assumes constant pressure.
610 ConstantPressureLoad* pLoad = dynamic_cast< ConstantPressureLoad * >( load );
611
612 //std :: unique_ptr< IntegrationRule >iRule( giveInterpolation()->giveBoundaryIntegrationRule(load->giveApproxOrder(), iSurf) );
613 int nPointsTri = 6; //todo generalize
614 GaussIntegrationRule iRule(1, this);
615 iRule.SetUpPointsOnWedge(nPointsTri, 1, _3dMat);
616
617 FloatMatrix N, B, LB, NLB, L(7, 18);
618 FloatArray lcoords(3), solVec, pressure;
619 FloatArray genEps;
620
621 double xi = pLoad->giveLoadOffset();
622 this->giveUpdatedSolutionVector(solVec, tStep);
623
624 int ndof = Shell7Base :: giveNumberOfDofs();
625 answer.resize(ndof, ndof);
626 answer.zero();
627 for ( auto *ip: iRule ) { // rule #2 for surface integration
628 lcoords.at(1) = ip->giveNaturalCoordinate(1);
629 lcoords.at(2) = ip->giveNaturalCoordinate(2);
630 lcoords.at(3) = xi; // local coord where load is applied
631 double zeta = giveGlobalZcoord( lcoords );
632
633 this->computeNmatrixAt(lcoords, N);
634 this->computeBmatrixAt(lcoords, B);
635 genEps.beProductOf(B, solVec);
636
637 // Traction tangent, L = lambdaN * ( W2*lambdaG_1 - W1*lambdaG_2 )
638 load->computeValueAt(pressure, tStep, ip->giveNaturalCoordinates(), VM_Total); // pressure component
639 auto gcov = this->evalCovarBaseVectorsAt(lcoords, genEps, tStep);
640 auto g1 = gcov.column(0);
641 auto g2 = gcov.column(1);
642 auto W1 = this->giveAxialMatrix(g1);
643 auto W2 = this->giveAxialMatrix(g2);
644
645 auto lambdaG = this->computeLambdaGMatrices(genEps, zeta);
646 auto lambdaN = this->computeLambdaNMatrix(genEps, zeta);
647 FloatMatrix W2L, W1L;
648 W2L.beProductOf(W2,lambdaG[0]);
649 W1L.beProductOf(W1,lambdaG[1]);
650 W2L.subtract(W1L);
651 L.beTProductOf(lambdaN, W2L);
652 L.times( -pressure.at(1) );
653
654 // Tangent matrix (K = N^T*L*B*dA)
655 LB.beProductOf(L,B);
656 NLB.beTProductOf(N,LB);
657 double dA = this->computeAreaAround(ip, xi);
658 answer.add(dA, NLB);
659 }
660}
661
662
664Shell7Base :: giveAxialMatrix(const FloatArrayF<3> &v)
665{
666 // creates the skew-symmetric matrix W defined such that
667 // crossProduct(u,v) = W(v)*u
668 // W = [ 0 v(3) -v(2)
669 // -v(3) 0 v(1)
670 // v(2) -v(1) 0 ]
671 //
672 FloatMatrixF<3,3> answer;
673 answer.at(2, 3) = v.at(1);
674 answer.at(3, 2) = -v.at(1);
675 answer.at(1, 3) = -v.at(2);
676 answer.at(3, 1) = v.at(2);
677 answer.at(1, 2) = v.at(3);
678 answer.at(2, 1) = -v.at(3);
679 return answer;
680}
681
682#endif
683
684
685
686// Strain and stress
687
688#if 1
689
691Shell7Base :: computeFAt(const FloatArrayF<3> &lCoords, FloatArray &genEps, TimeStep *tStep)
692{
693 // Computes the deformation gradient in matrix form as open product(g_i, G^i) = gcov*Gcon^T
694 auto gcov = this->evalCovarBaseVectorsAt(lCoords, genEps, tStep);
695 auto Gcon = this->evalInitialContravarBaseVectorsAt(lCoords);
696 return dotT(gcov, Gcon);
697}
698
699
701Shell7Base :: computeStressMatrix(FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep)
702{
703 auto F = computeFAt(gp->giveNaturalCoordinates(), genEps, tStep);
704 auto vF = to_voigt_form_33(F);
705 auto vP = static_cast< StructuralMaterial * >( mat )->giveFirstPKStressVector_3d(vF, gp, tStep);
706 return from_voigt_form_9(vP);
707}
708
709
710void
711Shell7Base :: computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep)
712{
713 // Compute Cauchy stress from 2nd Piola stress
714 FloatArray solVec;
715 this->giveUpdatedSolutionVector(solVec, tStep);
716 const auto &lCoords = gp->giveNaturalCoordinates();
717 FloatMatrix B;
718 this->computeBmatrixAt(lCoords, B);
719 FloatArray genEps;
720 genEps.beProductOf(B, solVec);
721
722 auto F = this->computeFAt(lCoords, genEps, tStep);
723
724 FloatArray vS;
725 giveIPValue(vS, gp, IST_StressTensor, tStep); // expects Second PK stress
726
727 FloatMatrix S, temp, sigma;
728 S.beMatrixFormOfStress(vS);
729 temp.beProductTOf(S,F);
730 sigma.beProductOf(F,temp);
731 sigma.times( 1.0/ det(F) );
732 answer.beSymVectorForm(sigma);
733}
734
735
736int
737Shell7Base :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
738{
739 // Compute special IST quantities this element should support
740 switch (type) {
741 case IST_CauchyStressTensor:
742 this->computeCauchyStressVector(answer, gp, tStep);
743 return 1;
744 default:
745 return Element :: giveIPValue(answer, gp, type, tStep);
746 }
747}
748
749#endif
750
751
752
753
754// Internal forces
755
756#if 1
757
758
759void
760Shell7Base :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord)
761{
762 // Computes internal forces as a summation of: sectional forces + convective mass force
763
764 FloatArray solVec;
765 this->giveUpdatedSolutionVector(solVec, tStep); // placement vector x
766 this->computeSectionalForces(answer, tStep, solVec, useUpdatedGpRecord);
767
769}
770
771
772void
773Shell7Base :: computeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord)
774{
775 // Computation of sectional forces: f = \int_V B^t * \hat{N} dV = \int_V B^t*[N M T Ms Ts]^t dV
776 int ndofs = Shell7Base :: giveNumberOfDofs();
777
778 int numberOfLayers = this->layeredCS->giveNumberOfLayers();
779 FloatArray f, N;
780 FloatArray genEps;
781 FloatMatrix B;
782
783 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
784 Material *mat = domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) );
785
786 for (GaussPoint *gp : *integrationRulesArray [ layer - 1 ]) {
787 const FloatArray &lCoords = gp->giveNaturalCoordinates();
788 this->computeBmatrixAt(lCoords, B);
789 genEps.beProductOf(B, solVec);
790
791 double zeta = giveGlobalZcoord(lCoords);
792 this->computeSectionalForcesAt(N, gp, mat, tStep, genEps, zeta); // these are per unit volume
793
794 double dV = this->computeVolumeAroundLayer(gp, layer);
795 f.plusProduct(B, N, dV);
796 }
797 }
798
799 answer.resize( ndofs );
800 answer.zero();
801 answer.assemble(f, this->giveOrderingDofTypes());
802}
803
804
805void
806Shell7Base :: computeSectionalForcesAt(FloatArray &sectionalForces, IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta)
807{
808 // New, in terms of PK1 stress
809 // \Lambda_i * P * G^I
810 auto P = this->computeStressMatrix(genEps, ip, mat, tStep);
812 auto PG = dot(P, Gcon);
813 auto PG1 = PG.column(0);
814 auto PG2 = PG.column(1);
815 auto PG3 = PG.column(2);
816 auto lambda = this->computeLambdaGMatrices(genEps, zeta); // associated with the variation of the test functions
817
818 // f = lambda_1^T * P*G^1 + lambda_2^T * P*G^2 + lambda_3^T * P*G^3
819 sectionalForces.clear();
820 sectionalForces.plusProduct(lambda[0], PG1, 1.0);
821 sectionalForces.plusProduct(lambda[1], PG2, 1.0);
822 sectionalForces.plusProduct(lambda[2], PG3, 1.0);
823}
824
825#endif
826
827
828
829
830// Mass matrices
831
832#if 1
833
834void
835Shell7Base :: computeThicknessMappingCoeff(GaussPoint *gp, FloatArray &answer)
836{
837 //thickness jacobian = ratio between volume and area: j0 = a3 + a2*zeta^2 + a1 * zeta
838 // Returns array with a1-a3, used in expression for analytical integration of mass matrix.
839 const auto &lcoords = gp->giveNaturalCoordinates();
840
841 FloatMatrix dNdxi;
842 this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) );
843
844 FloatArrayF<3> M, dM1, dM2, dX1, dX2;
845 double gam, dg1, dg2;
846 FloatMatrix B;
847 this->computeBmatrixAt(lcoords, B);
848
849 FloatArray initSolVec, genEps;
850 initSolVec = this->giveInitialSolutionVector();
851 genEps.beProductOf(B, initSolVec);
852 this->giveGeneralizedStrainComponents(genEps, dX1, dX2, dM1, dM2, M, dg1, dg2, gam);
853
854 auto temp = cross(dX1, dX2);
855 double sc = norm(temp);
856 answer.resize(3);
857 answer.at(3) = dot(M, temp) / sc;
858
859 temp = cross(dX1, dM2) + cross(dX2, dM1);
860 answer.at(2) = dot(M, temp) / sc;
861
862 temp = cross(dM1, dM2);
863 //answer.at(1) = dot(M, temp)/sc;
864 answer.at(1) = norm(temp) / sc;
865}
866
867void
868Shell7Base :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep)
869{
870 // TODO: add algorithm for this
871 OOFEM_ERROR("Shell7Base :: computeLumpedMassMatrix - No lumping algorithm implemented");
872}
873
874
875void
876Shell7Base :: computeMassMatrix(FloatMatrix &answer, TimeStep *tStep)
877{
878 // Analytically integrated over the thickness. Constant density assumed.
879 int nPointsTri = 6; //todo generalize
880 GaussIntegrationRule iRule(1, this);
881 iRule.SetUpPointsOnWedge(nPointsTri, 1, _3dMat);
882
883
884 //------------------------------
885 FloatMatrix N, Ntm, NtmN, temp;
886 FloatArray solVec;
887 this->giveUpdatedSolutionVector(solVec, tStep);
888
890 Material *mat = domain->giveMaterial( this->layeredCS->giveLayerMaterial(1) ); // for now, while I don't have an analytical exp.
891
892 for ( auto &gp: iRule ) {
893 const FloatArray &lCoords = gp->giveNaturalCoordinates();
894 this->computeNmatrixAt(lCoords, N);
895 FloatArray unknowns, m(3);
896 unknowns.beProductOf(N, solVec); // [x, m, gam]^T
897 m = { unknowns.at(4), unknowns.at(5), unknowns.at(6) };
898 double gam = unknowns.at(7);
899
900 // Analytically integrated through the tickness
901 /* 3 3 1
902 * 3 [a*I b*I c*m [A B C
903 * 3 d*I e*m = D E
904 * 1 sym f*m.m] sym F]
905 */
906
907 double rho = mat->give('d', gp);
908 FloatArray factors;
909 this->giveMassFactorsAt(gp, factors, gam);
910
911 FloatMatrix mass;
912 mass.resize(7, 7);
913 mass.at(1, 1) = mass.at(2, 2) = mass.at(3, 3) = factors.at(1); // A
914 mass.at(1, 4) = mass.at(2, 5) = mass.at(3, 6) = factors.at(2); // B
915 mass.at(1, 7) = factors.at(3) * m.at(1);
916 mass.at(2, 7) = factors.at(3) * m.at(2);
917 mass.at(3, 7) = factors.at(3) * m.at(3); // C
918 mass.at(4, 4) = mass.at(5, 5) = mass.at(6, 6) = factors.at(4); // D
919 mass.at(4, 7) = factors.at(5) * m.at(1);
920 mass.at(5, 7) = factors.at(5) * m.at(2);
921 mass.at(6, 7) = factors.at(5) * m.at(3); // E
922 mass.at(7, 7) = factors.at(6) * m.dotProduct(m); // F
923 mass.symmetrized();
924 double xi = 0.0;
925 double dA = this->computeAreaAround(gp, xi);
926 Ntm.beTProductOf(N, mass);
927 NtmN.beProductOf(Ntm, N); // switch to sym prod upper something
928 NtmN.times(dA * rho);
929 temp.add(NtmN);
930 }
931
932 int ndofs = this->computeNumberOfDofs();
933 answer.resize(ndofs, ndofs);
934 answer.zero();
935 const IntArray &ordering = this->giveOrderingDofTypes();
936 answer.assemble(temp, ordering);
937 answer.symmetrized();
938}
939
940
941void
942Shell7Base :: giveMassFactorsAt(GaussPoint *gp, FloatArray &factors, double &gam)
943{
944 FloatArray coeff;
945 this->computeThicknessMappingCoeff(gp, coeff);
946 double a1 = coeff.at(1);
947 double a2 = coeff.at(2);
948 double a3 = coeff.at(3);
949
950 double h = this->giveCrossSection()->give(CS_Thickness,NULL);
951 double h2 = h * h;
952 double h3 = h2 * h;
953 double h5 = h2 * h3;
954 double gam2 = gam * gam;
955
956 factors.resize(6);
957 factors.at(1) = a3 * h + ( a1 * h3 ) / 12.;
958 factors.at(2) = h3 * ( 40. * a2 + 20. * a3 * gam + 3. * a1 * h2 * gam ) / 480.;
959 factors.at(3) = h3 * ( 20. * a3 + 3. * a1 * h2 ) / 480. * 1.0;
960 factors.at(4) = ( 28. * a3 * h3 * ( 80. + 3. * h2 * gam2 ) + 3. * h5 * ( 112. * a2 * gam + a1 * ( 112. + 5. * h2 * gam2 ) ) ) / 26880.;
961 factors.at(5) = h5 * ( 56. * a2 + 28. * a3 * gam + 5. * a1 * h2 * gam ) / 8960.;
962 factors.at(6) = h5 * ( 28. * a3 + 5. * a1 * h2 ) / 8960.;
963}
964
965void
966Shell7Base :: computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep)
967{
968 // Num refers in this case to numerical integration in both in-plane and through the thickness.
969 // For analytically integrated throught the thickness, see computeMassMatrix
970
971 FloatMatrix mass;
972 FloatArray solVec;
973 this->giveUpdatedSolutionVector(solVec, tStep);
974 int numberOfLayers = this->layeredCS->giveNumberOfLayers(); // conversion of data
975
976 FloatMatrix M(42,42);
977
978 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
979 Material *mat = domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) );
980
981 /* Consistent mass matrix M = int{N^t*mass*N}
982 *
983 * 3 3 1
984 * 3 [a*I b*I c*m [A B C
985 * mass = 3 d*I e*m = D E
986 * 1 sym f*m.m] sym F]
987 */
988
989 for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) {
990 const FloatArray &lCoords = gp->giveNaturalCoordinates();
991 FloatMatrix B, N, temp;
992 FloatArray genEps;
993 this->computeBmatrixAt(lCoords, B);
994 genEps.beProductOf(B, solVec);
995 double zeta = giveGlobalZcoord(gp->giveNaturalCoordinates());
996 auto lambda = this->computeLambdaNMatrix(genEps, zeta);
997
998 // could also create lambda*N and then plusProdSymm - probably faster
999 mass = Tdot(lambda, lambda);
1000 this->computeNmatrixAt(lCoords, N);
1001 temp.beProductOf(mass,N);
1002
1003 double dV = this->computeVolumeAroundLayer(gp, layer);
1004 double rho = mat->give('d', gp);
1005 M.plusProductSymmUpper(N, temp, rho*dV);
1006 }
1007 M.symmetrized();
1008 const IntArray &ordering = this->giveOrderingDofTypes();
1009 answer.zero();
1010 answer.assemble(M, ordering, ordering);
1011#endif
1012
1013 }
1014}
1015
1016
1017void
1018Shell7Base :: computeConvectiveMassForce(FloatArray &answer, TimeStep *tStep)
1019{
1021 // Analytically integrated over the thickness. Constant density assumed.
1022 int nPointsTri = 6; //todo generalize
1023 GaussIntegrationRule iRule(1, this);
1024 iRule.SetUpPointsOnWedge(nPointsTri, 1, _3dMat);
1025
1026 FloatMatrix N;
1027 FloatArray a, da, m, dm, aVec, daVec, fm(7);
1028 double gam, dgam, dA;
1029
1030 answer.resize(42);
1031 answer.zero();
1032 for ( auto &gp: iRule ) { // rule 2 for mid-plane integration only
1033 const FloatArray &lCoords = gp->giveNaturalCoordinates();
1034 this->computeNmatrixAt(lCoords, N);
1035 this->giveUpdatedSolutionVector(aVec, tStep);
1036 // Fix for the new numbering in B & N
1037
1038 a.beProductOf(N, aVec); // [ x, m, gam]^T
1039 da.beProductOf(N, daVec); // [dx, dm, dgam]^T
1040 m = { a.at(4), a.at(5), a.at(6) };
1041 gam = a.at(7);
1042 dm = { da.at(4), da.at(5), da.at(6) };
1043 dgam = da.at(7);
1044
1045 double a1, a2, a3, h, h2, h3, h5, fac1, fac2, fac3, rho;
1046 FloatArray coeff;
1047
1048 Material *mat = domain->giveMaterial( this->layeredCS->giveLayerMaterial(1) );
1049 rho = mat->give('d', gp);
1050 h = this->giveCrossSection()->give(CS_Thickness, gp);
1051 h2 = h * h;
1052 h3 = h2 * h;
1053 h5 = h2 * h3;
1054 this->computeThicknessMappingCoeff(gp, coeff);
1055 a1 = coeff.at(1);
1056 a2 = coeff.at(2);
1057 a3 = coeff.at(3);
1058
1059 // Convective mass "matrix"
1060 /* 3
1061 * 3 [ a*m
1062 * 3 b*m
1063 * 1 c*m.dm]*dgam
1064 */
1065
1066 fac1 = rho * h3 * ( 20. * a3 + 3. * a1 * h2 ) / 240.;
1067 fac2 = rho * h5 * ( 56. * a2 + 28. * a3 * gam + 5. * a1 * h2 * gam ) / 4480.;
1068 fac3 = rho * h5 * ( 28. * a3 + 5. * a1 * h2 ) / 4480.;
1069 fm.at(1) = fac1 * dm.at(1) * dgam;
1070 fm.at(2) = fac1 * dm.at(2) * dgam;
1071 fm.at(3) = fac1 * dm.at(3) * dgam;
1072 fm.at(4) = fac2 * dm.at(1) * dgam;
1073 fm.at(5) = fac2 * dm.at(2) * dgam;
1074 fm.at(6) = fac2 * dm.at(3) * dgam;
1075 fm.at(7) = fac3 * m.dotProduct(dm) * gam;
1076 double xi = 0.0;
1077 dA = this->computeAreaAround(gp, xi);
1078 answer.plusProduct(N, fm, dA);
1079 }
1080}
1081
1082
1083// External forces
1084
1085#if 1
1086void Shell7Base :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global)
1087{
1088 answer.clear();
1089 if ( type != ExternalForcesVector ) {
1090 return;
1091 }
1092 this->computeTractionForce(answer, boundary, load, tStep, mode);
1093}
1094
1095
1096/*
1097void
1098Shell7Base :: computeSurfaceLoadVectorAt(FloatArray &answer, Load *load,
1099 int iSurf, TimeStep *tStep, ValueModeType mode)
1100{
1101 BoundaryLoad *surfLoad = dynamic_cast< BoundaryLoad * >( load );
1102 if ( surfLoad ) {
1103 FloatArray solVec, force;
1104 this->giveUpdatedSolutionVector(solVec, tStep);
1105 this->computePressureForce(force, solVec, iSurf, surfLoad, tStep, mode);
1106 IntArray mask;
1107 this->giveSurfaceDofMapping(mask, 1); // same dofs regardless of iSurf->1
1108 answer.resize( this->computeNumberOfDofs() );
1109 answer.zero();
1110 answer.assemble(force, mask);
1111 } else {
1112 OOFEM_ERROR("Load type not supported");
1113 }
1114}
1115*/
1116
1117void
1118Shell7Base :: computePressureForce(FloatArray &answer, FloatArray solVec, const int iSurf, BoundaryLoad *surfLoad, TimeStep *tStep, ValueModeType mode)
1119{
1120 // Computes pressure loading. Acts normal to the current (deformed) surface.
1121// ConstantPressureLoad* pLoad = dynamic_cast< ConstantPressureLoad * >( surfLoad );
1122// ConstantSurfaceLoad* sLoad = dynamic_cast< ConstantSurfaceLoad * >( surfLoad );
1123 double xi = 0.0;
1124 if ( ConstantPressureLoad* pLoad = dynamic_cast< ConstantPressureLoad * >( surfLoad ) ) {
1125 xi = pLoad->giveLoadOffset();
1126 //printf("pLoad xi = %e \n",xi);
1127 }
1128 else if ( ConstantSurfaceLoad* sLoad = dynamic_cast< ConstantSurfaceLoad * >( surfLoad ) ) {
1129 xi = sLoad->giveLoadOffset();
1130 //printf("sLoad xi = %e \n",xi);
1131 }
1132
1133 int nPointsTri = 6; //todo generalize
1134 auto iRule = std::make_unique<GaussIntegrationRule>(1, this);
1135// iRule->SetUpPointsOnWedge(nPointsTri, 1, _3dMat); //@todo replce with triangle which has a xi3-coord
1136 iRule->SetUpPointsOnTriangle(nPointsTri, _3dMat);
1137
1138
1139 FloatMatrix N, B, lambda;
1140 FloatArray Fp, fp, genEps, genEpsC, traction, solVecC;
1141
1142 for ( auto *ip: *iRule ) { // rule #2 for surface integration
1143 FloatArrayF<3> lCoords = {
1144 ip->giveNaturalCoordinate(1),
1145 ip->giveNaturalCoordinate(2),
1146 xi,
1147 };
1148 double zeta = giveGlobalZcoord( lCoords );
1149 this->computeBmatrixAt(lCoords, B);
1150 this->computeNmatrixAt(lCoords, N);
1151 this->giveUpdatedSolutionVector(solVecC, tStep);
1152 genEpsC.beProductOf(B, solVecC);
1153 this->computePressureForceAt(ip, traction, iSurf, genEpsC, surfLoad, tStep, mode);
1154
1155 genEps.beProductOf(B, solVec);
1156 lambda = this->computeLambdaNMatrix(genEps, zeta);
1157 fp.beTProductOf(lambda,traction);
1158
1159 double dA = this->computeAreaAround(ip, xi);
1160
1161 Fp.plusProduct(N, fp, dA);
1162 }
1163 answer.resize( Shell7Base :: giveNumberOfDofs() );
1164 answer.zero();
1165 answer.assemble(Fp, this->giveOrderingDofTypes());
1166}
1167
1168
1169void
1170Shell7Base :: computePressureForceAt(GaussPoint *gp, FloatArray &traction, const int iSurf, FloatArray genEps, BoundaryLoad *surfLoad, TimeStep *tStep, ValueModeType mode)
1171{
1172 // Computes pressure loading. Acts normal to the current (deformed) surface.
1173 //@todo traction load should be moved outside this method
1174 if ( iSurf != 0 ) {
1175 OOFEM_ERROR("incompatible load surface must be 0 for this element");
1176 }
1177
1178 FloatArray load;
1179 if ( ConstantPressureLoad* pLoad = dynamic_cast< ConstantPressureLoad * >( surfLoad ) ) {
1180 FloatMatrix gcov;
1181 FloatArray g1, g2;
1182 FloatArray lcoords(3);
1183 lcoords.at(1) = gp->giveNaturalCoordinate(1);
1184 lcoords.at(2) = gp->giveNaturalCoordinate(2);
1185 lcoords.at(3) = pLoad->giveLoadOffset();
1186
1187 gcov = this->evalCovarBaseVectorsAt(lcoords, genEps, tStep);
1188 g1.beColumnOf(gcov,1);
1189 g2.beColumnOf(gcov,2);
1190 surfLoad->computeValueAt(load, tStep, lcoords, mode); // pressure component
1191 traction.beVectorProductOf(g1, g2); // normal vector (should not be normalized due to integraton in reference config.)
1192 traction.times( -load.at(1) );
1193 } else if ( ConstantSurfaceLoad* sLoad = dynamic_cast< ConstantSurfaceLoad * >( surfLoad ) ) {
1194 FloatArray lcoords(3), tempTraction;
1195 lcoords.at(1) = gp->giveNaturalCoordinate(1);
1196 lcoords.at(2) = gp->giveNaturalCoordinate(2);
1197 lcoords.at(3) = sLoad->giveLoadOffset();
1198 surfLoad->computeValueAt(tempTraction, tStep, lcoords, mode); // traction vector
1199 traction.resize(3);
1200 traction.zero();
1201 //IntArray sLoadDofIDs = sLoad->giveDofIDs();
1202 //sLoadDofIDs.printYourself("sLoadDofIDs");
1203 traction.assemble(tempTraction,sLoad->giveDofIDs());
1204 } else {
1205 OOFEM_ERROR("incompatible load type");
1206 }
1207
1208}
1209
1211Shell7Base :: evalCovarNormalAt(const FloatArrayF<3> &lCoords, FloatArray &genEpsC, TimeStep *tStep)
1212{
1213 auto gcov = this->evalCovarBaseVectorsAt(lCoords, genEpsC, tStep);
1214 auto g1 = gcov.column(0);
1215 auto g2 = gcov.column(1);
1216 return normalize(cross(g1, g2));
1217}
1218
1220Shell7Base :: evalInitialCovarNormalAt(const FloatArrayF<3> &lCoords)
1221{
1222 auto Gcov = this->evalInitialCovarBaseVectorsAt(lCoords);
1223 auto G1 = Gcov.column(0);
1224 auto G2 = Gcov.column(1);
1225 return normalize(cross(G1, G2));
1226}
1227
1228void
1229Shell7Base :: computeTractionForce(FloatArray &answer, const int iEdge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, bool map2elementDOFs)
1230{
1231
1232 int approxOrder = edgeLoad->giveApproxOrder() + this->giveInterpolation()->giveInterpolationOrder();
1233 int numberOfGaussPoints = ( int ) ceil( ( approxOrder + 1. ) / 2. );
1234 GaussIntegrationRule iRule(1, this, 1, 1);
1235 iRule.SetUpPointsOnLine(numberOfGaussPoints, _Unknown);
1236 FloatMatrix N, Q;
1237 FloatArray fT(7), Nf, components;
1238
1239 Load :: CoordSystType coordSystType = edgeLoad->giveCoordSystMode();
1240
1241 for ( GaussPoint *gp : iRule ) {
1242 const FloatArray &lCoords = gp->giveNaturalCoordinates();
1243 fT.zero();
1244 edgeLoad->computeValueAt(components, tStep, lCoords, mode);
1245 this->edgeComputeNmatrixAt(lCoords, N);
1246
1247 //if ( coordSystType == BoundaryLoad :: BL_UpdatedGlobalMode ) {
1248 if ( coordSystType == Load :: CST_UpdatedGlobal ) {
1249
1250 // Updated global coord system
1251 auto gcov = this->edgeEvalCovarBaseVectorsAt(lCoords, iEdge, tStep);
1252 Q.beTranspositionOf(gcov);
1253
1254 FloatArray distrForces(3), distrMoments(3), t1, t2;
1255 distrForces = { components.at(1), components.at(2), components.at(3)};
1256 distrMoments = { components.at(4), components.at(5), components.at(6) };
1257 t1.beTProductOf(Q, distrForces);
1258 t2.beTProductOf(Q, distrMoments);
1259 fT.addSubVector(t1,1);
1260 fT.addSubVector(t2,4);
1261 fT.at(7) = components.at(7); // don't do anything with the 'gamma'-load
1262
1263 } else if( coordSystType == Load :: CST_Global ) {
1264 // Undeformed global coord system
1265 for ( int i = 1; i <= 7; i++) {
1266 fT.at(i) = components.at(i);
1267 }
1268 } else {
1269 OOFEM_ERROR("Shell7Base :: computeTractionForce - does not support local coordinate system");
1270 }
1271
1272 double dL = this->edgeComputeLengthAround(gp, iEdge);
1273
1274 Nf.plusProduct(N, fT, dL);
1275 }
1276 /* Note: now used from computeBoundaryEdgeLoadVector, so result should be in global cs for edge dofs */
1277 if (map2elementDOFs) {
1278 IntArray mask;
1279 this->giveEdgeDofMapping(mask, iEdge);
1280 answer.resize( Shell7Base :: giveNumberOfDofs() );
1281 answer.zero();
1282 answer.assemble(Nf, mask);
1283 } else {
1284 answer = Nf;
1285 }
1286
1287}
1288
1289
1290void
1291Shell7Base :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode)
1292{
1293 OOFEM_ERROR("Shell7Base :: computeBodyLoadVectorAt - currently not implemented");
1294}
1295
1296#endif
1297
1298
1299
1300// Integration
1301#if 1
1302
1304double
1305Shell7Base :: edgeComputeLengthAround(GaussPoint *gp, const int iedge)
1306{
1307 const auto &lcoords = gp->giveNaturalCoordinates();
1308 //auto [G1, G3] = this->edgeEvalInitialCovarBaseVectorsAt(lcoords, iedge);
1309 auto tmp = this->edgeEvalInitialCovarBaseVectorsAt(lcoords, iedge);
1310 auto G1 = tmp.first;
1311 double detJ = norm(G1);
1312 return detJ * gp->giveWeight();
1313}
1314#endif
1315
1316
1317
1318// Recovery of nodal values
1319
1320#if 1
1321
1322void Shell7Base :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep)
1323{
1324 if ( type == IST_DirectorField ) {
1325 answer.resize(3);
1326 answer = this->giveInitialNodeDirector(node);
1327 answer.at(1) += this->giveNode(node)->giveDofWithID(W_u)->giveUnknown(VM_Total, tStep);
1328 answer.at(2) += this->giveNode(node)->giveDofWithID(W_v)->giveUnknown(VM_Total, tStep);
1329 answer.at(3) += this->giveNode(node)->giveDofWithID(W_w)->giveUnknown(VM_Total, tStep);
1330 answer.times( this->giveCrossSection()->give(CS_Thickness, NULL) );
1331 } else {
1332 answer.resize(0);
1333 }
1334}
1335
1336
1337void
1338Shell7Base :: NodalRecoveryMI_computeNValProduct(FloatMatrix &answer, int layer, InternalStateType type,
1339 TimeStep *tStep)
1340{
1341 // evaluates N^T sigma over element volume
1342 // N(nsigma, nsigma*nnodes)
1343 // Definition : sigmaVector = N * nodalSigmaVector
1344 FloatArray stressVector, n;
1345
1346 int size = 6;
1347
1348 answer.zero();
1349 for ( auto *gp: *integrationRulesArray [ layer - 1 ] ) {
1350 double dV = this->computeVolumeAroundLayer(gp, layer);
1351
1352 if ( !this->giveIPValue(stressVector, gp, type, tStep) ) {
1353 stressVector.resize(size);
1354 stressVector.zero();
1355 }
1356
1358 answer.plusDyadUnsym(n, stressVector, dV);
1359 }
1360}
1361
1362void
1363Shell7Base :: NodalRecoveryMI_computeNNMatrix(FloatArray &answer, int layer, InternalStateType type)
1364{
1365 //
1366 // Returns NTN matrix (lumped) for Zienkiewicz-Zhu
1367 // The size of N mtrx is (nstresses, nnodes*nstreses)
1368 // Definition : sigmaVector = N * nodalSigmaVector
1369 //
1370 FloatMatrix fullAnswer;
1371 FloatArray n;
1372
1373 for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) {
1374 double dV = this->computeVolumeAroundLayer(gp, layer);
1376 fullAnswer.plusDyadSymmUpper(n, dV);
1377 }
1378 fullAnswer.symmetrized();
1379
1381 answer.resize(fullAnswer.giveNumberOfRows());
1382 for ( int i = 1; i <= fullAnswer.giveNumberOfRows(); i++ ) {
1383 double sum = 0.0;
1384 for ( int j = 1; j <= fullAnswer.giveNumberOfColumns(); j++ ) {
1385 sum += fullAnswer.at(i, j);
1386 }
1387 answer.at(i) = sum;
1388 }
1389}
1390
1391void
1392Shell7Base :: ZZNodalRecoveryMI_ComputeEstimatedInterpolationMtrx(FloatArray &answer, GaussPoint *gp, InternalStateType type)
1393{
1394 // evaluates N matrix (interpolation estimated stress matrix)
1395 // according to Zienkiewicz & Zhu paper
1396 // N(nsigma, nsigma*nnodes)
1397 // Definition : sigmaVector = N * nodalSigmaVector
1398 FEInterpolation *interpol = static_cast< FEInterpolation * >( &this->interpolationForExport );
1399
1400 // test if underlying element provides interpolation
1401 if ( interpol ) {
1403
1404 interpol->evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
1405 } else {
1406 // ok default implementation can not work, as element is not providing valid interpolation
1407 // to resolve this, one can overload this method for element implementing ZZNodalRecoveryModelInterface
1408 // or element should provide interpolation.
1409 OOFEM_ERROR("Element %d not providing valid interpolation", this->giveNumber() );
1410 }
1411}
1412
1413
1414void
1415Shell7Base :: NodalRecoveryMI_recoverValues(std::vector<FloatArray> &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
1416{
1417 // ZZ recovery
1418 FloatArray nnMatrix;
1419 FloatMatrix nValProd;
1420 NodalRecoveryMI_computeNValProduct(nValProd, layer, type, tStep);
1421 NodalRecoveryMI_computeNNMatrix(nnMatrix, layer, type);
1422 int recoveredSize = nValProd.giveNumberOfColumns();
1423 int numNodes = nValProd.giveNumberOfRows();
1424 recoveredValues.resize(numNodes);
1425
1426 for ( int i = 1; i <= numNodes; i++ ) {
1427 FloatArray temp(6);
1428 recoveredValues[i-1].resize(9);
1429
1430 for ( int j = 1; j <= recoveredSize; j++ ) {
1431 temp.at(j) = nValProd.at(i,j) / nnMatrix.at(i);
1432 }
1433
1434 recoveredValues[i-1] = convV6ToV9Stress(temp);
1435 }
1436}
1437
1438#endif
1439
1440
1441
1442
1443// Computation of solution vectors
1444
1445#if 1
1446
1447void
1448Shell7Base :: temp_computeBoundaryVectorOf(IntArray &dofIdArray, int boundary, ValueModeType u, TimeStep *tStep, FloatArray &answer)
1449{
1451 // Routine to extract vector given an array of dofid items
1452 // If a certain dofId does not exist a zero is used as value
1453
1454 const auto &bNodes = this->fei->computeLocalEdgeMapping(boundary);
1455 this->computeBoundaryVectorOf(bNodes, dofIdArray, u, tStep, answer);
1456
1457 //answer.resize( dofIdArray.giveSize() * bNodes.giveSize() );
1458 //answer.zero();
1459 //int k = 0;
1460 //for ( int i = 1; i <= bNodes.giveSize(); i++ ) {
1461 // DofManager *dMan = this->giveDofManager(bNodes.at(i));
1462 // for (int j = 1; j <= dofIdArray.giveSize(); j++ ) {
1463 // Dof *d = dMan->giveDof(j);
1464 // k++;
1465 // if ( dMan->hasDofID( (DofIDItem) dofIdArray.at(j) ) ) {
1466 // answer.at(k) = d->giveUnknown(VM_Total, tStep);
1467 // }
1468 // }
1469 //}
1470
1471
1472}
1473
1474void
1475Shell7Base :: giveUpdatedSolutionVector(FloatArray &answer, TimeStep *tStep)
1476{
1477 // Computes updated solution as: x = X + dx, m = M + dM, gam = 0 + dgam
1478 // This is because the element formulation is in terms of placement and not displacement.
1479 answer = this->giveInitialSolutionVector();
1480 FloatArray temp;
1481 int dummy = 0;
1482 IntArray dofIdArray;
1483 Shell7Base::giveDofManDofIDMask(dummy, dofIdArray);
1484 Element :: computeVectorOf(dofIdArray, VM_Total, tStep, temp, true);
1485 answer.assemble( temp, this->giveOrderingNodes() );
1486}
1487
1488
1489void
1490Shell7Base :: setupInitialSolutionVector()
1491{
1492 // Gives the initial values of X, M and gamma which definies the initial position
1493 this->initialSolutionVector.resize( Shell7Base :: giveNumberOfDofs() );
1494 this->initialSolutionVector.zero();
1495 int ndofs_xm = 3 * this->giveNumberOfDofManagers();
1496
1497 // Reference position and directors
1498 for ( int i = 1, j = 0; i <= this->giveNumberOfDofManagers(); i++, j += 3 ) {
1499 const auto &Xi = this->giveNode(i)->giveCoordinates();
1500 const auto &Mi = this->giveInitialNodeDirector(i);
1501 this->initialSolutionVector.at(1 + j) = Xi.at(1);
1502 this->initialSolutionVector.at(2 + j) = Xi.at(2);
1503 this->initialSolutionVector.at(3 + j) = Xi.at(3);
1504 this->initialSolutionVector.at(ndofs_xm + 1 + j) = Mi.at(1);
1505 this->initialSolutionVector.at(ndofs_xm + 2 + j) = Mi.at(2);
1506 this->initialSolutionVector.at(ndofs_xm + 3 + j) = Mi.at(3);
1507 // Assumes gam=0 at t=0
1508 }
1509}
1510
1511
1512void
1513Shell7Base :: edgeGiveUpdatedSolutionVector(FloatArray &answer, const int iEdge, TimeStep *tStep)
1514{
1515 //this->edgeGiveInitialSolutionVector(answer, iedge);
1516 this->giveInitialEdgeSolutionVector(iEdge);
1517 FloatArray temp;
1518 int dummy = 0;
1519 IntArray dofIdArray;
1520 Shell7Base :: giveDofManDofIDMask(dummy, dofIdArray);
1521 this->temp_computeBoundaryVectorOf(dofIdArray, iEdge, VM_Total, tStep, temp);
1522 //answer.assemble( temp, this->giveOrdering(EdgeInv) );
1523 answer.assemble( temp, this->giveOrderingEdgeNodes());
1524}
1525
1526void
1527Shell7Base :: setupInitialEdgeSolutionVector()
1528{
1529 //int numEdges = this->giveNumberOfBoundarySides();///TODO fix
1530 int numEdges = 3;
1531 this->initialEdgeSolutionVectors.resize( numEdges );
1532 for ( int iEdge = 1; iEdge <= numEdges; iEdge++ ) {
1533 FloatArray &solVec = this->initialEdgeSolutionVectors[iEdge-1];
1534 solVec.resize( this->giveNumberOfEdgeDofs() );
1535 solVec.zero();
1536 const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iEdge);
1537 int ndofs_x = 3 * edgeNodes.giveSize();
1538 for ( int i = 1, j = 0; i <= edgeNodes.giveSize(); i++, j += 3 ) {
1539 const auto &Xi = this->giveNode( edgeNodes.at(i) )->giveCoordinates();
1540 const auto &Mi = this->giveInitialNodeDirector( edgeNodes.at(i) );
1541 solVec.at(1 + j) = Xi.at(1);
1542 solVec.at(2 + j) = Xi.at(2);
1543 solVec.at(3 + j) = Xi.at(3);
1544 solVec.at(ndofs_x + 1 + j) = Mi.at(1);
1545 solVec.at(ndofs_x + 2 + j) = Mi.at(2);
1546 solVec.at(ndofs_x + 3 + j) = Mi.at(3);
1547 // gam(t=0)=0 is assumed
1548 }
1549 }
1550}
1551
1552void
1553Shell7Base :: giveGeneralizedStrainComponents(FloatArray genEps, FloatArrayF<3> &dphidxi1, FloatArrayF<3> &dphidxi2, FloatArrayF<3> &dmdxi1,
1554 FloatArrayF<3> &dmdxi2, FloatArrayF<3> &m, double &dgamdxi1, double &dgamdxi2, double &gam)
1555{
1556 // generealized strain vector [dxdxi, dmdxi, m, dgamdxi, gam]^T
1557 dphidxi1 = { genEps.at(1), genEps.at(2), genEps.at(3) };
1558 dphidxi2 = { genEps.at(4), genEps.at(5), genEps.at(6) };
1559 dmdxi1 = { genEps.at(7), genEps.at(8), genEps.at(9) };
1560 dmdxi2 = { genEps.at(10), genEps.at(11), genEps.at(12) };
1561 m = { genEps.at(13), genEps.at(14), genEps.at(15) };
1562 dgamdxi1 = genEps.at(16);
1563 dgamdxi2 = genEps.at(17);
1564 gam = genEps.at(18);
1565}
1566
1567
1568void
1569Shell7Base :: giveUnknownsAt(const FloatArrayF<3> &lCoords, const FloatArray &solVec, FloatArrayF<3> &x, FloatArrayF<3> &m, double &gam, TimeStep *tStep)
1570{
1571 // returns the unknowns evaluated at a point (xi1, xi2, xi3)
1572 FloatMatrix N;
1573 this->computeNmatrixAt(lCoords, N);
1574 FloatArray temp;
1575 temp.beProductOf(N, solVec);
1576 x = { temp.at(1), temp.at(2), temp.at(3) };
1577 m = { temp.at(4), temp.at(5), temp.at(6) };
1578 gam = temp.at(7);
1579}
1580
1581
1582#endif
1583
1584
1585// N and B matrices
1586
1587#if 1
1588
1589
1590void
1591Shell7Base :: edgeComputeNmatrixAt(const FloatArray &lcoords, FloatMatrix &answer)
1592{
1593 // Returns the displacement interpolation matrix {N} of the receiver
1594 // evaluated at gaussPoint along one edge.
1595
1596 answer.resize( 7, this->giveNumberOfEdgeDofs() );
1597 answer.zero();
1598
1599 FloatArray N;
1600 this->fei->edgeEvalN( N, 1, lcoords, FEIElementGeometryWrapper(this) );
1601
1602 /* 9 9 3
1603 * 3 [N_x 0 0
1604 * 3 0 N_m 0
1605 * 1 0 0 N_gmm ]
1606 */
1607 int ndofs_xm = this->giveNumberOfEdgeDofs() / 7 * 3; // numEdgeNodes * 3 dofs
1608 for ( int i = 1, j = 0; i <= this->giveNumberOfEdgeDofManagers(); i++, j += 3 ) {
1609 answer.at(1, 1 + j) = N.at(i);
1610 answer.at(2, 2 + j) = N.at(i);
1611 answer.at(3, 3 + j) = N.at(i);
1612 answer.at(4, ndofs_xm + 1 + j) = N.at(i);
1613 answer.at(5, ndofs_xm + 2 + j) = N.at(i);
1614 answer.at(6, ndofs_xm + 3 + j) = N.at(i);
1615 answer.at(7, ndofs_xm * 2 + i) = N.at(i);
1616 }
1617}
1618
1619
1620void
1621Shell7Base :: edgeComputeBmatrixAt(const FloatArray &lcoords, FloatMatrix &answer, int li, int ui)
1622{
1623 // Returns the matrix {B} of the receiver, evaluated at gp. Such that
1624 // B*a = [dxbar_dxi, dwdxi, w, dgamdxi, gam]^T, where a is the vector of unknowns
1625
1626 answer.resize( 11, this->giveNumberOfEdgeDofs() );
1627 answer.zero();
1628 FloatArray N, dNdxi;
1629
1630 this->fei->edgeEvalN( N, 1, lcoords, FEIElementGeometryWrapper(this) );
1631 int iedge = 0;
1632 this->fei->edgeEvaldNdxi( dNdxi, iedge, lcoords, FEIElementGeometryWrapper(this) );
1633
1634 /*
1635 * 3 [B_u 0 0
1636 * 3 0 B_w 0
1637 * 3 0 N_w 0
1638 * 1 0 0 B_gam
1639 * 1 0 0 N_gam]
1640 */
1641 int ndofs_xm = this->giveNumberOfEdgeDofs() / 7 * 3; // numEdgeNodes * 3 dofs
1642 int ndofman = this->giveNumberOfEdgeDofManagers();
1643
1644 // First row
1645 for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
1646 answer.at(1, 1 + j) = dNdxi.at(i);
1647 answer.at(2, 2 + j) = dNdxi.at(i);
1648 answer.at(3, 3 + j) = dNdxi.at(i);
1649 }
1650
1651 // Second row
1652 for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
1653 answer.at(4, ndofs_xm + 1 + j) = dNdxi.at(i);
1654 answer.at(5, ndofs_xm + 2 + j) = dNdxi.at(i);
1655 answer.at(6, ndofs_xm + 3 + j) = dNdxi.at(i);
1656 answer.at(7, ndofs_xm + 1 + j) = N.at(i);
1657 answer.at(8, ndofs_xm + 2 + j) = N.at(i);
1658 answer.at(9, ndofs_xm + 3 + j) = N.at(i);
1659 }
1660
1661 // Third row
1662 for ( int i = 1, j = 0; i <= ndofman; i++, j += 1 ) {
1663 answer.at(10, ndofs_xm * 2 + 1 + j) = dNdxi.at(i);
1664 answer.at(11, ndofs_xm * 2 + 1 + j) = N.at(i);
1665 }
1666}
1667
1668
1669void
1670Shell7Base :: computeBmatrixAt(const FloatArray &lcoords, FloatMatrix &answer, int li, int ui)
1671{
1672 // Returns the matrix {B} of the receiver, evaluated at gp. Such that
1673 // B*a = [dxbar_dxi, dwdxi, w, dgamdxi, gam]^T, where a is the vector of unknowns
1674
1675 int ndofs = Shell7Base :: giveNumberOfDofs();
1676 int ndofs_xm = 3 * this->giveNumberOfDofManagers();
1677 answer.resize(18, ndofs);
1678 answer.zero();
1679 FloatArray N;
1680 FloatMatrix dNdxi;
1681 this->fei->evalN( N, lcoords, FEIElementGeometryWrapper(this) );
1682 this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) );
1683
1684 /* 18 18 6
1685 * 6 [B_u 0 0
1686 * 6 0 B_w 0
1687 * 3 0 N_w 0
1688 * 2 0 0 B_gam
1689 * 1 0 0 N_gam]
1690 */
1691 int ndofman = this->giveNumberOfDofManagers();
1692
1693 // First column
1694 for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
1695 answer.at(1, 1 + j) = dNdxi.at(i, 1);
1696 answer.at(2, 2 + j) = dNdxi.at(i, 1);
1697 answer.at(3, 3 + j) = dNdxi.at(i, 1);
1698 answer.at(4, 1 + j) = dNdxi.at(i, 2);
1699 answer.at(5, 2 + j) = dNdxi.at(i, 2);
1700 answer.at(6, 3 + j) = dNdxi.at(i, 2);
1701 }
1702
1703 // Second column
1704 for ( int i = 1, j = 0; i <= ndofman; i++, j += 3 ) {
1705 answer.at(7, ndofs_xm + 1 + j) = dNdxi.at(i, 1);
1706 answer.at(8, ndofs_xm + 2 + j) = dNdxi.at(i, 1);
1707 answer.at(9, ndofs_xm + 3 + j) = dNdxi.at(i, 1);
1708 answer.at(10, ndofs_xm + 1 + j) = dNdxi.at(i, 2);
1709 answer.at(11, ndofs_xm + 2 + j) = dNdxi.at(i, 2);
1710 answer.at(12, ndofs_xm + 3 + j) = dNdxi.at(i, 2);
1711 answer.at(13, ndofs_xm + 1 + j) = N.at(i);
1712 answer.at(14, ndofs_xm + 2 + j) = N.at(i);
1713 answer.at(15, ndofs_xm + 3 + j) = N.at(i);
1714 }
1715
1716 // Third column
1717 for ( int i = 1, j = 0; i <= ndofman; i++, j += 1 ) {
1718 answer.at(16, ndofs_xm * 2 + 1 + j) = dNdxi.at(i, 1);
1719 answer.at(17, ndofs_xm * 2 + 1 + j) = dNdxi.at(i, 2);
1720 answer.at(18, ndofs_xm * 2 + 1 + j) = N.at(i);
1721 }
1722}
1723
1724
1725void
1726Shell7Base :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer)
1727{
1728 // Returns the displacement interpolation matrix {N} of the receiver,
1729 // evaluated at gp.
1730
1731 int ndofs = Shell7Base :: giveNumberOfDofs();
1732 int ndofs_xm = 3 * this->giveNumberOfDofManagers();
1733 answer.resize(7, ndofs);
1734 answer.zero();
1735 FloatArray N;
1736 this->fei->evalN( N, iLocCoord, FEIElementGeometryWrapper(this) );
1737
1738 /* nno*3 nno*3 nno
1739 * 3 [N_x 0 0
1740 * 3 0 N_m 0
1741 * 1 0 0 N_gmm ]
1742 */
1743 for ( int i = 1, j = 0; i <= this->giveNumberOfDofManagers(); i++, j += 3 ) {
1744 answer.at(1, 1 + j) = N.at(i);
1745 answer.at(2, 2 + j) = N.at(i);
1746 answer.at(3, 3 + j) = N.at(i);
1747 answer.at(4, ndofs_xm + 1 + j) = N.at(i);
1748 answer.at(5, ndofs_xm + 2 + j) = N.at(i);
1749 answer.at(6, ndofs_xm + 3 + j) = N.at(i);
1750 answer.at(7, ndofs_xm * 2 + i) = N.at(i);
1751 }
1752}
1753
1754
1755#endif
1756
1757
1758// VTK export
1759#if 1
1761Shell7Base :: vtkEvalInitialGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer)
1762{
1763 double zeta = giveGlobalZcoordInLayer(localCoords.at(3), layer);
1764 FloatArray N;
1765 this->fei->evalN( N, localCoords, FEIElementGeometryWrapper(this) );
1766
1767 FloatArrayF<3> globalCoords;
1768 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
1769 const auto &xbar = FloatArrayF<3>(this->giveNode(i)->giveCoordinates());
1770 const auto &M = this->giveInitialNodeDirector(i);
1771 globalCoords += N.at(i) * ( xbar + zeta * M );
1772 }
1773 return globalCoords;
1774}
1775
1777Shell7Base :: vtkEvalInitialGlobalCZCoordinateAt(const FloatArrayF<3> &localCoords, int interface)
1778{
1779 double zeta = giveGlobalZcoordInLayer(1.0, interface);
1780 FloatArray N;
1781 this->fei->evalN( N, localCoords, FEIElementGeometryWrapper(this) );
1782
1783 FloatArrayF<3> globalCoords;
1784 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
1785 const auto &xbar = FloatArrayF<3>(this->giveNode(i)->giveCoordinates());
1786 const auto &M = this->giveInitialNodeDirector(i);
1787 globalCoords += N.at(i) * ( xbar + zeta * M );
1788 }
1789 return globalCoords;
1790}
1791
1793Shell7Base :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer, TimeStep *tStep)
1794{
1795 FloatArray solVec;
1796 this->giveUpdatedSolutionVector(solVec, tStep);
1797 FloatArrayF<3> x, m; double gam=0;
1798 this->giveUnknownsAt(localCoords, solVec, x, m, gam, tStep);
1799 double zeta = giveGlobalZcoordInLayer(localCoords.at(3), layer);
1800 double fac = ( zeta + 0.5 * gam * zeta * zeta );
1801 return x + fac*m;
1802}
1803
1804void
1805Shell7Base :: giveCompositeExportData(std::vector< ExportRegion > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep )
1806{
1807 vtkPieces.resize(1);
1808 this->giveShellExportData(vtkPieces[0], primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep );
1809 //this->giveCZExportData(vtkPieces[1], primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep );
1810}
1811
1812void
1813Shell7Base :: giveShellExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep )
1814{
1815 int numCells = this->layeredCS->giveNumberOfLayers();
1816 const int numCellNodes = 15; // quadratic wedge
1817 int numTotalNodes = numCellNodes*numCells;
1818
1819 vtkPiece.setNumberOfCells(numCells);
1820 vtkPiece.setNumberOfNodes(numTotalNodes);
1821
1822 int val = 1;
1823 int offset = 0;
1824 IntArray nodes(numCellNodes);
1825
1826 // Compute fictious node coords
1827 int nodeNum = 1;
1828 for ( int layer = 1; layer <= numCells; layer++ ) {
1829
1830 // Node coordinates
1831 auto nodeCoords = this->giveFictiousNodeCoordsForExport(layer);
1832
1833 for ( int node = 1; node <= numCellNodes; node++ ) {
1834 vtkPiece.setNodeCoords(nodeNum, nodeCoords[node-1] );
1835 nodeNum += 1;
1836 }
1837
1838 // Connectivity
1839 for ( int i = 1; i <= numCellNodes; i++ ) {
1840 nodes.at(i) = val++;
1841 }
1842 vtkPiece.setConnectivity(layer, nodes);
1843
1844 // Offset
1845 offset += numCellNodes;
1846 vtkPiece.setOffset(layer, offset);
1847
1848 // Cell types
1849 vtkPiece.setCellType(layer, 26); // Quadratic wedge
1850 }
1851
1852
1853 // Export nodal variables from primary fields
1854 vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes);
1855
1856 FloatArray u(3);
1857 std::vector<FloatArray> values;
1858 for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) {
1859 UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum);
1860 nodeNum = 1;
1861 for ( int layer = 1; layer <= numCells; layer++ ) {
1862
1863 if ( type == DisplacementVector ) { // compute displacement as u = x - X
1864 auto nodeCoords = this->giveFictiousNodeCoordsForExport(layer);
1865 auto updatedNodeCoords = this->giveFictiousUpdatedNodeCoordsForExport(layer, tStep);
1866 for ( int j = 1; j <= numCellNodes; j++ ) {
1867 u = updatedNodeCoords[j-1];
1868 u.subtract(nodeCoords[j-1]);
1869 vtkPiece.setPrimaryVarInNode(type, nodeNum, u);
1870 nodeNum += 1;
1871 }
1872
1873 } else {
1874 NodalRecoveryMI_recoverValues(values, layer, ( InternalStateType ) 1, tStep); // does not work well - fix
1875 for ( int j = 1; j <= numCellNodes; j++ ) {
1876 vtkPiece.setPrimaryVarInNode(type, nodeNum, values[j-1]);
1877 nodeNum += 1;
1878 }
1879 }
1880 }
1881 }
1882
1883 // Export nodal variables from internal fields
1884
1885 vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes );
1886 for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) {
1887 InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum);
1888 nodeNum = 1;
1889
1890// if ( recoverStress ) {
1891// // Recover shear stresses
1892// this->recoverShearStress(tStep);
1893// }
1894
1895 for ( int layer = 1; layer <= numCells; layer++ ) {
1896 recoverValuesFromIP(values, layer, type, tStep);
1897 for ( int j = 1; j <= numCellNodes; j++ ) {
1898 vtkPiece.setInternalVarInNode( type, nodeNum, values[j-1] );
1899 //ZZNodalRecoveryMI_recoverValues(el.nodeVars[fieldNum], layer, type, tStep);
1900 nodeNum += 1;
1901 }
1902 }
1903 }
1904
1905
1906 // Export cell variables
1907 FloatArray average;
1908 vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells);
1909 for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) {
1910 InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i);
1911
1912 for ( int layer = 1; layer <= numCells; layer++ ) {
1913 std :: unique_ptr< IntegrationRule > &iRuleL = integrationRulesArray [ layer - 1 ];
1914 VTKBaseExportModule::computeIPAverage(average, iRuleL.get(), this, type, tStep);
1915
1916 if ( average.giveSize() == 6 ) {
1917 vtkPiece.setCellVar(type, layer, convV6ToV9Stress(average) );
1918 } else {
1919 vtkPiece.setCellVar(type, layer, average );
1920 }
1921 }
1922 }
1923}
1924
1925
1926void
1927Shell7Base :: recoverValuesFromIP(std::vector<FloatArray> &recoveredValues, int layer, InternalStateType type, TimeStep *tStep, stressRecoveryType SRtype)
1928{
1929 // recover nodal values from IP:s
1930
1931 switch (SRtype) {
1932 case copyIPvalue:
1933 // Find closest ip to the nodes
1934 CopyIPvaluesToNodes(recoveredValues, layer, type, tStep);
1935 break;
1936 case LSfit:
1937 // Do least square fit
1938 nodalLeastSquareFitFromIP(recoveredValues, layer, type, tStep);
1939 break;
1940 case L2fit:
1941 // Do L2 fit
1942 OOFEM_ERROR("L2-fit not implemented.");
1943 break;
1944 default:
1945 OOFEM_ERROR("Incorrect stress recovery type.");
1946 }
1947#if 0
1948 if (this->giveGlobalNumber() == 20) {
1949 for (FloatArray inod: recoveredValues) {
1950 inod.printYourself("recovered-värden");
1951 }
1952 }
1953#endif
1954
1955}
1956
1957
1958void
1959Shell7Base :: CopyIPvaluesToNodes(std::vector<FloatArray> &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
1960{
1961 // Method for copying value in closest IP to nodes
1962
1963 // composite element interpolator
1964 FloatMatrix localNodeCoords;
1965 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, this->giveGeometryType());
1966
1967 int numNodes = localNodeCoords.giveNumberOfColumns();
1968 recoveredValues.resize(numNodes);
1969
1970 // Find closest ip to the nodes
1971 IntArray closestIPArray(numNodes);
1972 FloatArray nodeCoords, ipValues;
1973
1974 for ( int i = 1; i <= numNodes; i++ ) {
1975 nodeCoords.beColumnOf(localNodeCoords, i);
1976 double distOld = 3.0; // should not be larger
1977 std :: unique_ptr< IntegrationRule > &iRule = integrationRulesArray [ layer - 1 ];
1978 for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); ++j ) {
1979 IntegrationPoint *ip = iRule->getIntegrationPoint(j);
1980 const FloatArray &ipCoords = ip->giveNaturalCoordinates();
1982 double dist = distance(nodeCoords, ipCoords);
1983 if ( dist < distOld ) {
1984 closestIPArray.at(i) = j;
1985 distOld = dist;
1986 }
1987 }
1988 }
1989
1990 // recover ip values
1991 for ( int i = 1; i <= numNodes; i++ ) {
1992 IntegrationPoint *ip = integrationRulesArray [ layer - 1 ]->getIntegrationPoint( closestIPArray.at(i) );
1993 this->giveIPValue(ipValues, ip, type, tStep);
1995 recoveredValues[i-1].resize(9);
1996 recoveredValues[i-1] = convV6ToV9Stress(ipValues);
1997 //} else if ( ipValues.giveSize() == 0 && type == IST_AbaqusStateVector) {
1998 // recoveredValues[i-1].resize(23);
1999 // recoveredValues[i-1].zero();
2000 } else {
2001 recoveredValues[i-1] = ipValues;
2002 }
2003 }
2004}
2005
2006void
2007Shell7Base :: nodalLeastSquareFitFromIP(std::vector<FloatArray> &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
2008{
2009 // Method for computing nodal values from IP:s by least square fit
2010
2011 // composite element interpolator
2012 FloatMatrix localNodeCoords;
2013 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, EGT_wedge_2);
2014
2015 int numNodes = localNodeCoords.giveNumberOfColumns();
2016 recoveredValues.resize(numNodes);
2017
2018 std :: unique_ptr< IntegrationRule > &iRule = integrationRulesArray [ layer - 1 ];
2019 IntegrationPoint *ip;
2020 int numIP = iRule->giveNumberOfIntegrationPoints();
2021 FloatArray nodeCoords, ipCoords;
2023
2024 if (numNodes > numIP) {
2025 OOFEM_ERROR("Least square fit not possible for more nodes than IP:s per layer.");
2026 }
2027
2028 // Find IP values and set up matrix of base functions
2029 FloatMatrix Nbar, NbarTNbar, NbarTNbarInv, Nhat, ipValues, temprecovedValues, temprecovedValuesT;
2030 Nbar.resize(numIP,numNodes);
2031 //int numSC;
2032 //if ( valueType == ISVT_TENSOR_S3 ) { numSC = 6; } else { numSC = 9; };
2033 //ipValues.resize(numIP,numSC);
2034
2035 for ( int i = 0; i < numIP; i++ ) {
2036 ip = iRule->getIntegrationPoint(i);
2037 FloatArray tempIPvalues;
2038 this->giveIPValue(tempIPvalues, ip, type, tStep);
2039#if 0
2040 // Test of analytical dummy values in IPs
2041 FloatArray ipGlobalCoords;
2042 ipCoords = *ip->giveNaturalCoordinates();
2043 this->vtkEvalInitialGlobalCoordinateAt(ipCoords, layer, ipGlobalCoords);
2044// this->computeGlobalCoordinates( ipGlobalCoords, ipCoords );
2045 tempIPvalues.resize(9);
2046 tempIPvalues.zero();
2047 tempIPvalues.at(1) = 7.8608e+09 * ( 0.2 - ipGlobalCoords.at(1) ) * ipGlobalCoords.at(3);
2048#endif
2049 ipValues.addSubVectorRow(tempIPvalues,i+1,1);
2050
2051 // set up virtual cell geometry for an qwedge
2052 auto nodes = giveFictiousNodeCoordsForExport(layer);
2053 FEInterpolation *interpol = static_cast< FEInterpolation * >( &this->interpolationForExport );
2054 FloatArray N;
2055 interpol->evalN( N, ip->giveNaturalCoordinates(), FEIVertexListGeometryWrapper( nodes, this->giveGeometryType() ) );
2056 Nbar.addSubVectorRow(N,i+1,1);
2057 }
2058 // Nhat = inv(Nbar^T*Nbar)*Nbar^T
2059 NbarTNbar.beTProductOf(Nbar,Nbar);
2060 NbarTNbarInv.beInverseOf(NbarTNbar);
2061 Nhat.beProductTOf(NbarTNbarInv,Nbar);
2062
2063 temprecovedValues.beProductOf(Nhat,ipValues);
2064 temprecovedValuesT.beTranspositionOf(temprecovedValues);
2066 IntArray strangeNodeNumbering = {2, 1, 3, 5, 4, 6, 7, 9, 8, 10, 12, 11, 13, 14, 15 };
2067 for (int i = 0; i < numNodes; i++ ) {
2068 if ( valueType == ISVT_TENSOR_S3 ) {
2069 FloatArray nodalStresses;
2070 nodalStresses.beColumnOf(temprecovedValuesT,i+1);
2071 recoveredValues[strangeNodeNumbering[i]-1] = convV6ToV9Stress(nodalStresses);
2072 } else {
2073 recoveredValues[strangeNodeNumbering[i]-1].beColumnOf(temprecovedValuesT,i+1);
2074 }
2075 }
2076}
2077
2078void
2079Shell7Base :: giveL2contribution(FloatMatrix &ipValues, FloatMatrix &Nbar, int layer, InternalStateType type, TimeStep *tStep)
2080{
2081 // composite element interpolator
2082 FloatMatrix localNodeCoords;
2083 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, EGT_wedge_2);
2084
2085 int numNodes = localNodeCoords.giveNumberOfColumns();
2086
2087 std :: unique_ptr< IntegrationRule > &iRule = integrationRulesArray [ layer - 1 ];
2088 int numIP = iRule->giveNumberOfIntegrationPoints();
2089 FloatArray nodeCoords, ipCoords;
2091
2092 // Find IP values and set up matrix of base functions
2093 // FloatMatrix Nbar, NbarTNbar, NbarTNbarInv, Nhat, ipValues, temprecovedValues, temprecovedValuesT;
2094 Nbar.resize(numIP,numNodes);
2095 int numSC;
2096 if ( valueType == ISVT_TENSOR_S3 ) { numSC = 6; } else { numSC = 9; };
2097 ipValues.resize(numIP,numSC);
2098
2099 for ( int i = 0; i < numIP; i++ ) {
2100 auto *ip = iRule->getIntegrationPoint(i);
2101 FloatArray tempIPvalues;
2102 this->giveIPValue(tempIPvalues, ip, type, tStep);
2103 ipValues.addSubVectorRow(tempIPvalues,i+1,1);
2104
2105 // set up virtual cell geometry for an qwedge
2106 auto nodes = giveFictiousNodeCoordsForExport(layer);
2107 FEInterpolation *interpol = static_cast< FEInterpolation * >( &this->interpolationForExport );
2108 FloatArray N;
2109 interpol->evalN( N, ip->giveNaturalCoordinates(), FEIVertexListGeometryWrapper( nodes, this->giveGeometryType() ) );
2110 Nbar.addSubVectorRow(N,i+1,1);
2111 }
2112}
2113
2114void
2115Shell7Base :: giveSPRcontribution(FloatMatrix &eltIPvalues, FloatMatrix &eltPolynomialValues, int layer, InternalStateType type, TimeStep *tStep)
2116{
2117 /* Returns the integration point values and polynomial values of the element interpolation wedge at layer, such that
2118 [GPvalue] = [P(x_GP,y_GP,z_GP)]*a, where
2119 P(x,y,z) = [1 x y z yz xz xz x^2 y^2] (NB: z^2 term omitted)
2120 a = [a1 ... a9] is the vector of coefficients, which is to be found by the polynomial least square fit.
2121 */
2122
2123 std :: unique_ptr< IntegrationRule > &iRule = this->integrationRulesArray[layer-1]; // Stämmer det här???
2124 IntegrationPoint *ip;
2125 int numEltIP = iRule->giveNumberOfIntegrationPoints();
2126 eltIPvalues.clear();
2127 eltPolynomialValues.clear();
2128
2129 // Loop over IP:s in wedge interpolation
2130 for ( int iIP = 0; iIP < numEltIP; iIP++ ) {
2131 ip = iRule->getIntegrationPoint(iIP);
2132
2133 // Collect IP-value
2134 FloatArray IPvalues;
2135 this->giveIPValue(IPvalues, ip, type, tStep);
2136 eltIPvalues.addSubVectorRow(IPvalues,iIP+1,1);
2137
2138 // Collect global coordinates for IP and assemble to P.
2139 FloatArray IpCoords;
2140 IpCoords = ip->giveGlobalCoordinates();
2141 FloatArray iRowP = {1,IpCoords.at(1),IpCoords.at(2),IpCoords.at(3),
2142 IpCoords.at(2)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(2),
2143 IpCoords.at(1)*IpCoords.at(1),IpCoords.at(2)*IpCoords.at(2)};
2144 eltPolynomialValues.addSubVectorRow(iRowP,iIP+1,1);
2145
2146 }
2147}
2148
2149void
2150Shell7Base :: giveTractionBC(FloatMatrix &tractionTop, FloatMatrix &tractionBtm, TimeStep *tStep)
2151{
2152 int numInPlaneIP = tractionTop.giveNumberOfColumns();
2153 tractionTop.zero(); tractionBtm.zero();
2154
2155 int numLoads = this->boundaryLoadArray.giveSize() / 2;
2156
2157 for ( int i = 1; i <= numLoads; i++ ) { // For each pressure load that is applied
2158
2159 int load_number = this->boundaryLoadArray.at(2 * i - 1);
2160 //int iSurf = this->boundaryLoadArray.at(2 * i); // load_id
2161 Load *load = this->domain->giveLoad(load_number);
2162
2163 if ( ConstantSurfaceLoad* sLoad = dynamic_cast< ConstantSurfaceLoad * >( load ) ) {
2164
2165// FloatArray tractionBC, tempTractionTop, tempTractionBtm; tempTractionTop.clear(); tempTractionBtm.clear();
2166 FloatArray tractionBC(3), tempBC;
2167 load->computeComponentArrayAt(tempBC,tStep,VM_Total);
2168 double xi = sLoad->giveLoadOffset();
2169 tractionBC.assemble(tempBC,sLoad->giveDofIDs());
2170 if ( tractionBC.giveSize() != tractionBtm.giveNumberOfRows() ) {
2171 OOFEM_ERROR("Number of stress components don't match");
2172 }
2173
2174 // Assume linear variation of placement
2175 //tempTractionTop.add(((1.0+xi)/2.0),tractionBC); // positive z-normal
2176 //tempTractionBtm.add((-(1.0-xi)/2.0),tractionBC); // negative z-normal
2177 for (int iIP = 1 ; iIP <= numInPlaneIP ; iIP++ ) {
2178
2179 tractionTop.addSubVectorCol(((1.0+xi)/2.0)*tractionBC,1,iIP);
2180 tractionBtm.addSubVectorCol((-(1.0-xi)/2.0)*tractionBC,1,iIP);
2181 }
2182 } else {
2183 OOFEM_ERROR("Load type not supported");
2184 }
2185 }
2186
2187// if (this->giveGlobalNumber() == 48) {
2188// tractionTop.printYourself("tractionTop");
2189// tractionBtm.printYourself("tractionBtm");
2190// }
2191}
2192
2193void
2194Shell7Base :: recoverShearStress(TimeStep *tStep)
2195{
2196 // Recover shear stresses at ip by integration of the momentum balance through the thickness
2197
2198 int numberOfLayers = this->layeredCS->giveNumberOfLayers(); // conversion of types
2199
2200 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2201 if (numThicknessIP < 2) {
2202 // Polynomial fit involves linear z-component at the moment
2203 OOFEM_ERROR("To few thickness IP per layer to do polynomial fit");
2204 }
2205
2206 int numInPlaneIP = 6;
2207// int numInPlaneIP = this->giveIntegrationRule()->giveNumberOfIntegrationPoints();
2208 int numWedgeIP = numInPlaneIP*numThicknessIP;
2209 double totalThickness = this->layeredCS->computeIntegralThick();
2210// double integralThickness = 0.0;
2211 double zeroThicknessLevel = - 0.5 * totalThickness; // assumes midplane is the geometric midplane of layered structure.
2212// double zeroThicknessLevel = this->layeredCS->give( CS_BottomZCoord, &lCoords, this, false );
2213// FloatArray Sold;
2214 FloatMatrix dSmatLayer(3,numInPlaneIP), SmatOld(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
2215 FloatMatrix dSmatLayerIP(3,numWedgeIP);
2216
2217 // Fitting of Szz to traction BC
2218 std::vector <FloatMatrix> dSmatIP; dSmatIP.resize(numberOfLayers); //recovered stress values in wedge IPs
2219 std::vector <FloatMatrix> dSmat; dSmat.resize(numberOfLayers); //recovered stress values at layer top
2220 std::vector <FloatMatrix> dSmatIPupd; dSmatIPupd.resize(numberOfLayers); //recovered stress values in wedge IPs fitted to top and btm traction BC.
2221 std::vector <FloatMatrix> dSmatupd; dSmatupd.resize(numberOfLayers); //recovered stress values at delamination top, adjusted for top and btm traction BC
2222
2223 // Find top and bottom BC NB: assumes constant over element surface.
2224 FloatMatrix tractionTop(3,numInPlaneIP), tractionBtm(3,numInPlaneIP);
2225 giveTractionBC(tractionTop, tractionBtm, tStep);
2226 SmatOld = tractionBtm; // integration performed from bottom
2227// SmatOld.zero();
2228// for ( int i = 1; i <= numInPlaneIP ; i++) {
2229// SmatOld.at(1,i) = tractionBtm.at(1);
2230// SmatOld.at(2,i) = tractionBtm.at(2);
2231// SmatOld.at(3,i) = tractionBtm.at(3);
2232// }
2233
2234 // Integration from the bottom
2235 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
2236
2237 /* Recover values by a polynomial fit to the stress values in a patch of elements closest to the this element.
2238 * The vector of GPvalues is [GPvalue] = [P(x_GP,y_GP,z_GP)]*a, where
2239 * P(x,y,z) = [1 x y z yz xz xz x^2 y^2] (NB: z^2 term omitted)
2240 * a = [a1 ... a9] is the vector of coefficients of P
2241 * a = inv(A)*b, where
2242 * A = [P]^T*[P], b = [P]^T*[GPvalue], calculated over the appropriate patch.
2243 * the gradient of the GP value (used in the stress recovery) is then directly calculated by
2244 * d[GPvalue]/di = [dP/di|GP]*a, i = x,y,z.
2245 * dP/dx = [0 1 0 0 0 z y 2x 0]
2246 * dP/dy = [0 0 1 0 z 0 x 0 2y]
2247 * dP/dz = [0 0 0 1 y x 0 0 0 ]
2248 * which is then analytically integrated over z (see giveZintegratedPolynomialGradientForStressRecAt)
2249 * The recovery of the transverse normal stress in performed using the same analytical expression
2250 * The values in the GP is overwritten by the recovery
2251 */
2252
2253#if 0
2254 // Integration from bottom and adjusting Szz to top/btm traction BC. Shear stress not adjusted to top BC.
2255 giveLayerContributionToSR(dSmatLayer, dSmatLayerIP, layer, zeroThicknessLevel, tStep);
2256
2257
2258 // Save layer stresses (IP- and interface values) to be able to fit to traction BC
2259 // Only Szz fitted. ///TODO fit shear stresses to traction BC?
2260 dSmatIP[layer-1].beSubMatrixOf(dSmatLayerIP, 3, 3, 1, numWedgeIP);
2261 dSmat[layer-1].beSubMatrixOf(dSmatLayer, 3, 3, 1, numInPlaneIP);
2262 //if (this->giveGlobalNumber() == 48 ) { dSmatLayerIP.printYourself(); dSmatIP[layer -1].printYourself(); }
2263
2264 updateLayerTransvShearStressesSR(dSmatLayerIP, SmatOld, layer);
2265
2266// updateLayerTransvStressesSR(dSmatLayerIP, SmatOld, layer);
2267
2268 SmatOld.add(dSmatLayer); // Integrated stress over laminate
2269#endif
2270
2271 // Perform integration and distribute the integration error to top and btm
2272 // Integration of Szz requires both top and btm traction BC
2273 // Integration of shear stresses only require one BC, however the error is distributed across thickness (ie the same as doing integration from top and btm and taking average)
2274 // fulfillment of top and btm traction BC optional for shear stresses.
2275
2276 giveLayerContributionToSR(dSmat[layer-1], dSmatIP[layer-1], layer, zeroThicknessLevel, tStep);
2277 SmatOld.add(dSmat[layer-1]); // Integrated stress over laminate
2278
2279 zeroThicknessLevel += this->layeredCS->giveLayerThickness(layer);
2280
2281// integralThickness += thickness;
2282
2283 }
2284
2285 // Fitting of stresses in IPs to traction BC
2286 zeroThicknessLevel = - 0.5 * totalThickness;
2287
2288#if 0
2289 // Only Szz
2290 FloatMatrix integratedStress;
2291 integratedStress.beSubMatrixOf(SmatOld, 3, 3, 1, numInPlaneIP);
2292 FloatArray tempTractionBtm = {tractionBtm.at(3)};
2293 FloatArray tempTractionTop = {tractionTop.at(3)};
2294 fitRecoveredStress2BC(dSmatIPupd, dSmat, dSmatIP, integratedStress, tempTractionBtm, tempTractionTop, zeroThicknessLevel, {1});
2295// fitRecoveredStress2BC(dSmatIPupd, dSmat, dSmatIP, integratedStress, {tractionBtm.at(3)}, {tractionBtm.at(3)}, zeroThicknessLevel, {1});
2296
2298 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
2299// if (this->giveGlobalNumber() == 48 ) { dSzzmatIP[layer -1].printYourself(); }
2300 updateLayerTransvNormalStressSR( dSmatIPupd[layer -1], zeros, layer); // traction on bottom already taken into account in the integration.
2301 }
2302#endif
2303
2304 // All transverse stress components
2305 fitRecoveredStress2BC(dSmatIPupd, dSmatupd, dSmat, dSmatIP, SmatOld, tractionBtm, tractionTop, zeroThicknessLevel, {0.0,0.0,1.0}, 1, numberOfLayers); // {0.0,0.0,1.0}: only Szz fulfills BC, shear stress integration error is only distributed to top and btm
2306
2307 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
2308 //if (this->giveGlobalNumber() == 84 ) { dSmatIPupd[layer -1].printYourself(); }
2309 updateLayerTransvStressesSR( dSmatIPupd[layer -1], layer);
2310 }
2311
2312
2313}
2314
2315void
2316Shell7Base :: giveRecoveredTransverseInterfaceStress(std::vector<FloatMatrix> &transverseStress, TimeStep *tStep)
2317{
2318 // Recover shear stresses at ip by integration of the momentum balance through the thickness
2319 transverseStress.clear();
2320
2321 int numberOfLayers = this->layeredCS->giveNumberOfLayers(); // conversion of types
2322 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2323 if (numThicknessIP < 2) {
2324 // Polynomial fit involves linear z-component at the moment
2325 OOFEM_ERROR("To few thickness IP per layer to do polynomial fit");
2326 }
2327
2328 int numInPlaneIP = 6;
2329 double totalThickness = this->layeredCS->computeIntegralThick();
2330 double zeroThicknessLevel = - 0.5 * totalThickness; // assumes midplane is the geometric midplane of layered structure.
2331
2332 FloatMatrix SmatOld(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
2333
2334 // Fitting of Szz to traction BC
2335 std::vector <FloatMatrix> dSmatIP; dSmatIP.resize(numberOfLayers); //recovered stress values in wedge IPs
2336 std::vector <FloatMatrix> dSmat; dSmat.resize(numberOfLayers); //recovered stress values at layer top
2337 std::vector <FloatMatrix> dSmatIPupd; dSmatIPupd.resize(numberOfLayers); //recovered stress values in wedge IPs fitted to top and btm traction BC.
2338 std::vector <FloatMatrix> dSmatupd; dSmatupd.resize(numberOfLayers); //recovered stress values at layer top, fitted to top and btm traction BC
2339
2340 // Find top and bottom BC NB: assumes constant over element surface.
2341 FloatMatrix tractionTop(3,numInPlaneIP), tractionBtm(3,numInPlaneIP);
2342 giveTractionBC(tractionTop, tractionBtm, tStep);
2343 SmatOld = tractionBtm; // integration performed from bottom
2344// if (this->giveGlobalNumber() == 10) {
2345// printf("Target time: %i \n",tStep->giveNumber());
2346// printf("Intrinsic time: %f \n",tStep->giveIntrinsicTime());
2347// printf("Target time: %f \n",tStep->giveTargetTime());
2348// tractionTop.printYourself("tractionTop");
2349// tractionBtm.printYourself("tractionBtm");
2350// }
2351
2352 // Integration from the bottom
2353 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
2354
2355 /* Recover values by a polynomial fit to the stress values in a patch of elements closest to the this element.
2356 * The vector of GPvalues is [GPvalue] = [P(x_GP,y_GP,z_GP)]*a, where
2357 * P(x,y,z) = [1 x y z yz xz xz x^2 y^2] (NB: z^2 term omitted)
2358 * a = [a1 ... a9] is the vector of coefficients of P
2359 * a = inv(A)*b, where
2360 * A = [P]^T*[P], b = [P]^T*[GPvalue], calculated over the appropriate patch.
2361 * the gradient of the GP value (used in the stress recovery) is then directly calculated by
2362 * d[GPvalue]/di = [dP/di|GP]*a, i = x,y,z.
2363 * dP/dx = [0 1 0 0 0 z y 2x 0]
2364 * dP/dy = [0 0 1 0 z 0 x 0 2y]
2365 * dP/dz = [0 0 0 1 y x 0 0 0 ]
2366 * which is then analytically integrated over z (see giveZintegratedPolynomialGradientForStressRecAt)
2367 * The recovery of the transverse normal stress in performed using the same analytical expression
2368 * The values in the GP is overwritten by the recovery
2369 */
2370
2371 // Perform integration and distribute the integration error to top and btm
2372 // Integration of Szz requires both top and btm traction BC
2373 // Integration of shear stresses only require one BC, however the error is distributed across thickness (ie the same as doing integration from top and btm and taking average)
2374 // fulfillment of top and btm traction BC optional for shear stresses.
2375
2376 giveLayerContributionToSR(dSmat[layer-1], dSmatIP[layer-1], layer, zeroThicknessLevel, tStep);
2377 SmatOld.add(dSmat[layer-1]); // Integrated stress over laminate
2378
2379 zeroThicknessLevel += this->layeredCS->giveLayerThickness(layer);
2380
2381 }
2382
2383 // Fitting of stresses in IPs to traction BC
2384 zeroThicknessLevel = - 0.5 * totalThickness;
2385
2386 // All transverse stress components
2387 transverseStress.resize(numberOfLayers-1); //recovered stress values at layer interfaces
2388 fitRecoveredStress2BC(dSmatIPupd, dSmatupd, dSmat, dSmatIP, SmatOld, tractionBtm, tractionTop, zeroThicknessLevel, {0.0,0.0,1.0}, 1, numberOfLayers); // {0.0,0.0,1.0}: only Szz fulfills BC, shear stress integration error is only distributed to top and btm
2389
2390 for ( int layer = 1 ; layer < numberOfLayers ; layer++ ) {
2391 transverseStress[layer-1] = dSmatupd[layer-1];
2392// if ( this->giveGlobalNumber() == 61 ) {
2393// transverseStress[layer-1].printYourself();
2394// }
2395 }
2396}
2397
2398void
2399Shell7Base :: giveLayerContributionToSR(FloatMatrix &dSmatLayer, FloatMatrix &dSmatLayerIP, int layer, double zeroThicknessLevel, TimeStep *tStep)
2400{
2401 /* Recover values by a polynomial fit to the stress values in a patch of elements closest to the this element.
2402 * The vector of GPvalues is [GPvalue] = [P(x_GP,y_GP,z_GP)]*a, where
2403 * P(x,y,z) = [1 x y z yz xz xz x^2 y^2] (NB: z^2 term omitted)
2404 * a = [a1 ... a9] is the vector of coefficients of P
2405 * a = inv(A)*b, where
2406 * A = [P]^T*[P], b = [P]^T*[GPvalue], calculated over the appropriate patch.
2407 * the gradient of the GP value (used in the stress recovery) is then directly calculated by
2408 * d[GPvalue]/di = [dP/di|GP]*a, i = x,y,z.
2409 * dP/dx = [0 1 0 0 0 z y 2x 0]
2410 * dP/dy = [0 0 1 0 z 0 x 0 2y]
2411 * dP/dz = [0 0 0 1 y x 0 0 0 ]
2412 * which is then analytically integrated over z (see giveZintegratedPolynomialGradientForStressRecAt)
2413 * The recovery of the transverse normal stress in performed using the same analytical expression
2414 */
2415 std :: unique_ptr< IntegrationRule > &iRuleL = this->integrationRulesArray [ layer - 1 ];
2416
2417 int numInPlaneIP = 6;
2418 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2419 dSmatLayer.clear(); dSmatLayer.resize(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip
2420 dSmatLayerIP.clear(); dSmatLayerIP.resize(3,numInPlaneIP*numThicknessIP); // 3 stress components (S_xz, S_yz, S_zz) * num of wedge IP
2421
2422 //recoveredValues.resize(numWedgeNodes);
2423 IntArray centreElNum = {this->giveGlobalNumber()};
2424 IntArray centreElNodes = this->giveDofManArray();
2425 IntArray patchEls;
2426 int numSampledIP = 0, numCoefficents = 11;
2427// int numPatchEls = patchEls.giveSize();
2428// FloatMatrix patchIpValues(numPatchEls*numThicknessIP*numInPlaneIP,6), P(numPatchEls*numThicknessIP*numInPlaneIP,numCoefficents);
2429 FloatMatrix patchIpValues, P;
2430 patchIpValues.zero();
2431 P.zero();
2432
2433 Domain *d = this->giveDomain();
2434 d->giveConnectivityTable()->giveElementNeighbourList(patchEls,centreElNum);
2435
2436 for (int patchElNum : patchEls) {
2437
2438
2439 // Get (pointer to) current element in patch and calculate its addition to the patch
2440 Shell7Base *patchEl = static_cast<Shell7Base*>(d->giveElement(patchElNum));
2441
2442 std :: unique_ptr< IntegrationRule > &iRule = patchEl->integrationRulesArray[layer-1]; // Stämmer det här???
2443 IntegrationPoint *ip;
2444 int numEltIP = iRule->giveNumberOfIntegrationPoints();
2445
2446 // Loop over IP:s in wedge interpolation
2447 for ( int iIP = 0; iIP < numEltIP; iIP++ ) {
2448 ip = iRule->getIntegrationPoint(iIP);
2449// printf("blajjja \n");
2450
2451 // Collect IP-value
2452 FloatArray tempIPvalues;
2453 patchEl->giveIPValue(tempIPvalues, ip, IST_StressTensor, tStep);
2454 patchIpValues.addSubVectorRow(tempIPvalues,numSampledIP + iIP+1,1);
2455
2456 // Collect global coordinates for IP and assemble to P.
2457 FloatArray IpCoords;
2458 IpCoords = ip->giveGlobalCoordinates();
2459// IpCoords.at(3) -= zeroThicknessLevel; // make bottom of layer ref point for polynimial fit, ie using layer z-coords (not shell)
2460/* FloatArray iRowP = {1,IpCoords.at(1),IpCoords.at(2),IpCoords.at(3),
2461 IpCoords.at(2)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(2),
2462 IpCoords.at(1)*IpCoords.at(1),IpCoords.at(2)*IpCoords.at(2)}; */
2463 // P = [1 x y z yz xz xy x² y² x²y x²z]
2464 FloatArray iRowP = {1.0,IpCoords.at(1),IpCoords.at(2),IpCoords.at(3),
2465 IpCoords.at(2)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(2),
2466 IpCoords.at(1)*IpCoords.at(1),IpCoords.at(2)*IpCoords.at(2),
2467 IpCoords.at(1)*IpCoords.at(1)*IpCoords.at(3),IpCoords.at(2)*IpCoords.at(2)*IpCoords.at(3)};
2468 // P = [x y yz xz xy x² y² x²y x²z]
2469// FloatArray iRowP = {IpCoords.at(1),IpCoords.at(2),
2470// IpCoords.at(2)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(2),
2471// IpCoords.at(1)*IpCoords.at(1),IpCoords.at(2)*IpCoords.at(2),
2472// IpCoords.at(1)*IpCoords.at(1)*IpCoords.at(3),IpCoords.at(2)*IpCoords.at(2)*IpCoords.at(3)};
2473 // P = [x y yz xz xy x² y² x³ y³ xyz x²z y²z]
2474// FloatArray iRowP = {IpCoords.at(1),IpCoords.at(2),
2475// IpCoords.at(2)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(3),IpCoords.at(1)*IpCoords.at(2),
2476// IpCoords.at(1)*IpCoords.at(1),IpCoords.at(2)*IpCoords.at(2),
2477// IpCoords.at(1)*IpCoords.at(1)*IpCoords.at(1),IpCoords.at(2)*IpCoords.at(2)*IpCoords.at(2),IpCoords.at(1)*IpCoords.at(2)*IpCoords.at(3),
2478// IpCoords.at(1)*IpCoords.at(1)*IpCoords.at(3),IpCoords.at(2)*IpCoords.at(2)*IpCoords.at(3)};
2479 P.addSubVectorRow(iRowP,numSampledIP + iIP+1,1);
2480
2481 }
2482
2483#if 0
2484 // Replace above with function
2485 // Get contribution from element in patch
2486 FloatMatrix eltIPvalues, eltPolynomialValues;
2487 patchEl->giveSPRcontribution(eltIPvalues,eltPolynomialValues,layer,IST_StressTensor,tStep);
2488 int numEltIP = eltIPvalues.giveNumberOfRows();
2489
2490 // Add to patch
2491 P.setSubMatrix(eltPolynomialValues,numSampledIP+1,1);
2492 patchIpValues.setSubMatrix(eltIPvalues,numSampledIP+1,1);
2493#endif
2494
2495 // increase number of sampled IPs
2496 numSampledIP += numEltIP;
2497 }
2498
2499 if (numSampledIP < numCoefficents*numThicknessIP) {
2500 // Polynomial fit involves quadratic x- and y-components
2501 OOFEM_ERROR("To few in-plane IP to do polynomial fit");
2502 }
2503
2504 // Find polynomial coefficients for patch
2505 FloatMatrix A, invA, Abar, a;
2506 // A = P^T*P
2507 A.beTProductOf(P,P);
2508 //A.writeCSV("Amatrix");
2509 invA.beInverseOf(A);
2510 // Abar = inv(A)*P^T
2511 Abar.beProductTOf(invA,P);
2512 // a = Abar*ipValues, a.size = 11 x StressComponents (11 = number of coefficients)
2513 a.beProductOf(Abar,patchIpValues);
2514
2515
2516 // Assemble appropriate coefficients matrix for computing S_xz and S_yz and S_zz
2517 // aSiz = [a(:,1)^T a(:,6)^T; a(:,6)^T a(:,2)^T]
2518 // aSzz = [a(:,1)^T 2*a(:,6)^T a(:,2)^T]
2519 // aSzz = sum[a81 a76 a82]
2520 FloatMatrix aSiz, aSzz;
2521 aSiz.resize(2,numCoefficents*2);
2522 aSzz.resize(1,numCoefficents*3);
2523 for (int iCol = 1; iCol <= numCoefficents; iCol++) {
2524 aSiz.at(1,iCol) = a.at(iCol,1);
2525 aSiz.at(1,iCol+numCoefficents) = a.at(iCol,6);
2526 aSiz.at(2,iCol) = a.at(iCol,6);
2527 aSiz.at(2,iCol+numCoefficents) = a.at(iCol,2);
2528 aSzz.at(1,iCol) = a.at(iCol,1);
2529 aSzz.at(1,iCol+numCoefficents) = 2.0*a.at(iCol,6);
2530 aSzz.at(1,iCol+2*numCoefficents) = a.at(iCol,2);
2531 }
2532// double aSzz = a.at(8,1) + a.at(7,6) + a.at(8,2);
2533
2534
2535 // Integrate gradient of S_xz, S_yz and S_zz in all IP-stacks
2536 dSmatLayer.zero();
2537 dSmatLayerIP.zero();
2538 double thickness = this->layeredCS->giveLayerThickness(layer);
2539
2540 // Compute recovered stresses
2541 for ( int j = 0; j < numInPlaneIP; j++ ) {
2542 FloatArray dS, GPcoords(3), dSzz;
2543
2544 // Approximation at bottom of layer (to fulfill integration BC)
2545 FloatArray dSBtm, dSzzBtm;
2546 GaussPoint *gp = iRuleL->getIntegrationPoint(j);
2547 GPcoords.zero();
2548 GPcoords = gp->giveGlobalCoordinates();
2549 GPcoords.at(3) = zeroThicknessLevel;
2550 // S_xz and S_yz
2551 dSBtm.zero();
2552 FloatArray intGradPBtm;
2553 this->giveZintegratedPolynomialGradientForStressRecAt(intGradPBtm,GPcoords);
2554 dSBtm.beProductOf(aSiz,intGradPBtm);
2555 // S_zz and dSzz/dz
2556 dSzzBtm.zero();
2557 FloatArray int2Grad2PBtm;
2558 this->giveZ2integratedPolynomial2GradientForStressRecAt(int2Grad2PBtm,GPcoords);
2559 dSzzBtm.beProductOf(aSzz,int2Grad2PBtm*(-1.0));
2560
2561 // thickness GPs
2562 for ( int i = 0; i < numThicknessIP; i++ ) {
2563
2564 int point = i*numInPlaneIP + j; // wedge integration point number
2565
2566 GaussPoint *gp = iRuleL->getIntegrationPoint(point);
2567 GPcoords.zero();
2568 GPcoords = gp->giveGlobalCoordinates();
2569 #if 0
2570 if (this->giveGlobalNumber() == 126) {
2571 if (layer == 1) {
2572 if (i == 0) {
2573 GPcoords.printYourself("wedge GPs");
2574 }
2575 }
2576 }
2577 #endif
2578// GPcoords.at(3) -= zeroThicknessLevel; // Using layer z-coords (not shell)
2579
2580 // Calculate z-integration of fitted stress variation in position of GP such that
2581 // Siz = - Integral( dS_ij/dx + dS_ij/dy )dz = - [a(ij) a(ij)]*Integral( dP/dx dP/dy )dz = - [a(ij) a(ij)]*IntGradP + Sij^k-1
2582
2583 // S_xz and S_yz
2584 dS.zero();
2585 FloatArray intGradP;
2586 this->giveZintegratedPolynomialGradientForStressRecAt(intGradP,GPcoords);
2587 dS.beProductOf(aSiz,intGradP*(-1.0));
2588// dSmatLayerIP.at(1,point+1) = dS.at(1); // S_xz
2589// dSmatLayerIP.at(2,point+1) = dS.at(2); // S_yz
2590 dSmatLayerIP.at(1,point+1) = dS.at(1) + dSBtm.at(1); // S_xz Using polynomial fit to shell coordinates
2591 dSmatLayerIP.at(2,point+1) = dS.at(2) + dSBtm.at(2); // S_yz Using polynomial fit to shell coordinates
2592
2593 // S_zz
2594 dSzz.zero();
2595 FloatArray int2Grad2P;
2596 this->giveZ2integratedPolynomial2GradientForStressRecAt(int2Grad2P,GPcoords);
2597 dSzz.beProductOf(aSzz,int2Grad2P);
2598 // Using only polynomial fit
2599 // dSmatLayerIP.at(3,point+1) = dSzz.at(1);
2600 // Using polynomial fit to shell coordinates
2601 dSmatLayerIP.at(3,point+1) = dSzz.at(1) + dSzzBtm.at(1);
2602 // Old polynomial fit
2603 // dSmatLayerIP.at(3,point+1) = aSzz*GPcoords.at(3)*GPcoords.at(3);
2604
2605 }
2606
2607 // Calculate stresses at upper interface of layer (use the x-y-coords of the upper GP of the layer)
2608
2609// GPcoords.at(3) = thickness; // Using layer z-coords (not shell)
2610 GPcoords.at(3) = thickness + zeroThicknessLevel;
2611
2612 // S_xz and S_yz
2613 dS.zero();
2614 FloatArray intGradP;
2615 this->giveZintegratedPolynomialGradientForStressRecAt(intGradP,GPcoords);
2616 dS.beProductOf(aSiz,intGradP*(-1.0));
2617// dSmatLayer.at(1,j+1) = dS.at(1); // S_xz
2618// dSmatLayer.at(2,j+1) = dS.at(2); // S_yz
2619 dSmatLayer.at(1,j+1) = dS.at(1) + dSBtm.at(1); // S_xz
2620 dSmatLayer.at(2,j+1) = dS.at(2) + dSBtm.at(2); // S_yz
2621
2622 // S_zz
2623 dSzz.zero();
2624 FloatArray int2Grad2P;
2625 this->giveZ2integratedPolynomial2GradientForStressRecAt(int2Grad2P,GPcoords);
2626 dSzz.beProductOf(aSzz,int2Grad2P);
2627 // Using only polynomial fit
2628// dSmatLayer.at(3,j+1) = dSzz.at(1);
2629 // Using polynomial fit to shell coordinates
2630 dSmatLayer.at(3,j+1) = dSzz.at(1) + dSzzBtm.at(1);
2631 // Old polynomial fit
2632// dSmatLayer.at(3,j+1) = aSzz*GPcoords.at(3)*GPcoords.at(3);
2633
2634 }
2635
2636# if 0
2637 // Fit P2(x,y) = [x y xy]*a to S_xz and S_xy in element layer and add to integration of Szz.
2638 int numCoefficents2 = 2;
2639 FloatMatrix eltIpValues, P2;
2640 eltIpValues.zero();
2641 P2.zero();
2642
2643 // Loop over IP:s in wedge interpolation
2644 IntegrationPoint *ip;
2645 int numEltIP = iRuleL->giveNumberOfIntegrationPoints();
2646 for ( int iIP = 0; iIP < numEltIP; iIP++ ) {
2647 ip = iRuleL->getIntegrationPoint(iIP);
2648
2649 // Collect IP-value
2650 FloatArray tempIPvalues;
2651 this->giveIPValue(tempIPvalues, ip, IST_StressTensor, tStep);
2652 FloatArray tempSaz(2); tempSaz.beSubArrayOf(tempIPvalues,{4,5}); // extract Syz and Sxz
2653 eltIpValues.addSubVectorRow(tempSaz,iIP+1,1);
2654
2655 // Collect global coordinates for IP and assemble to P.
2656 FloatArray IpCoords;
2657 IpCoords = ip->giveGlobalCoordinates();
2658 IpCoords.at(3) -= zeroThicknessLevel; // make bottom of layer ref point for polynimial fit.
2659 // P = [x y]
2660 FloatArray iRowP = {IpCoords.at(1),IpCoords.at(2)};
2661 // P = [x y xy]
2662// FloatArray iRowP = {IpCoords.at(1),IpCoords.at(2),IpCoords.at(1)*IpCoords.at(2)};
2663 P2.addSubVectorRow(iRowP,iIP+1,1);
2664
2665 }
2666
2667 // Find polynomial coefficients for patch
2668 FloatMatrix A2, invA2, A2bar, a2;
2669 // A2 = P2^T*P2
2670 A2.beTProductOf(P2,P2);
2671 invA2.beInverseOf(A2);
2672 // A2bar = inv(A2)*P2^T
2673 A2bar.beProductTOf(invA2,P2);
2674 // a2 = A2bar*ipValues, a2.size = number of coefficients x 2
2675 a2.beProductOf(A2bar,eltIpValues);
2676
2677 // Assemble appropriate coefficients matrix for computing S_zz
2678 // a2Szz = [a2(:,1)^T a2(:,2)^T]
2679 FloatMatrix a2Szz;
2680 a2Szz.resize(1,numCoefficents2*2);
2681 FloatArray temp;
2682 temp.beColumnOf(a2,1);
2683 a2Szz.addSubVectorRow(temp,1,1);
2684 temp.beColumnOf(a2,2);
2685 a2Szz.addSubVectorRow(temp,1,numCoefficents2+1);
2686// if ( this->giveGlobalNumber() == 50) {
2687// a2.printYourself("a2");
2688// a2Szz.printYourself("a2Szz");
2689// }
2690
2691 for ( int j = 0; j < numInPlaneIP; j++ ) {
2692
2693 FloatArray GPcoords(3), dSzz2;
2694
2695 // thickness GPs
2696 for ( int i = 0; i < numThicknessIP; i++ ) {
2697
2698 int point = i*numInPlaneIP + j; // wedge integration point number
2699
2700 GaussPoint *gp = iRuleL->getIntegrationPoint(point);
2701 GPcoords.zero();
2702 GPcoords = gp->giveGlobalCoordinates();
2703 GPcoords.at(3) -= zeroThicknessLevel;
2704
2705 dSzz2.zero();
2706 // P = [x y]
2707 FloatArray intGradP2 = {GPcoords.at(3),0,
2708 0,GPcoords.at(3)};
2709 // P = [x y xy]
2710 // FloatArray intGradP2 = {GPcoords.at(3),0,GPcoords.at(2)*GPcoords.at(3),
2711 // 0,GPcoords.at(3),GPcoords.at(1)*GPcoords.at(3)};
2712 dSzz2.beProductOf(a2Szz,intGradP2*(-1.0));
2713 dSmatLayerIP.at(3,point+1) += dSzz2.at(1);
2714 }
2715
2716 GPcoords.at(3) = thickness;
2717 dSzz2.zero();
2718 // P = [x y]
2719 FloatArray intGradP2 = {GPcoords.at(3),0,
2720 0,GPcoords.at(3)};
2721 // P = [x y xy]
2722// FloatArray intGradP2 = {GPcoords.at(3),0,GPcoords.at(2)*GPcoords.at(3),
2723// 0,GPcoords.at(3),GPcoords.at(1)*GPcoords.at(3)};
2724 dSzz2.beProductOf(a2Szz,intGradP2*(-1.0));
2725 if ( this->giveGlobalNumber() == 50) {
2726 a2Szz.printYourself("a2Szz");
2727 intGradP2.printYourself("intGradP2");
2728 dSzz2.printYourself("dSzz2");
2729 }
2730 dSmatLayer.at(3,j+1) += dSzz2.at(1);
2731 }
2732# endif
2733
2734}
2735
2736void
2737Shell7Base :: 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)
2738{
2739
2740 // Adjust the integrated stress values to take top and bottom surface BC into account
2741 // Optional fulfillment of shear traction BC (default is distribution of integration error across thickness)
2742 // NB: recovery of normal stress (Szz) requires both top and bottom BC fulfillment.
2743
2744 int numInPlaneIP = 6;
2745 int numberOfLayers = startLayer - endLayer + 1;
2746 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2747 int numSC = SmatOld.giveNumberOfRows(); // assume same number of stress component to be fitted in each layer
2748 double totalThickness = 0.0;
2749 if ( numberOfLayers == this->layeredCS->giveNumberOfLayers() ) {
2750 totalThickness = this->layeredCS->computeIntegralThick();
2751 } else {
2752 for ( int layer = startLayer ; layer <= endLayer; layer++ ) {
2753 totalThickness += this->layeredCS->giveLayerThickness(layer);
2754 }
2755 }
2756
2757 if (numSC != tractionBtm.giveNumberOfRows() || numSC != tractionTop.giveNumberOfRows() ) {
2758 OOFEM_ERROR("Number of stress components don't match");
2759 }
2760
2761 // Find integration error and correction term
2762 // Assumes constant integration error across thickness
2763 FloatMatrix C1(numSC,numInPlaneIP);
2764 FloatMatrix intError(numSC,numInPlaneIP);
2765 FloatMatrix SOld(numSC,numInPlaneIP);
2766 for ( int iSC = 1; iSC <= numSC; iSC++) {
2767
2768 for ( int j = 0 ; j < numInPlaneIP ; j++ ) {
2769
2770 intError.at(iSC,j+1) = tractionTop.at(iSC,j+1) - SmatOld.at(iSC,j+1);
2771 C1.at(iSC,j+1) = (1.0/totalThickness)*intError.at(iSC,j+1);
2772 SOld.at(iSC,j+1) = tractionBtm.at(iSC,j+1) - 0.5*(1.0 - fulfillBC.at(iSC))*intError.at(iSC,j+1); // last term distributes integration error on top and btm if fulfillBC = 0;
2773
2774 }
2775 }
2776
2777 FloatArray GPcoords;
2778
2779 for ( int layer = startLayer ; layer <= endLayer; layer++ ) {
2780
2781 std :: unique_ptr< IntegrationRule > &iRuleL = this->integrationRulesArray [ layer - 1 ];
2782 answer1[layer-startLayer].resize(numSC,numInPlaneIP*numThicknessIP);
2783 answer2[layer-startLayer].resize(numSC,numInPlaneIP);
2784
2785 for ( int iSC = 1; iSC <= numSC; iSC++) {
2786
2787 for ( int j = 0 ; j < numInPlaneIP ; j++ ) {
2788
2789// if ( layer == 1 ) {
2790// SOld.at(iSC,j+1) = tractionBtm.at(iSC,j+1);
2791// }
2792
2793 // Assume constant integration error across thickness
2794 //double C1 = (1.0/totalThickness)*(tractionTop.at(iSC,j+1) - SmatOld.at(iSC,j+1));
2795
2796 for ( int i = 0 ; i < numThicknessIP ; i++ ) {
2797
2798 int point = i*numInPlaneIP + j; // wedge integration point number
2799
2800 GaussPoint *gp = iRuleL->getIntegrationPoint(point);
2801 GPcoords.zero();
2802 GPcoords = gp->giveGlobalCoordinates();
2803 GPcoords.at(3) -= zeroThicknessLevel;
2804
2805 // Stress in wedge GP:s
2806 answer1[layer-startLayer].at(iSC,point+1) = dSmatIP[layer-startLayer].at(iSC,point+1) + C1.at(iSC,j+1)*GPcoords.at(3) + SOld.at(iSC,j+1);
2807 }
2808
2809 GPcoords.at(3) = this->layeredCS->giveLayerThickness(layer);
2810 SOld.at(iSC,j+1) += dSmat[layer-startLayer].at(iSC,j+1) + C1.at(iSC,j+1)*GPcoords.at(3);
2811
2812 }
2813 // Stress in interface GP:s
2814 answer2[layer-startLayer] = SOld;
2815 }
2816 zeroThicknessLevel += this->layeredCS->giveLayerThickness(layer);
2817 }
2818}
2819
2820void
2821Shell7Base :: updateLayerTransvStressesSR(FloatMatrix &dSmatLayerIP, int layer)
2822{
2823 // add stresses from lower interface AND replace stresses in wedge GP
2824
2825 std :: unique_ptr< IntegrationRule > &iRuleL = this->integrationRulesArray [ layer - 1 ];
2826
2827 int numInPlaneIP = 6;
2828 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2829
2830 for ( int j = 0; j < numInPlaneIP; j++ ) {
2831 for ( int i = 0; i < numThicknessIP; i++ ) {
2832 int point = i*numInPlaneIP + j; // wedge integration point number
2833 //dSmatLayerIP.at(1,point+1) += SmatOld.at(1,j+1); // S_xz
2834 //dSmatLayerIP.at(2,point+1) += SmatOld.at(2,j+1); // S_yz
2835 //dSmatLayerIP.at(3,point+1) += SmatOld.at(3,j+1); // S_zz
2836
2837 // Replace stresses
2838 GaussPoint *gp = iRuleL->getIntegrationPoint(point);
2839 StructuralMaterialStatus* status = dynamic_cast< StructuralMaterialStatus* > ( gp->giveMaterialStatus() );
2840 FloatArray Sold = status->giveStressVector();
2841
2842 Sold.at(5) = dSmatLayerIP.at(1,point+1); // S_xz
2843 Sold.at(4) = dSmatLayerIP.at(2,point+1); // S_yz
2844 Sold.at(3) = dSmatLayerIP.at(3,point+1); // S_zz
2845 if ( Sold.giveSize() > 6 ) {
2846 Sold.at(8) = Sold.at(5); // S_xz
2847 Sold.at(7) = Sold.at(4); // S_yz
2848 }
2849 status->letStressVectorBe(Sold);
2850 }
2851 }
2852}
2853
2854# if 1
2855void
2856Shell7Base :: updateLayerTransvShearStressesSR(FloatMatrix &dSmatLayerIP, FloatMatrix &SmatOld, int layer)
2857{
2858 // add stresses from lower interface AND replace stresses in wedge GP
2859
2860 std :: unique_ptr< IntegrationRule > &iRuleL = this->integrationRulesArray [ layer - 1 ];
2861
2862 int numInPlaneIP = 6;
2863 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2864
2865 for ( int j = 0; j < numInPlaneIP; j++ ) {
2866 for ( int i = 0; i < numThicknessIP; i++ ) {
2867 int point = i*numInPlaneIP + j; // wedge integration point number
2868 //dSmatLayerIP.at(1,point+1) += SmatOld.at(1,j+1); // S_xz
2869 //dSmatLayerIP.at(2,point+1) += SmatOld.at(2,j+1); // S_yz
2870
2871 // Replace stresses
2872 GaussPoint *gp = iRuleL->getIntegrationPoint(point);
2873 StructuralMaterialStatus* status = dynamic_cast< StructuralMaterialStatus* > ( gp->giveMaterialStatus() );
2874 FloatArray Sold = status->giveStressVector();
2875 #if 0
2876 if (this->giveGlobalNumber() == 126) {
2877 if (j == 3) {
2878 if (i == 1) {
2879 Sold.printYourself("Original");
2880 }
2881 }
2882 }
2883 #endif
2884 Sold.at(5) = dSmatLayerIP.at(1,point+1); // S_xz
2885 Sold.at(4) = dSmatLayerIP.at(2,point+1); // S_yz
2886 if ( Sold.giveSize() > 6 ) {
2887 Sold.at(8) = Sold.at(5); // S_xz
2888 Sold.at(7) = Sold.at(4); // S_yz
2889 }
2890 status->letStressVectorBe(Sold);
2891 }
2892 }
2893}
2894
2895void
2896Shell7Base :: updateLayerTransvNormalStressSR(FloatMatrix &dSzzMatLayerIP, FloatArray &SzzMatOld, int layer)
2897{
2898 // add stresses from lower interface AND replace stresses in wedge GP
2899
2900 std :: unique_ptr< IntegrationRule > &iRuleL = this->integrationRulesArray [ layer - 1 ];
2901
2902 int numInPlaneIP = 6;
2903 int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer();
2904
2905 for ( int j = 0; j < numInPlaneIP; j++ ) {
2906 for ( int i = 0; i < numThicknessIP; i++ ) {
2907 int point = i*numInPlaneIP + j; // wedge integration point number
2908 dSzzMatLayerIP.at(1,point+1) += SzzMatOld.at(j+1); // S_zz
2909
2910 // Replace stresses
2911 GaussPoint *gp = iRuleL->getIntegrationPoint(point);
2912 StructuralMaterialStatus* status = dynamic_cast< StructuralMaterialStatus* > ( gp->giveMaterialStatus() );
2913 FloatArray Sold = status->giveStressVector();
2914
2915 Sold.at(3) = dSzzMatLayerIP.at(1,point+1); // S_zz
2916 status->letStressVectorBe(Sold);
2917 }
2918 }
2919}
2920# endif
2921
2922#if 0
2923void
2924Shell7Base :: givePolynomialGradientForStressRecAt(FloatArray &answer, FloatArray &coords)
2925{
2926 /* Return the special matrix {gradP} of the reciever evaluated at a global coordinate (of a Gauss point)
2927 * Used for integration of S_xz and S_yz such that
2928 * a(ij)*gradP = dS_ij/dx + dS_ij/dy, where a(ij) is a vector of coefficients to the polynomial
2929 * P(x,y,z) = [1 x y z yz xz xy x² y² x²z y²z] (NB: z^2 term omitted)
2930 * associated with stress component ij.
2931 * The gradient of P(x,y,z) is given by
2932 * dP/dx = [0 1 0 0 0 z y 2x 0]
2933 * dP/dy = [0 0 1 0 z 0 x 0 2y]
2934 * dP/dz = [0 0 0 1 y x 0 0 0 ] (NB not returned atm)
2935 * answer = gradP = [dP/dx dP/dy]^T
2936 */
2937
2938 answer.zero();
2939 answer = {0,1,0,0, 0,coords.at(3),coords.at(2),2.0*coords.at(1), 0,
2940 0,0,1,0,coords.at(3), 0,coords.at(1), 0,2.0*coords.at(2)};
2941}
2942#endif
2943
2944
2945void
2946Shell7Base :: giveZintegratedPolynomialGradientForStressRecAt(FloatArray &answer, FloatArray &coords)
2947{
2948 /* Return the special matrix {gradP} of the reciever evaluated at a global coordinate (of a Gauss point)
2949 * Used for integration of S_xz and S_yz such that
2950 * a(ij)*gradP = dS_ij/dx + dS_ij/dy, where a(ij) is a vector of coefficients to the polynomial
2951 * P(x,y,z) = [1 x y z yz xz xy x² y² x²z y²z] (NB: z^2 term omitted)
2952 * associated with stress component ij.
2953 * The gradient of P(x,y,z) is given by
2954 * dP/dx = [0 1 0 0 0 z y 2x 0 2xz 0]
2955 * dP/dy = [0 0 1 0 z 0 x 0 2y 0 2yz]
2956 * and the z-integration is then:
2957 * I[dP/dx]dz = [0 z 0 0 0 z²/2 yz 2xz 0 xz² 0 ]
2958 * I[dP/dy]dz = [0 0 z 0 z²/2 0 xz 0 2yz 0 yz²]
2959 * answer = IntgradP = [I[dP/dx]dz I[dP/dy]yz]^T
2960 */
2961
2962 answer.zero();
2963 // P = [1 x y z yz xz xy x² y²]
2964// answer = {0,coords.at(3), 0,0, 0,0.5*coords.at(3)*coords.at(3),coords.at(2)*coords.at(3),2.0*coords.at(1)*coords.at(3), 0,
2965// 0, 0,coords.at(3),0,0.5*coords.at(3)*coords.at(3), 0,coords.at(1)*coords.at(3), 0,2.0*coords.at(2)*coords.at(3)};
2966
2967 // P = [1 x y z yz xz xy x² y² x²z y²z]
2968 answer = {0,coords.at(3),0,0,0,0.5*coords.at(3)*coords.at(3),coords.at(2)*coords.at(3),2.0*coords.at(1)*coords.at(3),0,coords.at(1)*coords.at(3)*coords.at(3),0,
2969 0,0,coords.at(3),0,0.5*coords.at(3)*coords.at(3),0,coords.at(1)*coords.at(3),0,2.0*coords.at(2)*coords.at(3),0,coords.at(2)*coords.at(3)*coords.at(3)};
2970
2971 // P = [x y yz xz xy x² y² x²z y²z]
2972// answer = {coords.at(3),0,0,0.5*coords.at(3)*coords.at(3),coords.at(2)*coords.at(3),2.0*coords.at(1)*coords.at(3),0,coords.at(1)*coords.at(3)*coords.at(3),0,
2973// 0,coords.at(3),0.5*coords.at(3)*coords.at(3),0,coords.at(1)*coords.at(3),0,2.0*coords.at(2)*coords.at(3),0,coords.at(2)*coords.at(3)*coords.at(3)};
2974
2975 // P = [x y yz xz xy x² y² x²z y²z xyz]
2976// answer = {coords.at(3),0,0,0.5*coords.at(3)*coords.at(3),coords.at(2)*coords.at(3),2.0*coords.at(1)*coords.at(3),0,coords.at(1)*coords.at(3)*coords.at(3),0,0.5*coords.at(2)*coords.at(3)*coords.at(3),
2977// 0,coords.at(3),0.5*coords.at(3)*coords.at(3),0,coords.at(1)*coords.at(3),0,2.0*coords.at(2)*coords.at(3),0,coords.at(2)*coords.at(3)*coords.at(3),0.5*coords.at(1)*coords.at(3)*coords.at(3)};
2978
2979 // P = [x y yz xz xy x² y² x³ y³ xyz x²z y²z]
2980// answer = {coords.at(3),0,0,0.5*coords.at(3)*coords.at(3),coords.at(2)*coords.at(3),2.0*coords.at(1)*coords.at(3),0,3.0*coords.at(1)*coords.at(1)*coords.at(3),0,0.5*coords.at(2)*coords.at(3)*coords.at(3),coords.at(1)*coords.at(3)*coords.at(3),0,
2981// 0,coords.at(3),0.5*coords.at(3)*coords.at(3),0,coords.at(1)*coords.at(3),0,2.0*coords.at(2)*coords.at(3),0,3.0*coords.at(2)*coords.at(2)*coords.at(3),0.5*coords.at(1)*coords.at(3)*coords.at(3),0,coords.at(2)*coords.at(3)*coords.at(3)};
2982
2983
2984}
2985
2986void
2987Shell7Base :: giveZ2integratedPolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords)
2988{
2989 /*
2990 * I[d(I[dP/dx]dz)/dx]dz = [0 0 0 0 0 0 0 z² 0 z³/3 0 ]
2991 * I[d(I[dP/dy]dz)/dy]dz = [0 0 0 0 0 0 0 0 z² 0 z³/3]
2992 * I[d(I[dP/dx]dz)/dy]dz = I[d(I[dP/dy]dz)/dx]dz = [0 0 0 0 0 0 z²/2 0 0 0 0]
2993 * answer = int2grad2P = [I[d(I[dP/dx]dz)/dx]dz I[d(I[dP/dx]dz)/dy]dz I[d(I[dP/dy]dz)/dy]dz]^T
2994 */
2995
2996 answer.zero();
2997
2998 // P = [1 x y z yz xz xy x² y² x²z y²z]
2999 answer = {0,0,0,0,0,0,0,coords.at(3)*coords.at(3),0,(1.0/3.0)*coords.at(3)*coords.at(3)*coords.at(3),0,
3000 0,0,0,0,0,0,0.5*coords.at(3)*coords.at(3),0,0,0,0,
3001 0,0,0,0,0,0,0,0,coords.at(3)*coords.at(3),0,(1.0/3.0)*coords.at(3)*coords.at(3)*coords.at(3)};
3002
3003 // P = [x y yz xz xy x² y² x²z y²z]
3004// answer = {0,0,0,0,0,coords.at(3)*coords.at(3),0,(1.0/3.0)*coords.at(3)*coords.at(3)*coords.at(3),0,
3005// 0,0,0,0,0.5*coords.at(3)*coords.at(3),0,0,0,0,
3006// 0,0,0,0,0,0,coords.at(3)*coords.at(3),0,(1.0/3.0)*coords.at(3)*coords.at(3)*coords.at(3)};
3007//
3008 // P = [x y yz xz xy x² y² x²z y²z]
3009// answer = {0,0,0,0,0,coords.at(3)*coords.at(3),0,3.0*coords.at(1)*coords.at(3)*coords.at(3),0,0,(1.0/3.0)*coords.at(3)*coords.at(3)*coords.at(3),0,
3010// 0,0,0,0,0.5*coords.at(3)*coords.at(3),0,0,0,0,(1.0/6.0)*coords.at(3)*coords.at(3)*coords.at(3),0,0,
3011// 0,0,0,0,0,0,coords.at(3)*coords.at(3),0,3.0*coords.at(2)*coords.at(3)*coords.at(3),0,0,(1.0/3.0)*coords.at(3)*coords.at(3)*coords.at(3)};
3012
3013}
3014
3015#if 0
3016void
3017Shell7Base :: computeBmatrixForStressRecAt(FloatArray &lcoords, FloatMatrix &answer, int layer, bool intSzz)
3018{
3019 /* Returns the special matrix {B} of the receiver, evaluated at aGaussPoint.
3020 * For integration of S_xz and S_yz such that
3021 * B*a = [dS_xx/dx + dS_xy/dy, dS_yx/dx + dS_yy/dy ]^T, where a is the vector of in plane
3022 * stresses a = [S1_xx, S1_yy, S1_xy, ..., Sn_xx, Sn_yy, Sn_xy] for n layer nodes
3023 * For integration of S_zz such that
3024 * B*a = [dS_yz/dx + dS_yz/dy ]^T, where a is the vector of in plane
3025 * stresses a = [S1_xz, S1_yz, ..., Sn_xz, Sn_yz] for n layer nodes
3026 */
3027
3028 // set up virtual cell geometry for an qwedge
3029 const int numNodes = this->interpolationForExport.giveNumberOfNodes();
3030 std::vector<FloatArray> nodes;
3031 giveFictiousNodeCoordsForExport(nodes, layer);
3032
3033 FEInterpolation *interpol = static_cast< FEInterpolation * >( &this->interpolationForExport );
3034 FloatMatrix dNdx;
3035 interpol->evaldNdx( dNdx, lcoords, FEIVertexListGeometryWrapper( nodes ) );
3036
3037 /*
3038 * 1 [d/dx 0 d/dy
3039 * 1 0 d/dy d/dx]
3040 */
3041 if (!intSzz) {
3042 int ndofs = numNodes*3;
3043 answer.resize(2, ndofs);
3044 for ( int i = 1, j = 0; i <= numNodes; i++, j += 3 ) {
3045 answer.at(1, j + 1) = dNdx.at(i, 1);
3046 answer.at(1, j + 3) = dNdx.at(i, 2);
3047 answer.at(2, j + 2) = dNdx.at(i, 2);
3048 answer.at(2, j + 3) = dNdx.at(i, 1);
3049 }
3050 } else {
3051 int ndofs = numNodes*2;
3052 answer.resize(1, ndofs);
3053 for ( int i = 1, j = 0; i <= numNodes; i++, j += 2 ) {
3054 answer.at(1, j + 1) = dNdx.at(i, 1);
3055 answer.at(1, j + 2) = dNdx.at(i, 2);
3056 }
3057 }
3058
3059}
3060#endif
3061
3062
3063
3064
3065std::vector<FloatArray>
3066Shell7Base :: giveFictiousNodeCoordsForExport(int layer)
3067{
3068 // compute fictious node coords
3069 FloatMatrix localNodeCoords;
3070 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, EGT_wedge_2);
3071
3072 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
3073 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
3074 FloatArray localCoords(3);
3075 localCoords.beColumnOf(localNodeCoords,i);
3076
3077 nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer);
3078 }
3079 return nodes;
3080}
3081
3082
3083std::vector<FloatArray>
3084Shell7Base :: giveFictiousCZNodeCoordsForExport(int interface)
3085{
3086 // compute fictious node coords
3087 FloatMatrix localNodeCoords;
3088 this->interpolationForCZExport.giveLocalNodeCoords(localNodeCoords, EGT_triangle_2);
3089
3090 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
3091 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
3092 FloatArray localCoords(3);
3093 localCoords.beColumnOf(localNodeCoords,i);
3094
3095 localCoords.at(3) = 1.0;
3096 nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, interface);
3097 }
3098 return nodes;
3099}
3100
3101std::vector<FloatArray>
3102Shell7Base :: giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep)
3103{
3104 // compute fictious node coords
3105
3106 FloatMatrix localNodeCoords;
3107 this->interpolationForExport.giveLocalNodeCoords(localNodeCoords, EGT_wedge_2);
3108 std::vector<FloatArray> nodes(localNodeCoords.giveNumberOfColumns());
3109 for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){
3110 FloatArray localCoords(3);
3111 localCoords.beColumnOf(localNodeCoords,i);
3112
3113 nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, tStep);
3114 }
3115 return nodes;
3116}
3117
3118
3119#endif
3120
3121
3122
3123// Misc functions
3124
3126Shell7Base :: convV6ToV9Stress(const FloatArrayF<6> &V6)
3127{
3128 FloatArrayF<9> answer;
3129 answer.at(1) = V6.at(1);
3130 answer.at(2) = V6.at(2);
3131 answer.at(3) = V6.at(3);
3132 answer.at(4) = answer.at(7) = V6.at(4);
3133 answer.at(5) = answer.at(8) = V6.at(5);
3134 answer.at(6) = answer.at(9) = V6.at(6);
3135 return answer;
3136};
3137
3138
3139void
3140Shell7Base :: computeInterLaminarStressesAt(int interfaceNum, TimeStep *tStep, std::vector < FloatArray > &interLamStresses)
3141{
3142
3143 // Get integration rules on the upper and lower sides of the interface
3144
3145
3146 LayeredIntegrationRule *irLower = static_cast< LayeredIntegrationRule * >(this->giveIntegrationRule(interfaceNum-1)); // index from 0
3147 LayeredIntegrationRule *irUpper = static_cast< LayeredIntegrationRule * >(this->giveIntegrationRule(interfaceNum));
3148 IntegrationPoint *ip;
3149
3150 // compute stresses
3151 int numInterfaceIP = irLower->upperInterfacePoints.giveSize();
3152 interLamStresses.resize(numInterfaceIP);
3153 FloatArray vSLower, vSUpper, nCov, vSMean(6), stressVec;
3154 FloatMatrix SMean;
3155 // compute mean interface stress vector for a gp-pair
3156 for ( int i = 1; i <= numInterfaceIP; i++ ) {
3157 ip = irUpper->getIntegrationPoint( irUpper->lowerInterfacePoints.at(i) );
3158 this->giveIPValue(vSUpper, ip, IST_CauchyStressTensor, tStep);
3159 ip = irLower->getIntegrationPoint( irLower->upperInterfacePoints.at(i) );
3160 this->giveIPValue(vSLower, ip, IST_CauchyStressTensor, tStep);
3161
3163 vSMean = 0.5 * ( vSUpper + vSLower );
3164 SMean.beMatrixFormOfStress(vSMean);
3165 stressVec.beProductOf(SMean,nCov);
3166 interLamStresses.at(i-1).resize( stressVec.giveSize() );
3167 interLamStresses.at(i-1) = stressVec;
3168 }
3169}
3170
3171
3172void
3173Shell7Base :: evaluateFailureCriteriaQuantities(FailureCriteriaStatus *fc, TimeStep *tStep)
3174{
3175 //switch ( fc->giveType() ) {
3176
3177 //case FC_MaxShearStress:
3178 // // Stress ordering (1, 5, 9, 6, 3, 2) = (xx, yy, zz, yz, xz, xy)
3179 // int numInterfaces = this->layeredCS->giveNumberOfLayers() - 1;
3180 // std::vector < FloatArray > interLamStresses;
3181 // fc->quantities.resize(numInterfaces); // will overwrite this every time
3182 // for (int i = 1; i <= numInterfaces; i++ ) {
3183 // this->computeInterLaminarStressesAt(i, tStep, interLamStresses); // all 6 components in each evaluation point (ip)
3184 // int numEvalPoints = interLamStresses.size();
3185 // fc->quantities[i-1].resize(numEvalPoints); // most often = numIP
3186 //
3187 // for ( int j = 1; j <= numEvalPoints; j++) {
3188 // FloatArray &values = fc->quantities[i-1][j-1]; // one resulting shear stress
3189 // FloatArray &vS = interLamStresses[j-1]; // Stress in eval point
3190 // values.resize(1); // scalar measure in this case
3191 //
3192 // 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?
3193
3194 // }
3195 // }
3196
3197 //};
3198}
3199
3200int
3202{
3203 // Returns the Voigt index corresponding to two given tensor indices for a symmetric tensor.
3204 // [11 12 13 [1 6 5
3205 // 21 22 23 = > 6 2 4
3206 // 31 32 33] 5 4 3]
3207 //
3208 std :: vector< std::vector<int> > voigtIndices =
3209 {
3210 { 1, 6, 5 },
3211 { 6, 2, 4 },
3212 { 5, 4, 3 }
3213 };
3214
3215 return voigtIndices[ind1][ind2];
3216
3217};
3218
3219
3220int
3222{
3223 // Returns the Voigt index corresponding to two given tensor indices for a general tensor.
3224 // [11 12 13 [1 6 5
3225 // 21 22 23 = > 9 2 4
3226 // 31 32 33] 8 7 3]
3227 //
3228 //std::vector< std::vector<int> > voigtIndices;
3229 //voigtIndices.resize(3);
3230 //voigtIndices[0] = { 1, 6, 5 };
3231 //voigtIndices[1] = { 9, 2, 4 };
3232 //voigtIndices[2] = { 8, 7, 3 };
3233
3234 return this->voigtIndices[ind1-1][ind2-1];
3235};
3236
3237
3238} // 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)
ConnectivityTable * giveConnectivityTable()
Definition domain.C:1240
Element * giveElement(int n)
Definition domain.C:165
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
virtual IntegrationRule * giveIntegrationRule(int i)
Definition element.h:899
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
CrossSection * giveCrossSection()
Definition element.C:534
void printOutputAt(FILE *file, TimeStep *tStep) override
Definition element.C:804
void computeBoundaryVectorOf(const IntArray &bNodes, const IntArray &dofIDMask, ValueModeType u, TimeStep *tStep, FloatArray &answer, bool padding=false)
Definition element.C:163
virtual Element_Geometry_Type giveGeometryType() const =0
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 setCellType(int cellNum, int type)
void setNumberOfCellVarsToExport(const IntArray &cellVars, int numCells)
void setNumberOfInternalVarsToExport(const IntArray &ists, 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)
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
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 number
Component number.
Definition femcmpnn.h:77
int giveNumber() const
Definition femcmpnn.h:104
double & at(std::size_t i)
void beSymVectorForm(const FloatMatrix &aMatrix)
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 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 beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beVectorProductOf(const FloatArray &v1, const FloatArray &v2)
Definition floatarray.C:476
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
void setColumn(const FloatArrayF< N > &src, std::size_t c)
double at(std::size_t i, std::size_t j) const
void times(double f)
void addSubVectorRow(const FloatArray &src, int sr, int sc)
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 beProductTOf(const FloatMatrix &a, const FloatMatrix &b)
int giveNumberOfColumns() const
Returns number of columns of receiver.
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
void setSubMatrix(const FloatMatrix &src, int sr, int sc)
void addSubVectorCol(const FloatArray &src, int sr, int sc)
void beTranspositionOf(const FloatMatrix &src)
void zero()
Zeroes all coefficient of receiver.
void beMatrixFormOfStress(const FloatArray &aArray)
bool beInverseOf(const FloatMatrix &src)
*Prints matrix to stdout Useful for debugging void printYourself() const
void plusDyadSymmUpper(const FloatArray &a, double dV)
int giveNumberOfRows() const
Returns number of rows of receiver.
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
void subtract(const FloatMatrix &a)
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
int SetUpPointsOnLine(int nPoints, MaterialMode mode) override
int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) override
double giveNaturalCoordinate(int i) const
Returns i-th natural element coordinate of receiver.
Definition gausspoint.h:136
const FloatArray & giveGlobalCoordinates()
Definition gausspoint.h:159
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
double giveWeight()
Returns integration weight of receiver.
Definition gausspoint.h:180
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
GaussPoint * getIntegrationPoint(int n)
virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode)=0
virtual void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
Definition load.C:84
virtual double give(int aProperty, GaussPoint *gp) const
Definition material.C:51
NLStructuralElement(int n, Domain *d)
int nlGeometry
Flag indicating if geometrical nonlinearities apply.
FloatArray initialSolutionVector
Definition shell7base.h:129
FloatMatrixF< 3, 3 > computeStressMatrix(FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep)
Definition shell7base.C:701
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
void computePressureForceAt(GaussPoint *gp, FloatArray &answer, const int iSurf, FloatArray genEps, BoundaryLoad *surfLoad, TimeStep *tStep, ValueModeType mode)
FloatArrayF< 3 > & giveInitialNodeDirector(int i)
Definition shell7base.h:125
void NodalRecoveryMI_computeNValProduct(FloatMatrix &answer, int layer, InternalStateType type, TimeStep *tStep)
static FEI3dWedgeQuad interpolationForExport
Definition shell7base.h:116
std::array< FloatMatrixF< 3, 18 >, 3 > computeLambdaGMatrices(FloatArray &genEps, double zeta)
Definition shell7base.C:447
virtual void giveShellExportData(ExportRegion &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep)
virtual FloatMatrixF< 3, 3 > evalCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords, FloatArray &genEps, TimeStep *tStep)
Definition shell7base.C:350
virtual double giveGlobalZcoord(const FloatArrayF< 3 > &lCoords)
Definition shell7base.C:201
FloatArray & giveInitialSolutionVector()
Definition shell7base.h:130
void giveTractionBC(FloatMatrix &tractionTop, FloatMatrix &tractionBtm, TimeStep *tStep)
static void giveGeneralizedStrainComponents(FloatArray genEps, FloatArrayF< 3 > &dphidxi1, FloatArrayF< 3 > &dphidxi2, FloatArrayF< 3 > &dmdxi1, FloatArrayF< 3 > &dmdxi2, FloatArrayF< 3 > &m, double &dgamdxi1, double &dgamdxi2, double &gam)
virtual FloatArrayF< 3 > vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF< 3 > &localCoords, int layer, TimeStep *tStep)
Shell7Base(int n, Domain *d)
Definition shell7base.C:63
virtual void recoverShearStress(TimeStep *tStep)
void NodalRecoveryMI_recoverValues(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
virtual double computeVolumeAroundLayer(GaussPoint *mastergp, int layer)=0
std::vector< std::vector< int > > voigtIndices
Definition shell7base.h:288
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
Definition shell7base.C:737
virtual void edgeGiveUpdatedSolutionVector(FloatArray &answer, const int iedge, TimeStep *tStep)
static ParamKey IPK_Shell7Base_recoverStress
Definition shell7base.h:73
virtual void setupInitialNodeDirectors()
Definition shell7base.C:323
virtual double giveGlobalZcoordInLayer(double xi, int layer)
Definition shell7base.C:208
virtual FloatArrayF< 3 > vtkEvalInitialGlobalCoordinateAt(const FloatArrayF< 3 > &localCoords, int layer)
void computeThicknessMappingCoeff(GaussPoint *gp, FloatArray &answer)
Definition shell7base.C:835
void giveSPRcontribution(FloatMatrix &eltIPvalues, FloatMatrix &eltPolynomialValues, int layer, InternalStateType type, TimeStep *tStep)
void recoverValuesFromIP(std::vector< FloatArray > &nodes, int layer, InternalStateType type, TimeStep *tStep, stressRecoveryType SRtype=copyIPvalue)
virtual const IntArray & giveOrderingNodes() const =0
void computePressureTangentMatrix(FloatMatrix &answer, Load *load, const int iSurf, TimeStep *tStep)
Definition shell7base.C:607
FloatMatrixF< 3, 3 > evalInitialCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords)
Definition shell7base.C:220
void nodalLeastSquareFitFromIP(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
FloatMatrixF< 3, 3 > evalInitialContravarBaseVectorsAt(const FloatArrayF< 3 > &lCoords)
Definition shell7base.C:274
FloatArray & giveInitialEdgeSolutionVector(int i)
Definition shell7base.h:135
virtual void computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, TimeStep *tStep)
Definition shell7base.C:514
virtual void computeTractionForce(FloatArray &answer, const int iedge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, bool map2elementDOFs=false)
void computeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord=0)
Definition shell7base.C:773
void setupInitialEdgeSolutionVector()
void CopyIPvaluesToNodes(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep)
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 void edgeComputeBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, int li=1, int ui=ALL_STRAINS)
virtual FloatArrayF< 3 > evalInitialCovarNormalAt(const FloatArrayF< 3 > &lCoords)
virtual int giveNumberOfEdgeDofs()=0
void computeSectionalForcesAt(FloatArray &sectionalForces, IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEpsC, double zeta)
Definition shell7base.C:806
void updateLayerTransvStressesSR(FloatMatrix &dSmatLayerIP, int layer)
static FloatMatrixF< 3, 3 > giveDualBase(FloatMatrixF< 3, 3 > &base1)
Definition shell7base.C:282
void updateLayerTransvShearStressesSR(FloatMatrix &dSmatLayerIP, FloatMatrix &SmatOld, 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
virtual void giveMassFactorsAt(GaussPoint *gp, FloatArray &answer, double &gam)
Definition shell7base.C:942
void giveDofManDofIDMask(int inode, IntArray &) const override
Definition shell7base.C:145
virtual void computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep)
Definition shell7base.C:711
void printOutputAt(FILE *file, TimeStep *tStep) override
Definition shell7base.C:109
FloatMatrixF< 3, 3 > edgeEvalCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords, const int iedge, TimeStep *tStep)
Definition shell7base.C:375
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
std::vector< FloatArray > initialEdgeSolutionVectors
Definition shell7base.h:134
void giveUpdatedSolutionVector(FloatArray &answer, TimeStep *tStep)
void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li=1, int ui=ALL_STRAINS) override
Definition shell7base.h:269
FloatArrayF< 3 > evalInitialDirectorAt(const FloatArrayF< 3 > &lCoords)
Definition shell7base.C:292
void temp_computeBoundaryVectorOf(IntArray &dofIdArray, int boundary, ValueModeType u, TimeStep *tStep, FloatArray &answer)
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)
void giveZ2integratedPolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords)
FEInterpolation3d * fei
Definition shell7base.h:118
int giveSymVoigtIndex(int ind1, int ind2)
virtual int giveNumberOfEdgeDofManagers()=0
void giveUnknownsAt(const FloatArrayF< 3 > &lcoords, const FloatArray &solVec, FloatArrayF< 3 > &x, FloatArrayF< 3 > &m, double &gam, TimeStep *tStep)
void ZZNodalRecoveryMI_ComputeEstimatedInterpolationMtrx(FloatArray &answer, GaussPoint *gp, InternalStateType type)
std::vector< FloatArray > giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep)
virtual const IntArray & giveOrderingEdgeNodes() const =0
void updateLayerTransvNormalStressSR(FloatMatrix &dSzzMatLayerIP, FloatArray &SzzMatOld, int layer)
void giveZintegratedPolynomialGradientForStressRecAt(FloatArray &answer, FloatArray &coords)
static FEI3dTrQuad interpolationForCZExport
Definition shell7base.h:115
std::vector< FloatArray > giveFictiousNodeCoordsForExport(int layer)
virtual void edgeComputeNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer)
FloatArrayF< 3 > edgeEvalInitialDirectorAt(const FloatArrayF< 1 > &lCoords, const int iEdge)
Definition shell7base.C:306
void setupInitialSolutionVector()
std::vector< FloatArrayF< 3 > > initialNodeDirectors
Definition shell7base.h:124
void NodalRecoveryMI_computeNNMatrix(FloatArray &answer, int layer, InternalStateType type)
std::pair< FloatArrayF< 3 >, FloatArrayF< 3 > > edgeEvalInitialCovarBaseVectorsAt(const FloatArrayF< 1 > &lCoords, const int iedge)
Definition shell7base.C:249
int giveVoigtIndex(int ind1, int ind2)
void letStressVectorBe(const FloatArray &v)
Assigns stressVector to given vector v.
const FloatArray & giveStressVector() const
Returns the const pointer to receiver's stress vector.
virtual FloatMatrixF< 9, 9 > give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
static void computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep)
ZZNodalRecoveryModelInterface(Element *element)
Constructor.
#define OOFEM_ERROR(...)
Definition error.h:79
#define S(p)
Definition mdm.C:469
double norm(const FloatArray &x)
@ CS_Thickness
Thickness.
FloatMatrixF< N, P > Tdot(const FloatMatrixF< M, N > &a, const FloatMatrixF< M, P > &b)
Computes .
GaussPoint IntegrationPoint
Definition gausspoint.h:272
FloatMatrixF< 3, 3 > from_voigt_form_9(const FloatArrayF< 9 > &v)
FloatMatrixF< N, P > dotT(const FloatMatrixF< N, M > &a, const FloatMatrixF< P, M > &b)
Computes .
double det(const FloatMatrixF< 2, 2 > &mat)
Computes the determinant.
InternalStateValueType
Determines the type of internal variable.
@ ISVT_TENSOR_S3
Symmetric 3x3 tensor.
FloatArrayF< 9 > to_voigt_form_33(const FloatMatrixF< 3, 3 > &t)
FloatArrayF< 3 > cross(const FloatArrayF< 3 > &x, const FloatArrayF< 3 > &y)
Computes $ x \cross y $.
double sum(const FloatArray &x)
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< N, N > inv(const FloatMatrixF< N, N > &mat, double zeropiv=1e-24)
Computes the inverse.
@ ZZNodalRecoveryModelInterfaceType
@ LayeredCrossSectionInterfaceType
@ VTKXMLExportModuleElementInterfaceType
@ NodalAveragingRecoveryModelInterfaceType
@ FailureModuleElementInterfaceType
InternalStateValueType giveInternalStateValueType(InternalStateType type)
Definition cltypes.C:75
FloatArrayF< N > normalize(const FloatArrayF< N > &x)
Normalizes vector (L2 norm).
FloatArrayF< N > zeros()
For more readable code.
double distance(const FloatArray &x, const FloatArray &y)
#define PM_UPDATE_PARAMETER(_val, _pm, _ir, _componentnum, _paramkey, _prio)
#define ALL_STRAINS

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