OOFEM 3.0
Loading...
Searching...
No Matches
element.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
35#include "element.h"
36#include "crosssection.h"
37#include "integrationrule.h"
38#include "errorestimator.h"
39#include "intarray.h"
40#include "floatarray.h"
41#include "floatmatrix.h"
42#include "primaryfield.h"
43#include "verbose.h"
45#include "error.h"
46#include "classfactory.h"
47#include "datastream.h"
49#include "contextioerr.h"
50#include "mathfem.h"
51#include "feinterpol.h"
52#include "feinterpol1d.h"
53#include "feinterpol2d.h"
54#include "feinterpol3d.h"
55#include "function.h"
56#include "dofmanager.h"
57#include "node.h"
58#include "gausspoint.h"
60#include "dynamicinputrecord.h"
61#include "matstatmapperint.h"
62#include "parametermanager.h"
63#include "cltypes.h"
64#include "paramkey.h"
65
66#ifdef __OOFEG
67 #include "oofeggraphiccontext.h"
68#endif
69
70#include <cstdio>
71#include <cassert>
72
73namespace oofem {
74
85
86Element :: Element(int n, Domain *aDomain) :
87 FEMComponent(n, aDomain), dofManArray(), crossSection(0),
90{
91 material = 0;
94}
95
96
97Element :: ~Element()
98{
99}
100
101
102void
103Element :: computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
104{
105 IntArray dofIDMask;
106 FloatMatrix G2L;
107 FloatArray vec;
108
109 answer.resize( this->computeNumberOfGlobalDofs() );
110 int offset=0;
111 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
112 this->giveDofManDofIDMask(i, dofIDMask);
113 this->giveDofManager(i)->giveUnknownVector(vec, dofIDMask, u, tStep, true);
114 answer.copySubVector(vec,offset+1);
115 offset+=vec.size();
116 }
117
118 for ( int i = 1; i <= giveNumberOfInternalDofManagers(); i++ ) {
119 this->giveInternalDofManDofIDMask(i, dofIDMask);
120 this->giveInternalDofManager(i)->giveUnknownVector(vec, dofIDMask, u, tStep, true);
121 answer.copySubVector(vec,offset+1);
122 offset+=vec.size();
123 }
124 assert(offset==(int)answer.size());
125
126 if ( this->computeGtoLRotationMatrix(G2L) ) {
127 answer.rotatedWith(G2L, 'n');
128 }
129}
130
131
132void
133Element :: computeVectorOf(const IntArray &dofIDMask, ValueModeType u, TimeStep *tStep, FloatArray &answer, bool padding)
134{
135 FloatMatrix G2L;
136 FloatArray vec;
137
138 answer.resize( dofIDMask.giveSize() * ( this->giveNumberOfDofManagers() + this->giveNumberOfInternalDofManagers() ) );
139 int offset=0;
140
141 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
142 this->giveDofManager(i)->giveUnknownVector(vec, dofIDMask, u, tStep, padding);
143 answer.copySubVector(vec,offset+1);
144 offset+=vec.size();
145 }
146
147 for ( int i = 1; i <= giveNumberOfInternalDofManagers(); i++ ) {
148 this->giveInternalDofManager(i)->giveUnknownVector(vec, dofIDMask, u, tStep, padding);
149 answer.copySubVector(vec,offset+1);
150 offset+=vec.size();
151 }
152 assert(offset==(int)answer.size());
153
155 if ( this->computeGtoLRotationMatrix(G2L) ) {
156 OOFEM_WARNING("The transformation matrix from global -> element local c.s. is not fully supported for this function (yet)");
157 answer.rotatedWith(G2L, 'n');
158 }
159}
160
161
162void
163Element :: computeBoundaryVectorOf(const IntArray &bNodes, const IntArray &dofIDMask, ValueModeType u, TimeStep *tStep, FloatArray &answer, bool padding)
164{
165 FloatMatrix G2L;
166 FloatArray vec;
167
168 answer.resize( dofIDMask.giveSize() * bNodes.giveSize() );
169 int offset=0;
170
171 for ( int bNode: bNodes ) {
172 this->giveDofManager( bNode )->giveUnknownVector(vec, dofIDMask, u, tStep, padding);
173 answer.copySubVector(vec,offset+1);
174 offset+=vec.size();
175 }
176 assert(offset==(int)answer.size());
177
178 if ( this->computeGtoLRotationMatrix(G2L) ) {
179 OOFEM_ERROR("Local coordinate system is not implemented yet");
180 }
181}
182
183
184void
185Element :: computeVectorOf(PrimaryField &field, const IntArray &dofIDMask, ValueModeType u, TimeStep *tStep, FloatArray &answer, bool padding)
186{
187 FloatMatrix G2L;
188 FloatArray vec;
189 answer.resize( this->computeNumberOfGlobalDofs() );
190 int offset=0;
191
192 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
193 this->giveDofManager(i)->giveUnknownVector(vec, dofIDMask, field, u, tStep);
194 answer.copySubVector(vec,offset+1);
195 offset+=vec.size();
196 }
197
198 for ( int i = 1; i <= giveNumberOfInternalDofManagers(); i++ ) {
199 this->giveInternalDofManager(i)->giveUnknownVector(vec, dofIDMask, field, u, tStep);
200 answer.copySubVector(vec,offset+1);
201 offset+=vec.size();
202 }
203 assert(offset==(int)answer.size());
204
205 if ( this->computeGtoLRotationMatrix(G2L) ) {
206 answer.rotatedWith(G2L, 'n');
207 }
208}
209
210
211void
212Element :: computeVectorOfPrescribed(ValueModeType u, TimeStep *tStep, FloatArray &answer)
213{
214 IntArray dofIDMask;
215 FloatMatrix G2L;
216 FloatArray vec;
217
218 answer.resize( this->computeNumberOfGlobalDofs() );
219 int offset=0;
220
221 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
222 this->giveDofManDofIDMask(i, dofIDMask);
223 this->giveDofManager(i)->givePrescribedUnknownVector(vec, dofIDMask, u, tStep);
224 answer.copySubVector(vec,offset+1);
225 offset+=vec.size();
226 }
227
228 for ( int i = 1; i <= giveNumberOfInternalDofManagers(); i++ ) {
229 this->giveInternalDofManDofIDMask(i, dofIDMask);
230 this->giveInternalDofManager(i)->givePrescribedUnknownVector(vec, dofIDMask, u, tStep);
231 answer.copySubVector(vec,offset+1);
232 offset+=vec.size();
233 }
234 assert(offset==(int)answer.size());
235
236 if ( this->computeGtoLRotationMatrix(G2L) ) {
237 answer.rotatedWith(G2L, 'n');
238 }
239
240}
241
242
243void
244Element :: computeVectorOfPrescribed(const IntArray &dofIDMask, ValueModeType mode, TimeStep *tStep, FloatArray &answer)
245{
246 FloatMatrix G2L;
247 FloatArray vec;
248
249 answer.resize( dofIDMask.giveSize() * this->computeNumberOfGlobalDofs() );
250 int offset=0;
251
252 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
253 this->giveDofManager(i)->givePrescribedUnknownVector(vec, dofIDMask, mode, tStep);
254 answer.copySubVector(vec,offset+1);
255 offset+=vec.size();
256 }
257
258 for ( int i = 1; i <= giveNumberOfInternalDofManagers(); i++ ) {
259 this->giveInternalDofManager(i)->givePrescribedUnknownVector(vec, dofIDMask, mode, tStep);
260 answer.copySubVector(vec,offset+1);
261 offset+=vec.size();
262 }
263 assert(offset==(int)answer.size());
264
265 if ( this->computeGtoLRotationMatrix(G2L) ) {
266 answer.rotatedWith(G2L, 'n');
267 }
268}
269
270
271int
272Element :: computeNumberOfGlobalDofs()
273{
274 return this->computeNumberOfDofs();
275}
276
277
278int
279Element :: computeNumberOfPrimaryMasterDofs()
280{
281 int answer = 0;
282 IntArray nodeDofIDMask;
283
284 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
285 this->giveDofManDofIDMask(i, nodeDofIDMask);
286 answer += this->giveDofManager(i)->giveNumberOfPrimaryMasterDofs(nodeDofIDMask);
287 }
288
289 for ( int i = 1; i <= giveNumberOfInternalDofManagers(); i++ ) {
290 this->giveInternalDofManDofIDMask(i, nodeDofIDMask);
291 answer += this->giveInternalDofManager(i)->giveNumberOfPrimaryMasterDofs(nodeDofIDMask);
292 }
293 return answer;
294}
295
296
297bool
298Element :: giveRotationMatrix(FloatMatrix &answer)
299{
300 bool is_GtoL, is_NtoG;
301 FloatMatrix GtoL, NtoG;
302 IntArray nodes;
303 nodes.enumerate( this->giveNumberOfDofManagers() );
304
305 is_GtoL = this->computeGtoLRotationMatrix(GtoL);
306 is_NtoG = this->computeDofTransformationMatrix(NtoG, nodes, true);
307
308#ifdef DEBUG
309 if ( is_GtoL ) {
310 if ( GtoL.giveNumberOfColumns() != this->computeNumberOfGlobalDofs() ) {
311 OOFEM_ERROR("GtoL transformation matrix size mismatch in columns");
312 }
313 if ( GtoL.giveNumberOfRows() != this->computeNumberOfDofs() ) {
314 OOFEM_ERROR("GtoL transformation matrix size mismatch in rows");
315 }
316 }
317 if ( is_NtoG ) {
318 if ( NtoG.giveNumberOfColumns() != this->computeNumberOfPrimaryMasterDofs() ) {
319 OOFEM_ERROR("NtoG transformation matrix size mismatch in columns");
320 }
321 if ( NtoG.giveNumberOfRows() != this->computeNumberOfGlobalDofs() ) {
322 OOFEM_ERROR("NtoG transformation matrix size mismatch in rows");
323 }
324 }
325#endif
326
327 if ( is_GtoL && NtoG.isNotEmpty() ) {
328 answer.beProductOf(GtoL, NtoG);
329 } else if ( is_GtoL ) {
330 answer = GtoL;
331 } else if ( is_NtoG ) {
332 answer = NtoG;
333 } else {
334 answer.clear();
335 return false;
336 }
337 return true;
338}
339
340
341bool
342Element :: computeDofTransformationMatrix(FloatMatrix &answer, const IntArray &nodes, bool includeInternal)
343{
344 bool flag = false;
345
346 // test if transformation is necessary
347 for ( int n : nodes ) {
348 flag = flag || this->giveDofManager( n )->requiresTransformation();
349 }
350
351 if ( !flag ) {
352 answer.clear();
353 return false;
354 }
355
356 // initialize answer
357 int gsize = this->computeNumberOfPrimaryMasterDofs();
358 answer.resize(this->computeNumberOfGlobalDofs(), gsize);
359 answer.zero();
360
361 FloatMatrix dofManT;
362 IntArray dofIDmask;
363 int nr, nc, lastRowPos = 0, lastColPos = 0;
364 // loop over nodes
365 for ( int n : nodes ) {
366 this->giveDofManDofIDMask(n, dofIDmask);
367 if ( !this->giveDofManager( n )->computeM2GTransformation(dofManT, dofIDmask) ) {
368 dofManT.resize( dofIDmask.giveSize(), dofIDmask.giveSize() );
369 dofManT.zero();
370 dofManT.beUnitMatrix();
371 }
372 nc = dofManT.giveNumberOfColumns();
373 nr = dofManT.giveNumberOfRows();
374 for ( int j = 1; j <= nr; j++ ) {
375 for ( int k = 1; k <= nc; k++ ) {
376 // localize node contributions
377 answer.at(lastRowPos + j, lastColPos + k) = dofManT.at(j, k);
378 }
379 }
380
381 lastRowPos += nr;
382 lastColPos += nc;
383 }
384 if ( includeInternal ) {
385 for ( int i = 1; i <= this->giveNumberOfInternalDofManagers(); i++ ) {
386 this->giveInternalDofManDofIDMask(i, dofIDmask);
387 if ( !this->giveInternalDofManager( nodes.at(i) )->computeM2GTransformation(dofManT, dofIDmask) ) {
388 dofManT.resize( dofIDmask.giveSize(), dofIDmask.giveSize() );
389 dofManT.zero();
390 dofManT.beUnitMatrix();
391 }
392 nc = dofManT.giveNumberOfColumns();
393 nr = dofManT.giveNumberOfRows();
394 for ( int j = 1; j <= nr; j++ ) {
395 for ( int k = 1; k <= nc; k++ ) {
396 // localize node contributions
397 answer.at(lastRowPos + j, lastColPos + k) = dofManT.at(j, k);
398 }
399 }
400
401 lastRowPos += nr;
402 lastColPos += nc;
403 }
404 }
405 answer.resizeWithData(lastRowPos, lastColPos);
406 return true;
407}
408
409
410IntArray *
411Element :: giveBodyLoadArray()
412// Returns the array which contains the number of every body load that act
413// on the receiver.
414{
415 return & bodyLoadArray;
416}
417
418
419IntArray *
420Element :: giveBoundaryLoadArray()
421// Returns the array which contains the number of every body load that act
422// on the receiver.
423{
424 return & boundaryLoadArray;
425}
426
427
428void
429Element :: giveLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, IntArray *dofIdArray) const
430{
431 IntArray masterDofIDs, nodalArray, ids;
432 locationArray.clear();
433 if ( dofIdArray ) {
434 dofIdArray->clear();
435 }
436 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
437 this->giveDofManDofIDMask(i, ids);
438 this->giveDofManager(i)->giveLocationArray(ids, nodalArray, s);
439 locationArray.followedBy(nodalArray);
440 if ( dofIdArray ) {
441 this->giveDofManager(i)->giveMasterDofIDArray(ids, masterDofIDs);
442 dofIdArray->followedBy(masterDofIDs);
443 }
444 }
445 for ( int i = 1; i <= this->giveNumberOfInternalDofManagers(); i++ ) {
446 this->giveInternalDofManDofIDMask(i, ids);
447 this->giveInternalDofManager(i)->giveLocationArray(ids, nodalArray, s);
448 locationArray.followedBy(nodalArray);
449 if ( dofIdArray ) {
450 this->giveInternalDofManager(i)->giveMasterDofIDArray(ids, masterDofIDs);
451 dofIdArray->followedBy(masterDofIDs);
452 }
453 }
454}
455
456
457void
458Element :: giveLocationArray(IntArray &locationArray, const IntArray &dofIDMask, const UnknownNumberingScheme &s, IntArray *dofIdArray) const
459{
460 IntArray masterDofIDs, nodalArray;
461 locationArray.clear();
462 if ( dofIdArray ) {
463 dofIdArray->clear();
464 }
465 for ( int i = 1; i <=this->giveNumberOfDofManagers(); i++ ) {
466 this->giveDofManager(i)->giveLocationArray(dofIDMask, nodalArray, s);
467 locationArray.followedBy(nodalArray);
468 if ( dofIdArray ) {
469 this->giveDofManager(i)->giveMasterDofIDArray(dofIDMask, masterDofIDs);
470 dofIdArray->followedBy(masterDofIDs);
471 }
472 }
473 for ( int i = 1; i <= this->giveNumberOfInternalDofManagers(); i++ ) {
474 this->giveInternalDofManager(i)->giveLocationArray(dofIDMask, nodalArray, s);
475 locationArray.followedBy(nodalArray);
476 if ( dofIdArray ) {
477 this->giveInternalDofManager(i)->giveMasterDofIDArray(dofIDMask, masterDofIDs);
478 dofIdArray->followedBy(masterDofIDs);
479 }
480 }
481}
482
483
484void
485Element :: giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIdArray)
486{
487 IntArray masterDofIDs, nodalArray, dofIDMask;
488 locationArray.clear();
489 if ( dofIdArray ) {
490 dofIdArray->clear();
491 }
492 for ( int i = 1; i <= bNodes.giveSize(); i++ ) {
493 this->giveDofManDofIDMask(bNodes.at(i), dofIDMask);
494 this->giveDofManager( bNodes.at(i) )->giveLocationArray(dofIDMask, nodalArray, s);
495 locationArray.followedBy(nodalArray);
496 if ( dofIdArray ) {
497 this->giveDofManager( bNodes.at(i) )->giveMasterDofIDArray(dofIDMask, masterDofIDs);
498 dofIdArray->followedBy(masterDofIDs);
499 }
500 }
501}
502
503
504void
505Element :: giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const IntArray &dofIDMask, const UnknownNumberingScheme &s, IntArray *dofIdArray)
506{
507 IntArray masterDofIDs, nodalArray;
508 locationArray.clear();
509 if ( dofIdArray ) {
510 dofIdArray->clear();
511 }
512 for ( int i = 1; i <= bNodes.giveSize(); i++ ) {
513 this->giveDofManager( bNodes.at(i) )->giveLocationArray(dofIDMask, nodalArray, s);
514 locationArray.followedBy(nodalArray);
515 if ( dofIdArray ) {
516 this->giveDofManager( bNodes.at(i) )->giveMasterDofIDArray(dofIDMask, masterDofIDs);
517 dofIdArray->followedBy(masterDofIDs);
518 }
519 }
520}
521
522
523Material *Element :: giveMaterial()
524{
525#ifdef DEBUG
526 if ( !material ) {
527 OOFEM_ERROR("material not defined");
528 }
529#endif
530 return domain->giveMaterial(material);
531}
532
533
534CrossSection *Element :: giveCrossSection()
535{
536#ifdef DEBUG
537 if ( !crossSection ) {
538 OOFEM_ERROR("crossSection not defined");
539 }
540#endif
541 return domain->giveCrossSection(crossSection);
542}
543
544
545int
546Element :: giveRegionNumber()
547{
548 return this->giveCrossSection()->giveNumber();
549}
550
551
553Element :: giveDofManager(int i) const
554{
555#ifdef DEBUG
556 if ( ( i <= 0 ) || ( i > dofManArray.giveSize() ) ) {
557 OOFEM_ERROR("Node %i is not defined", i);
558 }
559#endif
560 return domain->giveDofManager( dofManArray.at(i) );
561}
562
563void
564Element :: addDofManager(DofManager *dMan)
565{
566#ifdef DEBUG
567 if ( dMan == NULL ) {
568 OOFEM_ERROR("Element :: addDofManager - dMan is a null pointer");
569 }
570#endif
571 int size = dofManArray.giveSize();
572 this->dofManArray.resizeWithValues( size + 1 );
573 this->dofManArray.at(size + 1) = dMan->giveGlobalNumber();
574}
575
577Element :: giveSide(int i) const
578{
579#ifdef DEBUG
580 if ( ( i <= 0 ) || ( i > dofManArray.giveSize() ) ) {
581 OOFEM_ERROR("Side is not defined");
582 }
583#endif
584 return domain->giveSide( dofManArray.at(i) );
585}
586
587
588void
589Element :: setDofManagers(const IntArray &_dmans)
590{
591 this->dofManArray = _dmans;
592 this->numberOfDofMans = _dmans.giveSize();
593}
594
595void
596Element :: setDofManager(int id, int dm)
597{
598 if (this->dofManArray.giveSize() >= id) {
599 this->dofManArray.at(id)=dm;
600 } else {
601 OOFEM_ERROR("DofMAnager index out of bounds (index=%d, size=%d)", id, this->dofManArray.giveSize());
602 }
603}
604
605
606void
607Element :: setBodyLoads(const IntArray &_bodyLoads)
608{
609 this->bodyLoadArray = _bodyLoads;
610}
611
612void
613Element :: setIntegrationRules(std :: vector< std :: unique_ptr< IntegrationRule > > irlist)
614{
615 integrationRulesArray = std :: move(irlist);
616}
617
618
619void
620Element :: giveCharacteristicMatrix(FloatMatrix &answer,
621 CharType mtrx, TimeStep *tStep)
622//
623// returns characteristics matrix of receiver according to mtrx
624//
625{
626 OOFEM_ERROR("Unknown Type of characteristic mtrx.");
627}
628
629
630void
631Element :: giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep)
632//
633// returns characteristics vector of receiver according to mtrx
634//
635{
636 OOFEM_ERROR("Unknown Type of characteristic mtrx.");
637}
638
639
640void
641Element :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep)
642{
643 answer.clear();
644 OOFEM_ERROR("Unknown load type.");
645}
646
647
648void
649Element :: computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global)
650{
651 answer.clear();
652 OOFEM_ERROR("Unknown load type.");
653}
654
655
656void
657Element :: computeTangentFromSurfaceLoad(FloatMatrix &answer, BoundaryLoad *load, int boundary, MatResponseMode rmode, TimeStep *tStep)
658{
659 answer.clear();
660}
661
662 void
663Element :: computeTangentFromEdgeLoad(FloatMatrix &answer, BoundaryLoad *load, int boundary, MatResponseMode rmode, TimeStep *tStep)
664{
665 answer.clear();
666}
667
668void
669Element :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global)
670{
672 answer.clear();
673 OOFEM_ERROR("Unknown load type.");
674}
675
676
677double
678Element :: giveCharacteristicValue(CharType mtrx, TimeStep *tStep)
679//
680// returns characteristics value of receiver according to CharType
681//
682{
683 OOFEM_ERROR("Unknown Type of characteristic mtrx.");
684}
685
686void
687Element :: initializeFrom(InputRecord &ir, int priority)
688{
689# ifdef VERBOSE
690 // VERBOSE_PRINT1("Instanciating element ",number);
691# endif
692 ParameterManager &ppm = this->giveDomain()->elementPPM;
693 //IR_GIVE_FIELD(ir, material, _IFT_Element_mat);
694 PM_UPDATE_PARAMETER(material, ppm, ir, this->number, IPK_Element_mat, priority) ;
696 PM_UPDATE_PARAMETER(dofManArray, ppm, ir, this->number, IPK_Element_nodes, priority) ;
699 bool tripletsflag = false;
700 FloatArray triplets;
701 PM_UPDATE_PARAMETER_AND_REPORT(triplets, ppm, ir, this->number, IPK_Element_lcs, priority, tripletsflag) ;
702 PM_UPDATE_PARAMETER(partitions, ppm, ir, this->number, IPK_Element_partitions, priority) ;
705
706 if (tripletsflag ) { //local coordinate system
707 double n1 = 0.0, n2 = 0.0;
708 elemLocalCS.resize(3, 3);
709 for ( int j = 1; j <= 3; j++ ) {
710 elemLocalCS.at(j, 1) = triplets.at(j);
711 n1 += triplets.at(j) * triplets.at(j);
712 elemLocalCS.at(j, 2) = triplets.at(j + 3);
713 n2 += triplets.at(j + 3) * triplets.at(j + 3);
714 }
715
716 n1 = sqrt(n1);
717 n2 = sqrt(n2);
718 for ( int j = 1; j <= 3; j++ ) { // normalize e1' e2'
719 elemLocalCS.at(j, 1) /= n1;
720 elemLocalCS.at(j, 2) /= n2;
721 }
722
723 // vector e3' computed from vector product of e1', e2'
724 elemLocalCS.at(1, 3) = ( elemLocalCS.at(2, 1) * elemLocalCS.at(3, 2) - elemLocalCS.at(3, 1) * elemLocalCS.at(2, 2) );
725 elemLocalCS.at(2, 3) = ( elemLocalCS.at(3, 1) * elemLocalCS.at(1, 2) - elemLocalCS.at(1, 1) * elemLocalCS.at(3, 2) );
726 elemLocalCS.at(3, 3) = ( elemLocalCS.at(1, 1) * elemLocalCS.at(2, 2) - elemLocalCS.at(2, 1) * elemLocalCS.at(1, 2) );
727 }
728
729 bool flag = false;
730 PM_CHECK_FLAG_AND_REPORT(ppm, ir, this->number, IPK_Element_remote, priority, flag) ;
731 if (flag) {
733 } else {
735 }
736
737}
738
739
740void
741Element :: giveInputRecord(DynamicInputRecord &input)
742{
743 FEMComponent :: giveInputRecord(input);
744
745 input.setField(material, IPK_Element_mat.getNameCStr());
746
747 input.setField(crossSection, IPK_Element_crosssect.getNameCStr());
748
749 input.setField(dofManArray, IPK_Element_nodes.getNameCStr());
750
751 if ( bodyLoadArray.giveSize() > 0 ) {
752 input.setField(bodyLoadArray, IPK_Element_bodyload.getNameCStr());
753 }
754
755
756 if ( boundaryLoadArray.giveSize() > 0 ) {
758 }
759
760
761 if ( elemLocalCS.giveNumberOfRows() > 0 ) {
762 FloatArray triplets(6);
763 for ( int j = 1; j <= 3; j++ ) {
764 triplets.at(j) = elemLocalCS.at(j, 1);
765 triplets.at(j + 3) = elemLocalCS.at(j, 2);
766 }
767 input.setField(triplets, IPK_Element_lcs.getNameCStr());
768 }
769
770
771 if ( partitions.giveSize() > 0 ) {
772 input.setField(this->partitions, IPK_Element_partitions.getNameCStr());
773 if ( this->parallel_mode == Element_remote ) {
774 input.setField(IPK_Element_remote.getNameCStr());
775 }
776 }
777
778 if ( activityTimeFunction > 0 ) {
780 }
781
782 input.setField(numberOfGaussPoints, IPK_Element_nip.getNameCStr());
783}
784
785void
786Element :: initializeFinish()
787{
788 ParameterManager &ppm = this->giveDomain()->elementPPM;
789
790 //PM_ERROR_IFNOTSET(ppm, this->number, _IFT_Element_mat) ;
793}
794
795
796void
797Element :: postInitialize()
798{
799 this->computeGaussPoints();
800}
801
802
803void
804Element :: printOutputAt(FILE *file, TimeStep *tStep)
805{
806 fprintf( file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() );
807
808 for ( int i = 1; i <= this->giveNumberOfInternalDofManagers(); ++i ) {
809 DofManager *dman = this->giveInternalDofManager(i);
810 dman->printOutputAt(file, tStep);
811 }
812
813 if (this->isActivated(tStep) ) {
814 for ( auto &iRule: integrationRulesArray ) {
815 iRule->printOutputAt(file, tStep);
816 }
817 } else {
818 fprintf(file, "is not active in current time step\n");
819 }
820}
821
822
823void
824Element :: updateYourself(TimeStep *tStep)
825// Updates the receiver at end of step.
826{
827# ifdef VERBOSE
828 // VERBOSE_PRINT1("Updating Element ",number)
829# endif
830
831 for ( auto &iRule: integrationRulesArray ) {
832 iRule->updateYourself(tStep);
833 }
834}
835
836
837bool
838Element :: isActivated(TimeStep *tStep)
839{
840 if ( activityTimeFunction ) {
841 if ( tStep ) {
842 return ( domain->giveFunction(activityTimeFunction)->evaluateAtTime( tStep->giveIntrinsicTime() ) > 1.e-3 );
843 } else {
844 return false;
845 }
846 } else {
847 return true;
848 }
849}
850
851
852bool
853Element :: isCast(TimeStep *tStep)
854{
855 // this approach used to work when material was assigned to element
856 // if ( tStep->giveIntrinsicTime() >= this->giveMaterial()->giveCastingTime() )
857 if ( tStep ) {
858
859 double castingTime;
860 double tNow = tStep->giveIntrinsicTime();
861
862 for ( auto &iRule : integrationRulesArray ) {
863 for ( auto &gp: *iRule ) {
864 castingTime = this->giveCrossSection()->giveMaterial(gp)->giveCastingTime();
865
866 if ( tNow < castingTime ) {
867 return false;
868 }
869 }
870 }
871 return true;
872
873 } else {
874 return false;
875 }
876}
877
878void
879Element :: initForNewStep()
880// initializes receiver to new time step or can be used
881// if current time step must be restarted
882{
883 for ( auto &iRule: integrationRulesArray ) {
884 for ( auto &gp: *iRule ) {
885 this->giveCrossSection()->giveMaterial(gp)->initTempStatus(gp);
886 }
887 }
888}
889
890
892Element::giveBoundaryEdgeNodes(int boundary, bool includeHierarchical) const
893{
894 return this->giveInterpolation()->boundaryEdgeGiveNodes(boundary, this->giveGeometryType(), includeHierarchical);
895}
896
898Element::giveBoundarySurfaceNodes(int boundary, bool includeHierarchical) const
899{
900 return this->giveInterpolation()->boundarySurfaceGiveNodes(boundary, this->giveGeometryType(), includeHierarchical);
901}
902
904Element::giveBoundaryNodes(int boundary) const
905{
906 return this->giveInterpolation()->boundaryGiveNodes(boundary, this->giveGeometryType());
907}
908
909
910std::unique_ptr<IntegrationRule>
912{
913 return this->giveInterpolation()->giveBoundaryEdgeIntegrationRule(order, boundary, this->giveGeometryType());
914}
915
916std::unique_ptr<IntegrationRule>
918{
919 return this->giveInterpolation()->giveBoundarySurfaceIntegrationRule(order, boundary, this->giveGeometryType());
920}
921
922
923void Element :: saveContext(DataStream &stream, ContextMode mode)
924{
925 FEMComponent :: saveContext(stream, mode);
926
927 if ( ( mode & CM_Definition ) ) {
929 if ( !stream.write(numberOfDofMans) ) {
931 }
932
933 if ( !stream.write(material) ) {
935 }
936
937 if ( !stream.write(crossSection) ) {
939 }
940
941 if ( mode & CM_DefinitionGlobal ) {
942 // send global numbers instead of local ones
943 int s = dofManArray.giveSize();
944 IntArray globDN(s);
945 for ( int i = 1; i <= s; i++ ) {
946 globDN.at(i) = this->giveDofManager(i)->giveGlobalNumber();
947 }
948
949 if ( ( iores = globDN.storeYourself(stream) ) != CIO_OK ) {
950 THROW_CIOERR(iores);
951 }
952 } else {
953 if ( ( iores = dofManArray.storeYourself(stream) ) != CIO_OK ) {
954 THROW_CIOERR(iores);
955 }
956 }
957
958 if ( ( iores = bodyLoadArray.storeYourself(stream) ) != CIO_OK ) {
959 THROW_CIOERR(iores);
960 }
961
962 if ( ( iores = boundaryLoadArray.storeYourself(stream) ) != CIO_OK ) {
963 THROW_CIOERR(iores);
964 }
965
966 int numberOfIntegrationRules = (int)integrationRulesArray.size();
967 if ( !stream.write(numberOfIntegrationRules) ) {
969 }
970
971 for ( auto &iRule: integrationRulesArray ) {
972 int _val = iRule->giveIntegrationRuleType();
973 if ( !stream.write(_val) ) {
975 }
976 }
977
978 int _mode;
979 if ( !stream.write(globalNumber) ) {
981 }
982
983 _mode = parallel_mode;
984 if ( !stream.write(_mode) ) {
986 }
987
988 if ( ( iores = partitions.storeYourself(stream) ) != CIO_OK ) {
989 THROW_CIOERR(iores);
990 }
991 }
992
993 for ( auto &iRule: integrationRulesArray ) {
994 iRule->saveContext(stream, mode);
995 }
996}
997
998
999void Element :: restoreContext(DataStream &stream, ContextMode mode)
1000{
1001 contextIOResultType iores;
1002 int _nrules;
1003
1004 FEMComponent :: restoreContext(stream, mode);
1005
1006 if ( mode & CM_Definition ) {
1007 if ( !stream.read(numberOfDofMans) ) {
1009 }
1010
1011 if ( !stream.read(material) ) {
1013 }
1014
1015 if ( !stream.read(crossSection) ) {
1017 }
1018
1019 if ( ( iores = dofManArray.restoreYourself(stream) ) != CIO_OK ) {
1020 THROW_CIOERR(iores);
1021 }
1022
1023 if ( ( iores = bodyLoadArray.restoreYourself(stream) ) != CIO_OK ) {
1024 THROW_CIOERR(iores);
1025 }
1026
1027 if ( ( iores = boundaryLoadArray.restoreYourself(stream) ) != CIO_OK ) {
1028 THROW_CIOERR(iores);
1029 }
1030
1031 if ( !stream.read(_nrules) ) {
1033 }
1034
1035 // restore integration rules
1036 IntArray dtypes(_nrules);
1037 for ( int i = 1; i <= _nrules; i++ ) {
1038 if ( !stream.read(dtypes.at(i)) ) {
1040 }
1041 }
1042
1043 if ( _nrules != (int)integrationRulesArray.size() ) {
1044
1045 // AND ALLOCATE NEW ONE
1046 integrationRulesArray.resize( _nrules );
1047 for ( int i = 0; i < _nrules; i++ ) {
1048 integrationRulesArray [ i ] = classFactory.createIRule( ( IntegrationRuleType ) dtypes[i], i + 1, this );
1049 }
1050 } else {
1051 for ( int i = 0; i < _nrules; i++ ) {
1052 if ( integrationRulesArray [ i ]->giveIntegrationRuleType() != dtypes[i] ) {
1053 integrationRulesArray [ i ] = classFactory.createIRule( ( IntegrationRuleType ) dtypes[i], i + 1, this );
1054 }
1055 }
1056 }
1057
1058 int _mode;
1059 if ( !stream.read(globalNumber) ) {
1061 }
1062
1063 if ( !stream.read(_mode) ) {
1065 }
1066
1068 if ( ( iores = partitions.restoreYourself(stream) ) != CIO_OK ) {
1069 THROW_CIOERR(iores);
1070 }
1071 }
1072
1073
1074 for ( auto &iRule: integrationRulesArray ) {
1075 iRule->restoreContext(stream, mode);
1076 }
1077}
1078
1079
1080double
1081Element :: computeVolumeAreaOrLength()
1082// the element computes its volume, area or length
1083// (depending on the spatial dimension of that element)
1084{
1085 double answer = 0.;
1087 if ( iRule ) {
1088 for ( auto &gp: *iRule ) {
1089 answer += this->computeVolumeAround(gp);
1090 }
1091
1092 return answer;
1093 }
1094
1095 return -1.; // means "cannot be evaluated"
1096}
1097
1098
1099double
1100Element :: computeMeanSize()
1101// Computes the size of the element defined as its length,
1102// square root of area or cube root of volume (depending on spatial dimension)
1103{
1104 double volume = this->computeVolumeAreaOrLength();
1105 if ( volume < 0. ) {
1106 return -1.; // means "cannot be evaluated"
1107 }
1108
1109 int dim = this->giveSpatialDimension();
1110 switch ( dim ) {
1111 case 1: return volume;
1112
1113 case 2: return sqrt(volume);
1114
1115 case 3: return cbrt(volume);
1116 }
1117
1118 return -1.; // means "cannot be evaluated"
1119}
1120
1121
1122double
1123Element :: computeVolume()
1124{
1125 FEInterpolation3d *fei = dynamic_cast< FEInterpolation3d * >( this->giveInterpolation() );
1126#ifdef DEBUG
1127 if ( !fei ) {
1128 OOFEM_ERROR("Function not overloaded and necessary interpolator isn't available");
1129 }
1130#endif
1131 return fei->giveVolume( FEIElementGeometryWrapper(this) );
1132}
1133
1134
1135double
1136Element :: computeArea()
1137{
1138 FEInterpolation2d *fei = dynamic_cast< FEInterpolation2d * >( this->giveInterpolation() );
1139#ifdef DEBUG
1140 if ( !fei ) {
1141 OOFEM_ERROR("Function not overloaded and necessary interpolator isn't available");
1142 }
1143#endif
1144 return fei->giveArea( FEIElementGeometryWrapper(this) );
1145}
1146
1147
1148double
1149Element :: computeLength()
1150{
1151 FEInterpolation1d *fei = dynamic_cast< FEInterpolation1d * >( this->giveInterpolation() );
1152#ifdef DEBUG
1153 if ( !fei ) {
1154 OOFEM_ERROR("Function not overloaded and necessary interpolator isn't available");
1155 }
1156#endif
1157 return fei->giveLength( FEIElementGeometryWrapper(this) );
1158}
1159
1160
1161double
1162Element :: giveLengthInDir(const FloatArray &normalToCrackPlane)
1163//
1164// returns receiver's size projected onto the direction given by normalToCrackPlane
1165// (exploited by the crack band approach)
1166//
1167{
1168 double maxDis, minDis;
1169 int nnode = giveNumberOfNodes();
1170
1171 const auto &coords = this->giveNode(1)->giveCoordinates();
1172 minDis = maxDis = normalToCrackPlane.dotProduct( coords, coords.giveSize() );
1173
1174 for ( int i = 2; i <= nnode; i++ ) {
1175 const auto &coords = this->giveNode(i)->giveCoordinates();
1176 double dis = normalToCrackPlane.dotProduct( coords, coords.giveSize() );
1177 if ( dis > maxDis ) {
1178 maxDis = dis;
1179 } else if ( dis < minDis ) {
1180 minDis = dis;
1181 }
1182 }
1183
1184 return maxDis - minDis;
1185}
1186
1187double
1188Element :: giveCharacteristicLengthForPlaneElements(const FloatArray &normalToCrackPlane)
1189//
1190// returns receiver's size projected onto the direction given by normalToCrackPlane
1191// or, if that direction is not in-plane, the square root of element area
1192// (this can happen if the crack normal is set to the maximum principal stress direction
1193// and the in-plane principal stresses are negative)
1194//
1195{
1196 if ( normalToCrackPlane.at(3) < 0.5 ) { // check whether the projection direction is in-plane
1197 return this->giveLengthInDir(normalToCrackPlane);
1198 } else { // if not, compute the size from element area
1199 return this->computeMeanSize();
1200 }
1201}
1202
1203double
1204Element :: giveCharacteristicLengthForAxisymmElements(const FloatArray &normalToCrackPlane)
1205//
1206// returns receiver's size projected onto the direction given by normalToCrackPlane
1207// or, if that direction is not in-plane, the distance from the axis of symmetry
1208// multiplied by pi, assuming that two symmetrically located radial cracks will form
1209// (this can happen if the cracking is caused by the hoop stress)
1210//
1211{
1212 if ( normalToCrackPlane.at(3) < 0.5 ) { // check whether the projection direction is in-plane
1213 return this->giveLengthInDir(normalToCrackPlane);
1214 } else { // if not, take the average distance from axis of symmetry multiplied by pi
1215 double r = 0.;
1216 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
1217 r += this->giveNode(i)->giveCoordinate(1);
1218 }
1219 r = r * M_PI / ( ( double ) this->giveNumberOfDofManagers() );
1220 return r;
1221 }
1222}
1223
1224int
1225Element :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords)
1226{
1227 FEInterpolation *fei = this->giveInterpolation();
1228#ifdef DEBUG
1229 if ( !fei ) {
1230 answer.clear();
1231 return false;
1232 }
1233#endif
1234 fei->local2global( answer, lcoords, FEIElementGeometryWrapper(this) );
1235 return true;
1236}
1237
1238
1239bool
1240Element :: computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
1241{
1242 FEInterpolation *fei = this->giveInterpolation();
1243 if ( fei ) {
1244 return fei->global2local( answer, gcoords, FEIElementGeometryWrapper(this) );
1245 } else {
1246 return false;
1247 }
1248}
1249
1250
1251int
1252Element :: giveLocalCoordinateSystem(FloatMatrix &answer)
1253{
1254 if ( elemLocalCS.isNotEmpty() ) {
1255 answer = elemLocalCS;
1256 return 1;
1257 } else {
1258 answer.clear();
1259 }
1260
1261 return 0;
1262}
1263
1264void
1265Element :: giveLocalCoordinateSystemVector(InternalStateType isttype, FloatArray &answer)
1266{
1267 int col = 0;
1268 FloatMatrix rotMat;
1269
1270 if ( isttype == IST_X_LCS ) {
1271 col = 1;
1272 } else if ( isttype == IST_Y_LCS ) {
1273 col = 2;
1274 } else if ( isttype == IST_Z_LCS ) {
1275 col = 3;
1276 } else {
1277 OOFEM_ERROR("Only IST_X_LCS, IST_Y_LCS, IST_Z_LCS options are permitted, you provided %s", __InternalStateTypeToString(isttype));
1278 }
1279
1280 if ( !this->giveLocalCoordinateSystem(rotMat) ) {
1281 rotMat.resize(3, 3);
1282 rotMat.beUnitMatrix();
1283 }
1284 answer.beRowOf(rotMat, col);
1285}
1286
1287
1288void
1289Element :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *)
1290// valid only for plane elements (shells, plates, ....)
1291// computes mid-plane normal at gaussPoint - for materials with orthotrophy
1292{
1293 OOFEM_ERROR("Unable to compute mid-plane normal, not supported");
1294}
1295
1296
1297int
1298Element :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
1299{
1300 if ( type == IST_ErrorIndicatorLevel ) {
1301 ErrorEstimator *ee = this->giveDomain()->giveErrorEstimator();
1302 if ( ee ) {
1303 answer.resize(1);
1306 answer.at(1) = ee->giveElementError(internalStressET, this, tStep);
1307 } else {
1308 answer.clear();
1309 return 0;
1310 }
1311
1312 return 1;
1313 } else if ( type == IST_InternalStressError ) {
1314 ErrorEstimator *ee = this->giveDomain()->giveErrorEstimator();
1315 if ( ee ) {
1316 answer.resize(1);
1317 answer.at(1) = ee->giveElementError(internalStressET, this, tStep);
1318 } else {
1319 answer.clear();
1320 return 0;
1321 }
1322 return 1;
1323 } else if ( type == IST_PrimaryUnknownError ) {
1324 ErrorEstimator *ee = this->giveDomain()->giveErrorEstimator();
1325 if ( ee ) {
1326 answer.resize(1);
1327 answer.at(1) = ee->giveElementError(primaryUnknownET, this, tStep);
1328 } else {
1329 answer.clear();
1330 return 0;
1331 }
1332 return 1;
1333 } else if ( type == IST_CrossSectionNumber ) {
1334 answer.resize(1);
1335 answer.at(1) = gp->giveCrossSection()->giveNumber();
1336 return 1;
1337 } else if ( type == IST_ElementNumber ) {
1338 answer.resize(1);
1339 answer.at(1) = this->giveNumber();
1340 return 1;
1341 } else if ( type == IST_X_LCS || type == IST_Y_LCS || type == IST_Z_LCS ) {
1342 this->giveLocalCoordinateSystemVector(type, answer);
1343 return 1;
1344 } else {
1345 return this->giveCrossSection()->giveIPValue(answer, gp, type, tStep);
1346 }
1347}
1348
1349int
1350Element :: giveGlobalIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
1351{
1353 if ( elemLocalCS.isNotEmpty() && valtype != ISVT_SCALAR ) {
1354 FloatArray ans;
1355 FloatMatrix full;
1356 int ret = this->giveIPValue(ans, gp, type, tStep);
1357 if ( ret == 0 ) return 0;
1358 if ( valtype == ISVT_VECTOR ) {
1360 answer.beProductOf(elemLocalCS, ans);
1361 return 1;
1362 }
1363
1364 // Tensors are more complicated to transform, easiest to write them in matrix form first
1365 if ( valtype == ISVT_TENSOR_S3E ) {
1366 ans.at(4) *= 0.5;
1367 ans.at(5) *= 0.5;
1368 ans.at(6) *= 0.5;
1369 } else if ( valtype != ISVT_TENSOR_G && valtype != ISVT_TENSOR_S3 ) {
1370 OOFEM_ERROR("Unsupported internal state value type for computing global IP value");
1371 }
1373 full.beMatrixForm(ans);
1374 full.rotatedWith(elemLocalCS, 'n');
1375 answer.beVectorForm(full);
1376 if ( valtype == ISVT_TENSOR_S3 ) {
1377 answer.resizeWithValues(6);
1378 } else if ( valtype == ISVT_TENSOR_S3E ) {
1379 answer.at(4) += answer.at(7);
1380 answer.at(5) += answer.at(8);
1381 answer.at(6) += answer.at(9);
1382 answer.resizeWithValues(6);
1383 }
1384 return 1;
1385 } else {
1386 return this->giveIPValue(answer, gp, type, tStep);
1387 }
1388}
1389
1390int
1391Element :: giveSpatialDimension()
1392{
1394 switch ( this->giveGeometryType() ) {
1395 case EGT_point:
1396 return 0;
1397
1398 case EGT_line_1:
1399 case EGT_line_2:
1400 return 1;
1401
1402 case EGT_triangle_1:
1403 case EGT_triangle_2:
1404 case EGT_quad_1:
1405 case EGT_quad_2:
1406 case EGT_quad9_2:
1407 case EGT_quad_1_interface:
1408 case EGT_quad_21_interface:
1409 return 2;
1410
1411 case EGT_tetra_1:
1412 case EGT_tetra_2:
1413 case EGT_hexa_1:
1414 case EGT_hexa_2:
1415 case EGT_hexa_27:
1416 case EGT_wedge_1:
1417 case EGT_wedge_2:
1418 return 3;
1419
1420 case EGT_Composite:
1421 case EGT_unknown:
1422 break;
1423 }
1424
1425 OOFEM_ERROR("failure (maybe new element type was registered)");
1426}
1427
1428
1429int
1430Element :: giveNumberOfBoundarySides()
1431{
1433 switch ( this->giveGeometryType() ) {
1434 case EGT_point:
1435 return 0;
1436
1437 case EGT_line_1:
1438 case EGT_line_2:
1439 case EGT_quad_1_interface:
1440 case EGT_quad_21_interface:
1441 return 2;
1442
1443 case EGT_triangle_1:
1444 case EGT_triangle_2:
1445 return 3;
1446
1447 case EGT_quad_1:
1448 case EGT_quad_2:
1449 case EGT_quad9_2:
1450 return 4;
1451
1452 case EGT_tetra_1:
1453 case EGT_tetra_2:
1454 return 4;
1455
1456 case EGT_wedge_1:
1457 case EGT_wedge_2:
1458 return 5;
1459
1460 case EGT_hexa_1:
1461 case EGT_hexa_2:
1462 case EGT_hexa_27:
1463 return 6;
1464
1465 case EGT_Composite:
1466 case EGT_unknown:
1467 break;
1468 }
1469
1470 OOFEM_ERROR("failure, unsupported geometry type (%s)",
1472}
1473
1474
1475int
1476Element :: giveNumberOfEdges() const
1477{
1478 switch ( this->giveGeometryType() ) {
1479 case EGT_point:
1480 return 0;
1481 case EGT_line_1:
1482 case EGT_line_2:
1483 case EGT_quad_1_interface:
1484 case EGT_quad_21_interface:
1485 return 1;
1486
1487 case EGT_triangle_1:
1488 case EGT_triangle_2:
1489 return 3;
1490
1491 case EGT_quad_1:
1492 case EGT_quad_2:
1493 case EGT_quad9_2:
1494 return 4;
1495
1496 case EGT_tetra_1:
1497 case EGT_tetra_2:
1498 return 6;
1499
1500 case EGT_wedge_1:
1501 case EGT_wedge_2:
1502 return 9;
1503
1504 case EGT_hexa_1:
1505 case EGT_hexa_2:
1506 case EGT_hexa_27:
1507 return 12;
1508
1509 case EGT_Composite:
1510 case EGT_unknown:
1511 break;
1512 }
1513
1514 OOFEM_ERROR("failure, unsupported geometry type (%s)",
1516}
1517
1518int
1519Element :: giveNumberOfSurfaces() const
1520{
1521 switch ( this->giveGeometryType() ) {
1522 case EGT_point:
1523 case EGT_line_1:
1524 case EGT_line_2:
1525 case EGT_quad_1_interface:
1526 case EGT_quad_21_interface:
1527 case EGT_triangle_1:
1528 case EGT_triangle_2:
1529 case EGT_quad_1:
1530 case EGT_quad_2:
1531 case EGT_quad9_2:
1532 return 0;
1533
1534 case EGT_tetra_1:
1535 case EGT_tetra_2:
1536 return 4;
1537
1538 case EGT_wedge_1:
1539 case EGT_wedge_2:
1540 return 5;
1541
1542 case EGT_hexa_1:
1543 case EGT_hexa_2:
1544 case EGT_hexa_27:
1545 return 6;
1546
1547 case EGT_Composite:
1548 case EGT_unknown:
1549 break;
1550 }
1551
1552 OOFEM_ERROR("failure, unsupported geometry type (%s)",
1554}
1555
1558 switch ( this->giveGeometryType() ) {
1559 case EGT_line_1:
1560 case EGT_triangle_1:
1561 case EGT_quad_1:
1562 case EGT_tetra_1:
1563 case EGT_wedge_1:
1564 case EGT_hexa_1:
1565 return EGT_line_1;
1566
1567 case EGT_line_2:
1568 case EGT_triangle_2:
1569 case EGT_quad_2:
1570 case EGT_quad9_2:
1571 case EGT_tetra_2:
1572 case EGT_wedge_2:
1573 case EGT_hexa_2:
1574 case EGT_hexa_27:
1575 return EGT_line_2;
1576 default:
1577 OOFEM_ERROR("failure, unsupported geometry type (%s)",
1579 }
1580}
1581
1584 switch ( this->giveGeometryType() ) {
1585
1586 case EGT_tetra_1:
1587 return EGT_triangle_1;
1588 case EGT_tetra_2:
1589 return EGT_triangle_2;
1590 case EGT_hexa_1:
1591 return EGT_quad_1;
1592 case EGT_hexa_2:
1593 return EGT_quad_2;
1594 case EGT_wedge_1:
1595 if (id<3) return EGT_triangle_1;
1596 else return EGT_quad_1;
1597 default:
1598 OOFEM_ERROR("failure, unsupported geometry type (%s)",
1600 }
1601}
1602
1603int
1604Element :: adaptiveMap(Domain *oldd, TimeStep *tStep)
1605{
1606 int result = 1;
1607 CrossSection *cs = this->giveCrossSection();
1608
1609 for ( auto &iRule: integrationRulesArray ) {
1610 for ( auto &gp: *iRule ) {
1613 if ( interface ) {
1614 result &= interface->MMI_map(gp, oldd, tStep);
1615 } else {
1616 result = 0;
1617 }
1618 }
1619 }
1620
1621 return result;
1622}
1623
1624int
1625Element :: mapStateVariables(Domain &iOldDom, const TimeStep &iTStep)
1626{
1627 int result = 1;
1628
1629 // create source set (this is quite inefficient here as done for each element.
1630 // the alternative MaterialModelMapperInterface approach allows to cache sets on material model
1631 Set sourceElemSet = Set(0, & iOldDom);
1632 int materialNum = this->giveMaterial()->giveNumber();
1633 sourceElemSet.setElementList( iOldDom.giveElementsWithMaterialNum(materialNum) );
1634
1635 for ( auto &iRule: integrationRulesArray ) {
1636 for ( GaussPoint *gp: *iRule ) {
1637
1638 MaterialStatus *ms = dynamic_cast< MaterialStatus * >( gp->giveMaterialStatus() );
1639 if ( ms == NULL ) {
1640 OOFEM_ERROR("failed to fetch MaterialStatus.");
1641 }
1642
1643 MaterialStatusMapperInterface *interface = dynamic_cast< MaterialStatusMapperInterface * >(ms);
1644 if ( interface == NULL ) {
1645 OOFEM_ERROR("Failed to fetch MaterialStatusMapperInterface.");
1646 }
1647
1648 result &= interface->MSMI_map( *gp, iOldDom, sourceElemSet, iTStep, * ( ms ) );
1649 }
1650 }
1651
1652 return result;
1653}
1654
1655
1656int
1657Element :: adaptiveFinish(TimeStep *tStep)
1658{
1660 ( this->giveMaterial()->giveInterface(MaterialModelMapperInterfaceType) );
1661
1662 if ( !interface ) {
1663 return 0;
1664 }
1665#if 0
1666 int result = 1;
1667 for ( auto &iRule: integrationRulesArray ) {
1668 for ( GaussPoint *gp: *iRule ) {
1669 result &= interface->MMI_finish(tStep);
1670 }
1671 }
1672
1673 return result;
1674#else
1675 return interface->MMI_finish(tStep);
1676#endif
1677}
1678
1679
1680void
1681Element :: updateLocalNumbering(EntityRenumberingFunctor &f)
1682{
1683 for ( auto &dnum : dofManArray ) {
1684 if (dnum) {
1685 dnum = f(dnum, ERS_DofManager);
1686 }
1687 }
1688
1689}
1690
1691
1693Element :: giveIntegrationDomain() const
1694{
1695 FEInterpolation *fei = this->giveInterpolation();
1697}
1698
1699/*
1700Element_Geometry_Type
1701Element :: giveGeometryType() const
1702{
1703 return EGT_unknown;
1704 //FEInterpolation *fei = this->giveInterpolation();
1705 //return fei ? fei->giveGeometryType() : EGT_unknown;
1706}
1707*/
1708
1709bool
1710Element :: computeGtoLRotationMatrix(FloatMatrix &answer)
1711{
1712 answer.clear();
1713 return false;
1714}
1715
1716
1717int
1718Element :: packUnknowns(DataStream &buff, TimeStep *tStep)
1719{
1720 int result = 1;
1721
1722 for ( auto &iRule: integrationRulesArray ) {
1723 for ( GaussPoint *gp: *iRule ) {
1724 result &= this->giveCrossSection()->packUnknowns( buff, tStep, gp );
1725 }
1726 }
1727
1728 return result;
1729}
1730
1731
1732int
1733Element :: unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep)
1734{
1735 int result = 1;
1736
1737 for ( auto &iRule: integrationRulesArray ) {
1738 for ( GaussPoint *gp: *iRule ) {
1739 result &= this->giveCrossSection()->unpackAndUpdateUnknowns( buff, tStep, gp );
1740 }
1741 }
1742
1743 return result;
1744}
1745
1746
1747int
1748Element :: estimatePackSize(DataStream &buff)
1749{
1750 int result = 0;
1751
1752 for ( auto &iRule: integrationRulesArray ) {
1753 for ( GaussPoint *gp: *iRule ) {
1754 result += this->giveCrossSection()->estimatePackSize( buff, gp );
1755 }
1756 }
1757
1758 return result;
1759}
1760
1761
1762double
1763Element :: predictRelativeComputationalCost()
1764{
1765 double wgt = 0;
1767 for ( GaussPoint *gp: *iRule ) {
1768 wgt += this->giveCrossSection()->predictRelativeComputationalCost( gp );
1769 }
1770
1771 return ( this->giveRelativeSelfComputationalCost() * wgt );
1772}
1773
1774
1775#ifdef __OOFEG
1776void
1777Element :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep)
1778{
1779 OGC_PlotModeType mode = gc.giveIntVarPlotMode();
1780
1781 if ( mode == OGC_rawGeometry ) {
1782 this->drawRawGeometry(gc, tStep);
1783 } else if ( mode == OGC_elementAnnotation ) {
1784 this->drawAnnotation(gc, tStep);
1785 } else if ( mode == OGC_deformedGeometry ) {
1786 this->drawDeformedGeometry(gc, tStep, DisplacementVector);
1787 } else if ( mode == OGC_eigenVectorGeometry ) {
1788 this->drawDeformedGeometry(gc, tStep, EigenVector);
1789 } else if ( mode == OGC_scalarPlot ) {
1790 this->drawScalar(gc, tStep);
1791 } else if ( mode == OGC_elemSpecial ) {
1792 this->drawSpecial(gc, tStep);
1793 } else {
1794 OOFEM_ERROR("unsupported mode");
1795 }
1796}
1797
1798
1799void
1800Element :: drawAnnotation(oofegGraphicContext &gc, TimeStep *tStep)
1801{
1802 int count = 0;
1803 Node *node;
1804 WCRec p [ 1 ]; /* point */
1805 GraphicObj *go;
1806 char num [ 30 ];
1807
1808 p [ 0 ].x = p [ 0 ].y = p [ 0 ].z = 0.0;
1809 // compute element center
1810 for ( int i = 1; i <= numberOfDofMans; i++ ) {
1811 if ( ( node = this->giveNode(i) ) ) {
1812 p [ 0 ].x += node->giveCoordinate(1);
1813 p [ 0 ].y += node->giveCoordinate(2);
1814 p [ 0 ].z += node->giveCoordinate(3);
1815 count++;
1816 }
1817 }
1818
1819 p [ 0 ].x /= count;
1820 p [ 0 ].y /= count;
1821 p [ 0 ].z /= count;
1822
1823 EASValsSetLayer(OOFEG_ELEMENT_ANNOTATION_LAYER);
1824 EASValsSetColor( gc.getElementColor() );
1825 sprintf( num, "%d(%d)", this->giveNumber(), this->giveGlobalNumber() );
1826
1827 go = CreateAnnText3D(p, num);
1828 EGWithMaskChangeAttributes(COLOR_MASK | LAYER_MASK, go);
1829 EMAddGraphicsToModel(ESIModel(), go);
1830}
1831
1832
1833int
1834Element :: giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode,
1835 int node, TimeStep *tStep)
1836{
1837 if ( type == IST_RelMeshDensity ) {
1838 ErrorEstimator *ee = this->giveDomain()->giveErrorEstimator();
1839 if ( ee ) {
1840 answer.resize(1);
1841 answer.at(1) = this->giveDomain()->giveErrorEstimator()->giveRemeshingCrit()->
1842 giveRequiredDofManDensity(this->giveNode(node)->giveNumber(), tStep, 1);
1843 return 1;
1844 } else {
1845 answer.clear();
1846 return 0;
1847 }
1848 } else {
1849 if ( mode == ISM_recovered ) {
1850 const FloatArray *nodval;
1851 NodalRecoveryModel *smoother = this->giveDomain()->giveSmoother();
1852 int result = smoother->giveNodalVector( nodval, this->giveNode(node)->giveNumber() );
1853 if ( nodval ) {
1854 answer = * nodval;
1855 } else {
1856 answer.clear();
1857 }
1858
1859 return result;
1860 } else {
1861 return 0;
1862 }
1863 }
1864}
1865
1866
1867#endif
1868} // end namespace oofem
virtual Material * giveMaterial(IntegrationPoint *ip) const =0
hidden by virtual oofem::Material* TransportCrossSection::giveMaterial() const
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
int giveGlobalNumber() const
Definition dofmanager.h:515
double giveCoordinate(int i) const
Definition dofmanager.h:383
void printOutputAt(FILE *file, TimeStep *tStep) override
Definition dofmanager.C:507
const IntArray & giveElementsWithMaterialNum(int iMaterialNum) const
Definition domain.C:214
void setField(int item, InputFieldType id)
virtual void drawAnnotation(oofegGraphicContext &gc, TimeStep *tStep)
Definition element.C:1800
double computeMeanSize()
Definition element.C:1100
int giveGlobalNumber() const
Definition element.h:1129
Node * giveNode(int i) const
Definition element.h:629
virtual int computeNumberOfGlobalDofs()
Definition element.C:272
static ParamKey IPK_Element_crosssect
Definition element.h:199
IntArray boundaryLoadArray
Definition element.h:147
virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep)
Definition element.h:1075
virtual void computeGaussPoints()
Definition element.h:1255
virtual bool computeGtoLRotationMatrix(FloatMatrix &answer)
Definition element.C:1710
virtual bool computeDofTransformationMatrix(FloatMatrix &answer, const IntArray &nodes, bool includeInternal)
Definition element.C:342
IntArray globalEdgeIDs
Definition element.h:190
IntArray dofManArray
Array containing dofmanager numbers.
Definition element.h:138
virtual bool isActivated(TimeStep *tStep)
Definition element.C:838
virtual double giveLengthInDir(const FloatArray &normalToCrackPlane)
Definition element.C:1162
static ParamKey IPK_Element_nodes
Definition element.h:200
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
static ParamKey IPK_Element_bodyload
Definition element.h:201
virtual void giveInternalDofManDofIDMask(int inode, IntArray &answer) const
Definition element.h:501
virtual int giveSpatialDimension()
Definition element.C:1391
virtual std::unique_ptr< IntegrationRule > giveBoundaryEdgeIntegrationRule(int order, int boundary)
Definition element.C:911
virtual int giveNumberOfNodes() const
Definition element.h:703
virtual IntArray giveBoundaryEdgeNodes(int boundary, bool includeHierarchical=false) const
Definition element.C:892
virtual int giveNumberOfInternalDofManagers() const
Definition element.h:243
virtual Element_Geometry_Type giveSurfaceGeometryType(int id) const
Returns the receiver surface geometry type.
Definition element.C:1583
virtual int computeNumberOfDofs()
Definition element.h:436
static ParamKey IPK_Element_activityTimeFunction
Definition element.h:206
virtual void giveDofManDofIDMask(int inode, IntArray &answer) const
Definition element.h:488
virtual void giveLocalCoordinateSystemVector(InternalStateType isttype, FloatArray &answer)
Definition element.C:1265
virtual double computeVolumeAreaOrLength()
Computes the volume, area or length of the element depending on its spatial dimension.
Definition element.C:1081
virtual Material * giveMaterial()
Definition element.C:523
virtual IntArray giveBoundarySurfaceNodes(int boundary, bool includeHierarchical=false) const
Definition element.C:898
static ParamKey IPK_Element_nip
Definition element.h:207
virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep)
Definition element.h:1077
virtual std::unique_ptr< IntegrationRule > giveBoundarySurfaceIntegrationRule(int order, int boundary)
Definition element.C:917
virtual double giveRelativeSelfComputationalCost()
Definition element.h:1199
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
virtual IntArray giveBoundaryNodes(int boundary) const
Definition element.C:904
int computeNumberOfPrimaryMasterDofs()
Definition element.C:279
int activityTimeFunction
Element activity time function. If defined, nonzero value indicates active receiver,...
Definition element.h:163
IntArray partitions
Definition element.h:184
virtual int giveLocalCoordinateSystem(FloatMatrix &answer)
Definition element.C:1252
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
static ParamKey IPK_Element_remote
Definition element.h:205
int material
Number of associated material.
Definition element.h:140
virtual DofManager * giveInternalDofManager(int i) const
Definition element.h:249
int crossSection
Number of associated cross section.
Definition element.h:142
int numberOfGaussPoints
Definition element.h:175
virtual int giveNumberOfDofManagers() const
Definition element.h:695
IntArray globalSurfaceIDs
Definition element.h:195
DofManager * giveDofManager(int i) const
Definition element.C:553
FloatMatrix elemLocalCS
Transformation material matrix, used in orthotropic and anisotropic materials, global->local transfor...
Definition element.h:160
CrossSection * giveCrossSection()
Definition element.C:534
static ParamKey IPK_Element_boundaryload
Definition element.h:202
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType)
Definition element.h:1076
virtual Element_Geometry_Type giveEdgeGeometryType(int id) const
Returns the receiver edge geometry type.
Definition element.C:1557
static ParamKey IPK_Element_partitions
Definition element.h:204
static ParamKey IPK_Element_mat
Definition element.h:198
virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep)
Definition element.h:1078
static ParamKey IPK_Element_lcs
Definition element.h:203
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Definition element.C:1298
virtual double computeVolumeAround(GaussPoint *gp)
Definition element.h:530
elementParallelMode parallel_mode
Determines the parallel mode of the element.
Definition element.h:178
int giveLabel() const
Definition element.h:1125
IntArray bodyLoadArray
Definition element.h:147
virtual Element_Geometry_Type giveGeometryType() const =0
virtual double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep)=0
virtual double giveLength(const FEICellGeometry &cellgeo) const
virtual double giveArea(const FEICellGeometry &cellgeo) const
virtual double giveVolume(const FEICellGeometry &cellgeo) const
virtual std::unique_ptr< IntegrationRule > giveBoundaryEdgeIntegrationRule(int order, int boundary, const Element_Geometry_Type) const
Definition feinterpol.C:112
virtual IntArray boundaryEdgeGiveNodes(int boundary, const Element_Geometry_Type, bool includeHierarchical=false) const =0
virtual IntArray boundaryGiveNodes(int boundary, const Element_Geometry_Type) const =0
virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const =0
virtual IntArray boundarySurfaceGiveNodes(int boundary, const Element_Geometry_Type, bool includeHierarchical=false) const =0
virtual integrationDomain giveIntegrationDomain(const Element_Geometry_Type) const =0
virtual std::unique_ptr< IntegrationRule > giveBoundarySurfaceIntegrationRule(int order, int boundary, const Element_Geometry_Type) const
Definition feinterpol.C:123
virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
virtual Interface * giveInterface(InterfaceType t)
Definition femcmpnn.h:181
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int number
Component number.
Definition femcmpnn.h:77
int giveNumber() const
Definition femcmpnn.h:104
FEMComponent(int n, Domain *d)
Definition femcmpnn.h:88
Index size() const
Definition floatarray.h:162
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
void resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void copySubVector(const FloatArray &src, int si)
Definition floatarray.C:886
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beVectorForm(const FloatMatrix &aMatrix)
void beRowOf(const FloatMatrix &mat, Index row)
void rotatedWith(const FloatMatrix &r, char mode='n')
void resizeWithData(Index, Index)
Definition floatmatrix.C:91
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
int giveNumberOfColumns() const
Returns number of columns of receiver.
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void zero()
Zeroes all coefficient of receiver.
bool isNotEmpty() const
Tests for empty matrix.
void beMatrixForm(const FloatArray &aArray)
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
void beUnitMatrix()
Sets receiver to unity matrix.
CrossSection * giveCrossSection()
Returns reference to cross section associated to related element of receiver.
Definition gausspoint.h:199
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void enumerate(int maxVal)
Definition intarray.C:85
contextIOResultType storeYourself(DataStream &stream) const
Definition intarray.C:238
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
virtual int MMI_finish(TimeStep *tStep)=0
virtual int MSMI_map(const GaussPoint &iGP, const Domain &iOldDom, Set &sourceSet, const TimeStep &iTStep, MaterialStatus &oStatus)
int giveNodalVector(const FloatArray *&ptr, int node)
void setElementList(IntArray newElements)
Definition set.C:231
double giveIntrinsicTime()
Returns intrinsic time, e.g. time in which constitutive model is evaluated.
Definition timestep.h:166
#define THROW_CIOERR(e)
#define CM_DefinitionGlobal
Definition contextmode.h:48
#define CM_Definition
Definition contextmode.h:47
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define M_PI
Definition mathfem.h:52
const char * __InternalStateTypeToString(InternalStateType _value)
Definition cltypes.C:309
long ContextMode
Definition contextmode.h:43
double cbrt(double x)
Returns the cubic root of x.
Definition mathfem.h:122
elementParallelMode
Definition element.h:87
@ Element_remote
Element in active domain is only mirror of some remote element.
Definition element.h:89
@ Element_local
Element is local, there are no contributions from other domains to this element.
Definition element.h:88
const char * __Element_Geometry_TypeToString(Element_Geometry_Type _value)
Definition cltypes.C:325
@ _UnknownIntegrationDomain
InternalStateMode
Determines the mode of internal variable.
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.
@ ISVT_TENSOR_G
General tensor.
ClassFactory & classFactory
@ MaterialModelMapperInterfaceType
InternalStateValueType giveInternalStateValueType(InternalStateType type)
Definition cltypes.C:75
@ CIO_IOERR
General IO error.
@ primaryUnknownET
@ internalStressET
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]
#define OOFEG_ELEMENT_ANNOTATION_LAYER
#define PM_UPDATE_PARAMETER_AND_REPORT(_val, _pm, _ir, _componentnum, _paramkey, _prio, _flag)
#define PM_CHECK_FLAG_AND_REPORT(_pm, _ir, _componentnum, _paramkey, _prio, _flag)
#define PM_ELEMENT_ERROR_IFNOTSET(_pm, _componentnum, _paramkey)
#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