OOFEM 3.0
Loading...
Searching...
No Matches
quad1mindlinshell3d.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 "node.h"
40#include "material.h"
41#include "crosssection.h"
42#include "gausspoint.h"
44#include "floatmatrix.h"
45#include "floatarray.h"
46#include "floatmatrixf.h"
47#include "floatarrayf.h"
48#include "intarray.h"
49#include "load.h"
50#include "mathfem.h"
51#include "fei2dquadlin.h"
52#include "classfactory.h"
53#include "parametermanager.h"
54#include "paramkey.h"
55
56namespace oofem {
58
60IntArray Quad1MindlinShell3D::shellOrdering = { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23 };
61IntArray Quad1MindlinShell3D::drillOrdering = { 6, 12, 18, 24 };
63
64
74
75
81
82
88
89
90void
92// Sets up the array containing the four Gauss points of the receiver.
93{
94 if ( integrationRulesArray.size() == 0 ) {
95 integrationRulesArray.resize(1);
96 integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 5);
98 }
100 this->computeLCS();
101}
102
103
104void
105Quad1MindlinShell3D::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode)
106{
107 // Only gravity load
108 FloatArray forceX, forceY, forceZ, glob_gravity, gravity, n;
109
110 if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) {
111 OOFEM_ERROR("unknown load type");
112 }
113
114 // note: force is assumed to be in global coordinate system.
115 forLoad->computeComponentArrayAt(glob_gravity, tStep, mode);
116 // Transform the load into the local c.s.
117 gravity.beProductOf(this->lcsMatrix, glob_gravity);
118
119 if ( gravity.giveSize() ) {
120 for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) {
121 this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() );
122 double dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp);
123 double density = this->giveStructuralCrossSection()->give('d', gp);
124
125 forceX.add(density * gravity.at(1) * dV, n);
126 forceY.add(density * gravity.at(2) * dV, n);
127 forceZ.add(density * gravity.at(3) * dV, n);
128 }
129
130 answer.resize(24);
131 answer.zero();
132
133 answer.at(1) = forceX.at(1);
134 answer.at(2) = forceY.at(1);
135 answer.at(3) = forceZ.at(1);
136
137 answer.at(7) = forceX.at(2);
138 answer.at(8) = forceY.at(2);
139 answer.at(9) = forceZ.at(2);
140
141 answer.at(13) = forceX.at(3);
142 answer.at(14) = forceY.at(3);
143 answer.at(15) = forceZ.at(3);
144
145 answer.at(19) = forceX.at(4);
146 answer.at(20) = forceY.at(4);
147 answer.at(21) = forceZ.at(4);
148 } else {
149 answer.clear();
150 }
151}
152
153#if 0
154void
155Quad1MindlinShell3D::computeSurfaceLoadVectorAt(FloatArray &answer, Load *load,
156 int iSurf, TimeStep *tStep, ValueModeType mode)
157{
158 BoundaryLoad *surfLoad = static_cast< BoundaryLoad * >( load );
159 if ( dynamic_cast< ConstantPressureLoad * >( surfLoad ) ) { // Just checking the type of b.c.
160 // EXPERIMENTAL CODE:
161 FloatArray n, gcoords, pressure;
162
163 answer.resize(24);
164 answer.zero();
165
166 for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) {
167 double dV = this->computeVolumeAround(gp);
168 this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() );
169 this->interp.local2global(gcoords, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
170 surfLoad->computeValueAt(pressure, tStep, gcoords, mode);
171
172 answer.at(3) += n.at(1) * pressure.at(1) * dV;
173 answer.at(9) += n.at(2) * pressure.at(1) * dV;
174 answer.at(15) += n.at(3) * pressure.at(1) * dV;
175 answer.at(21) += n.at(4) * pressure.at(1) * dV;
176 }
177 // Second surface is the outside;
178 if ( iSurf == 2 ) {
179 answer.negated();
180 }
181 } else {
182 OOFEM_ERROR("only supports constant pressure boundary load.");
183 }
184}
185#endif
186
187void
189{
190 const auto &localCoords = gp->giveNaturalCoordinates();
191
192 auto tmp = this->interp.evaldNdx( localCoords, FEIVertexListGeometryWrapper(lnodes, this->giveGeometryType()) );
193 auto dn = tmp.second;
194 auto n = this->interp.evalN(localCoords);
195
196 // enforce one-point reduced integration if requested
199 if ( this->reducedIntegrationFlag ) {
200 FloatArray lc(2); // set to element center coordinates
201 auto tmp = this->interp.evaldNdx( lc, FEIVertexListGeometryWrapper(lnodes, this->giveGeometryType()) );
202 dns = tmp.second;
203 ns = this->interp.evalN(lc);
204 } else {
205 dns = dn;
206 ns = n;
207 }
208
209 answer.resize(8, 4 * 5);
210 answer.zero();
211
212 // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.)
213 for ( int i = 0; i < 4; ++i ) {
215 // Part related to the membrane (columns represent coefficients for D_u, D_v)
216 answer(0, 0 + i * 5) = dn(0, i); // eps_x = du/dx
217 answer(1, 1 + i * 5) = dn(1, i); // eps_y = dv/dy
218 answer(2, 0 + i * 5) = dn(1, i); // gamma_xy = du/dy+dv/dx
219 answer(2, 1 + i * 5) = dn(0, i);
220
221 // Part related to the plate (columns represent the dofs D_w, R_u, R_v)
223 answer(3 + 0, 2 + 2 + i * 5) = dn(0, i); // kappa_x = d(fi_y)/dx
224 answer(3 + 1, 2 + 1 + i * 5) = -dn(1, i); // kappa_y = -d(fi_x)/dy
225 answer(3 + 2, 2 + 2 + i * 5) = dn(1, i); // kappa_xy=d(fi_y)/dy-d(fi_x)/dx
226 answer(3 + 2, 2 + 1 + i * 5) = -dn(0, i);
227
228 // shear strains
229 answer(3 + 3, 2 + 0 + i * 5) = dns(0, i); // gamma_xz = fi_y+dw/dx
230 answer(3 + 3, 2 + 2 + i * 5) = ns [ i ];
231 answer(3 + 4, 2 + 0 + i * 5) = dns(1, i); // gamma_yz = -fi_x+dw/dy
232 answer(3 + 4, 2 + 1 + i * 5) = -ns [ i ];
233 }
234
235
236#if 0
237 // Experimental MITC4 support.
238 // Based on "Short communication A four-node plate bending element based on mindling/reissner plate theory and a mixed interpolation"
239 // KJ Bathe, E Dvorkin
240
241 double x1, x2, x3, x4;
242 double y1, y2, y3, y4;
243 double Ax, Bx, Cx, Ay, By, Cy;
244
245 double r = localCoords [ 0 ];
246 double s = localCoords [ 1 ];
247
248 x1 = lnodes [ 0 ] [ 0 ];
249 x2 = lnodes [ 1 ] [ 0 ];
250 x3 = lnodes [ 2 ] [ 0 ];
251 x4 = lnodes [ 3 ] [ 0 ];
252
253 y1 = lnodes [ 0 ] [ 1 ];
254 y2 = lnodes [ 1 ] [ 1 ];
255 y3 = lnodes [ 2 ] [ 1 ];
256 y4 = lnodes [ 3 ] [ 1 ];
257
258 Ax = x1 - x2 - x3 + x4;
259 Bx = x1 - x2 + x3 - x4;
260 Cx = x1 + x2 - x3 - x4;
261
262 Ay = y1 - y2 - y3 + y4;
263 By = y1 - y2 + y3 - y4;
264 Cy = y1 + y2 - y3 - y4;
265
266 FloatMatrix jac;
267 this->interp.giveJacobianMatrixAt( jac, localCoords, FEIVertexListGeometryWrapper(lnodes) );
268 double detJ = jac.giveDeterminant();
269
270 double rz = sqrt(sqr(Cx + r * Bx) + sqr(Cy + r * By) ) / ( 16 * detJ );
271 double sz = sqrt(sqr(Ax + s * Bx) + sqr(Ay + s * By) ) / ( 16 * detJ );
272
273 // TODO: Not sure about this part (the reference is not explicit about these angles. / Mikael
274 // Not sure about the transpose either.
275 OOFEM_WARNING("The MITC4 implementation isn't verified yet. Highly experimental");
276 FloatArray dxdr = { jac(0, 0), jac(0, 1) };
277 dxdr.normalize();
278 FloatArray dxds = { jac(1, 0), jac(1, 1) };
279 dxds.normalize();
280
281 double c_b = dxdr(0); //cos(beta);
282 double s_b = dxdr(1); //sin(beta);
283 double c_a = dxds(0); //cos(alpha);
284 double s_a = dxds(1); //sin(alpha);
285
286 // gamma_xz = "fi_y+dw/dx" in standard formulation
287 answer(6, 2 + 5 * 0) = rz * s_b * ( ( 1 + s ) ) - sz * s_a * ( ( 1 + r ) );
288 answer(6, 2 + 5 * 1) = rz * s_b * ( -( 1 + s ) ) - sz * s_a * ( ( 1 - r ) );
289 answer(6, 2 + 5 * 2) = rz * s_b * ( -( 1 - s ) ) - sz * s_a * ( -( 1 - r ) );
290 answer(6, 2 + 5 * 3) = rz * s_b * ( ( 1 - s ) ) - sz * s_a * ( -( 1 + r ) );
291
292 answer(6, 3 + 5 * 0) = rz * s_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) - sz * s_a * ( y4 - y1 ) * 0.5 * ( 1 + r ); // tx1
293 answer(6, 4 + 5 * 0) = rz * s_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) - sz * s_a * ( x1 - x4 ) * 0.5 * ( 1 + r ); // ty1
294
295 answer(6, 3 + 5 * 1) = rz * s_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) - sz * s_a * ( y3 - x2 ) * 0.5 * ( 1 + r ); // tx2
296 answer(6, 4 + 5 * 1) = rz * s_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) - sz * s_a * ( x2 - x3 ) * 0.5 * ( 1 + r ); // ty2
297
298 answer(6, 3 + 5 * 2) = rz * s_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) - sz * s_a * ( y3 - y2 ) * 0.5 * ( 1 - r ); // tx3
299 answer(6, 4 + 5 * 2) = rz * s_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) - sz * s_a * ( x2 - x3 ) * 0.5 * ( 1 - r ); // ty3
300
301 answer(6, 3 + 5 * 3) = rz * s_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) - sz * s_a * ( y4 - y1 ) * 0.5 * ( 1 - r ); // tx4
302 answer(6, 4 + 5 * 3) = rz * s_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) - sz * s_a * ( x1 - x4 ) * 0.5 * ( 1 - r ); // ty4
303
304 // gamma_yz = -fi_x+dw/dy in standard formulation
305 answer(7, 2 + 5 * 0) = -rz * c_b * ( ( 1 + s ) ) + sz * c_a * ( ( 1 + r ) );
306 answer(7, 2 + 5 * 1) = -rz * c_b * ( -( 1 + s ) ) + sz * c_a * ( ( 1 - r ) );
307 answer(7, 2 + 5 * 2) = -rz * c_b * ( -( 1 - s ) ) + sz * c_a * ( -( 1 - r ) );
308 answer(7, 2 + 5 * 3) = -rz * c_b * ( ( 1 - s ) ) + sz * c_a * ( -( 1 + r ) );
309
310 answer(7, 3 + 5 * 0) = -rz * c_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) + sz * c_a * ( y4 - y1 ) * 0.5 * ( 1 + r ); // tx1
311 answer(7, 4 + 5 * 0) = -rz * c_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) + sz * c_a * ( x1 - x4 ) * 0.5 * ( 1 + r ); // ty1
312
313 answer(7, 3 + 5 * 1) = -rz * c_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) + sz * c_a * ( y3 - x2 ) * 0.5 * ( 1 + r ); // tx2
314 answer(7, 4 + 5 * 1) = -rz * c_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) + sz * c_a * ( x2 - x3 ) * 0.5 * ( 1 + r ); // ty2
315
316 answer(7, 3 + 5 * 2) = -rz * c_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) + sz * c_a * ( y3 - y2 ) * 0.5 * ( 1 - r ); // tx3
317 answer(7, 4 + 5 * 2) = -rz * c_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) + sz * c_a * ( x2 - x3 ) * 0.5 * ( 1 - r ); // ty3
318
319 answer(7, 3 + 5 * 3) = -rz * c_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) + sz * c_a * ( y4 - y1 ) * 0.5 * ( 1 - r ); // tx4
320 answer(7, 4 + 5 * 3) = -rz * c_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) + sz * c_a * ( x1 - x4 ) * 0.5 * ( 1 - r ); // ty4
321#endif
322}
323
324
325void
327{
328 answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Shell(strain, gp, tStep);
329}
330
331
332void
334{
335 answer = this->giveStructuralCrossSection()->give3dShellStiffMtrx(rMode, gp, tStep);
336}
337
338
339void
341{
342 FloatArray tmp;
343 this->computeVectorOf(mode, tStep, tmp);
344 shell.beSubArrayOf(tmp, this->shellOrdering);
345 drill.beSubArrayOf(tmp, this->drillOrdering);
346}
347
348
349void
351{
352 FloatArray shellUnknowns, tmp;
353 FloatMatrix b;
354 /* Here we do compute only the "traditional" part of shell strain vector, the quasi-strain related to rotations is not computed */
355 this->computeVectorOfUnknowns(VM_Total, tStep, shellUnknowns, tmp);
356
357 this->computeBmatrixAt(gp, b);
358 answer.beProductOf(b, shellUnknowns);
359}
360
361
362void
364{
365 // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8)
366 // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components.
367 FloatMatrix b;
368 FloatArray n, strain, stress;
369 FloatArray shellUnknowns, drillUnknowns;
370 bool drillCoeffFlag = false;
371
372 // Split this for practical reasons into normal shell dofs and drilling dofs
373 this->computeVectorOfUnknowns(VM_Total, tStep, shellUnknowns, drillUnknowns);
374
375 FloatArray shellForces, drillMoment;
377
378 for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) {
379 this->computeBmatrixAt(gp, b);
380 double dV = this->computeVolumeAround(gp);
381 double drillCoeff = cs->give(CS_DrillingStiffness, gp);
382
383 if ( useUpdatedGpRecord ) {
384 stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector();
385 } else {
386 strain.beProductOf(b, shellUnknowns);
387 stress = cs->giveGeneralizedStress_Shell(strain, gp, tStep);
388 }
389 shellForces.plusProduct(b, stress, dV);
390
391 // Drilling stiffness is here for improved numerical properties
392 if ( drillCoeff > 0. ) {
393 this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() );
394 for ( int j = 0; j < 4; j++ ) {
395 n(j) -= 0.25;
396 }
397 double dtheta = n.dotProduct(drillUnknowns);
398 drillMoment.add(drillCoeff * dV * dtheta, n);
399 drillCoeffFlag = true;
400 }
401 }
402
403 answer.resize(24);
404 answer.zero();
405 answer.assemble(shellForces, this->shellOrdering);
406
407 if ( drillCoeffFlag ) {
408 answer.assemble(drillMoment, this->drillOrdering);
409 }
410}
411
412
413void
415{
416 // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8)
417 // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components.
418 FloatMatrix d, b, db;
419 FloatArray n;
420 bool drillCoeffFlag = false;
421
422 FloatMatrix shellStiffness, drillStiffness;
423
424 for ( auto &gp: * integrationRulesArray [ 0 ] ) {
425 this->computeBmatrixAt(gp, b);
426 double dV = this->computeVolumeAround(gp);
427 double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp);
428
429 this->computeConstitutiveMatrixAt(d, rMode, gp, tStep);
430
431 db.beProductOf(d, b);
432 shellStiffness.plusProductSymmUpper(b, db, dV);
433
434 // Drilling stiffness is here for improved numerical properties
435 if ( drillCoeff > 0. ) {
436 this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() );
437 for ( int j = 0; j < 4; j++ ) {
438 n(j) -= 0.25;
439 }
440 drillStiffness.plusDyadSymmUpper(n, drillCoeff * dV);
441 drillCoeffFlag = true;
442 }
443 }
444 shellStiffness.symmetrized();
445
446 answer.resize(24, 24);
447 answer.zero();
448 answer.assemble(shellStiffness, this->shellOrdering);
449
450 if ( drillCoeffFlag ) {
451 drillStiffness.symmetrized();
452 answer.assemble(drillStiffness, this->drillOrdering);
453 }
454}
455
456
457void
464
465
466void
468{
469 answer = { D_u, D_v, D_w, R_u, R_v, R_w };
470}
471
472
473void
475{
478
479 auto n = cross(u, v);
480 answer = n / norm(n);
481}
482
483
484double
486{
487 return this->giveLengthInDir(normalToCrackPlane);
488}
489
490
491double
493{
494 double weight = gp->giveWeight();
495 double detJ = fabs(this->interp.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes, this->giveGeometryType()) ) );
496 return detJ * weight;
497}
498
499
500void
502// Returns the lumped mass matrix of the receiver.
503{
504 double mass = 0.;
505
506 for ( auto &gp: * integrationRulesArray [ 0 ] ) {
507 mass += this->computeVolumeAround(gp) * this->giveStructuralCrossSection()->give('d', gp);
508 }
509
510 answer.resize(24, 24);
511 answer.zero();
512 for ( int i = 0; i < 4; i++ ) {
513 answer(i * 6 + 0, i * 6 + 0) = mass * 0.25;
514 answer(i * 6 + 1, i * 6 + 1) = mass * 0.25;
515 answer(i * 6 + 2, i * 6 + 2) = mass * 0.25;
516 }
517}
518
519
520int
522{
523 FloatArray s;
524 answer.resize(6);
525 if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) {
526 if ( type == IST_ShellForceTensor ) {
527 s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector();
528 } else {
529 s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector();
530 }
531 answer.at(1) = s.at(1); // nx
532 answer.at(2) = s.at(2); // ny
533 answer.at(3) = 0.0; // nz
534 answer.at(4) = s.at(8); // vyz
535 answer.at(5) = s.at(7); // vxy
536 answer.at(6) = s.at(3); // vxy
537 return 1;
538 } else if ( type == IST_ShellMomentTensor || type == IST_CurvatureTensor ) {
539 if ( type == IST_ShellMomentTensor ) {
540 s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector();
541 } else {
542 s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector();
543 }
544 answer.at(1) = s.at(4); // mx
545 answer.at(2) = s.at(5); // my
546 answer.at(3) = 0.0; // mz
547 answer.at(4) = 0.0; // mzy
548 answer.at(5) = 0.0; // mzx
549 answer.at(6) = s.at(6); // mxy
550 return 1;
551 } else {
552 return StructuralElement::giveIPValue(answer, gp, type, tStep);
553 }
554}
555
556
557void
559{
560 if ( iEdge == 1 ) { // edge between nodes 1 2
561 answer = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
562 } else if ( iEdge == 2 ) { // edge between nodes 2 3
563 answer = { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
564 } else if ( iEdge == 3 ) { // edge between nodes 3 4
565 answer = { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
566 } else if ( iEdge == 4 ) { // edge between nodes 4 1
567 answer = { 19, 20, 21, 22, 23, 24, 1, 2, 3, 4, 5, 6 };
568 } else {
569 OOFEM_ERROR("wrong edge number");
570 }
571}
572
573
574double
576{
577 double detJ = this->interp.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes, this->giveGeometryType()) );
578 return detJ * gp->giveWeight();
579}
580
581/*
582 * void
583 * Quad1MindlinShell3D :: computeEdgeIpGlobalCoords(FloatArray &answer, GaussPoint *gp, int iEdge)
584 * {
585 * FloatArray local;
586 * this->interp.edgeLocal2global( local, iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) );
587 * local.resize(3);
588 * local.at(3) = 0.;
589 * answer.beProductOf(this->lcsMatrix, local);
590 * }
591 */
592
593int
595{
596 const auto &edgeNodes = this->interp.computeLocalEdgeMapping(iEdge);
597
598 auto nodeA = this->giveNode(edgeNodes.at(1) );
599 auto nodeB = this->giveNode(edgeNodes.at(2) );
600
601 double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1);
602 double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2);
603 double length = sqrt(dx * dx + dy * dy);
604
606 answer.resize(3, 3);
607 answer.zero();
608 answer.at(1, 1) = 1.0;
609 answer.at(2, 2) = dx / length;
610 answer.at(2, 3) = -dy / length;
611 answer.at(3, 2) = -answer.at(2, 3);
612 answer.at(3, 3) = answer.at(2, 2);
613
614 return 1;
615}
616
617
618void
620{
621 // compute e1' = [N2-N1] and help = [N4-N1]
622 //auto e1 = normalize(node(2).coord - node(1).coord);
623 //auto help = node(4).coord - node(1).coord;
624 auto e1 = normalize( FloatArrayF< 3 >( this->giveNode(2)->giveCoordinates() ) - FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() ) );
625 auto help = FloatArrayF< 3 >( this->giveNode(4)->giveCoordinates() ) - FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() );
626 auto e3 = normalize( cross(e1, help) );
627 auto e2 = cross(e3, e1);
628
629 lcsMatrix.resize(3, 3); // Note! G -> L transformation matrix
630 for ( int i = 1; i <= 3; i++ ) {
631 this->lcsMatrix.at(1, i) = e1.at(i);
632 this->lcsMatrix.at(2, i) = e2.at(i);
633 this->lcsMatrix.at(3, i) = e3.at(i);
634 }
635
636 for ( int i = 1; i <= 4; i++ ) {
637 this->lnodes [ i - 1 ].beProductOf(this->lcsMatrix, this->giveNode(i)->giveCoordinates() );
638 }
639}
640
641
642bool
644{
645 answer.resize(24, 24);
646 answer.zero();
647
648 for ( int i = 0; i < 4; i++ ) { // Loops over nodes
649 // In each node, transform global c.s. {D_u, D_v, D_w, R_u, R_v, R_w} into local c.s.
650 answer.setSubMatrix(this->lcsMatrix, 1 + i * 6, 1 + i * 6); // Displacements
651 answer.setSubMatrix(this->lcsMatrix, 1 + i * 6 + 3, 1 + i * 6 + 3); // Rotations
652 }
653
654 return true;
655}
656
657Interface *
659{
660 if ( interface == ZZNodalRecoveryModelInterfaceType ) {
661 return static_cast< ZZNodalRecoveryModelInterface * >( this );
662 } else if ( interface == SPRNodalRecoveryModelInterfaceType ) {
663 return static_cast< SPRNodalRecoveryModelInterface * >( this );
664 }
665
666 return nullptr;
667}
668
669
670
671void
673{
674 pap.resize(4);
675 for ( int i = 1; i < 5; i++ ) {
676 pap.at(i) = this->giveNode(i)->giveNumber();
677 }
678}
679
680void
682{
683 int found = 0;
684 answer.resize(1);
685
686 for ( int i = 1; i < 5; i++ ) {
687 if ( pap == this->giveNode(i)->giveNumber() ) {
688 found = 1;
689 }
690 }
691
692 if ( found ) {
693 answer.at(1) = pap;
694 } else {
695 OOFEM_ERROR("node unknown");
696 }
697}
698} // end namespace oofem
double length(const Vector &a)
Definition CSG.h:88
#define REGISTER_Element(class)
void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override
virtual double give(CrossSectionProperty a, GaussPoint *gp) const
virtual int setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element)
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
ParameterManager elementPPM
Definition domain.h:133
Node * giveNode(int i) const
Definition element.h:629
virtual double giveLengthInDir(const FloatArray &normalToCrackPlane)
Definition element.C:1162
static ParamKey IPK_Element_activityTimeFunction
Definition element.h:206
void initializeFrom(InputRecord &ir, int priority) override
Definition element.C:687
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
int numberOfGaussPoints
Definition element.h:175
CrossSection * giveCrossSection()
Definition element.C:534
void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
static FloatArrayF< 4 > evalN(const FloatArrayF< 2 > &lcoords)
Domain * giveDomain() const
Definition femcmpnn.h:97
int number
Component number.
Definition femcmpnn.h:77
int giveNumber() const
Definition femcmpnn.h:104
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void plusProduct(const FloatMatrix &b, const FloatArray &s, double dV)
Definition floatarray.C:288
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void add(const FloatArray &src)
Definition floatarray.C:218
void beSubArrayOf(const FloatArray &src, const IntArray &indx)
Definition floatarray.C:440
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void setSubMatrix(const FloatMatrix &src, int sr, int sc)
void zero()
Zeroes all coefficient of receiver.
double giveDeterminant() const
void plusDyadSymmUpper(const FloatArray &a, double dV)
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
double giveWeight()
Returns integration weight of receiver.
Definition gausspoint.h:180
virtual bcGeomType giveBCGeoType() const
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
virtual void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
Definition load.C:84
Quad1MindlinShell3D(int n, Domain *d)
void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override
double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override
void computeVectorOfUnknowns(ValueModeType mode, TimeStep *tStep, FloatArray &shellUnknowns, FloatArray &drillUnknowns)
void initializeFrom(InputRecord &ir, int priority) override
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override
int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override
void giveDofManDofIDMask(int inode, IntArray &) const override
Element_Geometry_Type giveGeometryType() const override
void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override
void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord=0) override
void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override
double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override
static IntArray drillOrdering
Ordering for the drilling dofs (the out-of-plane rotations).
void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override
void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override
bool computeGtoLRotationMatrix(FloatMatrix &answer) override
static IntArray shellOrdering
Ordering for the normal shell stiffness (everything but the out-of-plane rotations).
Interface * giveInterface(InterfaceType it) override
FEInterpolation * giveInterpolation() const override
double computeVolumeAround(GaussPoint *gp) override
void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override
static ParamKey IPK_Quad1MindlinShell3D_reducedIntegration
void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override
void giveEdgeDofMapping(IntArray &answer, int iEdge) const override
void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int=1, int=ALL_STRAINS) override
std::vector< FloatArray > lnodes
Cached nodal coordinates in local c.s.,.
bool reducedIntegrationFlag
Flag controlling reduced (one - point) integration for shear.
FloatMatrix lcsMatrix
Cached coordinates in local c.s.,.
void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override
virtual FloatMatrixF< 8, 8 > give3dShellStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const =0
virtual FloatArrayF< 8 > giveGeneralizedStress_Shell(const FloatArrayF< 8 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const =0
StructuralCrossSection * giveStructuralCrossSection()
Helper function which returns the structural cross-section for the element.
StructuralElement(int n, Domain *d)
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
const FloatArray & giveStrainVector() const
Returns the const pointer to receiver's strain vector.
const FloatArray & giveStressVector() const
Returns the const pointer to receiver's stress vector.
ZZNodalRecoveryModelInterface(Element *element)
Constructor.
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
double norm(const FloatArray &x)
@ CS_DrillingStiffness
Penalty stiffness for drilling DOFs.
@ CS_Thickness
Thickness.
@ BodyLoadBGT
Distributed body load.
Definition bcgeomtype.h:43
double sqr(double x)
Definition mathfem.h:125
FloatArrayF< 3 > cross(const FloatArrayF< 3 > &x, const FloatArrayF< 3 > &y)
Computes $ x \cross y $.
@ ForceLoadBVT
Definition bcvaltype.h:43
@ SPRNodalRecoveryModelInterfaceType
@ ZZNodalRecoveryModelInterfaceType
FloatArrayF< N > normalize(const FloatArrayF< N > &x)
Normalizes vector (L2 norm).
#define PM_UPDATE_PARAMETER(_val, _pm, _ir, _componentnum, _paramkey, _prio)

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