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

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:31 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011