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