xc
ASDEICR.h
1 /* ****************************************************************** **
2 ** OpenSees - Open System for Earthquake Engineering Simulation **
3 ** Pacific Earthquake Engineering Research Center **
4 ** **
5 ** **
6 ** (C) Copyright 1999, The Regents of the University of California **
7 ** All Rights Reserved. **
8 ** **
9 ** Commercial use of this program without express permission of the **
10 ** University of California, Berkeley, is strictly prohibited. See **
11 ** file 'COPYRIGHT' in main directory for information on usage and **
12 ** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. **
13 ** **
14 ** Developed by: **
15 ** Frank McKenna (fmckenna@ce.berkeley.edu) **
16 ** Gregory L. Fenves (fenves@ce.berkeley.edu) **
17 ** Filip C. Filippou (filippou@ce.berkeley.edu) **
18 ** **
19 ** ****************************************************************** */
20 
21 // $Revision: 1.10 $
22 // $Date: 2020/05/18 22:51:21 $
23 
24 // Original implementation: Massimo Petracca (ASDEA)
25 //
26 // Implementation of the EICR (Element Independent CoRotational) formulation
27 //
28 // References:
29 //
30 // Felippa, Carlos A.
31 // "A systematic approach to the element-independent corotational
32 // dynamics of finite elements".
33 // Technical Report CU-CAS-00-03, Center for Aerospace Structures, 2000.
34 //
35 // Felippa, Carlos A., and Bjorn Haugen.
36 // "A unified formulation of small-strain corotational finite elements: I. Theory."
37 // Computer Methods in Applied Mechanics and Engineering 194.21-24 (2005): 2285-2335.
38 //
39 
40 #ifndef ASDEICR_h
41 #define ASDEICR_h
42 
43 #include "ASDMath.h"
44 #include <vector>
45 
46 namespace XC {
47 
56 class EICR
57  {
58 
59  public:
60 
61  typedef std::size_t size_t;
62 
64 
65  typedef std::vector<Vector3Type> NodeContainerType;
66 
67  typedef Vector VectorType;
68 
69  typedef Matrix MatrixType;
70 
72 
73 public:
74 
81  template< class TVec, class TMat>
82  inline static void Spin(const TVec& V, TMat& S)
83  {
84  S(0, 0) = 0.00; S(0, 1) = -V(2); S(0, 2) = V(1);
85  S(1, 0) = V(2); S(1, 1) = 0.00; S(1, 2) = -V(0);
86  S(2, 0) = -V(1); S(2, 1) = V(0); S(2, 2) = 0.00;
87  }
88 
97  template< class TVec, class TMat>
98  inline static void Spin_AtRow(const TVec& V, TMat& S, size_t row_index)
99  {
100  size_t i0 = row_index;
101  size_t i1 = 1 + row_index;
102  size_t i2 = 2 + row_index;
103  double v0 = V(i0);
104  double v1 = V(i1);
105  double v2 = V(i2);
106  S(i0, 0) = 0.00; S(i0, 1) = -v2; S(i0, 2) = v1;
107  S(i1, 0) = v2; S(i1, 1) = 0.00; S(i1, 2) = -v0;
108  S(i2, 0) = -v1; S(i2, 1) = v0; S(i2, 2) = 0.00;
109  }
110 
120  template< class TVec, class TMat>
121  inline static void Spin_AtRow(const TVec& V, TMat& S, size_t vector_index, size_t matrix_row_index)
122  {
123  size_t i0 = matrix_row_index;
124  size_t i1 = 1 + matrix_row_index;
125  size_t i2 = 2 + matrix_row_index;
126  double v0 = V(vector_index);
127  double v1 = V(vector_index + 1);
128  double v2 = V(vector_index + 2);
129  S(i0, 0) = 0.00; S(i0, 1) = -v2; S(i0, 2) = v1;
130  S(i1, 0) = v2; S(i1, 1) = 0.00; S(i1, 2) = -v0;
131  S(i2, 0) = -v1; S(i2, 1) = v0; S(i2, 2) = 0.00;
132  }
133 
142  template< class TVec, class TMat>
143  inline static void Spin(const TVec& V, TMat& S, double mult)
144  {
145  S(0, 0) = 0.00; S(0, 1) = -mult * V(2); S(0, 2) = mult * V(1);
146  S(1, 0) = mult * V(2); S(1, 1) = 0.00; S(1, 2) = -mult * V(0);
147  S(2, 0) = -mult * V(1); S(2, 1) = mult * V(0); S(2, 2) = 0.00;
148  }
149 
160  template< class TVec, class TMat>
161  inline static void Spin_AtRow(const TVec& V, TMat& S, double mult, size_t row_index)
162  {
163  size_t i0 = row_index;
164  size_t i1 = 1 + row_index;
165  size_t i2 = 2 + row_index;
166  double v0 = mult * V(i0);
167  double v1 = mult * V(i1);
168  double v2 = mult * V(i2);
169  S(i0, 0) = 0.00; S(i0, 1) = -v2; S(i0, 2) = v1;
170  S(i1, 0) = v2; S(i1, 1) = 0.00; S(i1, 2) = -v0;
171  S(i2, 0) = -v1; S(i2, 1) = v0; S(i2, 2) = 0.00;
172  }
173 
185  template< class TVec, class TMat>
186  inline static void Spin_AtRow(const TVec& V, TMat& S, double mult, size_t vector_index, size_t matrix_row_index)
187  {
188  size_t i0 = matrix_row_index;
189  size_t i1 = 1 + matrix_row_index;
190  size_t i2 = 2 + matrix_row_index;
191  double v0 = mult * V(vector_index);
192  double v1 = mult * V(vector_index + 1);
193  double v2 = mult * V(vector_index + 2);
194  S(i0, 0) = 0.00; S(i0, 1) = -v2; S(i0, 2) = v1;
195  S(i1, 0) = v2; S(i1, 1) = 0.00; S(i1, 2) = -v0;
196  S(i2, 0) = -v1; S(i2, 1) = v0; S(i2, 2) = 0.00;
197  }
198 
199  static void SetZero(size_t n, size_t m, MatrixType& I);
200 
201 
208  inline static void SetIdentity(size_t n, MatrixType& I, double value = 1.0)
209  {
210  SetZero(n, n, I);
211  for (size_t j = 0; j < n; ++j)
212  I(j, j) = value;
213  }
214 
223  inline static void GetBlock(const VectorType& A, size_t begin, size_t end, VectorType& B)
224  {
225  size_t n = end - begin;
226  for (size_t i = 0; i < n; ++i)
227  B(i) = A(i + begin);
228  }
229 
238  inline static void GetBlock(const MatrixType& A, size_t begin, size_t end, MatrixType& B)
239  {
240  size_t n = end - begin;
241  for (size_t i = 0; i < n; ++i)
242  for (size_t j = 0; j < n; ++j)
243  B(i, j) = A(i + begin, j + begin);
244  }
245 
254  inline static void SetBlock(MatrixType& A, size_t begin, size_t end, const MatrixType& B)
255  {
256  size_t n = end - begin;
257  for (size_t i = 0; i < n; ++i)
258  for (size_t j = 0; j < n; ++j)
259  A(i + begin, j + begin) = B(i, j);
260  }
261 
262  static void OuterProd(const VectorType& A, const VectorType& B, MatrixType& C);
263 
264 public:
265 
273  inline static void Compute_Pt(size_t num_nodes, MatrixType& P)
274  {
275  double a = double(num_nodes - 1) / double(num_nodes);
276  double b = -1.0 / double(num_nodes);
277 
278  size_t num_dofs = num_nodes * 6;
279 
280  SetIdentity(num_dofs, P);
281 
282  for (size_t i = 0; i < num_nodes; i++)
283  {
284  size_t j = i * 6;
285 
286  // diagonal block
287  P(j, j) = a;
288  P(j + 1, j + 1) = a;
289  P(j + 2, j + 2) = a;
290 
291  // out-of-diagonal block
292  for (size_t k = i + 1; k < num_nodes; k++)
293  {
294  size_t w = k * 6;
295 
296  P(j, w) = b;
297  P(j + 1, w + 1) = b;
298  P(j + 2, w + 2) = b;
299 
300  P(w, j) = b;
301  P(w + 1, j + 1) = b;
302  P(w + 2, j + 2) = b;
303  }
304  }
305  }
306 
314  inline static void Compute_S(const NodeContainerType& nodes, MatrixType& S)
315  {
316  size_t num_nodes = nodes.size();
317  size_t num_dofs = num_nodes * 6;
318 
319  SetZero(num_dofs, 3, S);
320 
321  for (size_t i = 0; i < num_nodes; i++)
322  {
323  size_t j = i * 6;
324 
325  Spin_AtRow(nodes[i], S, -1.0, 0, j);
326 
327  S(j + 3, 0) = 1.0;
328  S(j + 4, 1) = 1.0;
329  S(j + 5, 2) = 1.0;
330  }
331  }
332 
340  inline static void Compute_H(const VectorType& displacements, MatrixType& H)
341  {
342  size_t num_dofs = displacements.Size();
343  size_t num_nodes = num_dofs / 6;
344 
345  SetIdentity(num_dofs, H);
346 
347  static MatrixType Omega(3, 3);
348  static MatrixType Omega2(3, 3);
349  static MatrixType Hi(3, 3);
350  static VectorType rv(3);
351 
352  for (size_t i = 0; i < num_nodes; i++)
353  {
354  size_t index = i * 6;
355 
356  GetBlock(displacements, index + 3, index + 6, rv);
357 
358  double angle = rv.Norm();
359 
360  if (angle >= 2.0 * M_PI)
361  angle = std::fmod(angle, 2.0 * M_PI);
362 
363  double eta;
364  if (angle < 0.05) {
365  double angle2 = angle * angle;
366  double angle4 = angle2 * angle2;
367  double angle6 = angle4 * angle2;
368  eta = 1.0 / 12.0 + 1.0 / 720.0 * angle2 + 1.0 / 30240.0 * angle4 + 1.0 / 1209600.0 * angle6;
369  }
370  else {
371  eta = (1.0 - 0.5 * angle * std::tan(0.5 * M_PI - 0.5 * angle)) / (angle * angle);
372  }
373 
374  Spin(rv, Omega);
375  Omega2.addMatrixProduct(0.0, Omega, Omega, 1.0);
376 
377  // Hi = I - 0.5*Omega + eta*Omega*Omega
378  SetIdentity(3, Hi);
379  Hi.addMatrix(1.0, Omega, -0.5);
380  Hi.addMatrix(1.0, Omega2, eta);
381 
382  SetBlock(H, index + 3, index + 6, Hi);
383  }
384  }
385 
395  inline static void Compute_L(const VectorType& displacements, const VectorType& forces, const MatrixType& H, MatrixType& L)
396  {
397  size_t num_dofs = displacements.Size();
398  size_t num_nodes = num_dofs / 6;
399 
400  SetZero(num_dofs, num_dofs, L);
401 
402  static VectorType rotationVector(3);
403  static VectorType momentVector(3);
404  static MatrixType Omega(3, 3);
405  static MatrixType Omega2(3, 3);
406  static MatrixType Li(3, 3);
407  static MatrixType LiTemp1(3, 3);
408  static MatrixType MxR(3, 3);
409  static MatrixType RxM(3, 3);
410  static MatrixType Hi(3, 3);
411 
412  for (size_t i = 0; i < num_nodes; i++)
413  {
414  size_t index = i * 6;
415 
416  GetBlock(displacements, index + 3, index + 6, rotationVector);
417  GetBlock(forces, index + 3, index + 6, momentVector);
418 
419  double angle = rotationVector.Norm();
420 
421  if (angle >= 2.0 * M_PI)
422  angle = std::fmod(angle, 2.0 * M_PI);
423 
424  double angle2 = angle * angle;
425  double angle4 = angle2 * angle2;
426  double angle6 = angle4 * angle2;
427 
428  double eta;
429  double mu;
430  if (angle < 0.05) {
431  eta = 1.0 / 12.0 + angle2 / 720.0 + angle4 / 30240.0 + angle6 / 1209600.0;
432  mu = 1.0 / 360.0 + angle2 / 7560.0 + angle4 / 201600.0 + angle6 / 5987520.0;
433  }
434  else {
435  eta = (1.0 - 0.5 * angle * std::tan(0.5 * M_PI - 0.5 * angle)) / (angle * angle);
436  double sin_h_angle = std::sin(0.5 * angle);
437  mu = (angle2 + 4.0 * std::cos(angle) + angle * std::sin(angle) - 4.0) / (4.0 * angle4 * sin_h_angle * sin_h_angle);
438  }
439 
440  Spin(rotationVector, Omega);
441  Omega2.addMatrixProduct(0.0, Omega, Omega, 1.0);
442 
443  OuterProd(momentVector, rotationVector, MxR);
444  OuterProd(rotationVector, momentVector, RxM);
445 
446  SetIdentity(3, Li, (rotationVector ^ momentVector));
447  Li.addMatrix(1.0, RxM, 1.0);
448  Li.addMatrix(1.0, MxR, -1.0);
449 
450  LiTemp1.addMatrixProduct(0.0, Omega2, MxR, mu);
451  Spin(momentVector, MxR, 0.5);
452  LiTemp1.addMatrix(1.0, MxR, -1.0);
453 
454  LiTemp1.addMatrix(1.0, Li, eta);
455 
456  GetBlock(H, index + 3, index + 6, Hi);
457  Li.addMatrixProduct(0.0, LiTemp1, Hi, 1.0);
458 
459  SetBlock(L, index + 3, index + 6, Li);
460  }
461  }
462  };
463 } // end of XC namespace
464 #endif // !ASDEICR_h
Float vector abstraction.
Definition: Vector.h:94
static void SetZero(size_t n, size_t m, MatrixType &I)
Sets the input matrix to the zero matrix of requested size.
Definition: ASDEICR.cc:34
double Norm(void) const
Return the norm of vector.
Definition: Vector.cpp:780
static void Compute_Pt(size_t num_nodes, MatrixType &P)
Computes the Translational Projector Matrix.
Definition: ASDEICR.h:273
static void Compute_H(const VectorType &displacements, MatrixType &H)
Computes the Axial Vector Jacobian.
Definition: ASDEICR.h:340
static void Spin_AtRow(const TVec &V, TMat &S, double mult, size_t vector_index, size_t matrix_row_index)
Computes the Spin of the input vector V, from the specified index, and saves the result into the outp...
Definition: ASDEICR.h:186
static void OuterProd(const VectorType &A, const VectorType &B, MatrixType &C)
computes the outer product A x B, in C.
Definition: ASDEICR.cc:46
static void GetBlock(const VectorType &A, size_t begin, size_t end, VectorType &B)
Copies the block [begin:end[ from A to B.
Definition: ASDEICR.h:223
static void Spin_AtRow(const TVec &V, TMat &S, size_t row_index)
Computes the Spin of the input vector V, and saves the result into the output matrix S...
Definition: ASDEICR.h:98
static void SetIdentity(size_t n, MatrixType &I, double value=1.0)
Sets the input matrix to the identity of requested size.
Definition: ASDEICR.h:208
int Size(void) const
Returns the size of the Vector.
Definition: Vector.h:235
static void Spin_AtRow(const TVec &V, TMat &S, double mult, size_t row_index)
Computes the Spin of the input vector V, and saves the result into the output matrix S...
Definition: ASDEICR.h:161
static void Spin(const TVec &V, TMat &S)
Computes the Spin of the input vector V, and saves the result into the output matrix S...
Definition: ASDEICR.h:82
static void GetBlock(const MatrixType &A, size_t begin, size_t end, MatrixType &B)
Copies the block [begin:end[ from A to B.
Definition: ASDEICR.h:238
static void Compute_S(const NodeContainerType &nodes, MatrixType &S)
Computes the Spin Lever Matrix.
Definition: ASDEICR.h:314
static void Spin(const TVec &V, TMat &S, double mult)
Computes the Spin of the input vector V, and saves the result into the output matrix S...
Definition: ASDEICR.h:143
int addMatrix(double factThis, const Matrix &other, double factOther)
Add a factor fact times the Matrix other to the current Matrix.
Definition: Matrix.cpp:566
EICR Element Independent CoRotational formulation.
Definition: ASDEICR.h:56
static void Compute_L(const VectorType &displacements, const VectorType &forces, const MatrixType &H, MatrixType &L)
Computes the Spin derivative of (Axial Vector Jacobian)^T contracted with the nodal moment vector...
Definition: ASDEICR.h:395
Open source finite element program for structural analysis.
Definition: ContinuaReprComponent.h:35
Matrix of floats.
Definition: Matrix.h:111
static void Spin_AtRow(const TVec &V, TMat &S, size_t vector_index, size_t matrix_row_index)
Computes the Spin of the input vector V, from the specified index, and saves the result into the outp...
Definition: ASDEICR.h:121
static void SetBlock(MatrixType &A, size_t begin, size_t end, const MatrixType &B)
Copies the block [begin:end[ from B to A.
Definition: ASDEICR.h:254
ASDQuaternion A simple class that implements the main features of quaternion algebra.
Definition: ASDMath.h:328