OOFEM 3.0
Loading...
Searching...
No Matches
fei2dlinequad.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 "fei2dlinequad.h"
36#include "mathfem.h"
37#include "floatmatrix.h"
38#include "floatarray.h"
40
41namespace oofem {
42void FEI2dLineQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
43{
44 double xi = lcoords(0);
45 answer.resize(3);
46 answer(0) = 0.5 * ( xi - 1.0 ) * xi;
47 answer(1) = 0.5 * ( xi + 1.0 ) * xi;
48 answer(2) = 1.0 - xi * xi;
49}
50
51double FEI2dLineQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
52{
53 // Not meaningful to return anything.
54 answer.clear();
55 return 0.;
56}
57
58void
59FEI2dLineQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
60{
61 double xi = lcoords(0);
62 answer.resize(3, 1);
63 answer.at(1, 1) = xi - 0.5;
64 answer.at(2, 1) = xi + 0.5;
65 answer.at(3, 1) = -2.0 * xi;
66}
67
68void FEI2dLineQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
69{
70 FloatArray n;
71 this->evalN(n, lcoords, cellgeo);
72 answer.resize(2);
73 answer.at(1) = n(0) * cellgeo.giveVertexCoordinates(1).at(xind) +
74 n(1) * cellgeo.giveVertexCoordinates(2).at(xind) +
75 n(2) * cellgeo.giveVertexCoordinates(3).at(xind);
76 answer.at(2) = n(0) * cellgeo.giveVertexCoordinates(1).at(yind) +
77 n(1) * cellgeo.giveVertexCoordinates(2).at(yind) +
78 n(2) * cellgeo.giveVertexCoordinates(3).at(yind);
79}
80
81int FEI2dLineQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const
82{
83 double x1_x2, y1_y2, px_x3, py_y3, x3_x2_x1, y3_y2_y1;
84 double b0, b1, b2, b3;
85
86 x1_x2 = cellgeo.giveVertexCoordinates(1).at(xind) - cellgeo.giveVertexCoordinates(2).at(xind);
87 y1_y2 = cellgeo.giveVertexCoordinates(1).at(yind) - cellgeo.giveVertexCoordinates(2).at(yind);
88 px_x3 = gcoords.at(1) - cellgeo.giveVertexCoordinates(3).at(xind);
89 py_y3 = gcoords.at(2) - cellgeo.giveVertexCoordinates(3).at(yind);
90 x3_x2_x1 = 2 * cellgeo.giveVertexCoordinates(3).at(xind) - cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind);
91 y3_y2_y1 = 2 * cellgeo.giveVertexCoordinates(3).at(yind) - cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind);
92
93 b0 = 0.50 * ( x1_x2 * px_x3 + y1_y2 * py_y3 );
94 b1 = 0.25 * ( x1_x2 * x1_x2 + y1_y2 * y1_y2 ) + x3_x2_x1 * px_x3 + y3_y2_y1 * py_y3;
95 b2 = 0.75 * ( x1_x2 * x3_x2_x1 + y1_y2 * y3_y2_y1 );
96 b3 = 0.50 * ( x3_x2_x1 * x3_x2_x1 + y3_y2_y1 * y3_y2_y1 );
97
98 double r [ 3 ];
99 int roots;
100 cubic(b3, b2, b1, b0, & r [ 0 ], & r [ 1 ], & r [ 2 ], & roots);
101
102 // Copy them over, along with boundary cases.
103 int points = 2;
104 double p [ 5 ] = {
105 -1.0, 1.0
106 };
107 for ( int i = 0; i < roots; i++ ) {
108 if ( r [ i ] > -1.0 && r [ i ] < 1.0 ) {
109 // The cubic solver has pretty bad accuracy, performing a single newton iteration
110 // which typically improves the solution by many many orders of magnitude.
112 r [ i ] -= ( b0 + b1 * r [ i ] + b2 * r [ i ] * r [ i ] + b3 * r [ i ] * r [ i ] * r [ i ] ) / ( b1 + 2 * b2 * r [ i ] + 3 * b3 * r [ i ] * r [ i ] );
113 p [ points ] = r [ i ];
114 points++;
115 }
116 }
117
118 double min_distance2 = 0.0, min_xi = 0;
119 FloatArray f(2);
120 answer.resize(1);
121
122 for ( int i = 0; i < points; i++ ) {
123 answer(0) = p [ i ];
124 this->local2global(f, answer, cellgeo);
125 double distance2 = distance_square(f, gcoords);
126 if ( i == 0 || distance2 < min_distance2 ) {
127 min_distance2 = distance2;
128 min_xi = answer(0);
129 }
130 }
131
132 answer(0) = clamp(min_xi, -1., 1.); // Make sure to only give coordinates within the geometry.
133
134 return false; // It will never land exactly on the geometry.
135}
136
137IntArray FEI2dLineQuad :: computeLocalEdgeMapping(int iedge) const
138{
139 return {1, 2, 3};
140}
141
142void FEI2dLineQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
143{
144 this->evalN(answer, lcoords, cellgeo);
145}
146
147void FEI2dLineQuad :: edgeEvaldNds(FloatArray &answer, int iedge,
148 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
149{
150 double xi = lcoords(0);
151 answer.resize(3);
152 answer(0) = -0.5 + xi;
153 answer(1) = 0.5 + xi;
154 answer(2) = -2.0 * xi;
155
156 double es1 = answer(0) * cellgeo.giveVertexCoordinates(1).at(xind) +
157 answer(1) * cellgeo.giveVertexCoordinates(2).at(xind) +
158 answer(2) * cellgeo.giveVertexCoordinates(3).at(xind);
159
160 double es2 = answer(0) * cellgeo.giveVertexCoordinates(1).at(yind) +
161 answer(1) * cellgeo.giveVertexCoordinates(2).at(yind) +
162 answer(2) * cellgeo.giveVertexCoordinates(3).at(yind);
163
164 double J = sqrt(es1 * es1 + es2 * es2);
165 answer.times(1 / J);
166 //return J;
167}
168
169double FEI2dLineQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
170{
171 const auto &edgeNodes = this->computeLocalEdgeMapping(iedge);
172 double xi = lcoords(0);
173 double dN1dxi = -0.5 + xi;
174 double dN2dxi = 0.5 + xi;
175 double dN3dxi = -2.0 * xi;
176
177 normal.resize(2);
178
179 normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) +
180 dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) +
181 dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind);
182
183 normal.at(2) = - dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) +
184 - dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) +
185 - dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind);
186
187 return normal.normalize_giveNorm();
188}
189
190void FEI2dLineQuad :: edgeLocal2global(FloatArray &answer, int iedge,
191 const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
192{
193 this->local2global(answer, lcoords, cellgeo);
194}
195
196double FEI2dLineQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
197{
198 double xi = lcoords(0);
199 double a1 = -0.5 + xi;
200 double a2 = 0.5 + xi;
201 double a3 = -2.0 * xi;
202
203 double es1 = a1 * cellgeo.giveVertexCoordinates(1).at(xind) +
204 a2 * cellgeo.giveVertexCoordinates(2).at(xind) +
205 a3 * cellgeo.giveVertexCoordinates(3).at(xind);
206 double es2 = a1 * cellgeo.giveVertexCoordinates(1).at(yind) +
207 a2 * cellgeo.giveVertexCoordinates(2).at(yind) +
208 a3 * cellgeo.giveVertexCoordinates(3).at(yind);
209
210 return sqrt(es1 * es1 + es2 * es2);
211}
212
213void FEI2dLineQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
214{
215 double xi = lcoords(0);
216 double dN1dxi = -0.5 + xi;
217 double dN2dxi = 0.5 + xi;
218 double dN3dxi = -2.0 * xi;
219
220 double es1 = dN1dxi * cellgeo.giveVertexCoordinates(1).at(xind) +
221 dN2dxi * cellgeo.giveVertexCoordinates(2).at(xind) +
222 dN3dxi * cellgeo.giveVertexCoordinates(3).at(xind);
223 double es2 = dN1dxi * cellgeo.giveVertexCoordinates(1).at(yind) +
224 dN2dxi * cellgeo.giveVertexCoordinates(2).at(yind) +
225 dN3dxi * cellgeo.giveVertexCoordinates(3).at(yind);
226
227 double J = sqrt(es1 * es1 + es2 * es2);
228
229 // Only used for determined deformation of element, not sure about the transpose here;
230 jacobianMatrix.resize(2, 2);
231 jacobianMatrix(0, 0) = es1 / J;
232 jacobianMatrix(0, 1) = es2 / J;
233 jacobianMatrix(1, 0) = -es2 / J;
234 jacobianMatrix(1, 1) = es1 / J;
235}
236
237double FEI2dLineQuad :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const
238{
239 OOFEM_ERROR("Not implemented");
240 //return 0.0;
241}
242
243double FEI2dLineQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const
244{
245 const auto &node1 = cellgeo.giveVertexCoordinates(1);
246 double x1 = node1.at(xind);
247 double y1 = node1.at(yind);
248
249 const auto &node2 = cellgeo.giveVertexCoordinates(2);
250 double x2 = node2.at(xind);
251 double y2 = node2.at(yind);
252
253 const auto &node3 = cellgeo.giveVertexCoordinates(3);
254 double x3 = node3.at(xind);
255 double y3 = node3.at(yind);
256
257 return ( x1 * y2 - x2 * y1 + 4 * ( x3 * ( y1 - y2 ) + y3 * ( x2 - x1 ) ) ) / 3.0;
258}
259
260std::unique_ptr<IntegrationRule> FEI2dLineQuad :: giveIntegrationRule(int order, Element_Geometry_Type egt) const
261{
262 auto iRule = std::make_unique<GaussIntegrationRule>(1, nullptr);
263 int points = iRule->getRequiredNumberOfIntegrationPoints(_Line, order + 1);
264 iRule->SetUpPointsOnLine(points, _Unknown);
265 return std::move(iRule);
266}
267} // end namespace oofem
IntArray computeLocalEdgeMapping(int iedge) const override
void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override
virtual const FloatArray giveVertexCoordinates(int i) const =0
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double normalize_giveNorm()
Definition floatarray.C:850
void times(double s)
Definition floatarray.C:834
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()
double at(std::size_t i, std::size_t j) const
#define OOFEM_ERROR(...)
Definition error.h:79
void cubic(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Definition mathfem.C:43
double distance_square(const FloatArray &x, const FloatArray &y)
double clamp(int a, int lower, int upper)
Returns the clamped value of a between upper and lower.
Definition mathfem.h:88

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