OOFEM 3.0
Loading...
Searching...
No Matches
trwarp.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 * OOFEM : Object Oriented Finite Element Code
11 *
12 * Copyright (C) 1993 - 2025 Borek Patzak
13 *
14 *
15 *
16 * Czech Technical University, Faculty of Civil Engineering,
17 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Lesser General Public
21 * License as published by the Free Software Foundation; either
22 * version 2.1 of the License, or (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
28 *
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 */
33
34#include "trwarp.h"
35#include "node.h"
37#include "gausspoint.h"
39#include "floatmatrix.h"
40#include "floatarray.h"
41#include "intarray.h"
42#include "mathfem.h"
44#include "classfactory.h"
45#include "load.h"
47#include "engngm.h"
48#include "dof.h"
50
51
52
53namespace oofem {
55
56FEI2dTrLin Tr_Warp :: interp(1, 2);
57
58Tr_Warp :: Tr_Warp(int n, Domain *aDomain) :
60{
63}
64
65Tr_Warp :: ~Tr_Warp()
66{ }
67
68void
69Tr_Warp :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode,
70 TimeStep *tStep)
71//
72// returns characteristics vector of receiver according to mtrx
73//
74{
75 if ( mtrx == ExternalForcesVector ) {
76 // include implicit edge contribution
77 this->computeEdgeLoadVectorAt(answer, NULL, tStep, mode);
78 } else {
79 StructuralElement::giveCharacteristicVector(answer, mtrx, mode, tStep);
80 }
81}
82
83
84void
85Tr_Warp :: computeGaussPoints()
86// Sets up the array containing the Gauss point of the receiver.
87{
88 if ( integrationRulesArray.size() == 0 ) {
89 integrationRulesArray.resize(1);
90 integrationRulesArray [ 0 ] = std::make_unique<GaussIntegrationRule>(1, this, 1, 4);
91 this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this);
92 }
93}
94
95
96void
97Tr_Warp :: initializeFrom(InputRecord &ir, int priority)
98{
100 StructuralElement :: initializeFrom(ir, priority);
101}
102
103
104void
105Tr_Warp :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep)
106{
107 answer = this->giveStructuralCrossSection()->giveRealStress_Warping(strain, gp, tStep);
108}
109
110
111void
112Tr_Warp :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep)
113{
114 this->giveStructuralCrossSection()->giveCharMaterialStiffnessMatrix(answer, rMode, gp, tStep);
115}
116
117
118void
119Tr_Warp :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer)
120{
121 int numNodes = this->giveNumberOfDofManagers();
122 FloatArray N(numNodes);
123
124 // int dim = this->giveSpatialDimension();
125
126 answer.resize(1, numNodes);
127 answer.zero();
128 giveInterpolation()->evalN( N, iLocCoord, FEIElementGeometryWrapper(this) );
129
130 answer.beNMatrixOf(N, 1);
131}
132
133void
134Tr_Warp :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer,
135 int li, int ui)
136// Returns the [2x4] strain-displacement matrix {B} of the receiver, eva-
137// luated at gp.
138{
139 FloatMatrix dN;
140 FloatArray tc(2);
141 this->interp.evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
142 // gausspoint coordinates
143 FloatArray gcoords;
144 Element *elem = gp->giveElement();
145 elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() );
146
147 this->transformCoordinates( tc, gcoords, this->giveCrossSection()->giveNumber() );
148
149 answer.resize(2, 4);
150
151 answer.at(1, 1) = dN.at(1, 1);
152 answer.at(1, 2) = dN.at(2, 1);
153 answer.at(1, 3) = dN.at(3, 1);
154 answer.at(1, 4) = -tc.at(2);
155
156 answer.at(2, 1) = dN.at(1, 2);
157 answer.at(2, 2) = dN.at(2, 2);
158 answer.at(2, 3) = dN.at(3, 2);
159 answer.at(2, 4) = tc.at(1);
160}
161
162
163void
164Tr_Warp :: transformCoordinates(FloatArray &answer, FloatArray &c, const int CGnumber)
165{
166 answer.resize(2);
167 FreeWarping *em = dynamic_cast< FreeWarping * >( this->giveDomain()->giveEngngModel() );
168 if ( em ) {
169 FloatMatrix CG;
170 em->getCenterOfGravity(CG);
171 answer.at(1) = c.at(1) - CG.at(CGnumber, 1);
172 answer.at(2) = c.at(2) - CG.at(CGnumber, 2);
173 } else {
174 OOFEM_ERROR("Error during transformCoordinates");
175 }
176}
177
178void
179Tr_Warp :: computeFirstMomentOfArea(FloatArray &answer)
180// Returns the portion of the receiver which is attached to gp.
181{
182 answer.resize(2);
183
184 FloatArray gcoords;
185 GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0);
186 double A = this->computeVolumeAround(gp);
187 Element *elem = gp->giveElement();
189 answer.times(A);
190}
191
192double
193Tr_Warp :: computeVolumeAround(GaussPoint *gp)
194// Returns the portion of the receiver which is attached to gp.
195{
196 double determinant, weight, volume;
197 determinant = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) );
198 weight = gp->giveWeight();
199 volume = determinant * weight;
200 return volume;
201}
202
203void
204Tr_Warp :: giveEdgeDofMapping(IntArray &answer, int iEdge) const
205{
206 /*
207 * provides dof mapping of local edge dofs (only nonzero are taken into account)
208 * to global element dofs
209 */
210
211 answer.resize(2);
212 if ( iEdge == 1 ) { // edge between nodes 1,2
213 answer.at(1) = 1;
214 answer.at(2) = 2;
215 } else if ( iEdge == 2 ) { // edge between nodes 2 3
216 answer.at(1) = 2;
217 answer.at(2) = 3;
218 } else if ( iEdge == 3 ) { // edge between nodes 3 1
219 answer.at(1) = 3;
220 answer.at(2) = 1;
221 } else {
222 OOFEM_ERROR("wrong edge number");
223 }
224}
225
226
227void
228Tr_Warp :: computeEdgeLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode)
229{
230 // computes the edge load vector of the receiver corresponding to the inhomogeneous Neumann condition
231 // the given load is a dummy variable because the boundary condition for the warping equation
232 // is determined by the geometry and thus the load intensity is not needed
233 // (what is needed is just the indication that the given element edge is a part of the domain boundary)
234 answer.resize(4);
235 answer.zero();
236 for ( int iEdge = 1; iEdge < 4; iEdge++ ) {
237 IntArray mask;
238 this->giveEdgeDofMapping(mask, iEdge);
239
240 // coordinates of the initial and final node of the edge
241 const auto &coord1 = giveNode( mask.at(1) )->giveCoordinates();
242 const auto &coord2 = giveNode( mask.at(2) )->giveCoordinates();
243 // components of the edge vector (from the initial to the final node)
244 double dx = coord2.at(1) - coord1.at(1);
245 double dy = coord2.at(2) - coord1.at(2);
246 // coordinates of the initial node
247 double x1 = coord1.at(1);
248 double y1 = coord1.at(2);
249 // coordinates of the final node
250 double x2 = coord2.at(1);
251 double y2 = coord2.at(2);
252
253 // transform to coordinates w.r. center of gravity
254 FloatArray tc1(2), c1(2), tc2(2), c2(2);
255 c1.at(1) = x1;
256 c1.at(2) = y1;
257 this->transformCoordinates( tc1, c1, this->giveCrossSection()->giveNumber() );
258 x1 = tc1.at(1);
259 y1 = tc1.at(2);
260 c2.at(1) = x2;
261 c2.at(2) = y2;
262 this->transformCoordinates( tc2, c2, this->giveCrossSection()->giveNumber() );
263 x2 = tc2.at(1);
264 y2 = tc2.at(2);
265
266 // equivalent nodal "loads" (obtained by exact integration)
267 double f1 = ( dx * x2 + dy * y2 ) / 3.0 + ( dx * x1 + dy * y1 ) / 6.0;
268 double f2 = ( dx * x1 + dy * y1 ) / 3.0 + ( dx * x2 + dy * y2 ) / 6.0;
269
270 // the load value has the meaning of relative twist
271 double theta = this->giveDofManager(4)->giveDofWithID(24)->giveUnknown(VM_Total, tStep);
272 FloatArray reducedAnswer, b;
273 b.resize(4);
274 b.zero();
275 reducedAnswer.resize(2);
276 reducedAnswer.at(1) = f1 * theta;
277 reducedAnswer.at(2) = f2 * theta;
278 b.assemble(reducedAnswer, mask);
279 answer.add(b);
280 }
281}
282
283
284double
285Tr_Warp :: giveThicknessAt(const FloatArray &gcoords)
286{
287 return 1.;
288}
289
290
291double
292Tr_Warp :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge)
293{
294 double determinant = fabs( this->interp.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) );
295 return determinant * gp->giveWeight();
296}
297
298
299void
300Tr_Warp :: giveDofManDofIDMask(int inode, IntArray &answer) const
301{
302 // define new dof names (types) in dofiditem.h
303 if ( inode > 0 && inode < 4 ) {
304 answer = {
305 Warp_PsiTheta
306 };
307 } else {
308 OOFEM_ERROR("Wrong numer of node");
309 }
310}
311
312
313void
314Tr_Warp :: giveInternalDofManDofIDMask(int inode, IntArray &answer) const
315{
316 answer = {
317 Warp_Theta
318 };
319}
320
322Tr_Warp :: giveInternalDofManager(int i) const
323{
324 return this->giveDofManager(4);
325}
326
327
328Interface *
329Tr_Warp :: giveInterface(InterfaceType interface)
330{
331 if ( interface == SpatialLocalizerInterfaceType ) {
332 return static_cast< SpatialLocalizerInterface * >(this);
333 // } else if ( interface == EIPrimaryFieldInterfaceType ) {
334 // return static_cast< EIPrimaryFieldInterface * >(this);
335 } else if ( interface == ZZNodalRecoveryModelInterfaceType ) {
336 return static_cast< ZZNodalRecoveryModelInterface * >(this);
337 }
338
339 return NULL;
340}
341
342int
343Tr_Warp :: SpatialLocalizerI_containsPoint(const FloatArray &coords)
344{
345 FloatArray lcoords;
346 return this->computeLocalCoordinates(lcoords, coords);
347}
348
349
350void
351Tr_Warp :: ZZNodalRecoveryMI_computeNNMatrix(FloatArray &answer, InternalStateType type)
352{
353 //
354 // Returns NTN matrix (lumped) for Zienkiewicz-Zhu
355 // The size of N mtrx is (nstresses, nnodes*nstreses)
356 // Definition : sigmaVector = N * nodalSigmaVector
357 //
358 //double volume = 0.0;
359 FloatMatrix fullAnswer;
360 FloatArray n;
361 FEInterpolation *interpol = this->giveInterpolation();
363
364 if ( !interpol ) {
365 OOFEM_ERROR( "ZZNodalRecoveryMI_computeNNMatrix: Element %d not providing interpolation", this->giveNumber() );
366 }
367
368 int size = 3; //this->giveNumberOfDofManagers();
369 fullAnswer.resize(size, size);
370 fullAnswer.zero();
371 //double pok = 0.0;
372
373 for ( auto &gp : *iRule ) {
374 double dV = this->computeVolumeAround(gp);
375 interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
376 fullAnswer.plusDyadSymmUpper(n, dV);
377 //pok += ( n.at(1) * dV ); ///@todo What is this? Completely unused.
378 //volume += dV;
379 }
380
381 fullAnswer.symmetrized();
382 answer.resize(4);
383 for ( int i = 1; i <= 3; i++ ) {
384 double sum = 0.0;
385 for ( int j = 1; j <= size; j++ ) {
386 sum += fullAnswer.at(i, j);
387 }
388
389 answer.at(i) = sum;
390 }
391 answer.at(4) = 1.0;
392}
393
394bool
395Tr_Warp :: ZZNodalRecoveryMI_computeNValProduct(FloatMatrix &answer, InternalStateType type,
396 TimeStep *tStep)
397{ // evaluates N^T sigma over element volume
398 // N(nsigma, nsigma*nnodes)
399 // Definition : sigmaVector = N * nodalSigmaVector
400 FloatArray stressVector, n;
401 FEInterpolation *interpol = this->giveInterpolation();
403
404 answer.clear();
405 for ( auto &gp : *iRule ) {
406 double dV = this->computeVolumeAround(gp);
407 //this-> computeStressVector(stressVector, gp, tStep);
408 if ( !this->giveIPValue(stressVector, gp, type, tStep) ) {
409 continue;
410 }
411
412 interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
413 answer.plusDyadUnsym(n, stressVector, dV);
414
415 // help.beTProductOf(n,stressVector);
416 // answer.add(help.times(dV));
417 }
418 answer.resizeWithData( 4, answer.giveNumberOfColumns() );
419 for ( int i = 1; i <= answer.giveNumberOfColumns(); i++ ) {
420 answer.at(4, i) = 0.0;
421 }
422 return true;
423}
424
425void
426Tr_Warp :: postInitialize()
427{
428 Element :: postInitialize();
429 dofManArray.resizeWithValues(4);
430 WarpingCrossSection *wcs = dynamic_cast< WarpingCrossSection * >( this->giveCrossSection() );
431 dofManArray.at(4) = wcs->giveWarpingNodeNumber();
432}
433} // end namespace oofem
#define N(a, b)
#define REGISTER_Element(class)
Node * giveNode(int i) const
Definition element.h:629
IntArray dofManArray
Array containing dofmanager numbers.
Definition element.h:138
virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords)
Definition element.C:1225
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
int numberOfGaussPoints
Definition element.h:175
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
CrossSection * giveCrossSection()
Definition element.C:534
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
Definition element.C:1240
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
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 zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void add(const FloatArray &src)
Definition floatarray.C:218
void times(double s)
Definition floatarray.C:834
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 beNMatrixOf(const FloatArray &n, int nsd)
void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
void zero()
Zeroes all coefficient of receiver.
void plusDyadSymmUpper(const FloatArray &a, double dV)
double at(std::size_t i, std::size_t j) const
void getCenterOfGravity(FloatMatrix &answer)
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
Element * giveElement()
Returns corresponding element to receiver.
Definition gausspoint.h:187
double giveWeight()
Returns integration weight of receiver.
Definition gausspoint.h:180
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
SpatialLocalizerInterface(Element *element)
void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override
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
void computeEdgeLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode)
Definition trwarp.C:228
void transformCoordinates(FloatArray &answer, FloatArray &c, const int CGnumber)
Definition trwarp.C:164
FEInterpolation * giveInterpolation() const override
Definition trwarp.h:88
double computeVolumeAround(GaussPoint *gp) override
Definition trwarp.C:193
static FEI2dTrLin interp
Definition trwarp.h:53
void giveEdgeDofMapping(IntArray &answer, int iEdge) const override
Definition trwarp.C:204
ZZNodalRecoveryModelInterface(Element *element)
Constructor.
#define OOFEM_ERROR(...)
Definition error.h:79
double sum(const FloatArray &x)
@ ZZNodalRecoveryModelInterfaceType
@ SpatialLocalizerInterfaceType

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