OOFEM 3.0
Loading...
Searching...
No Matches
layeredcrosssection.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
39#include "gausspoint.h"
40#include "material.h"
41#include "floatarray.h"
42#include "floatarrayf.h"
43#include "floatmatrixf.h"
44#include "contextioerr.h"
46#include "mathfem.h"
47#include "classfactory.h"
48#include "lobattoir.h"
49#include "dynamicinputrecord.h"
50#include "cltypes.h"
51#include "simplecrosssection.h"
52
53namespace oofem {
55
56
59{
61 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
63 int gpnum = gp->giveNumber();
64 int gpsperlayer = ngps / this->numberOfLayers;
65 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
66 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
67 if ( this->layerRots.at(layer) != 0. ) {
68 double rot = this->layerRots.at(layer);
69 double c = cos(rot * M_PI / 180.);
70 double s = sin(rot * M_PI / 180.);
71
72 FloatArrayF< 6 >rotStrain = {
73 c *c *strain.at(1) - c * s * strain.at(6) + s * s * strain.at(2),
74 c *c *strain.at(2) + c * s * strain.at(6) + s * s * strain.at(1),
75 strain.at(3),
76 c *strain.at(4) + s * strain.at(5),
77 c *strain.at(5) - s * strain.at(4),
78 ( c * c - s * s ) * strain.at(6) + 2 * c * s * ( strain.at(1) - strain.at(2) ),
79 };
80
81 auto rotStress = static_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_3d(rotStrain, gp, tStep);
82
83 return {
84 c *c *rotStress.at(1) + 2 * c * s * rotStress.at(6) + s * s * rotStress.at(2),
85 c *c *rotStress.at(2) - 2 * c * s * rotStress.at(6) + s * s * rotStress.at(1),
86 rotStress.at(3),
87 c *rotStress.at(4) - s * rotStress.at(5),
88 c *rotStress.at(5) + s * rotStress.at(4),
89 ( c * c - s * s ) * rotStress.at(6) - c * s * ( rotStress.at(1) - rotStress.at(2) ),
90 };
91 } else {
92 return static_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_3d(strain, gp, tStep);
93 }
94 } else {
95 OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections");
96 }
97}
98
99
102{
103 IntArray strainControl = { 1, 2, 4, 5, 6 };
104 auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) );
105
107 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
109 int gpnum = gp->giveNumber();
110 int gpsperlayer = ngps / this->numberOfLayers;
111 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
112 if ( this->layerRots.at(layer) != 0. ) {
113 double rot = this->layerRots.at(layer);
114 double c = cos(rot * M_PI / 180.);
115 double s = sin(rot * M_PI / 180.);
116
117 FloatArrayF< 6 >rotStrain = {
118 c *c *strain.at(1) - c * s * strain.at(6) + s * s * strain.at(2),
119 c *c *strain.at(2) + c * s * strain.at(6) + s * s * strain.at(1),
120 strain.at(3),
121 c *strain.at(4) + s * strain.at(5),
122 c *strain.at(5) - s * strain.at(4),
123 ( c * c - s * s ) * strain.at(6) + 2 * c * s * ( strain.at(1) - strain.at(2) ),
124 };
125
126 auto rotStress = mat->giveRealStressVector_ShellStressControl(rotStrain, strainControl, gp, tStep);
127
128 return {
129 c *c *rotStress.at(1) + 2 * c * s * rotStress.at(6) + s * s * rotStress.at(2),
130 c *c *rotStress.at(2) - 2 * c * s * rotStress.at(6) + s * s * rotStress.at(1),
131 rotStress.at(3),
132 c *rotStress.at(4) - s * rotStress.at(5),
133 c *rotStress.at(5) + s * rotStress.at(4),
134 ( c * c - s * s ) * rotStress.at(6) - c * s * ( rotStress.at(1) - rotStress.at(2) ),
135 };
136 } else {
137 return mat->giveRealStressVector_ShellStressControl(strain, strainControl, gp, tStep);
138 }
139 } else {
140 OOFEM_ERROR("Only _3dDegShell mode is meaningful for layered shells");
141 }
142}
143
144
147{
148 OOFEM_ERROR("Not supported");
149}
150
151
154{
155 //strain eps_x, eps_y, gamma_xy
156 //stress sig_x, sig_y, tau_xy
157 //answer n_x, n_y, n_xy
158
159 FloatArray layerStrain;
160
161 //double bottom = this->give(CS_BottomZCoord, masterGp);
162 //double top = this->give(CS_TopZCoord, masterGp);
163
164 auto element = dynamic_cast< StructuralElement * >( masterGp->giveElement() );
165 double totThick = 0.0;
166
167 FloatArrayF< 3 >answer;
168 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
169 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
170 auto layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1, igp);
171 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
172 auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) );
173 auto lgpw = layerGp->giveWeight();
174
175 // resolve current layer z-coordinate
176 double layerThick = this->layerThicks.at(layer);
177 totThick += layerThick * lgpw;
178 //double layerZeta = layerGp->giveNaturalCoordinate(3);
179 //double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
180
181 // Compute the layer stress
182 interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep);
183 auto reducedLayerStress = dynamic_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_PlaneStress(layerStrain, layerGp, tStep);
184 answer.at(1) += reducedLayerStress.at(1) * layerThick * lgpw;
185 answer.at(2) += reducedLayerStress.at(2) * layerThick * lgpw;
186 answer.at(3) += reducedLayerStress.at(3) * layerThick * lgpw; // * ( 5. / 6. );
187 }
188 }
189 answer *= ( 1. / totThick );
190 auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(masterGp) );
191 status->letTempStrainVectorBe(strain);
192 status->letTempStressVectorBe(answer);
193
194 return answer;
195}
196
197
200{
201 OOFEM_ERROR("Not supported");
202}
203
204
207{
208 OOFEM_ERROR("Not supported");
209}
210
211
213LayeredCrossSection::giveStiffnessMatrix_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
214{
216 OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections");
217 }
218 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
220 int gpnum = gp->giveNumber();
221 int gpsperlayer = ngps / this->numberOfLayers;
222 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
223 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
224 auto tangent = static_cast< StructuralMaterial * >( layerMat )->give3dMaterialStiffnessMatrix(rMode, gp, tStep);
225
226 if ( this->layerRots.at(layer) != 0. ) {
227 double rot = this->layerRots.at(layer);
228 double c = cos(rot * M_PI / 180.);
229 double s = sin(rot * M_PI / 180.);
230
231 FloatMatrixF< 6, 6 >rotTangent = {
232 c *c, s *s, 0., 0., 0., -c * s,
233 s *s, c *c, 0., 0., 0., c *s,
234 0., 0., 1., 0., 0., 0.,
235 0., 0., 0., c, s, 0.,
236 0., 0., 0., -s, c, 0.,
237 2 * c * s, -2 * c * s, 0., 0., 0., c *c - s * s,
238 };
239
240 return unrotate(tangent, rotTangent);
241 } else {
242 return tangent;
243 }
244}
245
246
248LayeredCrossSection::giveStiffnessMatrix_PlaneStress(MatResponseMode rMode, GaussPoint *masterGp, TimeStep *tStep) const
249{
251 double totThick = 0.;
252
253 //Average stiffness over all layers
254 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
255 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
256 auto slaveGP = this->giveSlaveGaussPoint(masterGp, layer - 1, igp);
257 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
258 auto sgpw = slaveGP->giveWeight();
259 double layerThick = this->layerThicks.at(layer);
260 totThick += layerThick * sgpw;
261 auto subAnswer = dynamic_cast< StructuralMaterial * >( layerMat )->givePlaneStressStiffMtrx(rMode, slaveGP, tStep);
262 answer += layerThick * sgpw * subAnswer;
263 }
264 }
265 //answer.at(3,3) *= (5./6.);
266 return answer * ( 1. / totThick );
267}
268
269
272{
273 OOFEM_ERROR("Not supported");
274}
275
276
278LayeredCrossSection::giveStiffnessMatrix_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
279{
280 OOFEM_ERROR("Not supported");
281}
282
283
286{
287 FloatArray layerStrain;
288 auto element = static_cast< StructuralElement * >( gp->giveElement() );
289 auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) );
290
291
292 // perform integration over layers
293 double bottom = this->give(CS_BottomZCoord, gp);
294 double top = this->give(CS_TopZCoord, gp);
295
296 if ( interface == nullptr ) {
297 OOFEM_ERROR("element with no layer support encountered");
298 }
299
300 FloatArrayF< 3 >answer;
301 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
302 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
303 auto layerGp = this->giveSlaveGaussPoint(gp, layer - 1, igp);
304 auto layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(layer) ) );
305 auto lgpw = layerGp->giveWeight();
306
307 // resolve current layer z-coordinate
308 double layerThick = this->layerThicks.at(layer);
309 double layerWidth = this->layerWidths.at(layer);
310 double layerZeta = layerGp->giveNaturalCoordinate(3);
311 double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
312
313 // Compute the layer stress
314 interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep);
315
316 FloatArrayF< 2 >reducedLayerStress;
317 if ( this->layerRots.at(layer) != 0. ) {
318 OOFEM_ERROR("Rotation not supported for beams");
319 } else {
320 reducedLayerStress = layerMat->giveRealStressVector_2dBeamLayer(layerStrain, layerGp, tStep);
321 }
322
323 answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw; //Nx
324 answer.at(2) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw * layerZCoord;//My
325 answer.at(3) += reducedLayerStress.at(2) * layerWidth * layerThick * lgpw * beamShearCoeffxz; //Vz
326 }
327 }
328
329 // Create material status according to the first layer material
331 //CrossSectionStatus *status = new CrossSectionStatus(gp);
332 //gp->setMaterialStatus(status);
333 auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) );
334 status->letTempStrainVectorBe(strain);
335 status->letTempStressVectorBe(answer);
336
337 return answer;
338}
339
340
343{
344 OOFEM_ERROR("Not supported");
345}
346
347
350{
351 FloatArray layerStrain;
352 auto element = static_cast< StructuralElement * >( gp->giveElement() );
353 auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) );
354
355 // perform integration over layers
356 double bottom = this->give(CS_BottomZCoord, gp);
357 double top = this->give(CS_TopZCoord, gp);
358
359 if ( interface == nullptr ) {
360 OOFEM_ERROR("element with no layer support encountered");
361 }
362
363 FloatArrayF< 5 >answer;
364 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
365 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
366 auto layerGp = this->giveSlaveGaussPoint(gp, layer - 1, igp);
367 auto layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(layer) ) );
368 auto lgpw = layerGp->giveWeight();
369
370 // resolve current layer z-coordinate
371 double layerThick = this->layerThicks.at(layer);
372 double layerWidth = this->layerWidths.at(layer);
373 double layerZeta = layerGp->giveNaturalCoordinate(3);
374 double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
375
376 // Compute the layer stress
377 interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep);
378
379 FloatArrayF< 5 >reducedLayerStress;
380 if ( this->layerRots.at(layer) != 0. ) {
381 double rot = this->layerRots.at(layer);
382 double c = cos(rot * M_PI / 180.);
383 double s = sin(rot * M_PI / 180.);
384
385 FloatArrayF< 5 >rotStrain = {
386 c *c *layerStrain.at(1) - c * s * layerStrain.at(5) + s * s * layerStrain.at(2),
387 c *c *layerStrain.at(2) + c * s * layerStrain.at(5) + s * s * layerStrain.at(1),
388 c *layerStrain.at(3) + s * layerStrain.at(4),
389 c *layerStrain.at(4) - s * layerStrain.at(3),
390 ( c * c - s * s ) * layerStrain.at(5) + c * s * ( layerStrain.at(1) - layerStrain.at(2) ),
391 };
392
393 auto rotStress = layerMat->giveRealStressVector_PlateLayer(rotStrain, layerGp, tStep);
394
395 reducedLayerStress = {
396 c *c *rotStress.at(1) + 2 * c * s * rotStress.at(5) + s * s * rotStress.at(2),
397 c *c *rotStress.at(2) - 2 * c * s * rotStress.at(5) + s * s * rotStress.at(1),
398 c *rotStress.at(3) - s * rotStress.at(4),
399 c *rotStress.at(4) + s * rotStress.at(3),
400 ( c * c - s * s ) * rotStress.at(5) - c * s * ( rotStress.at(1) - rotStress.at(2) ),
401 };
402 } else {
403 reducedLayerStress = layerMat->giveRealStressVector_PlateLayer(layerStrain, layerGp, tStep);
404 }
405
406 answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw * layerZCoord;
407 answer.at(2) += reducedLayerStress.at(2) * layerWidth * layerThick * lgpw * layerZCoord;
408 answer.at(3) += reducedLayerStress.at(5) * layerWidth * layerThick * lgpw * layerZCoord;
409 answer.at(4) += reducedLayerStress.at(4) * layerWidth * layerThick * lgpw * ( 5. / 6. );
410 answer.at(5) += reducedLayerStress.at(3) * layerWidth * layerThick * lgpw * ( 5. / 6. );
411 }
412 }
413
414 // now we must update master gp
415 // Create material status according to the first layer material
417 //CrossSectionStatus *status = new CrossSectionStatus(gp);
418 //gp->setMaterialStatus(status);
419 auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) );
420 status->letTempStrainVectorBe(strain);
421 status->letTempStressVectorBe(answer);
422 return answer;
423}
424
425
428{
429 FloatArray layerStrain;
430 auto element = static_cast< StructuralElement * >( gp->giveElement() );
431 auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) );
432
433 // perform integration over layers
434 double bottom = this->give(CS_BottomZCoord, gp);
435 double top = this->give(CS_TopZCoord, gp);
436
437 if ( interface == nullptr ) {
438 OOFEM_ERROR("element with no layer support encountered");
439 }
440
441 FloatArrayF< 8 >answer;
442 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
443 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
444 auto layerGp = this->giveSlaveGaussPoint(gp, layer - 1, igp);
445 auto layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(layer) ) );
446 auto lgpw = layerGp->giveWeight();
447
448 // resolve current layer z-coordinate
449 double layerThick = this->layerThicks.at(layer);
450 double layerWidth = this->layerWidths.at(layer);
451 double layerZeta = layerGp->giveNaturalCoordinate(3);
452 double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
453
454 // Compute the layer stress
455 interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); // FIXME convert to return value fixed size array.
456
457 FloatArrayF< 5 >reducedLayerStress;
458 if ( this->layerRots.at(layer) != 0. ) {
459 double rot = this->layerRots.at(layer);
460 double c = cos(rot * M_PI / 180.);
461 double s = sin(rot * M_PI / 180.);
462
463 FloatArrayF< 5 >rotStrain = {
464 c *c *layerStrain.at(1) - c * s * layerStrain.at(5) + s * s * layerStrain.at(2),
465 c *c *layerStrain.at(2) + c * s * layerStrain.at(5) + s * s * layerStrain.at(1),
466 c *layerStrain.at(3) + s * layerStrain.at(4),
467 c *layerStrain.at(4) - s * layerStrain.at(3),
468 ( c * c - s * s ) * layerStrain.at(5) + c * s * ( layerStrain.at(1) - layerStrain.at(2) ),
469 };
470
471 auto rotStress = layerMat->giveRealStressVector_PlateLayer(rotStrain, layerGp, tStep);
472
473 reducedLayerStress = {
474 c *c *rotStress.at(1) + 2 * c * s * rotStress.at(5) + s * s * rotStress.at(2),
475 c *c *rotStress.at(2) - 2 * c * s * rotStress.at(5) + s * s * rotStress.at(1),
476 c *rotStress.at(3) - s * rotStress.at(4),
477 c *rotStress.at(4) + s * rotStress.at(3),
478 ( c * c - s * s ) * rotStress.at(5) - c * s * ( rotStress.at(1) - rotStress.at(2) ),
479 };
480 } else {
481 reducedLayerStress = layerMat->giveRealStressVector_PlateLayer(layerStrain, layerGp, tStep);
482 }
483
484 // 1) membrane terms sx, sy, sxy
485 answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw;
486 answer.at(2) += reducedLayerStress.at(2) * layerWidth * layerThick * lgpw;
487 answer.at(3) += reducedLayerStress.at(5) * layerWidth * layerThick * lgpw;
488 // 2) bending terms mx, my, mxy
489 answer.at(4) += reducedLayerStress.at(1) * layerWidth * layerThick * layerZCoord * lgpw;
490 answer.at(5) += reducedLayerStress.at(2) * layerWidth * layerThick * layerZCoord * lgpw;
491 answer.at(6) += reducedLayerStress.at(5) * layerWidth * layerThick * layerZCoord * lgpw;
492 // 3) shear terms qx, qy
493 answer.at(7) += reducedLayerStress.at(4) * layerWidth * layerThick * lgpw * ( 5. / 6. );
494 answer.at(8) += reducedLayerStress.at(3) * layerWidth * layerThick * lgpw * ( 5. / 6. );
495 }
496 }
497
498
499 // now we must update master gp
501 //CrossSectionStatus *status = new CrossSectionStatus(gp);
502 //gp->setMaterialStatus(status);
503 // Create material status according to the first layer material
504 auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) );
505 status->letTempStrainVectorBe(strain);
506 status->letTempStressVectorBe(answer);
507
508 return answer;
509}
510
513{
514 FloatArrayF< 9 >answer;
515 FloatArrayF< 8 >rstrain;
516 for ( int i = 1; i <= 8; i++ ) {
517 rstrain.at(i) = strain.at(i);
518 }
519 FloatArray ra = this->giveGeneralizedStress_Shell(rstrain, gp, tStep);
520 for ( int i = 1; i <= 8; i++ ) {
521 answer.at(i) = ra.at(i);
522 }
523 answer.at(9) = this->give(CS_DrillingStiffness, gp) * strain.at(9);
524
525
527 //CrossSectionStatus *status = new CrossSectionStatus(gp);
528 //gp->setMaterialStatus(status);
529 // Create material status according to the first layer material
530 auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) );
531 status->letTempStrainVectorBe(strain);
532 status->letTempStressVectorBe(answer);
533
534 return answer;
535}
536
537
538
541{
542 //strain eps_x, eps_y, gamma_xy
543 //stress sig_x, sig_y, tau_xy
544 //answer n_x, n_y, n_xy
545
546 FloatArray layerStrain;
547
548 //double bottom = this->give(CS_BottomZCoord, masterGp);
549 //double top = this->give(CS_TopZCoord, masterGp);
550
551 auto element = dynamic_cast< StructuralElement * >( masterGp->giveElement() );
552 double totThick = 0.0;
553
554 FloatArrayF< 4 >answer;
555 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
556 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
557 auto layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1, igp);
558 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
559 auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) );
560 auto lgpw = layerGp->giveWeight();
561
562 // resolve current layer z-coordinate
563 double layerThick = this->layerThicks.at(layer);
564 totThick += layerThick * lgpw;
565 //double layerZeta = layerGp->giveNaturalCoordinate(3);
566 //double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
567
568 // Compute the layer stress
569 interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep);
570 // extract membrane part only
571 FloatArrayF< 3 >layerStrainMembrane( layerStrain.at(1), layerStrain.at(2), layerStrain.at(3) );
572 auto reducedLayerStress = dynamic_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_PlaneStress(layerStrainMembrane, layerGp, tStep);
573 answer.at(1) += reducedLayerStress.at(1) * layerThick * lgpw;
574 answer.at(2) += reducedLayerStress.at(2) * layerThick * lgpw;
575 answer.at(3) += reducedLayerStress.at(3) * layerThick * lgpw;
576 }
577 }
578
579 // assume rotation term elastic response
580 auto de = this->giveMembraneRotStiffMtrx(ElasticStiffness, masterGp, tStep);
581 answer.at(4) = strain.at(4) * de.at(4, 4) * totThick;
582 answer *= ( 1. / totThick );
583
584 auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(masterGp) );
585 status->letTempStrainVectorBe(strain);
586 status->letTempStressVectorBe(answer);
587
588 return answer;
589}
590
593{
594 OOFEM_ERROR("Not supported in given cross-section (yet).");
595}
596
597void
599 MatResponseMode rMode,
600 GaussPoint *gp,
601 TimeStep *tStep)
602//
603// only interface to material class, forcing returned matrix to be in reduced form.
604//
605{
606 MaterialMode mode = gp->giveMaterialMode();
607 if ( mode == _2dBeam ) {
608 answer = this->give2dBeamStiffMtrx(rMode, gp, tStep);
609 } else if ( mode == _3dBeam ) {
610 answer = this->give3dBeamStiffMtrx(rMode, gp, tStep);
611 } else if ( mode == _2dPlate ) {
612 answer = this->give2dPlateStiffMtrx(rMode, gp, tStep);
613 } else if ( mode == _3dShell ) {
614 answer = this->give3dShellStiffMtrx(rMode, gp, tStep);
615 } else {
617 int gpnum = gp->giveNumber();
618 int gpsperlayer = ngps / this->numberOfLayers;
619 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
620 auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) );
621 if ( mat->hasMaterialModeCapability(gp->giveMaterialMode() ) ) {
622 mat->giveStiffnessMatrix(answer, rMode, gp, tStep);
623 } else {
624 OOFEM_ERROR("unsupported StressStrainMode");
625 }
626 }
627}
628
629
631LayeredCrossSection::give2dPlateStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
632
633//
634// assumption sigma_z = 0.
635//
636// General strain layer vector has one of the following forms:
637// 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy}
638//
639// returned strain or stress vector has the form:
640// 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy}
641//
642{
643 // perform integration over layers
644 double bottom = this->give(CS_BottomZCoord, gp);
645 double top = this->give(CS_TopZCoord, gp);
646
648 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
649 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
650 auto layerGp = giveSlaveGaussPoint(gp, layer - 1, igp);
651 auto lgpw = layerGp->giveWeight();
652
654 auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) );
655 auto layerMatrix = mat->givePlateLayerStiffMtrx(rMode, layerGp, tStep);
656 if ( this->layerRots.at(layer) != 0. ) {
657 double rot = this->layerRots.at(layer);
658 double c = cos(rot * M_PI / 180.);
659 double s = sin(rot * M_PI / 180.);
660
661 FloatMatrixF< 5, 5 >rotTangent = {
662 c *c, s *s, 0., 0., -c * s,
663 s *s, c *c, 0., 0., c *s,
664 0., 0., c, s, 0.,
665 0., 0., -s, c, 0.,
666 2 * c * s, -2 * c * s, 0., 0., c *c - s * s,
667 };
668 layerMatrix = unrotate(layerMatrix, rotTangent);
669 }
670
671 //
672 // resolve current layer z-coordinate
673 //
674 double layerThick = this->layerThicks.at(layer);
675 double layerWidth = this->layerWidths.at(layer);
676 double layerZeta = layerGp->giveNaturalCoordinate(3);
677 double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
678 double layerZCoord2 = layerZCoord * layerZCoord;
679 //
680 // perform integration
681 //
682 // 1) bending terms mx, my, mxy
683 answer.at(1, 1) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
684 answer.at(1, 2) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
685 answer.at(1, 3) += layerMatrix.at(1, 5) * lgpw * layerWidth * layerThick * layerZCoord2;
686
687 answer.at(2, 1) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
688 answer.at(2, 2) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
689 answer.at(2, 3) += layerMatrix.at(2, 5) * lgpw * layerWidth * layerThick * layerZCoord2;
690
691 answer.at(3, 1) += layerMatrix.at(5, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
692 answer.at(3, 2) += layerMatrix.at(5, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
693 answer.at(3, 3) += layerMatrix.at(5, 5) * lgpw * layerWidth * layerThick * layerZCoord2;
694
695 // 2) shear terms qx = qxz, qy = qyz
696 answer.at(4, 4) += layerMatrix.at(4, 4) * lgpw * layerWidth * layerThick * ( 5. / 6. );
697 answer.at(4, 5) += layerMatrix.at(4, 3) * lgpw * layerWidth * layerThick * ( 5. / 6. );
698 answer.at(5, 4) += layerMatrix.at(3, 4) * lgpw * layerWidth * layerThick * ( 5. / 6. );
699 answer.at(5, 5) += layerMatrix.at(3, 3) * lgpw * layerWidth * layerThick * ( 5. / 6. );
700 }
701 }
702 return answer;
703}
704
705
707LayeredCrossSection::give3dShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
708//
709// assumption sigma_z = 0.
710//
711// General strain layer vector has one of the following forms:
712// 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy}
713//
714// returned strain or stress vector has the form:
715// 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy}
716//
717{
718 // perform integration over layers
719 double bottom = this->give(CS_BottomZCoord, gp);
720 double top = this->give(CS_TopZCoord, gp);
721 double shearcoeff = 5. / 6.;
722
724 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
725 for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) {
726 auto layerGp = giveSlaveGaussPoint(gp, layer - 1, igp);
727 auto lgpw = layerGp->giveWeight();
728
731 auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) );
732 auto layerMatrix = mat->givePlateLayerStiffMtrx(rMode, layerGp, tStep);
733 if ( this->layerRots.at(layer) != 0. ) {
734 double rot = this->layerRots.at(layer);
735 double c = cos(rot);
736 double s = sin(rot);
737
738 FloatMatrixF< 5, 5 >rotTangent = {
739 c *c, s *s, 0., 0., -c * s,
740 s *s, c *c, 0., 0., c *s,
741 0., 0., c, s, 0.,
742 0., 0., -s, c, 0.,
743 2 * c * s, -2 * c * s, 0., 0., c *c - s * s,
744 };
745 layerMatrix = unrotate(layerMatrix, rotTangent);
746 }
747
748 //
749 // resolve current layer z-coordinate
750 //
751 double layerThick = this->layerThicks.at(layer);
752 double layerWidth = this->layerWidths.at(layer);
753 double layerZeta = layerGp->giveNaturalCoordinate(3);
754 double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
755 double layerZCoord2 = layerZCoord * layerZCoord;
756 //
757 // perform integration
758 //
759 // 1) membrane terms sx, sy, sxy
760 answer.at(1, 1) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick;
761 answer.at(1, 2) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick;
762 answer.at(1, 3) += layerMatrix.at(1, 5) * lgpw * layerWidth * layerThick;
763
764 answer.at(2, 1) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick;
765 answer.at(2, 2) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick;
766 answer.at(2, 3) += layerMatrix.at(2, 5) * lgpw * layerWidth * layerThick;
767
768 answer.at(3, 1) += layerMatrix.at(5, 1) * lgpw * layerWidth * layerThick;
769 answer.at(3, 2) += layerMatrix.at(5, 2) * lgpw * layerWidth * layerThick;
770 answer.at(3, 3) += layerMatrix.at(5, 5) * lgpw * layerWidth * layerThick;
771
772 // 2) bending terms mx, my, mxy
773
774 answer.at(4, 4) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
775 answer.at(4, 5) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
776 answer.at(4, 6) += layerMatrix.at(1, 5) * lgpw * layerWidth * layerThick * layerZCoord2;
777
778 answer.at(5, 4) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
779 answer.at(5, 5) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
780 answer.at(5, 6) += layerMatrix.at(2, 5) * lgpw * layerWidth * layerThick * layerZCoord2;
781
782 answer.at(6, 4) += layerMatrix.at(5, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
783 answer.at(6, 5) += layerMatrix.at(5, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
784 answer.at(6, 6) += layerMatrix.at(5, 5) * lgpw * layerWidth * layerThick * layerZCoord2;
785
786 // 3) shear terms qx, qy
787 answer.at(7, 7) += layerMatrix.at(4, 4) * lgpw * layerWidth * layerThick * shearcoeff;
788 answer.at(7, 8) += layerMatrix.at(4, 3) * lgpw * layerWidth * layerThick * shearcoeff;
789 answer.at(8, 7) += layerMatrix.at(3, 4) * lgpw * layerWidth * layerThick * shearcoeff;
790 answer.at(8, 8) += layerMatrix.at(3, 3) * lgpw * layerWidth * layerThick * shearcoeff;
791 }
792 }
793 return answer;
794}
795
797LayeredCrossSection::give3dShellRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
798//
799// assumption sigma_z = 0.
800//
801// General strain layer vector has one of the following forms:
802// 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy}
803//
804// returned strain or stress vector has the form:
805// 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy, eps_normalRotation}
806//
807{
808 FloatMatrix d, answer;
809 d = this->give3dShellStiffMtrx(rMode, gp, tStep);
810 answer.resize(9, 9);
811 answer.zero();
812 answer.assemble(d, { 1, 2, 3, 4, 5, 6, 7, 8 });
813 answer.at(9, 9) = this->give(CS_DrillingStiffness, gp);
814 //answer.printYourself("De");
815
816 return answer;
817}
818
821{
822 auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) );
823 auto answer = mat->give3dMaterialStiffnessMatrix(rMode, gp, tStep);
824
825 answer.at(1, 1) -= answer.at(1, 3) * answer.at(3, 1) / answer.at(3, 3);
826 answer.at(2, 1) -= answer.at(2, 3) * answer.at(3, 1) / answer.at(3, 3);
827 answer.at(1, 2) -= answer.at(1, 3) * answer.at(3, 2) / answer.at(3, 3);
828 answer.at(2, 2) -= answer.at(2, 3) * answer.at(3, 2) / answer.at(3, 3);
829
830 answer.at(3, 1) = 0.0;
831 answer.at(3, 2) = 0.0;
832 answer.at(3, 3) = 0.0;
833 answer.at(2, 3) = 0.0;
834 answer.at(1, 3) = 0.0;
835 return answer;
836}
837
838
840LayeredCrossSection::give2dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
841//
842// assumption sigma_z = 0.
843//
844// General strain layer vector has one of the following forms:
845// 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy}
846//
847// returned strain or stress vector has the form:
848// 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy}
849//
850{
851 // perform integration over layers
852 double bottom = this->give(CS_BottomZCoord, gp);
853 double top = this->give(CS_TopZCoord, gp);
854
856 for ( int i = 1; i <= numberOfLayers; i++ ) {
857 for ( int igp = 0; igp < layerIntegrationPoints.at(i); igp++ ) {
858 auto layerGp = giveSlaveGaussPoint(gp, i - 1, igp);
859 auto lgpw = layerGp->giveWeight();
860
863 auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(i) ) );
864 auto layerMatrix = mat->give2dBeamLayerStiffMtrx(rMode, layerGp, tStep);
865 if ( this->layerRots.at(i) != 0. ) {
866 OOFEM_ERROR("Doesn't support layer rotations.");
867 }
868
869 //
870 // resolve current layer z-coordinate
871 //
872 double layerThick = this->layerThicks.at(i);
873 double layerWidth = this->layerWidths.at(i);
874 double layerZeta = layerGp->giveNaturalCoordinate(3);
875 double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top );
876 double layerZCoord2 = layerZCoord * layerZCoord;
877 //
878 // perform integration
879 //
880 // 1) membrane terms sx
881 answer.at(1, 1) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick;
882 answer.at(1, 3) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick;
883 // 2) bending terms my
884 answer.at(2, 2) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick * layerZCoord2;
885 answer.at(2, 3) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick * layerZCoord2;
886 // 3) shear terms qx
887 answer.at(3, 1) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick * beamShearCoeffxz;
888 answer.at(3, 3) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick * beamShearCoeffxz;
889 }
890 }
891 return answer;
892}
893
894
896LayeredCrossSection::give3dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const
897{
898 OOFEM_ERROR("Not implemented");
899}
900
901
904{
905 auto d = this->giveStiffnessMatrix_PlaneStress(rMode, gp, tStep);
906 auto de = this->giveStiffnessMatrix_PlaneStress(ElasticStiffness, gp, tStep);
907 auto ds = assemble< 4, 4 >(d, { 0, 1, 2 }, { 0, 1, 2 });
908 ds.at(4, 4) = 2.0 * de.at(3, 3); //this->give(CS_DrillingStiffness, gp);
909 return ds;
910}
911
914{
915 OOFEM_ERROR("Not implemented");
916}
917
918
919
922{
924 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
926 int gpnum = gp->giveNumber();
927 int gpsperlayer = ngps / this->numberOfLayers;
928 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
929 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
930 if ( this->layerRots.at(layer) != 0. ) {
931 double rot = this->layerRots.at(layer);
932 double c = cos(rot * M_PI / 180.);
933 double s = sin(rot * M_PI / 180.);
934 //rotation matrix
935 //Q = {{c, -s, 0}, {s, c, 0}, {0, 0, 1}};
937 c *c, s *s, 0., 0., 0., -c * s, 0., 0., -c * s,
938 s *s, c *c, 0., 0., 0., c *s, 0., 0., c *s,
939 0., 0., 1., 0., 0., 0., 0., 0., 0.,
940 0., 0., 0., c, s, 0., 0., 0., 0.,
941 0., 0., 0., -s, c, 0., 0., 0., 0.,
942 c *s, -c * s, 0., 0., 0., c *c, 0., 0., -s * s,
943 0., 0., 0., 0., 0., 0., c, s, 0.,
944 0., 0., 0., 0., 0., 0., -s, c, 0.,
945 c *s, -c * s, 0., 0., 0., -s * s, 0., 0., -c * c,
946 };
947 // Q^T F Q
948 auto rotvF = dot(Q, vF);
949 // compute rotated vP
950 auto rotvP = static_cast< StructuralMaterial * >( layerMat )->giveFirstPKStressVector_3d(rotvF, gp, tStep);
951 //
952 auto vP = Tdot(Q, rotvP);
953 return vP;
954 } else {
955 return static_cast< StructuralMaterial * >( layerMat )->giveFirstPKStressVector_3d(vF, gp, tStep);
956 }
957 } else {
958 OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections");
959 }
960}
961
962
963
966{
967 OOFEM_ERROR("Not supported");
968}
969
970
973{
974 OOFEM_ERROR("Not supported");
975 //@todo: implement this for large strains
976 //strain eps_x, eps_y, gamma_xy
977 //stress sig_x, sig_y, tau_xy
978 //answer n_x, n_y, n_xy
979
980 /* FloatArray layerStrain;
981 * auto element = dynamic_cast< StructuralElement * >( masterGp->giveElement() );
982 * double totThick = 0.0;
983 *
984 * FloatArrayF<3> answer;
985 * for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
986 * for (int igp = 0; igp < layerIntegrationPoints.at(layer); igp++) {
987 * auto layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1, igp);
988 * auto layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) );
989 * auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) );
990 * auto lgpw = layerGp->giveWeight();
991 *
992 * // resolve current layer z-coordinate
993 * double layerThick = this->layerThicks.at(layer);
994 * totThick += layerThick * lgpw;
995 *
996 * // Compute the layer stress
997 * interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep);
998 * auto reducedLayerStress = dynamic_cast< StructuralMaterial * >(layerMat)->giveRealStressVector_PlaneStress(layerStrain, layerGp, tStep);
999 * answer.at(1) += reducedLayerStress.at(1) * layerThick* lgpw;
1000 * answer.at(2) += reducedLayerStress.at(2) * layerThick* lgpw;
1001 * answer.at(3) += reducedLayerStress.at(3) * layerThick* lgpw; // * ( 5. / 6. );
1002 * }
1003 * }
1004 * answer*=(1./totThick);
1005 * auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial( layerMaterials.at(1) )->giveStatus(masterGp) );
1006 * status->letTempStrainVectorBe(strain);
1007 * status->letTempStressVectorBe(answer);
1008 *
1009 * return answer;
1010 */
1011}
1012
1013
1016{
1017 OOFEM_ERROR("Not supported");
1018}
1019
1020
1021
1022
1023void
1025 MatResponseMode rMode,
1026 GaussPoint *gp,
1027 TimeStep *tStep)
1028//
1029// only interface to material class, forcing returned matrix to be in reduced form.
1030//
1031{
1032 // MaterialMode mode = gp->giveMaterialMode();
1034 int gpnum = gp->giveNumber();
1035 int gpsperlayer = ngps / this->numberOfLayers;
1036 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
1037 auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) );
1038 if ( mat->hasMaterialModeCapability(gp->giveMaterialMode() ) ) {
1039 mat->giveStiffnessMatrix(answer, rMode, gp, tStep);
1040 } else {
1041 OOFEM_ERROR("unsupported StressStrainMode");
1042 }
1043}
1044
1045
1048{
1050 OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections");
1051 }
1052 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
1054 int gpnum = gp->giveNumber();
1055 int gpsperlayer = ngps / this->numberOfLayers;
1056 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
1057 auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
1058 auto tangent = static_cast< StructuralMaterial * >( layerMat )->give3dMaterialStiffnessMatrix_dPdF(rMode, gp, tStep);
1059
1060 if ( this->layerRots.at(layer) != 0. ) {
1061 double rot = this->layerRots.at(layer);
1062 double c = cos(rot * M_PI / 180.);
1063 double s = sin(rot * M_PI / 180.);
1064
1066 c *c, s *s, 0., 0., 0., -c * s, 0., 0., -c * s,
1067 s *s, c *c, 0., 0., 0., c *s, 0., 0., c *s,
1068 0., 0., 1., 0., 0., 0., 0., 0., 0.,
1069 0., 0., 0., c, s, 0., 0., 0., 0.,
1070 0., 0., 0., -s, c, 0., 0., 0., 0.,
1071 c *s, -c * s, 0., 0., 0., c *c, 0., 0., -s * s,
1072 0., 0., 0., 0., 0., 0., c, s, 0.,
1073 0., 0., 0., 0., 0., 0., -s, c, 0.,
1074 c *s, -c * s, 0., 0., 0., -s * s, 0., 0., -c * c,
1075 };
1076
1077 return unrotate(tangent, Q);
1078 } else {
1079 return tangent;
1080 }
1081}
1082
1083
1086{
1087 OOFEM_ERROR("Not supported");
1088 /*@todo: implement for large strains
1089 * FloatMatrixF<3,3> answer;
1090 * double totThick = 0.;
1091 *
1092 * //Average stiffness over all layers
1093 * for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
1094 * for (int igp=0; igp< layerIntegrationPoints.at(layer); igp++) {
1095 * auto slaveGP = this->giveSlaveGaussPoint(masterGp, layer - 1, igp);
1096 * auto layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) );
1097 * auto sgpw = slaveGP->giveWeight();
1098 * double layerThick = this->layerThicks.at(layer);
1099 * totThick += layerThick * sgpw;
1100 * auto subAnswer = dynamic_cast< StructuralMaterial * >(layerMat)->givePlaneStressStiffMtrx(rMode, slaveGP, tStep);
1101 * answer += layerThick * sgpw * subAnswer;
1102 * }
1103 * }
1104 * //answer.at(3,3) *= (5./6.);
1105 * return answer * (1./totThick);
1106 */
1107}
1108
1109
1112{
1113 OOFEM_ERROR("Not supported");
1114}
1115
1116
1119{
1120 OOFEM_ERROR("Not supported");
1121}
1122
1123
1124
1125FloatArray *
1127//
1128// returns modified gradient of stress vector, which is used to
1129// bring stresses back to yield surface.
1130//
1131// imposes zeros on places, where zero stress occurs. if energetically connected
1132// strain is zero, we do not impose zero there, because stress exist and
1133// must be taken into account when computing yeld function. In such case
1134// a problem is assumed to be full 3d with some explicit strain equal to 0.
1135//
1136// On the other hand, if some stress is imposed to be zero, we understand
1137// such case as subspace of 3d case (like a classical plane stess problem, with no
1138// tracing of ez, sigma_z)
1139//
1140{
1141 MaterialMode mode = gp->giveMaterialMode();
1142 int size = gradientStressVector3d->giveSize();
1143 if ( size != 6 ) {
1144 OOFEM_ERROR("size mismatch");
1145 }
1146
1147 switch ( mode ) {
1148 case _PlateLayer:
1149 gradientStressVector3d->at(3) = 0.;
1150 break;
1151 case _2dBeamLayer:
1152 for ( int i = 2; i <= 5; i++ ) {
1153 gradientStressVector3d->at(i) = 0.;
1154 }
1155
1156 break;
1157 default:
1159 }
1160
1161 return gradientStressVector3d;
1162}
1163
1164
1165FloatArray *
1167//
1168// returns modified gradient of strain vector, which is used to
1169// compute plastic strain increment.
1170//
1171// imposes zeros on places, where zero strain occurs or energetically connected stress
1172// is prescribed to be zero.
1173//
1174{
1175 MaterialMode mode = gp->giveMaterialMode();
1176 if ( gradientStrainVector3d->giveSize() != 6 ) {
1177 OOFEM_ERROR("size mismatch");
1178 }
1179
1180 switch ( mode ) {
1181 case _PlateLayer:
1182 gradientStrainVector3d->at(3) = 0.;
1183 break;
1184 case _2dBeamLayer:
1185 for ( int i = 2; i <= 5; i++ ) {
1186 gradientStrainVector3d->at(i) = 0.;
1187 }
1188
1189 break;
1190 default:
1192 }
1193
1194 return gradientStrainVector3d;
1195}
1196
1197
1198void
1200{
1202
1204 if ( numberOfLayers <= 0 ) {
1205 throw ValueInputException(ir, _IFT_LayeredCrossSection_nlayers, "numberOfLayers <= 0 is not allowed");
1206 }
1207
1208
1210 if ( numberOfLayers != layerMaterials.giveSize() ) {
1211 if ( layerMaterials.giveSize() == 1 ) {
1212 OOFEM_WARNING("Assuming same material in all layers");
1213 int temp = layerMaterials.at(1);
1215 layerMaterials.zero();
1216 layerMaterials.add(temp);
1217 } else {
1218 throw ValueInputException(ir, _IFT_LayeredCrossSection_layermaterials, "numberOfLayers does not equal given number of materials. ");
1219 }
1220 }
1221
1223 if ( numberOfLayers != layerThicks.giveSize() ) {
1224 if ( layerThicks.giveSize() == 1 ) {
1225 OOFEM_WARNING("Assuming same thickness in all layers");
1226 double temp = layerThicks.at(1);
1228 layerThicks.zero();
1229 layerThicks.add(temp);
1230 } else {
1231 throw ValueInputException(ir, _IFT_LayeredCrossSection_thicks, "numberOfLayers does not equal given number of thicknesses. ");
1232 }
1233 }
1234
1236 layerWidths.zero();
1238 layerRots.resize(numberOfLayers);
1239 layerRots.zero();
1241
1242 if ( numberOfLayers != layerRots.giveSize() ) { //|| ( numberOfLayers != layerWidths.giveSize() ) ) || numberOfLayers != layerThicks.giveSize() || numberOfLayers != layerMaterials.giveSize()
1243 throw ValueInputException(ir, _IFT_LayeredCrossSection_layerRotations, "numberOfLayers does not equal given number of layer rotations. ");
1244 }
1245
1246 // Interface materials // add check if correct numbers
1248 interfacerMaterials.zero();
1250
1254 for ( int i = 1; i <= numberOfLayers; i++ ) {
1256 }
1257
1259 if ( layerIntegrationPoints.giveSize() != numberOfLayers ) {
1260 throw ValueInputException(ir, _IFT_LayeredCrossSection_nlayerintegrationpoints, "size of layerIntegrationPoints does not equal given number of layers. ");
1261 }
1262
1263
1264 this->totalThick = layerThicks.sum();
1265 // read z-coordinate of mid-surface measured from bottom layer
1266 midSurfaceZcoordFromBottom = 0.5 * this->computeIntegralThick(); // Default: geometric midplane
1267 midSurfaceXiCoordFromBottom = 1.0; // add to IR
1269
1270 this->setupLayerMidPlanes();
1271
1272 this->area = this->layerThicks.dotProduct(this->layerWidths);
1274
1275 double value = 0.0;
1278
1279 value = 0.0;
1282
1283 value = 0.0;
1286}
1287
1301
1303{
1304 for ( int i = 1; i <= numberOfLayers; i++ ) {
1305 for ( int k = 0; k < layerIntegrationPoints.at(i); k++ ) {
1306 GaussPoint *layerGp = giveSlaveGaussPoint(& iGP, i - 1, k);
1307 StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(i) ) );
1308 //MaterialStatus *matStat = mat->CreateStatus(layerGp);
1309 layerGp->setMaterialStatus(mat->CreateStatus(layerGp));
1310 }
1311 }
1312}
1313
1314
1315void
1317{
1318 // z-coord of each layer midplane measured from the global cross section z-coord
1319 this->layerMidZ.resize(this->numberOfLayers);
1320 double layerBottomZ = -midSurfaceZcoordFromBottom; // initialize to the bottom coord
1321 for ( int j = 1; j <= numberOfLayers; j++ ) {
1322 double thickness = this->layerThicks.at(j);
1323 this->layerMidZ.at(j) = layerBottomZ + thickness * 0.5;
1324 layerBottomZ += thickness;
1325 }
1326}
1327
1328
1329Material *
1331{
1337 int gpnum = ip->giveNumber();
1338 int gpsperlayer = ngps / this->numberOfLayers;
1339 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
1340 return this->domain->giveMaterial(this->giveLayerMaterial(layer) );
1341 //return this->domain->giveMaterial( this->giveLayerMaterial(ip->giveNumber()) );
1342 }
1343
1344 if ( ip->hasSlaveGaussPoint() ) {
1345 return domain->giveMaterial(layerMaterials.at(1) ); //virtual master, has no material assigned in input file
1346 } else {
1347 return domain->giveMaterial(layerMaterials.at(1) ); //virtual master, has no material assigned in input file
1348 //OOFEM_ERROR("Not implemented.")
1349 }
1350 return nullptr;
1351}
1352
1353
1354int
1356{
1358 if ( element->giveIntegrationDomain() == _Cube ) {
1359#if 0
1361 return irule.SetUpPointsOnCubeLayers(npoints.at(1), npoints.at(2), this->numberOfIntegrationPoints,
1362 element->giveMaterialMode(), this->layerThicks);
1363
1364#else
1365 int points1 = ( int ) floor(cbrt(double ( npoints ) ) + 0.5);
1366 // If numberOfIntegrationPoints > 0 then use that, otherwise use the element's default.
1367 return irule.SetUpPointsOnCubeLayers(points1, points1, this->numberOfIntegrationPoints ? numberOfIntegrationPoints : points1,
1368 element->giveMaterialMode(), this->layerThicks);
1369
1370#endif
1371 } else if ( element->giveIntegrationDomain() == _Wedge ) {
1372#if 0
1374 return irule.SetUpPointsOnWedgeLayers(npoints.at(1), this->numberOfIntegrationPoints,
1375 element->giveMaterialMode(), this->layerThicks);
1376
1377#else
1378 if ( npoints == 2 ) {
1380 element->giveMaterialMode(), this->layerThicks);
1381 } else {
1383 element->giveMaterialMode(), this->layerThicks);
1384 }
1385#endif
1386 } else {
1387 return irule.setUpIntegrationPoints(element->giveIntegrationDomain(), npoints, element->giveMaterialMode() );
1388 }
1389}
1390
1391int
1392LayeredCrossSection::setupIntegrationPoints(IntegrationRule &irule, int nPointsXY, int nPointsZ, Element *element)
1393{
1394 switch ( element->giveIntegrationDomain() ) {
1395 case _3dDegShell:
1396 return irule.SetUpPointsOn3dDegShellLayers(nPointsXY, max(nPointsZ, this->numberOfIntegrationPoints), element->giveMaterialMode(), this->layerThicks);
1397
1398 default:
1399 OOFEM_ERROR( "Unknown mode (%d)", element->giveIntegrationDomain() );
1400 }
1401}
1402
1403
1404
1405int
1407{
1408 // slave gps stored at master in sequence
1409 // need to take into account variable number of IPs per layer
1410 int indx = 0;
1411 // count number of gps in preceeding layers
1412 for ( int i = 0; i < ilayer; i++ ) {
1413 indx += layerIntegrationPoints(i);
1414 }
1415 indx += igp;
1416 return indx;
1417}
1418
1419
1420GaussPoint *
1421LayeredCrossSection::giveSlaveGaussPoint(GaussPoint *masterGp, int ilayer, int igp) const
1422//
1423// return the i-th slave gauss point of master gp
1424// if slave gp don't exists - create them
1425// ilayer and igp numbered from 0
1426//
1427{
1428 auto slave = masterGp->giveSlaveGaussPoint( giveSlaveGPIndex(ilayer, igp) );
1429 if ( slave == nullptr ) {
1430 // check for proper dimensions - slave can be NULL if index too high or if not
1431 // slaves previously defined
1432 if ( ilayer > this->numberOfLayers ) {
1433 OOFEM_ERROR("no such layer defined");
1434 }
1435
1436 // create new slave record in masterGp
1437 // (requires that this is friend of gp)
1438 const auto &masterCoords = masterGp->giveNaturalCoordinates();
1439 // resolve slave material mode
1440 auto masterMode = masterGp->giveMaterialMode();
1441 auto slaveMode = this->giveCorrespondingSlaveMaterialMode(masterMode);
1442
1443 double bottom = this->give(CS_BottomZCoord, masterGp);
1444 double top = this->give(CS_TopZCoord, masterGp);
1445
1447 int numberOfSlaves = 0;
1448 for ( int i = 0; i < numberOfLayers; i++ ) {
1449 numberOfSlaves += layerIntegrationPoints(i);
1450 }
1451 masterGp->gaussPoints.resize(numberOfSlaves);
1452 // helper 1d rule
1453 double currentZTopCoord = -midSurfaceZcoordFromBottom;
1454 for ( int j = 0; j < numberOfLayers; j++ ) {
1455 FloatArray sgpc( layerIntegrationPoints.at(j + 1) );
1456 FloatArray sgpw( layerIntegrationPoints.at(j + 1) );
1458
1459 currentZTopCoord += this->layerThicks.at(j + 1);
1460 for ( int k = 0; k < layerIntegrationPoints.at(j + 1); k++ ) {
1461 FloatArray zCoord(3);
1462
1463 double currentZCoord = currentZTopCoord - this->layerThicks.at(j + 1) * ( 1 + sgpc(k) ) / 2.0; // z-coord of layer gp
1464 if ( masterCoords.giveSize() > 0 ) {
1465 zCoord.at(1) = masterCoords.at(1); // gp x-coord of mid surface
1466 }
1467
1468 if ( masterCoords.giveSize() > 1 ) {
1469 zCoord.at(2) = masterCoords.at(2); // gp y-coord of mid surface
1470 }
1471
1472 zCoord.at(3) = ( 2.0 * currentZCoord - top - bottom ) / ( top - bottom );
1473 //printf("SGP %d: currentZTopCoord %e, currentZCoord %e\n", j*numberOfIntegrationPoints+k, currentZTopCoord, currentZCoord);
1474 // in gp - is stored isoparametric coordinate (-1,1) of z-coordinate
1475 masterGp->gaussPoints [ giveSlaveGPIndex(j, k) ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, zCoord, sgpw(k) / 2.0, slaveMode);
1476
1477 // test - remove!
1478 // masterGp->gaussPoints [ j ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, zCoord, 1.0, slaveMode);
1479 }
1480 }
1481
1482 slave = masterGp->gaussPoints [ giveSlaveGPIndex(ilayer, igp) ];
1483 }
1484
1485 return slave;
1486}
1487
1488double
1493
1494
1495void
1497// Prints the receiver on screen.
1498{
1499 printf("Cross Section with properties: \n");
1500 propertyDictionary.printYourself();
1501 printf("Layer Materials: \n");
1502 layerMaterials.printYourself();
1503 printf("Thickness of each layer: \n");
1504 layerThicks.printYourself();
1505 if ( layerWidths.giveSize() ) {
1506 printf("Width of each layer: \n");
1507 layerWidths.printYourself();
1508 }
1509 printf("Number of integration points per layer: %i \n", this->numberOfIntegrationPoints);
1510 printf("MidSurfaceZCoordinate from bottom: %f \n", midSurfaceZcoordFromBottom);
1511}
1512
1513
1514void
1516{
1517 CrossSection::saveIPContext(stream, mode, masterGp);
1518
1519 // saved master gp record;
1520 // and now save slave gp of master:
1521 for ( int i = 1; i <= numberOfLayers; i++ ) {
1522 for ( int k = 0; k < layerIntegrationPoints.at(i); k++ ) {
1523 GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1, k);
1524 StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(i) ) );
1525 mat->saveIPContext(stream, mode, slaveGP);
1526 }
1527 }
1528}
1529
1530
1531void
1533{
1534 CrossSection::restoreIPContext(stream, mode, masterGp);
1535
1536 // and now save slave gp of master:
1537 for ( int i = 1; i <= numberOfLayers; i++ ) {
1538 for ( int k = 0; k < layerIntegrationPoints.at(i); k++ ) {
1539 // creates also slaves if they don't exists
1540 GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1, k);
1541 StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(i) ) );
1542 mat->restoreIPContext(stream, mode, slaveGP);
1543 }
1544 }
1545}
1546
1547
1548MaterialMode
1550//
1551// returns corresponding slave material mode to master mode
1552//
1553{
1554 if ( masterMode == _2dPlate ) {
1555 return _PlateLayer;
1556 } else if ( masterMode == _2dBeam ) {
1557 return _2dBeamLayer;
1558 } else if ( ( masterMode == _PlaneStress ) || ( masterMode == _PlaneStressRot ) ) {
1559 return _PlaneStress;
1560 } else if ( ( masterMode == _3dShell ) || ( masterMode == _3dShellRot ) ) {
1561 return _PlateLayer;
1562 } else if ( masterMode == _3dDegeneratedShell ) {
1563 return _3dDegeneratedShell;
1564 } else if ( masterMode == _3dMat ) {
1565 return _3dMat;
1566 } else {
1567 throw std::runtime_error("unsupported material mode");
1568 }
1569
1570 //return _Unknown;
1571}
1572
1573
1574double
1576{
1577 if ( aProperty == CS_Thickness ) {
1578 return this->computeIntegralThick();
1579 } else if ( aProperty == CS_TopZCoord ) {
1580 this->computeIntegralThick();
1582 } else if ( aProperty == CS_BottomZCoord ) {
1584 } else if ( aProperty == CS_Area ) {
1585 return this->giveArea();
1586 } else if ( aProperty == CS_NumLayers ) {
1587 return this->numberOfLayers;
1588 //} else if (aProperty == CS_Layer ) {
1589 // return this->giveLayer(gp);
1590 }
1591
1592 return CrossSection::give(aProperty, gp);
1593}
1594
1595int
1596LayeredCrossSection::giveLayer(GaussPoint *gp) const //@todo: works only for equal thickness of each layer
1597{
1598 FloatArray lCoords;
1599 int noLayers = this->giveNumberOfLayers();
1600 double dh = 2.0 / noLayers;
1601 lCoords = gp->giveNaturalCoordinates();
1602 double lowXi = -1.0;
1603
1604 for ( int i = 1; i <= noLayers; i++ ) {
1605 if ( lCoords.at(3) > lowXi && lCoords.at(3) < lowXi + dh ) {
1606 return i;
1607 }
1608 lowXi += dh;
1609 }
1610 OOFEM_ERROR("LayeredCrossSection :: giveLayer - the actual integration point can not be associated with a layer in the cross section");
1611}
1612
1613double
1614LayeredCrossSection::give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) const
1615{
1616 if ( aProperty == CS_Thickness ) {
1617 return this->computeIntegralThick();
1618 } else if ( aProperty == CS_TopZCoord ) {
1619 this->computeIntegralThick();
1621 } else if ( aProperty == CS_BottomZCoord ) {
1623 } else if ( aProperty == CS_Area ) {
1624 return this->giveArea();
1625 } else if ( aProperty == CS_NumLayers ) {
1626 return this->numberOfLayers;
1627 }
1628
1629 return CrossSection::give(aProperty, coords, elem, local);
1630}
1631
1632
1633int
1635{
1636 return this->numberOfLayers;
1637}
1638
1639double
1641{
1642 return area;
1643}
1644
1645
1647{
1648 for ( int i = 1; i <= this->numberOfLayers; i++ ) {
1649 if ( !this->domain->giveMaterial(this->giveLayerMaterial(i) )->isCharacteristicMtrxSymmetric(rMode) ) {
1650 return false;
1651 }
1652 }
1653 return true;
1654}
1655
1656
1657void
1659{
1660 // returns an array with the xi-coords corresponding to the boundaries where
1661 // the layers meet (size = number of layers -1)
1662
1663 int numInterfaces = this->giveNumberOfLayers() - 1;
1664 answer.resize(numInterfaces);
1665 double totalThickness = this->computeIntegralThick();
1666 for ( int i = 1; i <= numInterfaces; i++ ) {
1667 double midZ = this->giveLayerMidZ(i);
1668 double interfaceZ = midZ + this->giveLayerThickness(i) * 0.5;
1669 answer.at(i) = interfaceZ * ( 2.0 / totalThickness );
1670 }
1671}
1672
1673void
1674LayeredCrossSection::setupLayeredIntegrationRule(std::vector< std::unique_ptr< IntegrationRule > > &integrationRulesArray, Element *el, int numInPlanePoints)
1675{
1676 // Loop over each layer and set up an integration rule as if each layer was an independent element
1677 // @todo - only works for wedge integration at the moment
1678 int nLayers = this->giveNumberOfLayers();
1679 int numPointsThickness = this->giveNumIntegrationPointsInLayer();
1680
1681 integrationRulesArray.clear();
1682 integrationRulesArray.reserve(nLayers);
1683 for ( int i = 0; i < nLayers; i++ ) {
1684 integrationRulesArray.emplace_back(new LayeredIntegrationRule(i + 1, el) );
1685 integrationRulesArray.back()->SetUpPointsOnWedge(numInPlanePoints, numPointsThickness, _3dMat);
1686 }
1687 this->mapLayerGpCoordsToShellCoords(integrationRulesArray);
1688}
1689
1690
1691void
1692LayeredCrossSection::mapLayerGpCoordsToShellCoords(std::vector< std::unique_ptr< IntegrationRule > > &layerIntegrationRulesArray)
1693/*
1694 * Maps the local xi-coord (z-coord) in each layer [-1,1] to the corresponding
1695 * xi-coord in the cross section coordinate system.
1696 * Also renames the gp numbering from layerwise to global (1,2,1,2 -> 1,2,3,4)
1697 * xi
1698 * -------- 1 -------- 1
1699 | | |
1700 | | |
1701 | -------- -1 => -------- x
1702 | -------- 1 -------- x
1703 | | |
1704 | -------- -1 -------- -1
1705 */
1706{
1707 double scaleFactor = 0.999; // Will be numerically unstable with xfem if the endpoints lie at +-1
1708 double totalThickness = this->computeIntegralThick();
1709 int indx = 1;
1710 for ( int layer = 1; layer <= numberOfLayers; layer++ ) {
1711 for ( GaussPoint *gp: * layerIntegrationRulesArray [ layer - 1 ] ) {
1712 // Map local layer cs to local shell cs
1713 double zMid_i = this->giveLayerMidZ(layer); // global z-coord
1714 double xiMid_i = 1.0 - 2.0 * ( totalThickness - this->midSurfaceZcoordFromBottom - zMid_i ) / totalThickness; // local z-coord
1715 double deltaxi = gp->giveNaturalCoordinates().at(3) * this->giveLayerThickness(layer) / totalThickness; // distance from layer mid
1716 double xinew = xiMid_i + deltaxi * scaleFactor;
1717 FloatArray lcoords = gp->giveNaturalCoordinates();
1718 lcoords.at(3) = xinew;
1719 gp->setNaturalCoordinates(lcoords);
1720 gp->number = indx; // fix gp ordering
1721 indx++;
1722 }
1723 }
1724}
1725
1726
1728 int startIndx, int endIndx, bool dynamic) :
1729 IntegrationRule(n, e, startIndx, endIndx, dynamic) { }
1730
1733
1734
1735int
1736LayeredIntegrationRule::SetUpPointsOnWedge(int nPointsTri, int nPointsThickness, MaterialMode mode)
1737{
1738 // Set up integration rule for a specific layer
1739
1740 int nPoints = nPointsTri * nPointsThickness;
1741 //@todo - is not really a Gauss point but rather a hybrid.
1742 this->gaussPoints.resize(nPoints);
1743
1744 // uses Gauss integration in the plane and Lobatto in the thickness
1745 FloatArray coords_xi1, coords_xi2, coords_xi, weights_tri, weights_thickness;
1746 GaussIntegrationRule::giveTriCoordsAndWeights(nPointsTri, coords_xi1, coords_xi2, weights_tri);
1747 //LobattoIntegrationRule :: giveLineCoordsAndWeights(nPointsThickness, coords_xi, weights_thickness );
1748 GaussIntegrationRule::giveLineCoordsAndWeights(nPointsThickness, coords_xi, weights_thickness);
1749
1750 // Assumes that the integration rules of the layers are the same such that the ordering of the ip's are also
1751 // the same => upperInterfacePoints.at(i) of one layer is paired with lowerInterfacePoints.at(i) of the next.
1752 // This will be used to estimate interlaminar stresses, sice values in the two ip will generally be different
1753 // due to beam/plate/shell theory assumptions.
1754 if ( nPointsThickness != 1 ) { // otherwise there are no points on the interface
1755 this->lowerInterfacePoints.resize(nPointsTri);
1756 this->upperInterfacePoints.resize(nPointsTri);
1757 }
1758 for ( int i = 1, ind = 0; i <= nPointsThickness; i++ ) {
1759 for ( int j = 1; j <= nPointsTri; j++ ) {
1760 this->gaussPoints [ ind ] =
1761 new GaussPoint(this, 1, Vec3( coords_xi1.at(j), coords_xi2.at(j), coords_xi.at(i) ),
1762 weights_tri.at(j) * weights_thickness.at(i), mode);
1763
1764 // store interface points
1765 if ( i == 1 && nPointsThickness > 1 ) { //then lower surface
1766 this->lowerInterfacePoints.at(j) = ind;
1767 } else if ( i == nPointsThickness && nPointsThickness > 1 ) { //then upper surface
1768 this->upperInterfacePoints.at(j) = ind;
1769 }
1770 ind++;
1771 }
1772 }
1773 return this->giveNumberOfIntegrationPoints();
1774}
1775
1776
1777int
1779//
1780// check internal consistency
1781// mainly tests, whether material and crossSection data
1782// are safe for conversion to "Structural" versions
1783//
1784{
1785 int result = 1;
1786 for ( int i = 1; this->giveNumberOfLayers(); i++ ) {
1787 Material *mat = this->giveDomain()->giveMaterial(this->giveLayerMaterial(i) );
1788 if ( !dynamic_cast< StructuralMaterial * >( mat ) ) {
1789 OOFEM_WARNING( "material %s without structural support", mat->giveClassName() );
1790 result = 0;
1791 continue;
1792 }
1793 }
1794 return result;
1795}
1796
1797
1798int
1800{
1802 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
1804 int gpnum = gp->giveNumber();
1805 int gpsperlayer = ngps / this->numberOfLayers;
1806 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
1807 Material *layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
1808 if ( this->layerRots.at(layer) != 0. ) {
1809 FloatArray rotVal; // the requested value in the material c.s.
1811 double rot = this->layerRots.at(layer);
1812 double c = cos(rot * M_PI / 180.);
1813 double s = sin(rot * M_PI / 180.);
1814
1815 int ret = layerMat->giveIPValue(rotVal, gp, type, tStep);
1816 if ( ret == 0 ) {
1817 return 0;
1818 }
1819
1820 // Determine how to rotate it according to the value type
1821 if ( valType == ISVT_TENSOR_S3 ) {
1822 answer = Vec6(
1823 c *c *rotVal.at(1) + 2 * c * s * rotVal.at(6) + s * s * rotVal.at(2),
1824 c *c *rotVal.at(2) - 2 * c * s * rotVal.at(6) + s * s * rotVal.at(1),
1825 rotVal.at(3),
1826 c *rotVal.at(4) - s * rotVal.at(5),
1827 c *rotVal.at(5) + s * rotVal.at(4),
1828 ( c * c - s * s ) * rotVal.at(6) - c * s * ( rotVal.at(1) - rotVal.at(2) )
1829 );
1830 } else if ( valType == ISVT_TENSOR_S3E ) {
1831 answer = Vec6(
1832 c *c *rotVal.at(1) + c * s * rotVal.at(6) + s * s * rotVal.at(2),
1833 c *c *rotVal.at(2) - c * s * rotVal.at(6) + s * s * rotVal.at(1),
1834 rotVal.at(3),
1835 c *rotVal.at(4) - s * rotVal.at(5),
1836 c *rotVal.at(5) + s * rotVal.at(4),
1837 ( c * c - s * s ) * rotVal.at(6) - 2 * c * s * ( rotVal.at(1) - rotVal.at(2) )
1838 );
1839 } else if ( valType == ISVT_VECTOR ) {
1840 answer = Vec3(
1841 c *rotVal.at(1) - s * rotVal.at(2), s *rotVal.at(1) + c * rotVal.at(2), rotVal.at(3)
1842 );
1843 } else if ( valType == ISVT_SCALAR ) {
1844 answer = rotVal;
1845 } else {
1846 return 0;
1847 }
1848 return 1;
1849 } else {
1850 return layerMat->giveIPValue(answer, gp, type, tStep);
1851 }
1852 } else {
1853 //return CrossSection :: giveIPValue(answer, gp, type, tStep);
1854
1856 int layer = gp->giveIntegrationRule()->giveNumber();
1857 return this->giveDomain()->giveMaterial(this->giveLayerMaterial(layer) )->giveIPValue(answer, gp, type, tStep);
1858 }
1859}
1860
1861
1862double
1863LayeredCrossSection::give(int aProperty, GaussPoint *gp) const
1864{
1866 // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints)
1868 int gpnum = gp->giveNumber();
1869 int gpsperlayer = ngps / this->numberOfLayers;
1870 int layer = ( gpnum - 1 ) / gpsperlayer + 1;
1871 Material *layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) );
1872 return layerMat->give(aProperty, gp);
1873 } else {
1874 double average = 0.;
1875 for ( int layer = 1; layer <= numberOfLayers; ++layer ) {
1876 Material *mat = this->giveDomain()->giveMaterial(giveLayerMaterial(layer) );
1877 average += mat->give(aProperty, gp) * giveLayerThickness(layer);
1878 }
1879 return average / this->totalThick;
1880 }
1881}
1882} // end namespace oofem
#define REGISTER_CrossSection(class)
void giveInputRecord(DynamicInputRecord &input) override
Dictionary propertyDictionary
virtual double give(CrossSectionProperty a, GaussPoint *gp) const
virtual void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp)
void initializeFrom(InputRecord &ir) override
virtual void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp)
Material * giveMaterial(int n)
Definition domain.C:284
void setField(int item, InputFieldType id)
virtual MaterialMode giveMaterialMode()
Definition element.h:738
virtual integrationDomain giveIntegrationDomain() const
Definition element.C:1693
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
virtual const char * giveClassName() const =0
double & at(std::size_t i)
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
double at(std::size_t i, std::size_t j) const
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
static void giveTriCoordsAndWeights(int nPoints, FloatArray &coords_xi1, FloatArray &coords_xi2, FloatArray &weights)
static void giveLineCoordsAndWeights(int nPoints, FloatArray &coords_xi, FloatArray &weights)
int giveNumber()
Returns number of receiver.
Definition gausspoint.h:183
bool hasSlaveGaussPoint()
Definition gausspoint.C:109
IntegrationPointStatus * setMaterialStatus(std::unique_ptr< IntegrationPointStatus > ptr, IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:213
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
IntegrationRule * giveIntegrationRule()
Returns corresponding integration rule to receiver.
Definition gausspoint.h:185
Element * giveElement()
Returns corresponding element to receiver.
Definition gausspoint.h:187
int giveNumberOfIntegrationPoints() const
virtual int SetUpPointsOnCubeLayers(int nPoints1, int nPoints2, int nPointsDepth, MaterialMode mode, const FloatArray &layerThickness)
std::vector< GaussPoint * > gaussPoints
Array containing integration points.
virtual int SetUpPointsOn3dDegShellLayers(int nPointsXY, int nPointsZ, MaterialMode mode, const FloatArray &layerThickness)
IntegrationRule(int n, Element *e, int startIndx, int endIndx, bool dynamic)
int setUpIntegrationPoints(integrationDomain intdomain, int nPoints, MaterialMode matMode)
virtual int SetUpPointsOnWedgeLayers(int nPointsTri, int nPointsDepth, MaterialMode mode, const FloatArray &layerThickness)
integrationDomain giveIntegrationDomain() const
void printYourself() override
Prints receiver state on stdout. Useful for debugging.
FloatArray * imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *) override
FloatArrayF< 2 > giveRealStress_Warping(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 3, 3 > give2dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
void giveInputRecord(DynamicInputRecord &input) override
void createMaterialStatus(GaussPoint &iGP) override
FloatArrayF< 9 > giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatArray layerRots
Rotation of the material in each layer.
FloatMatrixF< 5, 5 > giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 6, 6 > give3dDegeneratedShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override
void setupLayeredIntegrationRule(std::vector< std::unique_ptr< IntegrationRule > > &layerIntegrationRulesArray, Element *el, int numInPlanePoints)
FloatMatrixF< 3, 3 > give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatArray layerThicks
Thickness for each layer.
int giveLayer(GaussPoint *gp) const
double giveLayerMidZ(int layer) const
FloatMatrixF< 4, 4 > giveStiffnessMatrix_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 5 > giveGeneralizedStress_Plate(const FloatArrayF< 5 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 8 > giveGeneralizedStress_Shell(const FloatArrayF< 8 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override
FloatArrayF< 3 > giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
double giveLayerThickness(int layer) const
void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override
FloatMatrixF< 4, 4 > giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 3, 3 > giveStiffnessMatrix_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
IntArray layerMaterials
Material of each layer.
FloatMatrixF< 1, 1 > giveStiffnessMatrix_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatArray * imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *) override
FloatArrayF< 3 > giveRealStress_PlaneStress(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 4 > giveRealStress_PlaneStrain(const FloatArrayF< 4 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override
int setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element) override
FloatArrayF< 4 > giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 6 > giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
IntArray interfacerMaterials
Interface (cohesive zone) material for each interface.
static MaterialMode giveCorrespondingSlaveMaterialMode(MaterialMode mode)
FloatArrayF< 1 > giveFirstPKStress_1d(const FloatArrayF< 1 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 4, 4 > giveMembraneRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
void mapLayerGpCoordsToShellCoords(std::vector< std::unique_ptr< IntegrationRule > > &layerIntegrationRulesArray)
double computeIntegralThick() const
Returns the total thickness of all layers.
FloatArrayF< 3 > giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 9, 9 > giveStiffnessMatrix_dPdF_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 6, 6 > give3dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 5, 5 > give2dPlateStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 1 > giveRealStress_1d(const FloatArrayF< 1 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override
void initializeFrom(InputRecord &ir) override
double give(CrossSectionProperty a, GaussPoint *gp) const override
int giveSlaveGPIndex(int ilayer, int igp) const
void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override
void giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override
FloatArrayF< 9 > giveFirstPKStress_3d(const FloatArrayF< 9 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override
bool isCharacteristicMtrxSymmetric(MatResponseMode mode) const override
FloatArrayF< 5 > giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override
int numberOfIntegrationPoints
number of integration points per layer (for 3D elements)
int giveLayerMaterial(int layer) const
FloatArrayF< 6 > giveRealStress_3d(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override
FloatArray layerWidths
Width for each layer.
void giveInterfaceXiCoords(FloatArray &answer) const
int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override
FloatMatrixF< 6, 6 > giveStiffnessMatrix_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 8, 8 > give3dShellStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatMatrixF< 9, 9 > give3dShellRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 6 > giveRealStress_3dDegeneratedShell(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override
Material * giveMaterial(IntegrationPoint *ip) const override
hidden by virtual oofem::Material* TransportCrossSection::giveMaterial() const
GaussPoint * giveSlaveGaussPoint(GaussPoint *gp, int layer, int igp) const
FloatMatrixF< 1, 1 > giveStiffnessMatrix_dPdF_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
FloatArrayF< 4 > giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override
FloatArray layerMidZ
z-coord of the mid plane for each layer
LayeredIntegrationRule(int n, Element *e, int startIndx, int endIndx, bool dynamic=false)
int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) override
virtual std::unique_ptr< MaterialStatus > CreateStatus(GaussPoint *gp) const
Definition material.h:332
virtual void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp)
Definition material.C:182
virtual void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp)
Definition material.C:169
virtual double give(int aProperty, GaussPoint *gp) const
Definition material.C:51
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Definition material.C:138
virtual FloatArray * imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d)
virtual FloatArray * imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d)
void letTempStrainVectorBe(const FloatArray &v)
Assigns tempStrainVector to given vector v.
virtual FloatMatrixF< 6, 6 > give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
virtual FloatMatrixF< 5, 5 > givePlateLayerStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const
virtual FloatMatrixF< 2, 2 > give2dBeamLayerStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define _IFT_LayeredCrossSection_midsurf
#define _IFT_LayeredCrossSection_thicks
#define _IFT_LayeredCrossSection_shearcoeff_xz
#define _IFT_LayeredCrossSection_layermaterials
#define _IFT_LayeredCrossSection_nintegrationpoints
#define _IFT_LayeredCrossSection_interfacematerials
#define _IFT_LayeredCrossSection_layerRotations
#define _IFT_LayeredCrossSection_widths
#define _IFT_LayeredCrossSection_nlayerintegrationpoints
#define _IFT_LayeredCrossSection_nlayers
#define M_PI
Definition mathfem.h:52
long ContextMode
Definition contextmode.h:43
CrossSectionProperty
List of properties possibly stored in a cross section.
@ CS_DrillingType
Type of artificially added drilling stiffness for drilling DOFs.
@ CS_DrillingStiffness
Penalty stiffness for drilling DOFs.
@ CS_BottomZCoord
Bottom z coordinate.
@ CS_RelDrillingStiffness
Relative penalty stiffness for drilling DOFs.
@ CS_Area
Area.
@ CS_Thickness
Thickness.
@ CS_NumLayers
Number of layers that makes up the cross section.
@ CS_TopZCoord
Top z coordinate.
double cbrt(double x)
Returns the cubic root of x.
Definition mathfem.h:122
FloatMatrixF< N, P > Tdot(const FloatMatrixF< M, N > &a, const FloatMatrixF< M, P > &b)
Computes .
GaussPoint IntegrationPoint
Definition gausspoint.h:272
FloatArrayF< N > assemble(const FloatArrayF< M > &x, int const (&c)[M])
Assemble components into zero matrix.
static FloatArray Vec6(const double &a, const double &b, const double &c, const double &d, const double &e, const double &f)
Definition floatarray.h:610
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
InternalStateValueType
Determines the type of internal variable.
@ ISVT_TENSOR_S3E
symmetric 3x3 tensor, packed with off diagonal components multiplied by 2 (engineering strain vector,...
@ ISVT_SCALAR
Scalar.
@ ISVT_TENSOR_S3
Symmetric 3x3 tensor.
@ ISVT_VECTOR
Vector.
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< M, M > unrotate(FloatMatrixF< N, N > &a, const FloatMatrixF< M, N > &r)
Computes .
@ LayeredCrossSectionInterfaceType
InternalStateValueType giveInternalStateValueType(InternalStateType type)
Definition cltypes.C:75
const int nLayers
static FloatArray Vec3(const double &a, const double &b, const double &c)
Definition floatarray.h:607
#define _IFT_SimpleCrossSection_drillType
Type of artificially added stiffnes for drilling DOFs.
#define _IFT_SimpleCrossSection_relDrillStiffness
Relative penalty term for drilling stiffness.
#define _IFT_SimpleCrossSection_drillStiffness
Penalty term for drilling stiffness.

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