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