MechanicalFemPhysics
The GeMA Mechanical FEM Physics Plugin
Loading...
Searching...
No Matches
gmpInterface.h
Go to the documentation of this file.
1/************************************************************************
2**
3** Copyright (C) 2014 by Carlos Augusto Teixera Mendes
4** All rights reserved.
5**
6** This file is part of the "GeMA" software. It's use should respect
7** the terms in the license agreement that can be found together
8** with this source code.
9** It is provided AS IS, with NO WARRANTY OF ANY KIND,
10** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
11** A PARTICULAR PURPOSE.
12**
13************************************************************************/
14
24#ifndef _GEMA_PLUGIN_MECHANICAL_PHYSICS_INTERFACE_H_
25#define _GEMA_PLUGIN_MECHANICAL_PHYSICS_INTERFACE_H_
26
27
29#include <gmTrace.h>
30#include <math.h>
31
32
34template <class T> class GmpInterface : public T
35{
36public:
37 GmpInterface(const char* pluginType, GmSimulationData* simulation, QString id, QString description,
38 const GmpFemPhysicsCommonMaterialFactory* matFactory, const GmLogCategory& logger)
39 : T(pluginType, simulation, id, description, matFactory, logger)
40 {}
41
42protected:
43 // Comments on the base class
44 virtual double fillBuMatrix(const GmElement* e, const GmShape* shape, const GmVector& ip, const GmMatrix& MX, const GmVector& N, const GmMatrix& J, GmMatrix& Bu)
45 {
46 S_TRACE();
47 assert(e); Q_UNUSED(MX); Q_UNUSED(N);
48 int cNodes, inNode, nv;
49 // Node Number and intermediate node number for quadratic interface element
50 int n = e->numNodes();
51 int d = GmpFemPhysicsCommon::nodeDim();
52
53 auto eType = e->type();
54 if (eType == GM_INT2DL6)
55 {
56 n = n - pow(2, d - 1);
57 }
58
59 // Compute the number of intermediate nodes and corner nodes
60
61 //int cNodes = pow(2, d - 1);
62 if (eType == GM_INT3DL6 || eType == GM_INT3DQ12)
63 {
64 inNode = (n - 3.0 * (d - 1)) / 2.0;
65 }
66 else
67 {
68 inNode = (n - pow(2.0, d)) / 2.0;
69 }
70
71 cNodes = 0.5 * n - inNode;
72
73 double detJ;
74 GmVector H;
75 GmMatrix R(d,d);
76
77 double detScale = 1.0;
78 //Elements based on triangle mus have its determinant scaled by 1/2
79 if (eType == GM_INT3DL6 || eType == GM_INT3DL9 || eType == GM_INT3DQ12 || eType == GM_INT3DQ15) {
80 detScale = 0.5;
81 }
82
83 assert(Bu.n_rows == d && Bu.n_cols == n*d);
84 // read the shapes values
85 shape->shapeValues(ip, H);
86 // 2D interface element
87 if (d == 2)
88 {
89 // compute determinant of the jacobian matrix
90 detJ = shape->scaledJacobianDet(J);
91 // fill the 2D rotation matrix
92 R(0, 0) = J(0, 0) / detJ;
93 R(0, 1) = J(0, 1) / detJ;
94 R(1, 0) = -R(0, 1);
95 R(1, 1) = R(0, 0);
96 }
97 // 3D interface element
98 else if (d == 3)
99 {
100 double J1 = 0.0, J2 = 0.0, J3 = 0.0;
101
102 J1 = J(0, 1)*J(1, 2) - J(1, 1)*J(0, 2);
103 J2 = J(1, 0)*J(0, 2) - J(0, 0)*J(1, 2);
104 J3 = J(0, 0)*J(1, 1) - J(1, 0)*J(0, 1);
105
106 double detJ1, detJ2;
107 detJ2 = sqrt(J1 * J1 + J2 * J2 + J3 * J3);
108 // scaled determinant of the Jacobian matrix
109 //Should be equal to scaledJacobianDet(J)
110 detJ = detJ2 * detScale;
111
112 // fill the 3D rotation matrix
113 // | Vs | V_xi / |V_xi|
114 // _R(3x3) = | Vt | = (Vn x Vs) / |(Vn x Vs)|
115 // | Vn | (V_xi x V_Eta) / |(V_xi x V_Eta)|
116
117
118 //Tangential Vs at shear direction 1
119 detJ1 = sqrt(J(0, 0)*J(0, 0) + J(0, 1)*J(0, 1) + J(0, 2)*J(0, 2));
120 R(0, 0) = J(0, 0) / detJ1; // Vs(0,0)
121 R(0, 1) = J(0, 1) / detJ1; // Vs(0,1)
122 R(0, 2) = J(0, 2) / detJ1; // Vs(0,2)
123 //Normal Vn at normal direction 3
124 R(2, 0) = J1 / detJ2; // Vn(0,0)
125 R(2, 1) = J2 / detJ2; // Vn(0,1)
126 R(2, 2) = J3 / detJ2; // Vn(0,2)
127 //Tangential Vt at shear direction 2
128 R(1, 0) = R(2, 1)*R(0, 2) - R(0, 1)*R(2, 2); // Vt(0,0)
129 R(1, 1) = R(0, 0)*R(2, 2) - R(2, 0)*R(0, 2); // Vt(0,1)
130 R(1, 2) = R(2, 0)*R(0, 1) - R(0, 0)*R(2, 1); // Vt(0,2)
131 //*/
132 //
133# if 0
134 double dipdir, dip2, dip, strike;
135 GmVector N2(3);
136 // unit vector at normal direction
137 N2(0) = J3 / detJ; // Un(0)
138 N2(1) = -J2 / detJ; // Un(1)
139 N2(2) = J1 / detJ; // Un(2)
140
141 dipdir =angleAtanD (N2(0),N2(1));
142
143 if (N2(2) > 0.00)
144 {
145 dip2 = 90.0 - angleAtanD(abs(N2(2)), sqrt(N2(0)*N2(0) + N2(1)*N2(1)));
146 }
147 else
148 {
149 dip2 = 90.00 + angleAtanD(abs(N2(2)),sqrt(N2(0)*N2(0)+N2(1)*N2(1)));
150 }
151
152 dip = -M_PI*(180 + dip2) / 180.0;
153 strike = M_PI*(90+dipdir)/180;
154
155 R(0, 0) = sin(strike); R(0, 1) = cos(strike); R(0, 2) = 0;
156 R(1, 0) = cos(dip)*cos(strike); R(1, 1) = -cos(dip)*sin(strike); R(1, 2) = -sin(dip);
157 R(2, 0) = -sin(dip)*cos(strike); R(2, 1) = sin(dip)*sin(strike); R(2, 2) = -cos(dip);
158# endif
159
160 # if 0
161 double easting, northing, dip, strike;
162 GmVector N2(3);
163
164 // unit vector at normal direction
165 N2(0) = J3 / detJ; // Un(0)
166 N2(1) = -J2 / detJ; // Un(1)
167 N2(2) = J1 / detJ; // Un(2)
168 //N(0) = -0.7715;
169 //N(1) = 0.6172;
170 //N(2) = -0.1543;
171
172 easting = (N2(2) < 0) ? N2(1) : -N2(1);
173
174 northing = (N2(2) > 0) ? N2(0) : -N2(0);
175
176 dip = abs(asin(sqrt(N2(0)*N2(0) + N2(1)*N2(1))));
177
178 strike = acos(northing / sqrt(easting*easting + northing*northing));
179
180 strike = (easting>= 0.0)? strike : (2 * M_PI - strike);
181
182 R(0, 0) = sin(strike); R(0, 1) = cos(strike); R(0, 2) = 0;
183 R(1, 0) = cos(dip)*cos(strike); R(1, 1) = -cos(dip)*sin(strike); R(1, 2) = -sin(dip);
184 R(2, 0) = -sin(dip)*cos(strike); R(2, 1) = sin(dip)*sin(strike); R(2, 2) = -cos(dip);
185 //R = R.t();
186 #endif
187 }
188 else
189 {
190 gmErrorMsg(logger(), QObject::tr("gmpInterface: Unsupported condition in fillStrainDisplacementMatrix"));
191 }
192
193 // Fill matrix B
194 // fill the matrix B with zeros.
195 Bu.zeros();
196 nv = 2 * cNodes;
197 // fill the matrix B for corner nodes
198 for (int i = 0; i < d; ++i)
199 {
200 for (int j = 0; j < cNodes; ++j)
201 {
202 if (d == 2)
203 {
204 // Bottom nodes
205 Bu(i, j * 2 + i) = -H(j);
206 // Top nodes
207 Bu(i, (j + 2) * 2 + i) = H(1 - j);
208 }
209 else if (d == 3)
210 {
211 // Bottom nodes
212 Bu(i, j * 3 + i) = -H(j);
213 // Top nodes
214 //Bu(i, (j + 4) * 3 + i) = H(j);
215 Bu(i, (j + cNodes) * 3 + i) = H(j);
216 }
217 else
218 {
219 gmErrorMsg(logger(), QObject::tr("GmpStdCohesive: Unsupported condition to fill B matrix."));
220 }
221 }
222 // fill the matrix B for intermediate nodes
223 for (int j = 0; j < inNode; ++j)
224 {
225 if (d == 2)
226 {
227 // Bottom nodes
228 Bu(i, (j + 4) * 2 + i) = -H(j + 2);
229 // Top nodes
230 Bu(i, (j + 4 + inNode) * 2 + i) = H(1 + inNode - j);
231 }
232 else if (d == 3)
233 {
234 // Bottom nodes
235 Bu(i, (nv + j) * 3 + i) = -H(cNodes + j);
236 // Top nodes
237 Bu(i, (nv + inNode + j) * 3 + i) = H(cNodes + j);
238 }
239 else
240 {
241 gmErrorMsg(logger(), QObject::tr("GmpInterface: Unsupported condition to fill B matrix."));
242 }
243 }
244
245 }
246
247 // Produto da Bu = R*Bu
248 Bu = R*Bu;
249
250 return detJ;
251
252 }
253
254 /*
255 double angleAtanD(double y, double x)
256 {
257 double PI, GRAUS, angle;
258
259 PI = acos(-1.00);
260 GRAUS = 180.0 / PI;
261
262 if (x == 0.00)
263 {
264 if (y > 0.00)
265 {
266 // I and II
267 angle = 90.0;
268 }
269 else if (y < 0.00)
270 {
271 // III and IV
272 angle = -90.0;
273 }
274 else if (y == 0.0)
275 {
276 // Not possible
277 }
278 }
279 else if (x>0.00)
280 {
281 if (y > 0.00)
282 {
283 // I(0<ANGLE<90)
284 angle = atan(y / x)*GRAUS;
285 }
286 else if (y < 0.00)
287 {
288 // IV(-90<ANGLE<0)
289 angle = atan(y / x)*GRAUS;
290 }
291 else if (y == 0.00)
292 {
293 // I and IV
294 angle = 0.00;
295 }
296 }
297 else if (x<0.00)
298 {
299 if (y>0.00)
300 {
301 // II(90<ANGLE<180)
302 angle = 180.00 - abs(atan(y / x)*GRAUS);
303 }
304 else if (y < 0.00)
305 {
306 // III(-180<ANGLE<-90)
307 angle = abs(atan(y / x)*GRAUS) - 180.00;
308 }
309 else if (y == 0.00)
310 {
311 // II and III
312 angle = 180.00;
313 }
314 }
315 return angle;
316 } */
317};
318// Axisymmetric interface element
319template <class T> class GmpAxiInterface : public T
320{
321public:
322 GmpAxiInterface(const char* pluginType, GmSimulationData* simulation, QString id, QString description,
323 const GmpFemPhysicsCommonMaterialFactory* matFactory, const GmLogCategory& logger)
324 : T(pluginType, simulation, id, description, matFactory, logger)
325 {}
326
327 virtual double fillBuMatrix(const GmElement* e, const GmShape* shape, const GmVector& ip, const GmMatrix& MX, const GmVector& N, const GmMatrix& J, GmMatrix& Bu)
328 {
329 S_TRACE();
330 assert(e); Q_UNUSED(MX); Q_UNUSED(N);
331 int cNodes, inNode, nv;
332 // Node Number and intermediate node number for quadratic interface element
333 int n = e->numNodes();
334 int d = GmpFemPhysicsCommon::nodeDim();
335 assert(d == 2);
336 if (e->type() == GM_INT2DL6)
337 {
338 n = n - pow(2, d - 1);
339 }
340 // Compute the number of intermediate nodes and corner nodes
341 inNode = (n - pow(2.0, d)) / 2.0;
342 cNodes = 0.5 * n - inNode;
343
344 double detJ;
345 GmVector H;
346 GmMatrix R(d, d);
347
348 assert(Bu.n_rows == d && Bu.n_cols == n * d);
349 // read the shapes values
350 shape->shapeValues(ip, H);
351 // 2D interface element
352 if (d == 2)
353 {
354 // compute determinant of the jacobian matrix
355 detJ = shape->scaledJacobianDet(J);
356 // fill the 2D rotation matrix
357 R(0, 0) = J(0, 0) / detJ;
358 R(0, 1) = J(0, 1) / detJ;
359 R(1, 0) = -R(0, 1);
360 R(1, 1) = R(0, 0);
361 }
362 // 3D interface element
363 else
364 {
365 gmErrorMsg(logger(), QObject::tr("gmpInterface: Axisymmetric interface element must be 2D model"));
366 }
367
368 // Fill matrix B
369 // fill the matrix B with zeros.
370 Bu.zeros();
371 nv = 2 * cNodes;
372 // fill the matrix B for corner nodes
373 for (int i = 0; i < d; ++i)
374 {
375 for (int j = 0; j < cNodes; ++j)
376 {
377 if (d == 2)
378 {
379 // Bottom nodes
380 Bu(i, j * 2 + i) = -H(j);
381 // Top nodes
382 Bu(i, (j + 2) * 2 + i) = H(1 - j);
383 }
384 else
385 {
386 gmErrorMsg(logger(), QObject::tr("GmpStdCohesive: Unsupported condition to fill B matrix."));
387 }
388 }
389 // fill the matrix B for intermediate nodes
390 for (int j = 0; j < inNode; ++j)
391 {
392 if (d == 2)
393 {
394 // Bottom nodes
395 Bu(i, (j + 4) * 2 + i) = -H(j + 2);
396 // Top nodes
397 Bu(i, (j + 4 + inNode) * 2 + i) = H(1 + inNode - j);
398 }
399 else
400 {
401 gmErrorMsg(logger(), QObject::tr("GmpInterface: Unsupported condition to fill B matrix."));
402 }
403 }
404
405 }
406
407 // Produto da Bu = R*Bu
408 Bu = R * Bu;
409
410 return detJ;;
411
412 }
413
414protected:
415 // Evaluates the axisymmetric factor
416 virtual double axisymmetricFactor(const GmElement* e, const GmMatrix& MX, const GmVector& N) const
417 {
418 S_TRACE();
419 assert(e);
420 // number of nodes
421 int n = e->numNodes();
422 int d = GmpFemPhysicsCommon::nodeDim();
423 // number of nodes for tri-nodded interface elements
424 if (e->type() == GM_INT2DL6)
425 {
426 n = n - pow(2, d - 1);
427 }
428 assert(MX.n_rows == n / 2 && MX.n_cols == d);
429
430 double rGauss = 0.0;
431 for (int j = 0; j < n/2; ++j)
432 rGauss += N(j)*MX(j, 0);
433
434 return 2 * arma::datum::pi * rGauss;
435 }
436
438 virtual bool isAxisymmetric() { return true; }
439
440};
441#endif
virtual int numNodes() const=0
virtual GmCellType type() const=0
virtual double scaledJacobianDet(const GmMatrix &J) const=0
virtual void shapeValues(const GmVector &ncoord, GmVector &N) const=0
Definition gmpInterface.h:320
virtual bool isAxisymmetric()
Returns TRUE only for axisymmetric models.
Definition gmpInterface.h:438
Zero-Thickness interface element 2D & 3D for Int2dl4 and Int2dl6, Int3dl8 and CZE3D8P "Linear interfa...
Definition gmpInterface.h:35
GM_INT3DL6
GM_INT2DL6
GM_INT3DQ12
GM_INT3DL9
GM_INT3DQ15
arma::mat GmMatrix
#define S_TRACE()
arma::vec GmVector
Declaration of the GmpMechanicalInterface classes.
QString tr(const char *sourceText, const char *disambiguation, int n)