OOFEM 3.0
Loading...
Searching...
No Matches
fei2dquadquad.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 "fei2dquadquad.h"
36#include "mathfem.h"
37#include "floatmatrix.h"
38#include "floatarray.h"
39#include "floatarrayf.h"
40#include "floatmatrixf.h"
42
43namespace oofem {
44double
45FEI2dQuadQuad :: giveArea(const FEICellGeometry &cellgeo) const
46{
47 double x1, x2, x3, x4, y1, y2, y3, y4;
48 double x85, x56, x67, x78, y85, y56, y67, y78;
49
50 const auto &node1 = cellgeo.giveVertexCoordinates(1);
51 const auto &node2 = cellgeo.giveVertexCoordinates(2);
52 const auto &node3 = cellgeo.giveVertexCoordinates(3);
53 const auto &node4 = cellgeo.giveVertexCoordinates(4);
54 const auto &node5 = cellgeo.giveVertexCoordinates(5);
55 const auto &node6 = cellgeo.giveVertexCoordinates(6);
56 const auto &node7 = cellgeo.giveVertexCoordinates(7);
57 const auto &node8 = cellgeo.giveVertexCoordinates(8);
58
59 x1 = node1.at(xind);
60 x2 = node2.at(xind);
61 x3 = node3.at(xind);
62 x4 = node4.at(xind);
63
64 y1 = node1.at(yind);
65 y2 = node2.at(yind);
66 y3 = node3.at(yind);
67 y4 = node4.at(yind);
68
69 x85 = node8.at(xind) - node5.at(xind);
70 x56 = node5.at(xind) - node6.at(xind);
71 x67 = node6.at(xind) - node7.at(xind);
72 x78 = node7.at(xind) - node8.at(xind);
73
74 y85 = node8.at(yind) - node5.at(yind);
75 y56 = node5.at(yind) - node6.at(yind);
76 y67 = node6.at(yind) - node7.at(yind);
77 y78 = node7.at(yind) - node8.at(yind);
78
79 double p1 = ( x2 - x4 ) * ( y1 - y3 ) - ( x1 - x3 ) * ( y2 - y4 );
80 double p2 = y1 * x85 + y2 * x56 + y3 * x67 + y4 * x78 - x1 * y85 - x2 * y56 - x3 * y67 - x4 * y78;
81
82 return fabs(p1 + p2 * 4.0) / 6.; // Expression derived with mathematica, but not verified in any computations
83}
84
85
87FEI2dQuadQuad :: evalN(const FloatArrayF<2> &lcoords)
88{
89 double ksi = lcoords[0];
90 double eta = lcoords[1];
91 return {
92 ( 1. + ksi ) * ( 1. + eta ) * 0.25 * ( ksi + eta - 1. ),
93 ( 1. - ksi ) * ( 1. + eta ) * 0.25 * ( -ksi + eta - 1. ),
94 ( 1. - ksi ) * ( 1. - eta ) * 0.25 * ( -ksi - eta - 1. ),
95 ( 1. + ksi ) * ( 1. - eta ) * 0.25 * ( ksi - eta - 1. ),
96 0.5 * ( 1. - ksi * ksi ) * ( 1. + eta ),
97 0.5 * ( 1. - ksi ) * ( 1. - eta * eta ),
98 0.5 * ( 1. - ksi * ksi ) * ( 1. - eta ),
99 0.5 * ( 1. + ksi ) * ( 1. - eta * eta )
100 };
101}
102
103
104void
105FEI2dQuadQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
106{
107 double ksi = lcoords.at(1);
108 double eta = lcoords.at(2);
109
110 answer = Vec8(
111 ( 1. + ksi ) * ( 1. + eta ) * 0.25 * ( ksi + eta - 1. ),
112 ( 1. - ksi ) * ( 1. + eta ) * 0.25 * ( -ksi + eta - 1. ),
113 ( 1. - ksi ) * ( 1. - eta ) * 0.25 * ( -ksi - eta - 1. ),
114 ( 1. + ksi ) * ( 1. - eta ) * 0.25 * ( ksi - eta - 1. ),
115 0.5 * ( 1. - ksi * ksi ) * ( 1. + eta ),
116 0.5 * ( 1. - ksi ) * ( 1. - eta * eta ),
117 0.5 * ( 1. - ksi * ksi ) * ( 1. - eta ),
118 0.5 * ( 1. + ksi ) * ( 1. - eta * eta )
119 );
120}
121
122
124FEI2dQuadQuad :: evaldNdxi(const FloatArrayF<2> &lcoords)
125{
126 double ksi = lcoords.at(1);
127 double eta = lcoords.at(2);
128
129 return {
130 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta ), // 1
131 0.25 * ( 1. + ksi ) * ( 2.0 * eta + ksi ),
132 -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta ), // 2
133 0.25 * ( 1. - ksi ) * ( 2.0 * eta - ksi ),
134 -0.25 * ( 1. - eta ) * ( -2.0 * ksi - eta ), // 3
135 -0.25 * ( 1. - ksi ) * ( -2.0 * eta - ksi ),
136 0.25 * ( 1. - eta ) * ( 2.0 * ksi - eta ), // 4
137 -0.25 * ( 1. + ksi ) * ( -2.0 * eta + ksi ),
138 -ksi * ( 1. + eta ), // 5
139 0.5 * ( 1. - ksi * ksi ),
140 -0.5 * ( 1. - eta * eta ), // 6
141 -eta * ( 1. - ksi ),
142 -ksi * ( 1. - eta ), // 7
143 -0.5 * ( 1. - ksi * ksi ),
144 0.5 * ( 1. - eta * eta ), // 83
145 -eta * ( 1. + ksi )
146 };
147}
148
149
150void FEI2dQuadQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
151{
152#if 0
153 answer = dNdxi(lcoords);
154#else
155 double ksi = lcoords.at(1);
156 double eta = lcoords.at(2);
157 answer.resize(8, 2);
158
159 // dn/dxi
160 answer.at(1, 1) = 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta );
161 answer.at(2, 1) = -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta );
162 answer.at(3, 1) = -0.25 * ( 1. - eta ) * ( -2.0 * ksi - eta );
163 answer.at(4, 1) = 0.25 * ( 1. - eta ) * ( 2.0 * ksi - eta );
164 answer.at(5, 1) = -ksi * ( 1. + eta );
165 answer.at(6, 1) = -0.5 * ( 1. - eta * eta );
166 answer.at(7, 1) = -ksi * ( 1. - eta );
167 answer.at(8, 1) = 0.5 * ( 1. - eta * eta );
168
169 answer.at(1, 2) = 0.25 * ( 1. + ksi ) * ( 2.0 * eta + ksi );
170 answer.at(2, 2) = 0.25 * ( 1. - ksi ) * ( 2.0 * eta - ksi );
171 answer.at(3, 2) = -0.25 * ( 1. - ksi ) * ( -2.0 * eta - ksi );
172 answer.at(4, 2) = -0.25 * ( 1. + ksi ) * ( -2.0 * eta + ksi );
173 answer.at(5, 2) = 0.5 * ( 1. - ksi * ksi );
174 answer.at(6, 2) = -eta * ( 1. - ksi );
175 answer.at(7, 2) = -0.5 * ( 1. - ksi * ksi );
176 answer.at(8, 2) = -eta * ( 1. + ksi );
177#endif
178}
179
180
181std::pair<double, FloatMatrixF<2,8>>
182FEI2dQuadQuad :: evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const
183{
184 auto dn = evaldNdxi(lcoords);
186 for ( std::size_t i = 1; i <= dn.cols(); i++ ) {
187 const auto &c = cellgeo.giveVertexCoordinates(i);
188 double x = c.at(xind);
189 double y = c.at(yind);
190
192 jacT(0, 0) += dn.at(1, i) * x;
193 jacT(0, 1) += dn.at(1, i) * y;
194 jacT(1, 0) += dn.at(2, i) * x;
195 jacT(1, 1) += dn.at(2, i) * y;
196 }
197
198 return {det(jacT), dot(inv(jacT), dn)};
199}
200
201
202double
203FEI2dQuadQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
204{
205#if 0
206 auto tmp = evaldNdx(lcoords, cellgeo);
207 answer = tmp.second;
208 return tmp.first;
209#else
210 FloatMatrix jacobianMatrix(2, 2), inv, dn;
211
212 this->evaldNdxi(dn, lcoords, cellgeo);
213#if 1
214 cellgeo.getGeometryInterpolation()->giveJacobianMatrixAt(jacobianMatrix, lcoords, cellgeo);
215#else
216 for ( int i = 1; i <= dn.giveNumberOfRows(); i++ ) {
217 double x = cellgeo.giveVertexCoordinates(i).at(xind);
218 double y = cellgeo.giveVertexCoordinates(i).at(yind);
219
220 jacobianMatrix.at(1, 1) += dn.at(i, 1) * x;
221 jacobianMatrix.at(1, 2) += dn.at(i, 1) * y;
222 jacobianMatrix.at(2, 1) += dn.at(i, 2) * x;
223 jacobianMatrix.at(2, 2) += dn.at(i, 2) * y;
224 }
225#endif
226 inv.beInverseOf(jacobianMatrix);
227
228 answer.beProductOf(dn, inv);
229 return jacobianMatrix.giveDeterminant();
230#endif
231}
232
233void
234FEI2dQuadQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
235{
236 FloatArray n;
237
238 this->evalN(n, lcoords, cellgeo);
239
240 answer.resize(2);
241 answer.zero();
242 for ( int i = 1; i <= n.giveSize(); i++ ) {
243 answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(xind);
244 answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(yind);
245 }
246}
247
248double FEI2dQuadQuad :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const
249{
250 const auto &n1 = cellgeo.giveVertexCoordinates(1);
251 const auto &n2 = cellgeo.giveVertexCoordinates(3);
252 return distance(n1, n2);
253}
254
255bool FEI2dQuadQuad :: inside(const FloatArray &lcoords) const
256{
257 const double point_tol = 1.0e-3;
258 bool inside = true;
259 for ( int i = 1; i <= 2; i++ ) {
260 if ( lcoords.at(i) < ( -1. - point_tol ) ) {
261 inside = false;
262 } else if ( lcoords.at(i) > ( 1. + point_tol ) ) {
263 inside = false;
264 }
265 }
266
267 return inside;
268}
269
270
271void
272FEI2dQuadQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
273{
274 // 1-------3-------2
275
276 double ksi = lcoords.at(1);
277 double n3 = 1. - ksi * ksi;
278
279 answer = Vec3( ( 1. - ksi - n3 ) * 0.5, ( 1. + ksi - n3 ) * 0.5, n3 );
280}
281
282void
283FEI2dQuadQuad :: edgeEvaldNds(FloatArray &answer, int iedge,
284 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
285{
286 double ksi = lcoords.at(1);
287 answer = Vec3( ksi - 0.5, ksi + 0.5, ksi * 2.0 );
288}
289
290void
291FEI2dQuadQuad :: edgeLocal2global(FloatArray &answer, int iedge,
292 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
293{
294 FloatArray n;
295 const auto &edgeNodes = this->computeLocalEdgeMapping(iedge);
296 this->edgeEvalN(n, iedge, lcoords, cellgeo);
297
298 answer.resize(2);
299 answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) +
300 n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) +
301 n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind);
302 answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) +
303 n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) +
304 n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind);
305}
306
307
309FEI2dQuadQuad :: computeLocalEdgeMapping(int iedge) const
310{
311 if ( iedge == 1 ) { // edge between nodes 1 2
312 return {1, 2, 5};
313 } else if ( iedge == 2 ) { // edge between nodes 2 3
314 return {2, 3, 6};
315 } else if ( iedge == 3 ) { // edge between nodes 2 3
316 return {3, 4, 7};
317 } else if ( iedge == 4 ) { // edge between nodes 3 4
318 return {4, 1, 8};
319 } else {
320 throw std::range_error("invalid edge number");
321 //return {};
322 }
323}
324
325double FEI2dQuadQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
326{
327 const auto &edgeNodes = this->computeLocalEdgeMapping(iedge);
328 double xi = lcoords(0);
329 double dN1dxi = -0.5 + xi;
330 double dN2dxi = 0.5 + xi;
331 double dN3dxi = -2.0 * xi;
332
333 normal.resize(2);
334
335 normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) +
336 dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) +
337 dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind);
338
339 normal.at(2) = - dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) +
340 - dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) +
341 - dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind);
342
343 return normal.normalize_giveNorm();
344}
345
346
347double
348FEI2dQuadQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const
349{
350 auto eNodes = this->computeLocalEdgeMapping(iEdge);
351
352 const FloatArray &node1 = cellgeo.giveVertexCoordinates( eNodes.at(1) );
353 double x1 = node1.at(xind);
354 double y1 = node1.at(yind);
355
356 const FloatArray &node2 = cellgeo.giveVertexCoordinates( eNodes.at(2) );
357 double x2 = node2.at(xind);
358 double y2 = node2.at(yind);
359
360 const FloatArray &node3 = cellgeo.giveVertexCoordinates( eNodes.at(3) );
361 double x3 = node3.at(xind);
362 double y3 = node3.at(yind);
363
364 return -( x1 * y2 - x2 * y1 + 4 * ( x3 * ( y1 - y2 ) + y3 * ( x2 - x1 ) ) ) / 3.0;
365}
366
367
368std::unique_ptr<IntegrationRule>
369FEI2dQuadQuad :: giveIntegrationRule(int order, Element_Geometry_Type egt) const
370{
371 auto iRule = std::make_unique<GaussIntegrationRule>(1, nullptr);
372 int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 4);
373 iRule->SetUpPointsOnSquare(points, _Unknown);
374 return std::move(iRule);
375}
376
377
378/*
379 * FEI2dQuadQuadAxi element
380 */
381double
382FEI2dQuadQuadAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
383{
385 this->evalN( N, lcoords, cellgeo);
386
387 double r = 0.0;
388 for ( int i = 1; i <= 8; i++ ) {
389 double x = cellgeo.giveVertexCoordinates(i).at(1);
390 r += x * N.at(i);
391 }
392
393 return r * FEI2dQuadQuad::giveTransformationJacobian(lcoords, cellgeo);
394}
395
396double
398 const FEICellGeometry &cellgeo) const
399{
400 FloatArray n;
401 const auto &edgeNodes = this->computeLocalEdgeMapping(iedge);
402 this->edgeEvalN(n, iedge, lcoords, cellgeo);
403
404 double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1)).at(1) +
405 n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2)).at(1) +
406 n.at(3)*cellgeo.giveVertexCoordinates(edgeNodes.at(3)).at(1);
407 return r * FEI2dQuadQuad::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo);
408
409}
410
411double
413{
414 return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo);
415}
416
417double
418FEI2dQuadQuadAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
419{
420 return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo);
421}
422
423} // end namespace oofem
#define N(a, b)
double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
static FloatMatrixF< 2, 8 > evaldNdxi(const FloatArrayF< 2 > &lcoords)
std::pair< double, FloatMatrixF< 2, 8 > > evaldNdx(const FloatArrayF< 2 > &lcoords, const FEICellGeometry &cellgeo) const
IntArray computeLocalEdgeMapping(int iedge) const override
bool inside(const FloatArray &lcoords) const override
void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
static FloatArrayF< 8 > evalN(const FloatArrayF< 2 > &lcoords)
virtual const FloatArray giveVertexCoordinates(int i) const =0
virtual const FEInterpolation * getGeometryInterpolation() const
Definition feinterpol.h:74
virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
Definition feinterpol.C:81
virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
Definition feinterpol.h:284
double & at(std::size_t i)
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
double normalize_giveNorm()
Definition floatarray.C:850
double at(std::size_t i, std::size_t j) const
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
double det(const FloatMatrixF< 2, 2 > &mat)
Computes the determinant.
static FloatArray Vec8(const double &a, const double &b, const double &c, const double &d, const double &e, const double &f, const double &g, const double &h)
Definition floatarray.h:612
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< N, N > inv(const FloatMatrixF< N, N > &mat, double zeropiv=1e-24)
Computes the inverse.
double distance(const FloatArray &x, const FloatArray &y)
static FloatArray Vec3(const double &a, const double &b, const double &c)
Definition floatarray.h:607

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