Skip to content

Commit 3d53917

Browse files
JWock82JWock82
authored andcommitted
Added alternate Jacobian matrix derivation for reference
1 parent c92cb9a commit 3d53917

1 file changed

Lines changed: 61 additions & 6 deletions

File tree

‎PyNite/Quad3D.py‎

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ def __init__(self, name, i_node, j_node, m_node, n_node, t, material_name, model
5353
raise KeyError('Please define the material ' + str(material_name) + ' before assigning it to plates.')
5454

5555
# def _local_coords(self):
56-
# '''
56+
# """
5757
# Calculates or recalculates and stores the local (x, y) coordinates for each node of the
5858
# quadrilateral.
59-
# '''
59+
# """
6060

6161
# # Get the global coordinates for each node
6262
# X1, Y1, Z1 = self.i_node.X, self.i_node.Y, self.i_node.Z
@@ -98,10 +98,9 @@ def __init__(self, name, i_node, j_node, m_node, n_node, t, material_name, model
9898
# self.y4 = np.dot(vector_04, y_axis)
9999

100100
def _local_coords(self):
101-
'''
102-
Calculates or recalculates and stores the local (x, y) coordinates for each node of the
103-
quadrilateral.
104-
'''
101+
"""
102+
Calculates or recalculates and stores the local (x, y) coordinates for each node of the quadrilateral.
103+
"""
105104

106105
# Get the global coordinates for each node
107106
X1, Y1, Z1 = self.i_node.X, self.i_node.Y, self.i_node.Z
@@ -205,6 +204,62 @@ def P_k(self, k, xi, eta):
205204
return 1/2*(1 - xi)*(1 - eta**2)
206205
else:
207206
raise Exception('Unable to calculate shape function. Invalid value specified for k.')
207+
208+
def Co(self, xi, eta):
209+
"""This alternate calculation of the Jacobian matrix follows "The development of DKMQ plate bending element for thick to thin shell analysis based on the Naghdi/Reissner/Mindlin shell theory" by Katili, Batoz, Maknun and Hamdouni (2015). In the reference "C^o" is used instead of "J" to refer to the Jacobian. This method does not seem to produce correct results, but will be kept for future reference. It is helpful for understanding this plate element and may prove a useful simplification to the code base if implemented correctly someday.
210+
"""
211+
212+
# Nodal global coordinates (i=1, j=2, m=3, n=4)
213+
x_1 = np.array([[self.i_node.X, self.i_node.Y, self.i_node.Z]])
214+
x_2 = np.array([[self.j_node.X, self.j_node.Y, self.j_node.Z]])
215+
x_3 = np.array([[self.m_node.X, self.m_node.Y, self.m_node.Z]])
216+
x_4 = np.array([[self.n_node.X, self.n_node.Y, self.n_node.Z]])
217+
218+
# Derivatives of the bilinear interpolation functions
219+
N1_xi = 0.25*(eta - 1)
220+
N2_xi = -0.25*(eta - 1)
221+
N3_xi = 0.25*(eta + 1)
222+
N4_xi = -0.25*(eta + 1)
223+
N1_eta = 0.25*(xi - 1)
224+
N2_eta = -0.25*(xi + 1)
225+
N3_eta = 0.25*(xi + 1)
226+
N4_eta = -0.25*(xi - 1)
227+
228+
# Equation 4 - Katili 2015
229+
a_1 = N1_xi*x_1 + N2_xi*x_2 + N3_xi*x_3 + N4_xi*x_4
230+
a_2 = N1_eta*x_1 + N2_eta*x_2 + N3_eta*x_3 + N4_eta*x_4
231+
232+
# Normal vector
233+
n = np.cross(a_1, a_2)/np.linalg.norm(np.cross(a_1, a_2))
234+
235+
# Global unit vectors
236+
i = np.array([[1.0, 0.0, 0.0]])
237+
k = np.array([[0.0, 0.0, 1.0]])
238+
239+
if np.array_equal(n, k) or np.array_equal(n, -k):
240+
t_1 = i
241+
else:
242+
t_1 = np.cross(n, k)
243+
244+
t_2 = np.cross(n, t_1)
245+
246+
a_11 = np.dot(a_1, a_1.T)[0, 0]
247+
a_12 = np.dot(a_1, a_2.T)[0, 0]
248+
a_21 = np.dot(a_2, a_1.T)[0, 0]
249+
a_22 = np.dot(a_2, a_2.T)[0, 0]
250+
251+
a = np.array([[a_11, a_12],
252+
[a_21, a_22]])
253+
254+
a_det = np.linalg.det(a)
255+
256+
a1 = 1/a_det*(a_22*a_1 - a_12*a_2)
257+
a2 = 1/a_det*(-a_21*a_1 + a_11*a_2)
258+
259+
Co = np.array([[np.dot(a1, t_1.T)[0, 0], np.dot(a1, t_2.T)[0, 0]],
260+
[np.dot(a2, t_1.T)[0, 0], np.dot(a2, t_2.T)[0, 0]]])
261+
262+
return Co
208263

209264
def J(self, xi, eta):
210265
"""

0 commit comments

Comments
 (0)