OOFEM 3.0
Loading...
Searching...
No Matches
fei3dwedgelin.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 "fei3dwedgelin.h"
36#include "floatarray.h"
37#include "floatmatrix.h"
38#include "floatarrayf.h"
39#include "floatmatrixf.h"
40#include "intarray.h"
42
43namespace oofem {
44
46FEI3dWedgeLin :: evalN(const FloatArrayF<3> &lcoords)
47{
48 double u = lcoords[0];
49 double v = lcoords[1];
50 double w = lcoords[2];
51 double x = 1. - u - v;
52 return {
53 0.5 * ( 1. - w ) * x,
54 0.5 * ( 1. - w ) * u,
55 0.5 * ( 1. - w ) * v,
56 0.5 * ( 1. + w ) * x,
57 0.5 * ( 1. + w ) * u,
58 0.5 * ( 1. + w ) * v,
59 };
60}
61
62
63void
64FEI3dWedgeLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
65{
66 double u, v, w;
67 answer.resize(6);
68
69 u = lcoords.at(1);
70 v = lcoords.at(2);
71 w = lcoords.at(3);
72
73 answer.at(1) = 0.5 * ( 1. - w ) * ( 1. - u - v );
74 answer.at(2) = 0.5 * ( 1. - w ) * u;
75 answer.at(3) = 0.5 * ( 1. - w ) * v;
76 answer.at(4) = 0.5 * ( 1. + w ) * ( 1. - u - v );
77 answer.at(5) = 0.5 * ( 1. + w ) * u;
78 answer.at(6) = 0.5 * ( 1. + w ) * v;
79}
80
81
83FEI3dWedgeLin :: evaldNdxi(const FloatArrayF<3> &lcoords)
84{
85 double u = lcoords.at(1);
86 double v = lcoords.at(2);
87 double w = lcoords.at(3);
88 double x = 1. - u - v;
89
90 return {
91 -0.5 * ( 1. - w ),
92 -0.5 * ( 1. - w ),
93 -0.5 * x,
94 0.5 * ( 1. - w ),
95 0.,
96 -0.5 * u,
97 0.,
98 0.5 * ( 1. - w ),
99 -0.5 * v,
100 -0.5 * ( 1. + w ),
101 -0.5 * ( 1. + w ),
102 0.5 * x,
103 0.5 * ( 1. + w ),
104 0.,
105 0.5 * u,
106 0.,
107 0.5 * ( 1. + w ),
108 0.5 * v,
109 };
110}
111
112
113void
114FEI3dWedgeLin :: evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &) const
115{
116 double u = lcoords.at(1);
117 double v = lcoords.at(2);
118 double w = lcoords.at(3);
119
120 dN.resize(6, 3);
121
122 dN.at(1, 1) = -0.5 * ( 1. - w );
123 dN.at(2, 1) = 0.5 * ( 1. - w );
124 dN.at(3, 1) = 0.;
125 dN.at(4, 1) = -0.5 * ( 1. + w );
126 dN.at(5, 1) = 0.5 * ( 1. + w );
127 dN.at(6, 1) = 0.;
128
129 dN.at(1, 2) = -0.5 * ( 1. - w );
130 dN.at(2, 2) = 0.;
131 dN.at(3, 2) = 0.5 * ( 1. - w );
132 dN.at(4, 2) = -0.5 * ( 1. + w );
133 dN.at(5, 2) = 0.;
134 dN.at(6, 2) = 0.5 * ( 1. + w );
135
136 dN.at(1, 3) = -0.5 * ( 1. - u - v );
137 dN.at(2, 3) = -0.5 * u;
138 dN.at(3, 3) = -0.5 * v;
139 dN.at(4, 3) = 0.5 * ( 1. - u - v );
140 dN.at(5, 3) = 0.5 * u;
141 dN.at(6, 3) = 0.5 * v;
142}
143
144
145std::pair<double, FloatMatrixF<3,6>>
146FEI3dWedgeLin :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo)
147{
148 auto dNduvw = evaldNdxi(lcoords);
149 FloatMatrixF<3,6> coords;
150 for ( int i = 0; i < 6; i++ ) {
151 coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i);
152 }
153 auto jacT = dotT(dNduvw, coords);
154 return {det(jacT), dot(inv(jacT), dNduvw)};
155}
156
157
158double
159FEI3dWedgeLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
160{
161 FloatMatrix jacobianMatrix, inv, dNduvw, coords;
162
163 this->evaldNdxi(dNduvw, lcoords, cellgeo);
164 coords.resize(3, 6);
165 for ( int i = 1; i <= 6; i++ ) {
166 coords.setColumn(cellgeo.giveVertexCoordinates(i), i);
167 }
168 jacobianMatrix.beProductOf(coords, dNduvw);
169 inv.beInverseOf(jacobianMatrix);
170
171 answer.beProductOf(dNduvw, inv);
172 return jacobianMatrix.giveDeterminant();
173}
174
175
176void
177FEI3dWedgeLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
178{
179 FloatArray n;
180
181 this->evalN(n, lcoords, cellgeo);
182
183 answer.clear();
184 for ( int i = 1; i <= 6; i++ ) {
185 answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) );
186 }
187}
188
189
190double FEI3dWedgeLin :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const
191{
192 const auto &n1 = cellgeo.giveVertexCoordinates(1);
193 const auto &n2 = cellgeo.giveVertexCoordinates(6);
195 return distance(n1, n2);
196}
197
198#define POINT_TOL 1.e-3
199
200int
201FEI3dWedgeLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const
202{
203 FloatArray res, delta, guess;
204 FloatMatrix jac;
205 double convergence_limit, error = 0.0;
206
207 // find a suitable convergence limit
208 convergence_limit = 1e-6 * this->giveCharacteristicLength(cellgeo);
209
210 // setup initial guess
211 answer.resize( gcoords.giveSize() );
212 answer.zero();
213
214 // apply Newton-Raphson to solve the problem
215 for ( int nite = 0; nite < 10; nite++ ) {
216 // compute the residual
217 this->local2global(guess, answer, cellgeo);
218 res.beDifferenceOf(gcoords, guess);
219
220 // check for convergence
221 error = res.computeNorm();
222 if ( error < convergence_limit ) {
223 break;
224 }
225
226 // compute the corrections
227 this->giveJacobianMatrixAt(jac, answer, cellgeo);
228 jac.solveForRhs(res, delta);
229
230 // update guess
231 answer.add(delta);
232 }
233 if ( error > convergence_limit ) { // Imperfect, could give false negatives.
234 //OOFEM_ERROR("no convergence after 10 iterations");
235 answer = Vec3(1. / 3., 1. / 3., 1. / 3.);
236 return false;
237 }
238
239 // check limits for each local coordinate [-1,1] for quadrilaterals. (different for other elements, typically [0,1]).
240 bool inside = true;
241 for ( int i = 1; i <= answer.giveSize(); i++ ) {
242 if ( answer.at(i) < ( 0. - POINT_TOL ) ) {
243 answer.at(i) = 0.;
244 inside = false;
245 } else if ( answer.at(i) > ( 1. + POINT_TOL ) ) {
246 answer.at(i) = 1.;
247 inside = false;
248 }
249 }
250
251 return inside;
252}
253
254
255double
256FEI3dWedgeLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
257{
258 FloatMatrix jacobianMatrix;
259
260 this->giveJacobianMatrixAt(jacobianMatrix, lcoords, cellgeo);
261 return jacobianMatrix.giveDeterminant();
262}
263
264
265void
266FEI3dWedgeLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
267// Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver.
268{
269 FloatMatrix dNduvw, coords;
270 this->evaldNdxi(dNduvw, lcoords, cellgeo);
271 coords.resize(3, 6);
272 for ( int i = 1; i <= 6; i++ ) {
273 coords.setColumn(cellgeo.giveVertexCoordinates(i), i);
274 }
275 jacobianMatrix.beProductOf(coords, dNduvw);
276}
277
278
279void
280FEI3dWedgeLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
281{
282 double ksi = lcoords.at(1);
283 answer.resize(2);
284 answer.at(1) = ( 1. - ksi ) * 0.5;
285 answer.at(2) = ( 1. - ksi ) * 0.5;
286}
287
288
289void
290FEI3dWedgeLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
291{
292 OOFEM_ERROR("not implemented");
293}
294
295
296void
297FEI3dWedgeLin :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
298{
299 FloatArray n;
300
301 const auto &nodes = this->computeLocalEdgeMapping(iedge);
302 this->edgeEvalN(n, iedge, lcoords, cellgeo);
303
304 answer.clear();
305 for ( int i = 1; i <= n.giveSize(); ++i ) {
306 answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) );
307 }
308}
309
310
312FEI3dWedgeLin :: computeLocalEdgeMapping(int iedge) const
313{
314 if ( iedge == 1 ) {
315 return {1, 2};
316 } else if ( iedge == 2 ) {
317 return {2, 3};
318 } else if ( iedge == 3 ) {
319 return {3, 1};
320 } else if ( iedge == 4 ) {
321 return {4, 5};
322 } else if ( iedge == 5 ) {
323 return {5, 6};
324 } else if ( iedge == 6 ) {
325 return {6, 4};
326 } else if ( iedge == 7 ) {
327 return {1, 4};
328 } else if ( iedge == 8 ) {
329 return {2, 5};
330 } else if ( iedge == 9 ) {
331 return {3, 6};
332 } else {
333 throw std::range_error("invalid edge number");
334 // return {};
335 }
336}
337
338
339double
340FEI3dWedgeLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
341{
342 OOFEM_ERROR("not implemented");
343 // return 0.0;
344}
345
346
347void
348FEI3dWedgeLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
349{
350 double ksi = lcoords.at(1);
351 double eta = lcoords.at(2);
352
353 if ( isurf <= 2 ) {
354 answer.resize(3);
355 answer.at(1) = ksi;
356 answer.at(2) = eta;
357 answer.at(3) = 1.0 - ksi - eta;
358 } else {
359 answer.resize(4);
360 answer.at(1) = ( 1. + ksi ) * ( 1. + eta ) * 0.25;
361 answer.at(2) = ( 1. - ksi ) * ( 1. + eta ) * 0.25;
362 answer.at(3) = ( 1. - ksi ) * ( 1. - eta ) * 0.25;
363 answer.at(4) = ( 1. + ksi ) * ( 1. - eta ) * 0.25;
364 }
365}
366
367
368void
369FEI3dWedgeLin :: surfaceLocal2global(FloatArray &answer, int isurf,
370 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
371{
372 FloatArray n;
373
374 const auto &nodes = this->computeLocalSurfaceMapping(isurf);
375 this->surfaceEvalN(n, isurf, lcoords, cellgeo);
376
377 answer.clear();
378 for ( int i = 1; i <= n.giveSize(); ++i ) {
379 answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) );
380 }
381}
382
383
385FEI3dWedgeLin :: computeLocalSurfaceMapping(int isurf) const
386{
387 if ( isurf == 1 ) {
388 return {1, 2, 3};
389 } else if ( isurf == 2 ) {
390 return {4, 5, 6};
391 } else if ( isurf == 3 ) {
392 return {1, 2, 5, 4};
393 } else if ( isurf == 4 ) {
394 return {2, 3, 6, 5};
395 } else if ( isurf == 5 ) {
396 return {3, 1, 4, 6};
397 } else {
398 throw std::range_error("invalid surface number");
399 //return {};
400 }
401}
402
403
404double
405FEI3dWedgeLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords,
406 const FEICellGeometry &cellgeo) const
407{
408 OOFEM_ERROR("not implemented");
409 // return 0;
410}
411
412
413std::unique_ptr<IntegrationRule>
414FEI3dWedgeLin :: giveIntegrationRule(int order, Element_Geometry_Type egt) const
415{
416 auto iRule = std::make_unique<GaussIntegrationRule>(1, nullptr);
418 //int points = iRule->getRequiredNumberOfIntegrationPoints(_Wedge, order);
419 OOFEM_WARNING("Warning.. ignoring 'order' argument: FIXME");
420 int pointsZeta = 1;
421 int pointsTriangle = 1;
422 iRule->SetUpPointsOnWedge(pointsTriangle, pointsZeta, _Unknown);
423 return std::move(iRule);
424}
425
426
427std::unique_ptr<IntegrationRule>
428FEI3dWedgeLin :: giveBoundaryIntegrationRule(int order, int boundary, Element_Geometry_Type egt) const
429{
430 auto iRule = std::make_unique<GaussIntegrationRule>(1, nullptr);
431 if ( boundary <= 2 ) {
432 int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 0);
433 iRule->SetUpPointsOnTriangle(points, _Unknown);
434 } else {
435 int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 2);
436 iRule->SetUpPointsOnSquare(points, _Unknown);
437 }
438 return std::move(iRule);
439}
440} // end namespace oofem
void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
IntArray computeLocalSurfaceMapping(int iSurf) const override
void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
static FloatArrayF< 6 > evalN(const FloatArrayF< 3 > &lcoords)
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
static FloatMatrixF< 3, 6 > evaldNdxi(const FloatArrayF< 3 > &lcoords)
double giveCharacteristicLength(const FEICellGeometry &cellgeo) const
virtual const FloatArray giveVertexCoordinates(int i) const =0
double & at(std::size_t i)
double computeNorm() const
Definition floatarray.C:861
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 beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void add(const FloatArray &src)
Definition floatarray.C:218
void setColumn(const FloatArrayF< N > &src, std::size_t c)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void setColumn(const FloatArray &src, int c)
double giveDeterminant() const
double at(std::size_t i, std::size_t j) const
bool solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose=false)
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define POINT_TOL
FloatMatrixF< N, P > dotT(const FloatMatrixF< N, M > &a, const FloatMatrixF< P, M > &b)
Computes .
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.
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