OOFEM 3.0
Loading...
Searching...
No Matches
fei3dtrquad.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 "fei3dtrquad.h"
36#include "mathfem.h"
37#include "floatmatrix.h"
38#include "floatarray.h"
40#include <stdexcept>
41
42namespace oofem {
43void
44FEI3dTrQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
45{
46 this->surfaceEvalN(answer, 1, lcoords, cellgeo);
47}
48
49double
50FEI3dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
51{
52 OOFEM_ERROR("FEI3dTrQuad :: evaldNdx - Not supported");
53 //return 0.;
54}
55
56
57void
58FEI3dTrQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
59{
60 this->surfaceEvaldNdxi(answer, lcoords);
61}
62
63
64void
65FEI3dTrQuad :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) const
66{
67 double l1, l2, l3;
68
69 l1 = lc.at(1);
70 l2 = lc.at(2);
71 l3 = 1.0 - l1 - l2;
72
73 n.resize(6);
74
75 n.at(1) = 4.0 * l1 - 1.0;
76 n.at(2) = 0.0;
77 n.at(3) = -1.0 * ( 4.0 * l3 - 1.0 );
78 n.at(4) = 4.0 * l2;
79 n.at(5) = -4.0 * l2;
80 n.at(6) = 4.0 * l3 - 4.0 * l1;
81}
82
83void
84FEI3dTrQuad :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) const
85{
86 double l1, l2, l3;
87
88 l1 = lc.at(1);
89 l2 = lc.at(2);
90 l3 = 1.0 - l1 - l2;
91
92 n.resize(6);
93
94 n.at(1) = 0.0;
95 n.at(2) = 4.0 * l2 - 1.0;
96 n.at(3) = -1.0 * ( 4.0 * l3 - 1.0 );
97 n.at(4) = 4.0 * l1;
98 n.at(5) = 4.0 * l3 - 4.0 * l2;
99 n.at(6) = -4.0 * l1;
100}
101
102
103void
104FEI3dTrQuad :: giveLocalNodeCoords(FloatMatrix &answer,const Element_Geometry_Type) const
105{
106
107 answer.resize(3,6);
108 answer.zero();
109 answer.at(1,1) = 1.0;
110 answer.at(1,2) = 0.0;
111 answer.at(1,3) = 0.0;
112 answer.at(1,4) = 0.5;
113 answer.at(1,5) = 0.0;
114 answer.at(1,6) = 0.5;
115
116 answer.at(2,1) = 0.0;
117 answer.at(2,2) = 1.0;
118 answer.at(2,3) = 0.0;
119 answer.at(2,4) = 0.5;
120 answer.at(2,5) = 0.5;
121 answer.at(2,6) = 0.0;
122
123}
124
125
126void
127FEI3dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
128{
129 FloatArray n;
130 this->evalN(n, lcoords, cellgeo);
131 answer.clear();
132 for ( int i = 1; i <= 6; ++i ) {
133 answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) );
134 }
135}
136
137#define POINT_TOL 1.e-3
138int
139FEI3dTrQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const
140{
141 //OOFEM_ERROR("FEI3dTrQuad :: global2local - Not supported");
142 //return -1;
143
145 int xind = 1;
146 int yind = 2;
147
148 double x1 = cellgeo.giveVertexCoordinates(1).at(xind);
149 double x2 = cellgeo.giveVertexCoordinates(2).at(xind);
150 double x3 = cellgeo.giveVertexCoordinates(3).at(xind);
151
152 double y1 = cellgeo.giveVertexCoordinates(1).at(yind);
153 double y2 = cellgeo.giveVertexCoordinates(2).at(yind);
154 double y3 = cellgeo.giveVertexCoordinates(3).at(yind);
155
156 double detJ = x1*(y2 - y3) + x2*(-y1 + y3) + x3*(y1 - y2);
157
158 answer.resize(3);
159 answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * gcoords.at(xind) + ( x3 - x2 ) * gcoords.at(yind) ) / detJ;
160 answer.at(2) = ( ( x3 * y1 - x1 * y3 ) + ( y3 - y1 ) * gcoords.at(xind) + ( x1 - x3 ) * gcoords.at(yind) ) / detJ;
161 answer.at(3) = 1. - answer.at(1) - answer.at(2);
162
163 // check if point is inside
164 bool inside = true;
165 for ( int i = 1; i <= 3; i++ ) {
166 if ( answer.at(i) < ( 0. - POINT_TOL ) ) {
167 answer.at(i) = 0.;
168 inside = false;
169 } else if ( answer.at(i) > ( 1. + POINT_TOL ) ) {
170 answer.at(i) = 1.;
171 inside = false;
172 }
173 }
174
175 return inside;
176
177}
178
179
180void
181FEI3dTrQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
182{
183 OOFEM_ERROR("Not supported");
184}
185
186
187void
188FEI3dTrQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
189{
190 double xi = lcoords.at(1);
191 answer.resize(3);
192 answer[0] = 0.5 * ( xi - 1.0 ) * xi;
193 answer[1] = 0.5 * ( xi + 1.0 ) * xi;
194 answer[2] = 1.0 - xi * xi;
195}
196
197
198
199void
200FEI3dTrQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge,
201 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
202{
203 OOFEM_ERROR("Not supported");
204}
205
206void
207FEI3dTrQuad :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
208{
209 double xi = lcoords.at(1);
210 answer.resize(3);
211 answer[0] = xi - 0.5;
212 answer[1] = xi + 0.5;
213 answer[2] = -2 * xi;
214}
215
216void
217FEI3dTrQuad :: edgeLocal2global(FloatArray &answer, int iedge,
218 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
219{
221 const auto &edgeNodes = this->computeLocalEdgeMapping(iedge);
222 this->edgeEvalN(N, iedge, lcoords, cellgeo);
223
224 answer.clear();
225 for ( int i = 0; i < N.giveSize(); ++i ) {
226 answer.add( N[i], cellgeo.giveVertexCoordinates( edgeNodes[i] ) );
227 }
228}
229
230
231double
232FEI3dTrQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
233{
234 FloatArray dNdu;
235 double u = lcoords.at(1);
236 const auto &eNodes = this->computeLocalEdgeMapping(iedge);
237 dNdu.add( u - 0.5, cellgeo.giveVertexCoordinates( eNodes.at(1) ) );
238 dNdu.add( u + 0.5, cellgeo.giveVertexCoordinates( eNodes.at(2) ) );
239 dNdu.add( -2. * u, cellgeo.giveVertexCoordinates( eNodes.at(3) ) );
240 return dNdu.computeNorm();
241}
242
243
245FEI3dTrQuad :: computeLocalEdgeMapping(int iedge) const
246{
247 if ( iedge == 1 ) { // edge between nodes 1 2
248 return {1, 2, 4};
249 } else if ( iedge == 2 ) { // edge between nodes 2 3
250 return {2, 3, 5};
251 } else if ( iedge == 3 ) { // edge between nodes 2 3
252 return {3, 1, 6};
253 } else {
254 throw std::range_error("invalid edge number");
255 //return {};
256 }
257}
258
259double
260FEI3dTrQuad :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const
261{
263 OOFEM_ERROR("Not supported");
264 //return -1;
265}
266
267void
268FEI3dTrQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
269{
270 double l1 = lcoords.at(1);
271 double l2 = lcoords.at(2);
272 double l3 = 1. - l1 - l2;
273
274 answer.resize(6);
275
276 answer.at(1) = ( 2. * l1 - 1. ) * l1;
277 answer.at(2) = ( 2. * l2 - 1. ) * l2;
278 answer.at(3) = ( 2. * l3 - 1. ) * l3;
279 answer.at(4) = 4. * l1 * l2;
280 answer.at(5) = 4. * l2 * l3;
281 answer.at(6) = 4. * l3 * l1;
282}
283
284void
285FEI3dTrQuad :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const
286{
287 // Returns matrix with derivatives wrt local coordinates
288 answer.resize(6, 2);
289 FloatArray dndxi(6), dndeta(6);
290
291 this->giveDerivativeXi(dndxi, lcoords);
292 this->giveDerivativeEta(dndeta, lcoords);
293 for ( int i = 1; i <= 6; ++i ) {
294 answer.at(i, 1) = dndxi.at(i);
295 answer.at(i, 2) = dndeta.at(i);
296 }
297}
298
299
300
301void
302FEI3dTrQuad :: surfaceLocal2global(FloatArray &answer, int isurf,
303 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
304{
305 //Note: This gives the coordinate in the reference system
307 this->surfaceEvalN(N, isurf, lcoords, cellgeo);
308
309 answer.clear();
310 for ( int i = 1; i <= N.giveSize(); ++i ) {
311 answer.add( N.at(i), cellgeo.giveVertexCoordinates(i) );
312 }
313}
314
315void
316FEI3dTrQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
317{
319 OOFEM_ERROR("Not supported");
320}
321
322void
323FEI3dTrQuad :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
324{
325 // Note: These are not normalized. Returns the two tangent vectors to the surface.
326 FloatMatrix dNdxi;
327 this->surfaceEvaldNdxi(dNdxi, lcoords);
328
329 G1.clear();
330 G2.clear();
331 for ( int i = 0; i < 6; ++i ) {
332 G1.add( dNdxi(i, 1), cellgeo.giveVertexCoordinates(i) );
333 G2.add( dNdxi(i, 2), cellgeo.giveVertexCoordinates(i) );
334 }
335}
336
337double
338FEI3dTrQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
339{
340 FloatArray G1, G2; // local curvilinear base vectors
341 this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo);
342 answer.beVectorProductOf(G1, G2);
343 double J = answer.computeNorm();
344 answer.times(1 / J);
345 return J;
346}
347
348void
349FEI3dTrQuad :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
350{
351 // Jacobian matrix consists of the three curvilinear base vectors. The third is taken as the normal to the surface.
352 // Note! The base vectors are not normalized except the third (normal)
353 FloatArray G1, G2, G3;
354 this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo);
355 G3.beVectorProductOf(G1, G2);
356
357 jacobianMatrix.resize(3, 3);
358 jacobianMatrix.at(1, 1) = G1.at(1);
359 jacobianMatrix.at(1, 2) = G2.at(1);
360 jacobianMatrix.at(1, 3) = G3.at(1);
361 jacobianMatrix.at(2, 1) = G1.at(2);
362 jacobianMatrix.at(2, 2) = G2.at(2);
363 jacobianMatrix.at(2, 3) = G3.at(2);
364 jacobianMatrix.at(3, 1) = G1.at(3);
365 jacobianMatrix.at(3, 2) = G2.at(3);
366 jacobianMatrix.at(3, 3) = G3.at(3);
367}
368
369double
370FEI3dTrQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
371{
372 OOFEM_ERROR("Not supported yet");
373 //return 0;
374}
375
377FEI3dTrQuad :: computeLocalSurfaceMapping(int isurf) const
378{
379 //surfNodes.setValues(6, 1, 2, 3, 4, 5, 6);
380 //surfNodes = {1, 2, 3, 4, 5, 6};
382 return computeLocalEdgeMapping(isurf);
383
384}
385
386std::unique_ptr<IntegrationRule>
387FEI3dTrQuad :: giveIntegrationRule(int order, Element_Geometry_Type egt) const
388{
389 auto iRule = std::make_unique<GaussIntegrationRule>(1, nullptr);
390 int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order);
391 iRule->SetUpPointsOnTriangle(points, _Unknown);
392 return std::move(iRule);
393}
394
395std::unique_ptr<IntegrationRule>
396FEI3dTrQuad :: giveBoundaryIntegrationRule(int order, int boundary, Element_Geometry_Type egt) const
397{
399 OOFEM_ERROR("FEI3dTrQuad :: giveBoundaryIntegrationRule - Not supported");
400 //return nullptr;
401}
402
403
404double
405FEI3dTrQuad :: giveArea(const FEICellGeometry &cellgeo) const
406{
408 const auto &p1 = cellgeo.giveVertexCoordinates(1);
409 double x1 = p1.at(1);
410 double y1 = p1.at(2);
411 const auto &p2 = cellgeo.giveVertexCoordinates(2);
412 double x2 = p2.at(1);
413 double y2 = p2.at(2);
414 const auto &p3 = cellgeo.giveVertexCoordinates(3);
415 double x3 = p3.at(1);
416 double y3 = p3.at(2);
417 const auto &p4 = cellgeo.giveVertexCoordinates(4);
418 double x4 = p4.at(1);
419 double y4 = p4.at(2);
420 const auto &p5 = cellgeo.giveVertexCoordinates(5);
421 double x5 = p5.at(1);
422 double y5 = p5.at(2);
423 const auto &p6 = cellgeo.giveVertexCoordinates(6);
424 double x6 = p6.at(1);
425 double y6 = p6.at(2);
426
427 return (4*(-(x4*y1) + x6*y1 + x4*y2 - x5*y2 + x5*y3 - x6*y3) + x2*(y1 - y3 - 4*y4 + 4*y5) +
428 x1*(-y2 + y3 + 4*y4 - 4*y6) + x3*(-y1 + y2 - 4*y5 + 4*y6))/6;
429}
430} // end namespace oofem
#define N(a, b)
void surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
Definition fei3dtrquad.C:44
void surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const override
void giveDerivativeEta(FloatArray &n, const FloatArray &lcoords) const
Definition fei3dtrquad.C:84
void giveDerivativeXi(FloatArray &n, const FloatArray &lcoords) const
Definition fei3dtrquad.C:65
void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
IntArray computeLocalEdgeMapping(int iedge) const override
void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
virtual const FloatArray giveVertexCoordinates(int i) const =0
double computeNorm() const
Definition floatarray.C:861
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void beVectorProductOf(const FloatArray &v1, const FloatArray &v2)
Definition floatarray.C:476
void add(const FloatArray &src)
Definition floatarray.C:218
void times(double s)
Definition floatarray.C:834
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
double at(std::size_t i, std::size_t j) const
#define OOFEM_ERROR(...)
Definition error.h:79
#define POINT_TOL

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