-
Notifications
You must be signed in to change notification settings - Fork 28
/
strain.py
130 lines (104 loc) · 3.36 KB
/
strain.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# -*- coding: utf-8 -*-
from __future__ import division, print_function
import numpy as np
from .core import Vec3, Group
from .helpers import sind, cosd
__all__ = ['DefGrad', 'VelGrad']
class DefGrad(np.ndarray):
"""class to store deformation gradient tensor derived from numpy.ndarray
"""
def __new__(cls, array):
# casting to our class
assert np.shape(array) == (3, 3), 'DefGrad must be 3x3 2D array'
obj = np.asarray(array).view(cls)
return obj
def __repr__(self):
return 'DefGrad:\n' + str(self)
def __mul__(self, other):
assert np.shape(other) == (3, 3), \
'DefGrad could by multiplied with 3x3 2D array'
return np.dot(self, other)
def __pow__(self, n):
# cross product or power of magnitude
assert np.isscalar(n), 'Exponent must be integer.'
return np.linalg.matrix_power(self, n)
def __eq__(self, other):
# equal
return bool(np.sum(abs(self-other)) < 1e-14)
def __ne__(self, other):
# not equal
return not self == other
@classmethod
def from_axis(cls, vector, theta):
x, y, z = vector.uv
c, s = cosd(theta), sind(theta)
xs, ys, zs = x*s, y*s, z*s
xc, yc, zc = x*(1-c), y*(1-c), z*(1-c)
xyc, yzc, zxc = x*yc, y*zc, z*xc
return cls([
[x*xc+c, xyc-zs, zxc+ys],
[xyc+zs, y*yc+c, yzc-xs],
[zxc-ys, yzc+xs, z*zc+c]])
@classmethod
def from_comp(cls,
xx=1, xy=0, xz=0,
yx=0, yy=1, yz=0,
zx=0, zy=0, zz=1):
return cls([
[xx, xy, xz],
[yx, yy, yz],
[zx, zy, zz]])
@property
def I(self):
return np.linalg.inv(self)
def rotate(self, vector, theta):
R = DefGrad.from_axis(vector, theta)
return R*self*R.T
@property
def eigenvals(self):
_, vals, _ = np.linalg.svd(self)
return tuple(vals)
@property
def eigenvects(self):
U, _, _ = np.linalg.svd(self)
return Group([Vec3(U.T[0]),
Vec3(U.T[1]),
Vec3(U.T[2])])
@property
def eigenlins(self):
return self.eigenvects.aslin
@property
def eigenfols(self):
return self.eigenvects.asfol
class VelGrad(np.ndarray):
"""class to store velocity gradient tensor derived from numpy.ndarray
"""
def __new__(cls, array):
# casting to our class
assert np.shape(array) == (3, 3), 'VelGrad must be 3x3 2D array'
obj = np.asarray(array).view(cls)
return obj
def __repr__(self):
return 'VelGrad:\n' + str(self)
def __pow__(self, n):
# cross product or power of magnitude
assert np.isscalar(n), 'Exponent must be integer.'
return np.linalg.matrix_power(self, n)
def __eq__(self, other):
# equal
return bool(np.sum(abs(self-other)) < 1e-14)
def __ne__(self, other):
# not equal
return not self == other
@classmethod
def from_comp(cls,
xx=0, xy=0, xz=0,
yx=0, yy=0, yz=0,
zx=0, zy=0, zz=0):
return cls([
[xx, xy, xz],
[yx, yy, yz],
[zx, zy, zz]])
def defgrad(self, time=1):
from scipy.linalg import expm
return DefGrad(expm(self*time))