-
Notifications
You must be signed in to change notification settings - Fork 18
/
SolidClass.py
143 lines (129 loc) · 6.51 KB
/
SolidClass.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
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
BEM-2D
A 2D boundary element method code
"""
import numpy as np
class solid(object):
'Toolkit for Finite Element structural analysis'
def __init__(self, Body, N_ELEMENTS_S,tmax):
"""
Iniitalizes object related variables needed for other class methods.
Args:
Body (object): A body object created from the swimmer class.
N_ELEMENTS (int): Number of elements to discretize the solid body.
t_max (float): Maximum thickness of the solid body.
"""
x_mid = (Body.BF.x[:-1]+Body.BF.x[1:])/2
self.Nelements = N_ELEMENTS_S
self.Nnodes = self.Nelements + 1
self.xp_0 = np.copy(Body.BF.x)
self.zp_0 = np.copy(Body.BF.z)
self.pivotPoint = (0.5*tmax) / (max(self.xp_0) - min(self.xp_0))
self.nodes = np.zeros((self.Nnodes,3))
self.nodesNew = np.zeros((self.Nnodes,3))
self.nodes_0 = np.zeros((self.Nnodes,3))
self.tempNodes = np.zeros((self.Nnodes,3))
self.tBeam = np.zeros((self.Nelements,1))
self.ttemp = np.zeros((self.Nelements,1))
self.tBeamStruct = np.zeros((self.Nelements,1))
self.meanline_p0 = Body.BF.x / (np.max(Body.BF.x) - np.min(Body.BF.x))
self.meanline_c0 = x_mid / (np.max(Body.BF.x) - np.min(Body.BF.x))
self.fixedCounter = 0
self.beamCounter = 0
self.elemAsso = np.zeros(Body.BF.x.shape, int)
def initThinPlate(self, tmax, c, SW_CNST_THK_BM, tConst, FLEX_RATIO):
"""
This function initializes the element nodal positions.
Args:
tmax (float): NumPy array of solid thicknesses for each element.
c (float): Undeformed/initial chord length.
tConst (float):constant thickness position (0 <= tConst <= 1)
FLEX_RATIO (float): Percent of the body to remain rigid as measured
from the leading edge.
"""
for i in xrange(self.Nelements):
if self.nodes[i,0] <= 0.5*tmax:
self.tBeam[i,0] = np.copy(tmax)
self.tBeamStruct[i,0] = 0.1*np.copy(self.tBeam[i,0])
self.ttemp[i,0] = 0.1*np.copy(self.tBeam[i,0])
self.beamCounter += 1
self.fixedCounter += 1
elif self.nodes[i,0] >= c-0.5*tmax:
self.tBeam[i,0] = 2*np.sqrt((0.5*tmax)**2 -(self.nodes[i,0]-(c-0.5*tmax))**2 )
self.tBeamStruct[i,0] = 0.1*np.copy(self.tBeam[i,0])
self.ttemp[i,0] = np.copy(self.tBeam[i,0])
else:
self.ttemp[i,0] = 0.1*np.copy(tmax)
self.tBeam[i,0] = np.copy(tmax)
self.tBeamStruct[i,0] = 0.1*np.copy(self.tBeam[i,0])
if (SW_CNST_THK_BM == 1 and self.nodes[i,2] >= tConst):
self.tBeamStruct[i,0] = np.copy(self.tBeamStruct[i-1,0])
else:
self.tBeamStruct[i,0] = 0.1*np.copy(self.tBeam[i,0])
if (self.nodes[i,2] <= FLEX_RATIO):
self.fixedCounter += 1
def initTearDrop(self, tmax, c, SW_CNST_THK_BM, tConst, FLEX_RATIO):
"""
This function initializes the element nodal positions.
Args:
tmax (float): NumPy array of solid thicknesses for each element.
c (float): Undeformed/initial chord length.
constThickBeam (bool): Flag argument for constant thickness properties
tConst (float):constant thickness position (0 <= tConst <= 1)
FLEX_RATIO (float): Percent of the body to remain rigid as measured
from the leading edge.
"""
for i in xrange(self.Nelements):
if self.nodes[i,0] <= 0.5*tmax:
self.tBeam[i,0] = np.copy(tmax)
self.tBeamStruct[i,0] = np.copy(self.tBeam[i,0])
self.ttemp[i,0] = np.copy(self.tBeam[i,0])
self.beamCounter += 1
self.fixedCounter += 1
else:
self.ttemp[i,0] = -tmax / (c - 0.5*tmax) * self.nodes[i,0] + tmax / (c - 0.5*tmax) * c
self.tBeam[i-1,0] = 0.5 * (self.ttemp[i,0] + self.ttemp[i-1,0])
self.tBeamStruct[i-1,0] = np.copy(self.tBeam[i-1,0])
if i == self.Nelements-1:
self.tBeam[i,0] = 0.5 * self.ttemp[i,0]
self.tBeamStruct[i,0] = np.copy(self.tBeam[i,0])
if (SW_CNST_THK_BM == 1 and self.nodes[i,2] >= tConst):
self.tBeamStruct[i,0] = np.copy(self.tBeamStruct[i-1,0])
if (SW_CNST_THK_BM == 1 and self.nodes[i,2] >= tConst):
self.tBeamStruct[i,0] = np.copy(self.tBeamStruct[i-1,0])
else:
self.tBeamStruct[i-1,0] = np.copy(self.tBeam[i-1,0])
if (self.nodes[i,2] <= FLEX_RATIO):
self.fixedCounter += 1
def initMesh(self):
"""
Initializes the finite element mesh based on the object's __init__
values. This is only valid for the undeformed structure at time t = 0.
"""
self.nodes[:,0] = np.arange(min(self.xp_0),max(self.xp_0)+(max(self.xp_0)-min(self.xp_0))/self.Nelements,\
(max(self.xp_0)-min(self.xp_0))/self.Nelements)
self.nodes[:,1] = np.zeros((self.Nnodes,1)).T
self.nodes[:,2] = self.nodes[:,0] / (max(self.nodes[:,0])-min(self.nodes[:,1]))
self.nodes_0 = np.copy(self.nodes)
self.nodesNew = np.copy(self.nodes)
for i in xrange(self.xp_0.shape[0]):
for j in xrange(self.Nelements):
if (self.xp_0[i] <= self.nodes_0[j+1,0] and self.xp_0[i] >= self.nodes_0[j,0]):
self.elemAsso[i] = np.copy(j)
#TODO: This function exists in FSIClass.py. Remove it in a future release?
def rotatePts(x0, y0, theta):
"""
Rotates a pair of points a specified angle.
Args:
x0 (float): A NumPy array of x-coordinates to be rotated.
y0 (float): A NumPy array of z-coordinates to be rotated.
theta (float): Angle (in radians) to rotate coordinates.
Returns:
x (float): Rotated x-coordinate NumPy array theta radians from x0.
y (float): Rotated y-coordinate NumPy array theta radians from y0.
"""
x = x0 * np.cos(theta) - y0 * np.sin(theta)
y = x0 * np.sin(theta) + y0 * np.cos(theta)
return (x, y)