OOFEM 3.0
Loading...
Searching...
No Matches
structuralelementevaluator.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
40#include "floatarray.h"
41#include "floatmatrix.h"
42#include "domain.h"
43#include "node.h"
44#include "gausspoint.h"
46#include "matresponsemode.h"
47#include "mathfem.h"
48#include "iga/iga.h"
49
50namespace oofem {
51StructuralElementEvaluator :: StructuralElementEvaluator()
52{
53 this->rotationMatrix.clear();
54}
55
56/*
57 * int StructuralElementEvaluator :: giveIntegrationElementCodeNumbers(IntArray &answer, Element *elem,
58 * IntegrationRule *ie) {
59 * int i;
60 * IntArray mask, nodeDofIDMask, nodalArray;
61 *
62 * // first evaluate nonzero basis function mask
63 * if ( elem->giveInterpolation()->hasSubPatchFormulation() ) {
64 * IGAIntegrationElement *ee = static_cast< IGAIntegrationElement * >( ie );
65 * elem->giveInterpolation()->giveKnotSpanBasisFuncMask(* ee->giveKnotSpan(), mask);
66 * // loop over nonzero shape functions and assemble localization array
67 * answer.clear();
68 * for ( i = 1; i <= mask.giveSize(); i++ ) {
69 * elem->giveDofManDofIDMask(mask.at(i), nodeDofIDMask);
70 * elem->giveDofManager( mask.at(i) )->giveLocationArray(nodeDofIDMask, nodalArray);
71 * answer.followedBy(nodalArray);
72 * }
73 *
74 * return 1;
75 * } else {
76 * return 0;
77 * }
78 * }
79 */
80
81int StructuralElementEvaluator :: giveIntegrationElementLocalCodeNumbers(IntArray &answer, Element *elem,
83{
84 int nsd;
85 IntArray mask, nodeDofIDMask, nodalArray;
86 int dofmandof;
87
88 // get number of dofs in node
89 elem->giveDofManDofIDMask(1, nodeDofIDMask);
90 dofmandof = nodeDofIDMask.giveSize();
91
92 nsd = elem->giveInterpolation()->giveNsd(elem->giveGeometryType());
93
94 // first evaluate nonzero basis function mask
96 IGAIntegrationElement *ee = static_cast< IGAIntegrationElement * >(ie);
98 // loop over nonzero shape functions and assemble localization array
99 answer.clear();
100 for ( int i = 1; i <= mask.giveSize(); i++ ) {
101 nodalArray.resize( nodeDofIDMask.giveSize() );
102 for ( int j = 1; j <= nsd; j++ ) {
103 nodalArray.at(j) = dofmandof * ( mask.at(i) - 1 ) + j;
104 }
105
106 answer.followedBy(nodalArray);
107 }
108
109 return 1;
110 } else {
111 return 0;
112 }
113}
114
115
116void StructuralElementEvaluator :: giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep)
117{
118 if ( type == InternalForcesVector ) {
119 this->giveInternalForcesVector(answer, tStep, false);
120 } else if ( type == LastEquilibratedInternalForcesVector ) {
121 this->giveInternalForcesVector(answer, tStep, true);
122 } else {
123 answer.clear();
124 }
125}
126
127
128void StructuralElementEvaluator :: giveCharacteristicMatrix(FloatMatrix &answer,
129 CharType mtrx, TimeStep *tStep)
130//
131// returns characteristics matrix of receiver according to mtrx
132//
133{
134 if ( mtrx == TangentStiffnessMatrix ) {
135 this->computeStiffnessMatrix(answer, TangentStiffness, tStep);
136 } else if ( mtrx == MassMatrix ) {
137 double mass;
138 this->computeConsistentMassMatrix(answer, tStep, mass);
139 } else if ( mtrx == LumpedMassMatrix ) {
140 this->computeLumpedMassMatrix(answer, tStep);
141 } else {
142 OOFEM_ERROR( "Unknown Type of characteristic mtrx (%s)", __CharTypeToString(mtrx) );
143 }
144}
145
146
147void StructuralElementEvaluator :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep)
148// Returns the lumped mass matrix of the receiver.
149{
150 double mass;
151 Element *elem = this->giveElement();
152 int numberOfDofMans = elem->giveNumberOfDofManagers();
153 IntArray nodeDofIDMask, dimFlag(3);
154 int indx = 0, ldofs, dim;
155 double summ;
156
157 if ( !this->isActivated(tStep) ) {
158 int ndofs = elem->computeNumberOfDofs();
159 answer.resize(ndofs, ndofs);
160 answer.zero();
161 return;
162 }
163
164 this->computeConsistentMassMatrix(answer, tStep, mass);
165 ldofs = answer.giveNumberOfRows();
166
167 for ( int i = 1; i <= numberOfDofMans; i++ ) {
168 elem->giveDofManDofIDMask(i, nodeDofIDMask);
169 for ( int j = 1; j <= nodeDofIDMask.giveSize(); j++ ) {
170 indx++;
171 // zero all off-diagonal terms
172 for ( int k = 1; k <= ldofs; k++ ) {
173 if ( k != indx ) {
174 answer.at(indx, k) = 0.;
175 answer.at(k, indx) = 0.;
176 }
177 }
178
179 if ( ( nodeDofIDMask.at(j) != D_u ) && ( nodeDofIDMask.at(j) != D_v ) && ( nodeDofIDMask.at(j) != D_w ) ) {
180 // zero corresponding diagonal member too <= no displacement dof
181 answer.at(indx, indx) = 0.;
182 } else if ( nodeDofIDMask.at(j) == D_u ) {
183 dimFlag.at(1) = 1;
184 } else if ( nodeDofIDMask.at(j) == D_v ) {
185 dimFlag.at(2) = 1;
186 } else if ( nodeDofIDMask.at(j) == D_w ) {
187 dimFlag.at(3) = 1;
188 }
189 }
190 }
191
192 if ( indx != ldofs ) {
193 OOFEM_ERROR("internal consistency check failed");
194 }
195
196 dim = dimFlag.at(1) + dimFlag.at(2) + dimFlag.at(3);
197 summ = 0.;
198 for ( int k = 1; k <= ldofs; k++ ) {
199 summ += answer.at(k, k);
200 }
201
202 answer.times(dim * mass / summ);
203}
204
205
206void StructuralElementEvaluator :: computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass)
207// Computes numerically the consistent (full) mass matrix of the receiver.
208{
209 //Element *elem = this->giveElement();
210 StructuralElement *elem = static_cast< StructuralElement * >( this->giveElement() );
211 int ndofs = elem->computeNumberOfDofs();
212 FloatMatrix n;
213 IntegrationRule *iRule;
214 IntArray mask;
215
216 answer.resize(ndofs, ndofs);
217 answer.zero();
218 if ( !this->isActivated(tStep) ) {
219 return;
220 }
221
222 if ( ( iRule = this->giveMassMtrxIntegrationRule() ) ) {
223 OOFEM_ERROR("no integration rule available");
224 }
225
226 this->giveMassMtrxIntegrationMask(mask);
227
228 mass = 0.;
229
230 for ( GaussPoint *gp: *iRule ) {
231 double density = elem->giveStructuralCrossSection()->give('d', gp);
232 double dV = this->computeVolumeAround(gp);
233 mass += density * dV;
234 this->computeNMatrixAt(n, gp);
235
236 if ( mask.isEmpty() ) {
237 answer.plusProductSymmUpper(n, n, density * dV);
238 } else {
239 for ( int i = 1; i <= ndofs; i++ ) {
240 for ( int j = i; j <= ndofs; j++ ) {
241 double summ = 0.;
242 for ( int k = 1; k <= n.giveNumberOfRows(); k++ ) {
243 if ( mask.at(k) == 0 ) {
244 continue;
245 }
246
247 summ += n.at(k, i) * n.at(k, j);
248 }
249
250 answer.at(i, j) += summ * density * dV;
251 }
252 }
253 }
254 }
255
256 answer.symmetrized();
257}
258
259
260void StructuralElementEvaluator :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, bool useUpdatedGpRecord)
261{
262 Element *elem = this->giveElement();
263 int ndofs = elem->computeNumberOfDofs();
264 FloatMatrix b;
265 FloatArray strain, stress, u, temp;
266 IntArray irlocnum;
267
268 elem->computeVectorOf(VM_Total, tStep, u);
269
270 answer.resize(ndofs);
271 answer.zero();
272 FloatArray *m = & answer;
273 if ( elem->giveInterpolation()->hasSubPatchFormulation() ) {
274 m = & temp;
275 }
276
277 int numberOfIntegrationRules = elem->giveNumberOfIntegrationRules();
278 // loop over individual integration rules
279 for ( int ir = 0; ir < numberOfIntegrationRules; ir++ ) {
280 m->clear();
281 IntegrationRule *iRule = elem->giveIntegrationRule(ir);
282 for ( GaussPoint *gp: *iRule ) {
283 this->computeBMatrixAt(b, gp);
284 if ( useUpdatedGpRecord ) {
285 stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector();
286 } else {
287 this->computeStrainVector(strain, gp, tStep, u);
288 this->computeStressVector(stress, strain, gp, tStep);
289 }
290
291 if ( stress.giveSize() == 0 ) {
292 break;
293 }
294
295 // compute nodal representation of internal forces using f = B^T*Sigma dV
296 double dV = this->computeVolumeAround(gp);
297 m->plusProduct(b, stress, dV);
298 }
299 // localize irule contribution into element matrix
300 if ( this->giveIntegrationElementLocalCodeNumbers(irlocnum, elem, iRule) ) {
301 answer.assemble(* m, irlocnum);
302 }
303 } // end loop over irules
304
305 // if inactive update state, but no contribution to global system
306 if ( !this->isActivated(tStep) ) {
307 answer.zero();
308 }
309}
310
311
312void StructuralElementEvaluator :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u)
313// Computes the vector containing the strains at the Gauss point gp of
314// the receiver, at time step tStep. The nature of these strains depends
315// on the element's type.
316{
317 FloatMatrix b;
318 FloatArray ur;
319 Element *elem = this->giveElement();
320
321 if ( !this->isActivated(tStep) ) {
322 answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) );
323 answer.zero();
324 return;
325 }
326
327 this->computeBMatrixAt(b, gp);
328
329 // get local code numbers corresponding to ir
330 IntArray lc;
332 ur.resize( b.giveNumberOfColumns() );
333 for ( int i = 1; i <= lc.giveSize(); i++ ) {
334 ur.at(i) = u.at( lc.at(i) );
335 }
336
337 answer.beProductOf(b, ur);
338}
339
340void StructuralElementEvaluator :: updateInternalState(TimeStep *tStep)
341// Updates the receiver at end of step.
342{
343 FloatArray u;
344 Element *elem = this->giveElement();
345
346 elem->computeVectorOf(VM_Total, tStep, u);
347
348#if 0
349 // subtract initial displacements, if defined
350 if ( initialDisplacements ) {
351 u.subtract(initialDisplacements);
352 }
353#endif
354
355 FloatArray strain, stress;
356
357 // force updating strains & stresses
358 for ( int i = 0; i < elem->giveNumberOfIntegrationRules(); i++ ) {
359#ifdef __MPI_PARALLEL_MODE
360 if ( this->giveElement()->giveKnotSpanParallelMode(i) == Element_remote ) {
361 continue;
362 }
363#endif
364 for ( GaussPoint *gp: *elem->giveIntegrationRule(i) ) {
365 this->computeStrainVector(strain, gp, tStep, u);
366 this->computeStressVector(stress, strain, gp, tStep);
367 }
368 }
369}
370
371
372void StructuralElementEvaluator :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
373{
374 int numberOfIntegrationRules;
375 FloatMatrix temp, bj, d, dbj;
376 Element *elem = this->giveElement();
377 StructuralCrossSection *cs = static_cast< StructuralCrossSection * >( elem->giveCrossSection() );
378 int ndofs = elem->computeNumberOfDofs();
379 bool matStiffSymmFlag = cs->isCharacteristicMtrxSymmetric(rMode);
380 IntArray irlocnum;
381
382 answer.resize(ndofs, ndofs);
383 answer.zero();
384
385 FloatMatrix *m = & answer;
386 if ( elem->giveInterpolation()->hasSubPatchFormulation() ) {
387 m = & temp;
388 }
389
390 numberOfIntegrationRules = elem->giveNumberOfIntegrationRules();
391 // loop over individual integration rules
392 for ( int ir = 0; ir < numberOfIntegrationRules; ir++ ) {
393#ifdef __MPI_PARALLEL_MODE
394 if ( this->giveElement()->giveKnotSpanParallelMode(ir) == Element_remote ) {
395 continue;
396 }
397 //fprintf (stderr, "[%d] Computing element.knotspan %d.%d\n", elem->giveDomain()->giveEngngModel()->giveRank(), elem->giveNumber(), ir);
398#endif
399 m->clear();
400 IntegrationRule *iRule = elem->giveIntegrationRule(ir);
401 // loop over individual integration points
402 for ( GaussPoint *gp: *iRule ) {
403 double dV = this->computeVolumeAround(gp);
404 this->computeBMatrixAt(bj, gp);
405 this->computeConstitutiveMatrixAt(d, rMode, gp, tStep);
406
407 dbj.beProductOf(d, bj);
408 if ( matStiffSymmFlag ) {
409 m->plusProductSymmUpper(bj, dbj, dV);
410 } else {
411 m->plusProductUnsym(bj, dbj, dV);
412 }
413 }
414
415 if ( matStiffSymmFlag ) {
416 m->symmetrized();
417 }
418
419 // localize irule contribution into element matrix
420 if ( this->giveIntegrationElementLocalCodeNumbers(irlocnum, elem, iRule) ) {
421 answer.assemble(* m, irlocnum);
422 }
423 } // end loop over irules
424}
425} // end namespace oofem
virtual double give(CrossSectionProperty a, GaussPoint *gp) const
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual int computeNumberOfDofs()
Definition element.h:436
virtual void giveDofManDofIDMask(int inode, IntArray &answer) const
Definition element.h:488
int giveNumberOfIntegrationRules()
Definition element.h:894
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
virtual IntegrationRule * giveIntegrationRule(int i)
Definition element.h:899
virtual int giveNumberOfDofManagers() const
Definition element.h:695
CrossSection * giveCrossSection()
Definition element.C:534
virtual Element_Geometry_Type giveGeometryType() const =0
virtual int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) const
Definition feinterpol.h:517
virtual bool hasSubPatchFormulation() const
Definition feinterpol.h:526
virtual int giveNsd(const Element_Geometry_Type) const =0
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
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 subtract(const FloatArray &src)
Definition floatarray.C:320
void times(double f)
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
void plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
int giveNumberOfColumns() const
Returns number of columns of receiver.
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void zero()
Zeroes all coefficient of receiver.
int giveNumberOfRows() const
Returns number of rows of receiver.
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
IntegrationRule * giveIntegrationRule()
Returns corresponding integration rule to receiver.
Definition gausspoint.h:185
const IntArray * giveKnotSpan() override
Returns receiver sub patch indices (if apply).
Definition iga.h:82
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resize(int n)
Definition intarray.C:73
bool isEmpty() const
Definition intarray.h:217
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
bool isCharacteristicMtrxSymmetric(MatResponseMode mode) const override=0
virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, bool useUpdatedGpRecord=false)
virtual void computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp)=0
virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep)=0
virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep)
virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass)
virtual double computeVolumeAround(GaussPoint *gp)
virtual void giveMassMtrxIntegrationMask(IntArray &answer)
void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u)
virtual Element * giveElement()=0
virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep)=0
virtual void computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp)=0
virtual int giveIntegrationElementLocalCodeNumbers(IntArray &answer, Element *elem, IntegrationRule *ie)
virtual IntegrationRule * giveMassMtrxIntegrationRule()
StructuralCrossSection * giveStructuralCrossSection()
Helper function which returns the structural cross-section for the element.
const FloatArray & giveStressVector() const
Returns the const pointer to receiver's stress vector.
#define OOFEM_ERROR(...)
Definition error.h:79
@ Element_remote
Element in active domain is only mirror of some remote element.
Definition element.h:89
const char * __CharTypeToString(CharType _value)
Definition cltypes.C:338

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