diff --git a/build-package.py b/build-package.py new file mode 100644 index 0000000..02c2df4 --- /dev/null +++ b/build-package.py @@ -0,0 +1,26 @@ + +import os, sys + +def update_setup(package_name, package_version, package_deps): + + with open("setup-template.py", "r") as f: + setup_template = f.read() + + with open("setup.py", "w") as f: + f.write(setup_template.format(package_name=package_name, package_version=package_version, package_depends=package_deps)) + +def build_package(): + os.system("python -m build --wheel") + +if __name__ == "__main__": + + package_version = "3.6.3" + + update_setup("calfem-python", package_version, "'numpy', 'visvis', 'pyvtk', 'matplotlib', 'scipy', 'gmsh', 'qtpy', 'vedo', 'tabulate'") + + build_package() + + update_setup("calfem-python-small", package_version, "'numpy', 'visvis', 'matplotlib', 'scipy', 'gmsh', 'tabulate'") + + build_package() + diff --git a/calfem/core.py b/calfem/core.py index 6029526..a9dd3fc 100644 --- a/calfem/core.py +++ b/calfem/core.py @@ -6,7 +6,7 @@ """ from scipy.sparse.linalg import dsolve -from scipy.linalg import eig +from scipy.linalg import eig, lu import numpy as np import logging as cflog @@ -77,384 +77,409 @@ def info(msg): """Write ``msg`` to info log.""" cflog.info(" calfem.core: "+msg) - def spring1e(ep): """ + Ke = spring1e(ep) + ------------------------------------------------------------- + PURPOSE Compute element stiffness matrix for spring element. - - :param float ep: spring stiffness or analog quantity (ep = k). - :return mat Ke: stiffness matrix, dim(Ke)= 2 x 2 - """ - k = ep - return np.mat([[k, -k], [-k, k]], 'd') - + + INPUT: ep = [k] spring stiffness or analog quantity + + OUTPUT: Ke : spring stiffness matrix, [2 x 2] + ------------------------------------------------------------- -def spring1s(ep, ed): - """ - Compute element force in spring element (spring1e). - - :param float ep: spring stiffness or analog quantity - :param list ed: element displacements [d0, d1] - :return float es: element force [N] + LAST MODIFIED: P-E Austrell 1994-11-02 + O Dahlblom 2022-11-15 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - k = ep - return k*(ed[1]-ed[0]) + k = ep + Ke = k * np.array([ + [1, -1], + [-1, 1] + ]) -def bar1e(ep): - """ - Compute element stiffness matrix for spring element. - - :param ep float: spring stiffness or analog quantity - :return mat Ke: stiffness matrix, dim(Ke)= 2 x 2 - """ - k = ep - return np.mat([[k, -k], [-k, k]], 'd') + return Ke -def bar1s(ep, ed): +def spring1s(ep, ed): """ + es = spring1s(ep, ed) + ------------------------------------------------------------- + PURPOSE Compute element force in spring element (spring1e). - :param float ep: spring stiffness or analog quantity - :param list ed: element displacements [d0, d1] - :return float es: element force - """ - k = ep - return k*(ed[1]-ed[0]) - - -def bar2e(ex, ey, ep): - """ - Compute the element stiffness matrix for two dimensional bar element. + INPUT: ep = [k] spring stiffness or analog quantity - :param list ex: element x coordinates [x1, x2] - :param list ey: element y coordinates [y1, y2] - :param list ep: [E, A]: E - Young's modulus, A - Cross section area - :return mat Ke: stiffness matrix, [4 x 4] - """ - E = ep[0] - A = ep[1] - - b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) - L = np.sqrt(b.T*b).item() - - Kle = np.mat([[1., -1.], [-1., 1.]])*E*A/L - - n = np.asarray(b.T/L).reshape(2,) - - G = np.mat([ - [n[0], n[1], 0., 0.], - [0., 0., n[0], n[1]] - ]) - - return G.T*Kle*G - + ed = [u1 u2] element displacement vector + + OUTPUT: es = [N] element force + ------------------------------------------------------------- -def bar2g(ex, ey, ep, N): - """ - Compute element stiffness matrix for two dimensional geometric - nonlinear bar element. - - :param list ex: element x coordinates [x1, x2] - :param list ey: element y coordinates [y1, y2] - :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area - :param float N: normal force - :return mat Ke: stiffness matrix [4 x 4] + LAST MODIFIED: P-E AUSTRELL 1994-11-02 + O Dahlblom 2022-11-14 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - E = ep[0] - A = ep[1] + k = ep - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]] - ]) + N = k*(ed[1]-ed[0]) + es = N - L = np.sqrt(b.T*b).item() + return es - n = np.asarray(b.T/L).reshape(2,) - G = np.mat([ - [n[0], n[1], 0., 0.], - [-n[1], n[0], 0., 0.], - [0., 0., n[0], n[1]], - [0., 0., -n[1], n[0]] - ]) +def bar1e(ex, ep, eq=None): + """ + Ke = bar1e (ex, ep) + Ke, fe = bar1e(ex, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a onedimensional bar element. - Kle = E*A/L*np.mat([ - [1, 0, -1, 0], - [0, 0, 0, 0], - [-1, 0, 1, 0], - [0, 0, 0, 0] - ])+N/L*np.mat([ - [0, 0, 0, 0], - [0, 1, 0, -1], - [0, 0, 0, 0], - [0, -1, 0, 1] - ]) + INPUT: ex = [x1 x2] element node coordinates - return G.T*Kle*G + ep = [E A] element properties; + E: Young's modulus + A: cross section area + ka: axial spring stiffness + eq = [qX] distributed load + + OUTPUT: Ke : bar stiffness matrix [2 x 2] + fe : element load vector [2 x 1] (if eq!=None) + ------------------------------------------------------------- -def bar2s(ex, ey, ep, ed): - """ - Compute normal force in two dimensional bar element. - - :param list ex: element x coordinates [x1, x2] - :param list ey: element y coordinates [y1, y2] - :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area - :param list ed: element displacements [u1, u2, u3, u4] - :return float N: element foce [N] + LAST MODIFIED: O Dahlblom 2015-10-22 + O Dahlblom 2022-11-14 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - E = ep[0] - A = ep[1] - - b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) - L = np.sqrt(b.T*b).item() + E, A = ep + DEA=E*A - #Kle = np.mat([[1.,-1.],[-1.,1.]])*E*A/L - - n = np.asarray(b.T/L).reshape(2,) + qX=0. + if not eq is None: + qX=eq[0] - G = np.mat([ - [n[0], n[1], 0., 0.], - [0., 0., n[0], n[1]] + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + Ke = DEA/L*np.array([ + [1, -1], + [-1, 1] ]) - - u = np.asmatrix(ed).T - N = E*A/L*np.mat([[-1., 1.]])*G*u - return N.item() + + fe = qX*L*np.array([1/2, 1/2]).reshape(2,1) + + if eq is None: + return Ke + else: + return Ke, fe -def bar3e(ex, ey, ez, ep): +def bar1s(ex, ep, ed, eq=None, nep=None): """ - Compute element stiffness matrix for three dimensional bar element. - - :param list ex: element x coordinates [x1, x2] - :param list ey: element y coordinates [y1, y2] - :param list ez: element z coordinates [z1, z2] - :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area - :return mat Ke: stiffness matrix, [6 x 6] - """ - E = ep[0] - A = ep[1] + es = bar1s(ex, ep, ed) + es = bar1s(ex, ep, ed, eq) + es, edi, eci = bar1s(ex, ep, ed, eq, nep) + ------------------------------------------------------------- + PURPOSE + Compute section forces in one dimensional bar element - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]], - [ez[1]-ez[0]] - ]) - L = np.sqrt(b.T*b).item() + INPUT: ex = [x1 x2] element node coordinates - n = np.asarray(b.T/L).reshape(3) + ep = [E A] element properties, + E: Young's modulus + A: cross section area + + ed = [u1 u2] element displacement vector - G = np.mat([ - [n[0], n[1], n[2], 0., 0., 0.], - [0., 0., 0., n[0], n[1], n[2]] - ]) + eq = [qX] distributed load - Kle = E*A/L*np.mat([ - [1, -1], - [-1, 1] - ]) + nep : number of evaluation points ( default=2 ) - return G.T*Kle*G + OUTPUT: es = [N1 ; section forces, local directions, in + N2 ; nep points along the beam, dim(es)= nep x 1 + ...] + + edi = [u1 ; element displacements, local directions, + u2 ; in n points along the bar, dim(edi)= nep x 1 + ...] + eci = [x1; evaluation points on the local x-axis, + x2; (x1=0 and xn=L) + ...] + ------------------------------------------------------------- -def bar3s(ex, ey, ez, ep, ed): - """ - Compute normal force in three dimensional bar element. - - :param list ex: element x coordinates [x1, x2] - :param list ey: element y coordinates [y1, y2] - :param list ez: element z coordinates [z1, z2] - :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area - :param list ed: element displacements [u1, ..., u6] - :return float N: normal force + LAST MODIFIED: O Dahlblom 2021-02-25 + O Dahlblom 2022-11-14 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - E = ep[0] - A = ep[1] + E, A = ep + DEA=E*A + + qX=0. + if not eq is None: + qX=eq[0] + + ne=2 + if nep != None: + ne=nep + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + a1 = ed.reshape(2,1) - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]], - [ez[1]-ez[0]] - ]) - L = np.sqrt(b.T*b).item() + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + + C1a = C1 @ a1 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + + if DEA != 0: + u = u -(X**2-L*X)*qX/(2*DEA) + du = du -(2*X-L)*qX/(2*DEA) + + N = DEA*du + es = N + edi=u + eci=X - n = np.asarray(b.T/L).reshape(3) + if nep == None: + return es + else: + return es, edi, eci - G = np.mat([ - [n[0], n[1], n[2], 0., 0., 0.], - [0., 0., 0., n[0], n[1], n[2]] - ]) - #Kle = E*A/L*np.mat([ - # [ 1,-1], - # [-1, 1] - #]) +def bar1we(ex, ep, eq=None): + """ + Ke = bar1we (ex, ep) + Ke, fe = bar1we(ex, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a onedimensional bar element with + axial springs. - u = np.asmatrix(ed).T - N = E*A/L*np.mat([[-1., 1.]])*G*u + INPUT: ex = [x1 x2] element node coordinates - return N.item() + ep = [E A kX] element properties; + E: Young's modulus + A: cross section area + kX: axial spring stiffness -def beam1e(ex, ep, eq=None): - """ - Compute the stiffness matrix for a one dimensional beam element. + eq = [qX] distributed load + + OUTPUT: Ke : bar stiffness matrix [2 x 2] + fe : element load vector [2 x 1] (if eq!=None) + ------------------------------------------------------------- - :param list ex: element x coordinates [x1, x2] - :param list ep: element properties [E, I], E - Young's modulus, I - Moment of inertia - :param float eq: distributed load [qy] - :return mat Ke: element stiffness matrix [4 x 4] - :return mat fe: element stiffness matrix [4 x 1] (if eq!=None) + LAST MODIFIED: O Dahlblom 2015-12-17 + O Dahlblom 2022-10-19 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - L = ex[1]-ex[0] - - E = ep[0] - I = ep[1] + E, A, kX = ep + DEA = E*A; - qy = 0. + qX = 0. if not eq is None: - qy = eq + qX = eq[0] + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) - Ke = E*I/(L**3) * np.mat([ - [12, 6*L, -12, 6*L], - [6*L, 4*L**2, -6*L, 2*L**2], - [-12, -6*L, 12, -6*L], - [6*L, 2*L**2, -6*L, 4*L**2] + K1 = DEA/L*np.array([ + [1, -1], + [-1, 1] ]) - fe = qy*np.mat([L/2, L**2/12, L/2, -L**2/12]).T + K2 = kX*L/6*np.array([ + [2, 1], + [1, 2] + ]) + + Ke = K1+K2 + fe = qX*L*np.array([1/2, 1/2]).reshape(2,1) + if eq is None: return Ke else: return Ke, fe -def beam1s(ex, ep, ed, eq=None, nep=None): - """ - Compute section forces in one dimensional beam element (beam1e). - Parameters: +def bar1ws(ex, ep, ed, eq=None, nep=None): + """ + es = bar1ws(ex, ep, ed) + es = bar1ws(ex, ep, ed, eq) + es, edi, eci = bar1ws(ex, ep, ed, eq, nep) + ------------------------------------------------------------- + PURPOSE + Compute section forces in one dimensional bar element - ex = [x1 x2] element node coordinates + INPUT: ex = [x1 x2] element node coordinates - ep = [E I] element properties, + ep = [E A kX] element properties, E: Young's modulus - I: moment of inertia - - ed = [u1 ... u4] element displacements - - eq = qy distributed load, local directions - - nep number of evaluation points ( default=2 ) + A: cross section area + kX: axial spring stiffness + + ed = [u1 u2] element displacement vector - Returns: + eq = [qX] distributed load - es = [ V1 M1 section forces, local directions, in - V2 M2 n points along the beam, dim(es)= n x 2 - .........] + nep : number of evaluation points ( default=2 ) - edi = [ v1 element displacements, local directions, - v2 in n points along the beam, dim(es)= n x 1 - .......] + OUTPUT: es = [N1 ; section forces, local directions, in + N2 ; nep points along the beam, dim(es)= nep x 1 + ...] + + edi = [u1 ; element displacements, local directions, + u2 ; in n points along the bar, dim(edi)= nep x 1 + ...] - eci = [ x1 local x-coordinates of the evaluation - x2 points, (x1=0 and xn=L) - ...] + eci = [x1; evaluation points on the local x-axis, + x2; (x1=0 and xn=L) + ...] + ------------------------------------------------------------- + LAST MODIFIED: O Dahlblom 2021-02-25 + O Dahlblom 2022-11-14 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - EI = ep[0]*ep[1] - L = ex[1]-ex[0] - - qy = 0. - - if not eq is None: - qy = eq - + E, A, kX = ep + DEA = E*A + + qX = 0. + if not eq is None: + qX = eq[0] + ne = 2 + if nep != None: + ne = nep + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + a1 = ed.reshape(2,1) - if nep != None: - ne = nep - - Cinv = np.mat([ - [1, 0, 0, 0], - [0, 1, 0, 0], - [-3/(L**2), -2/L, 3/(L**2), -1/L], - [2/(L**3), 1/(L**2), -2/(L**3), 1/(L**2)] - ]) - - Ca = (Cinv@ed).T + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + + C1a = C1 @ a1 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + + if DEA != 0: + u = u +kX/DEA*np.concatenate(((X**2-L*X)/2, (X**3-L**2*X)/6),1) @ C1a-(X**2-L*X)*qX/(2*DEA) + du = du +kX/DEA*np.concatenate(((2*X-L)/2, (3*X**2-L**2)/6),1) @ C1a-(2*X-L)*qX/(2*DEA) + + N = DEA*du + es = N + edi = u + eci = X - x = np.asmatrix(np.arange(0., L+L/(ne-1), L/(ne-1))).T - zero = np.asmatrix(np.zeros([len(x)])).T - one = np.asmatrix(np.ones([len(x)])).T + if nep == None: + return es + else: + return es, edi, eci - v = np.concatenate((one, x, np.power(x, 2), np.power(x, 3)), 1)@Ca \ - + qy/(24*EI)*(np.power(x,4) - 2*L*np.power(x,3) + (L**2)*np.power(x,2)) - d2v = np.concatenate((zero, zero, 2*one, 6*x), 1)@Ca \ - + qy/(2*EI)*(np.power(x,2) - L*x + L**2/12) - d3v = np.concatenate((zero, zero, zero, 6*one), 1)@Ca - qy*(x - L/2) - M = EI*d2v - V = -EI*d3v - edi = v - eci = x - es = np.concatenate((V, M), 1) +def bar2e(ex, ey, ep, eq=None): + """ + Ke = bar2e(ex, ey, ep) + Ke, fe = bar2e(ex, ey, ep, eq) + ---------------------------------------------------------------------- + PURPOSE + Compute the element stiffness matrix for two dimensional bar element. + + INPUT: ex = [x1 x2] element node coordinates - return (es, edi, eci) + ey = [y1 y2] element node coordinates + ep = [E A] element properties; + E: Young's modulus + A: cross section area + eq = [qX] distributed load + + OUTPUT: Ke : bar stiffness matrix [4 x 4] + fe : element load vector [4 x 1] (if eq!=None) + ------------------------------------------------------------- -def beam2e(ex, ey, ep, eq=None): - """ - Compute the stiffness matrix for a two dimensional beam element. - - :param list ex: element x coordinates [x1, x2] - :param list ey: element y coordinates [y1, y2] - :param list ep: element properties [E, A, I], E - Young's modulus, A - Cross section area, I - Moment of inertia - :param list eq: distributed loads, local directions [qx, qy] - :return mat Ke: element stiffness matrix [6 x 6] - :return mat fe: element stiffness matrix [6 x 1] (if eq!=None) + LAST MODIFIED: O Dahlblom 2015-10-20 + O Dahlblom 2022-11-16 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ + E, A = ep + DEA = E*A - b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b.T/L).reshape(2,) - - E = ep[0] - A = ep[1] - I = ep[2] - - qx = 0. - qy = 0. + qX = 0. if not eq is None: - qx = eq[0] - qy = eq[1] - - Kle = np.mat([ - [E*A/L, 0., 0., -E*A/L, 0., 0.], - [0., 12*E*I/L**3., 6*E*I/L**2., 0., -12*E*I/L**3., 6*E*I/L**2.], - [0., 6*E*I/L**2., 4*E*I/L, 0., -6*E*I/L**2., 2*E*I/L], - [-E*A/L, 0., 0., E*A/L, 0., 0.], - [0., -12*E*I/L**3., -6*E*I/L**2., 0., 12*E*I/L**3., -6*E*I/L**2.], - [0., 6*E*I/L**2., 2*E*I/L, 0., -6*E*I/L**2., 4*E*I/L] - ]) - - fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T + qX=eq[0] - G = np.mat([ - [n[0], n[1], 0., 0., 0., 0.], - [-n[1], n[0], 0., 0., 0., 0.], - [0., 0., 1., 0., 0., 0.], - [0., 0., 0., n[0], n[1], 0.], - [0., 0., 0., -n[1], n[0], 0.], - [0., 0., 0., 0., 0., 1.] + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + Kle = DEA/L*np.array([ + [1, -1], + [-1, 1] ]) - Ke = G.T*Kle*G - fe = G.T*fle + fle = qX*L*np.array([1/2, 1/2]).reshape(2,1) + + nxX=dx/L + nyX=dy/L + G = np.array([ + [nxX, nyX, 0, 0], + [ 0, 0, nxX, nyX] + ]) + + Ke = G.T @ Kle @ G + fe = G.T @ fle if eq is None: return Ke @@ -462,633 +487,2045 @@ def beam2e(ex, ey, ep, eq=None): return Ke, fe -def beam2s(ex, ey, ep, ed, eq=None, nep=None): +def bar2s(ex, ey, ep, ed, eq=None, nep=None): """ - Compute section forces in two dimensional beam element (beam2e). + es = bar2s(ex, ey, ep, ed) + es = bar2s(ex, ey, ep, ed, eq) + es, edi, eci = bar2s(ex, ey, ep, ed, eq, nep) + ------------------------------------------------------------- + PURPOSE + Compute normal force in two dimensional bar element. - Parameters: - - ex = [x1 x2] - ey = [y1 y2] element node coordinates + INPUT: ex = [x1 x2] element node coordinates - ep = [E A I] element properties, - E: Young's modulus - A: cross section area - I: moment of inertia - - ed = [u1 ... u6] element displacements + ey = [y1 y2] element node coordinates - eq = [qx qy] distributed loads, local directions - - nep number of evaluation points ( default=2 ) - - Returns: - - es = [ N1 V1 M1 section forces, local directions, in - N2 V2 M2 n points along the beam, dim(es)= n x 3 - .........] - - edi = [ u1 v1 element displacements, local directions, - u2 v2 in n points along the beam, dim(es)= n x 2 - .......] + ep = [E A] element properties, + E: Young's modulus + A: cross section area + + ed = [u1 ... u4] element displacement vector - eci = [ x1 local x-coordinates of the evaluation - x2 points, (x1=0 and xn=L) - ...] - - """ - EA = ep[0]*ep[1] - EI = ep[0]*ep[2] - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]] - ]) + eq = [qX] distributed load - L = np.sqrt(b.T*b).item() - n = np.asarray(b.T/L).reshape(2,) + nep : number of evaluation points ( default=2 ) - qx = 0. - qy = 0. + OUTPUT: es = [N1 ; section forces, local directions, in + N2 ; nep points along the beam, dim(es)= nep x 1 + ...] + + edi = [u1 ; element displacements, local directions, + u2 ; in n points along the bar, dim(edi)= nep x 1 + ...] - if not eq is None: - qx = eq[0] - qy = eq[1] + eci = [x1; evaluation points on the local x-axis, + x2; (x1=0 and xn=L) + ...] + ------------------------------------------------------------- + LAST MODIFIED: O Dahlblom 2015-12-04 + O Dahlblom 2022-11-16 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A = ep + DEA = E*A + + qX = 0. + if not eq is None: + qX = eq[0] + ne = 2 + if nep != None: + ne=nep - if nep != None: - ne = nep + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) - C = np.mat([ - [0., 0., 0., 1., 0., 0.], - [0., 0., 0., 0., 0., 1.], - [0., 0., 0., 0., 1., 0.], - [L, 0., 0., 1., 0., 0.], - [0., L**3, L**2, 0., L, 1.], - [0., 3*L**2, 2*L, 0., 1., 0.] - ]) + nxX = dx/L + nyX = dy/L - G = np.mat([ - [n[0], n[1], 0., 0., 0., 0.], - [-n[1], n[0], 0., 0., 0., 0.], - [0., 0., 1., 0., 0., 0.], - [0., 0., 0., n[0], n[1], 0.], - [0., 0., 0., -n[1], n[0], 0.], - [0., 0., 0., 0., 0., 1.] + G = np.array([ + [nxX, nyX, 0, 0], + [ 0, 0, nxX, nyX] ]) + + a1 = G @ ed.reshape(4,1) - M = np.ravel(C.I*(G*np.asmatrix(ed).T - - np.matrix([0., 0., 0., -qx*L**2/(2*EA), qy*L**4/(24*EI), qy*L**3/(6*EI)]).T)) - A = np.matrix([M[0], M[3]]).T - B = np.matrix([M[1], M[2], M[4], M[5]]).T - - x = np.asmatrix(np.arange(0., L+L/(ne-1), L/(ne-1))).T - zero = np.asmatrix(np.zeros([len(x)])).T - one = np.asmatrix(np.ones([len(x)])).T - - u = np.concatenate((x, one), 1)*A-np.power(x, 2)*qx/(2*EA) - du = np.concatenate((one, zero), 1)*A-x*qx/EA - v = np.concatenate((np.power(x, 3), np.power(x, 2), x, - one), 1)*B+np.power(x, 4)*qy/(24*EI) - d2v = np.concatenate((6*x, 2*one, zero, zero), 1) * \ - B+np.power(x, 2)*qy/(2*EI) - d3v = np.concatenate((6*one, zero, zero, zero), 1)*B+x*qy/EI - - N = EA*du - M = EI*d2v - V = -EI*d3v - edi = np.concatenate((u, v), 1) - eci = x - es = np.concatenate((N, V, M), 1) + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + + C1a = C1 @ a1 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + + if DEA != 0: + u = u -(X**2-L*X)*qX/(2*DEA) + du = du -(2*X-L)*qX/(2*DEA) + + N = DEA*du + es = N + edi = u + eci = X - return (es, edi, eci) + if nep == None: + return es + else: + return es, edi, eci -def beam2t(ex, ey, ep, eq=None): +def bar2ge(ex, ey, ep, QX): """ - Compute the stiffness matrix for a two dimensional elastic - Timoshenko beam element. - - Parameters: - - ex = [x1 x2] - ey = [y1 y2] element node coordinates - - ep = [E G A I ks] element properties - E: Young's modulus - G: Shear modulus - A: Cross section area - I: Moment of inertia - ks: Shear correction factor - - eq = [qx qy] distributed loads, local directions - - Returns: - - Ke element stiffness matrix (6 x 6) - - fe element load vector (6 x 1) + Ke = bar2ge(ex, ey, ep, QX) + ---------------------------------------------------------------------- + PURPOSE + Compute element stiffness matrix for two dimensional geometric + nonlinear bar element. - """ + INPUT: ex = [x1 x2] element node coordinates - b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b.T/L).reshape(2) + ey = [y1 y2] element node coordinates - E = ep[0] - Gm = ep[1] - A = ep[2] - I = ep[3] - ks = ep[4] + ep = [E A] element properties; + E: Young's modulus + A: cross section area - qx = 0. - qy = 0. - if eq != None: - qx = eq[0] - qy = eq[1] - - m = (12/L**2)*(E*I/(Gm*A*ks)) - - Kle = E/(1+m)*np.mat([ - [A*(1+m)/L, 0., 0., -A*(1+m)/L, 0., 0.], - [0., 12*I/L**3., 6*I/L**2., 0., -12*I/L**3., 6*I/L**2.], - [0., 6*I/L**2., 4*I * - (1+m/4.)/L, 0., -6*I/L**2., 2*I*(1-m/2)/L], - [-A*(1+m)/L, 0., 0., - A*(1+m)/L, 0., 0.], - [0., -12*I/L**3., -6*I/L**2., - 0., 12*I/L**3., -6*I/L**2.], - [0., 6*I/L**2., 2*I * - (1-m/2)/L, 0., -6*I/L**2., 4*I*(1+m/4)/L] - ]) + QX: axial force in the bar + + OUTPUT: Ke : bar stiffness matrix [4 x 4] + ------------------------------------------------------------- - fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T + LAST MODIFIED: O Dahlblom 2015-12-17 + O Dahlblom 2022-11-16 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A = ep + DEA = E*A - G = np.mat([ - [n[0], n[1], 0., 0., 0., 0.], - [-n[1], n[0], 0., 0., 0., 0.], - [0., 0., 1., 0., 0., 0.], - [0., 0., 0., n[0], n[1], 0.], - [0., 0., 0., -n[1], n[0], 0.], - [0., 0., 0., 0., 0., 1.] + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + K0le = DEA/L*np.array([ + [ 1, 0, -1, 0], + [ 0, 0, 0, 0], + [-1, 0, 1, 0], + [ 0, 0, 0, 0] + ]) + + Ksle = QX/L*np.array([ + [ 0, 0, 0, 0], + [ 0, 1, 0, -1], + [ 0, 0, 0, 0], + [ 0, -1, 0, 1] ]) - Ke = G.T*Kle*G - fe = G.T*fle - - if eq is None: - return Ke - else: - return Ke, fe + Kle = K0le + Ksle + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L -def beam2ts(ex, ey, ep, ed, eq=None, nep=None): - """ - Compute section forces in two dimensional beam element (beam2e). - - Parameters: - - ex = [x1, x2] - ey = [y1, y2] element node coordinates + G = np.array([ + [nxX, nyX, 0, 0], + [nxY, nyY, 0, 0], + [ 0, 0, nxX, nyX], + [ 0, 0, nxY, nyY] + ]) - ep = [E,G,A,I,ks] element properties, - E: Young's modulus - G: shear modulus - A: cross section area - I: moment of inertia + Ke = G.T @ Kle @ G - ed = [u1, ... ,u6] element displacements + return Ke - eq = [qx, qy] distributed loads, local directions - nep number of evaluation points ( default=2 ) - - Returns: - - es = [[N1,V1,M1], section forces, local directions, in - [N2,V2,M2], n points along the beam, dim(es)= n x 3 - ..........] - - edi = [[u1,v1,teta1], element displacements, local directions, - [u2,v2,teta2], and rotation of cross section at - .............] in n points along the beam, dim(es)= n x 2 - - (Note! Rotation of the cross section is not equal to dv/dx for Timoshenko beam element) - - eci = [[x1], local x-coordinates of the evaluation - [x2], points, (x1=0 and xn=L) - ....] - +def bar2gs(ex, ey, ep, ed, nep=None): """ - EA = ep[0]*ep[2] - EI = ep[0]*ep[3] - GAK = ep[1]*ep[2]*ep[4] - alfa = EI/GAK - - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]] - ]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b.T/L).reshape(2) - - qx = 0. - qy = 0. - if eq != None: - qx = eq[0] - qy = eq[1] + es, QX, edi, eci = bar2s(ex, ey, ep, ed) + es, QX, edi, eci = bar2s(ex, ey, ep, ed, nep) + ------------------------------------------------------------- + PURPOSE + Compute normal force in two dimensional bar element (bar2ge). + + INPUT: ex = [x1 x2] element node coordinates - ne = 2 + ey = [y1 y2] element node coordinates - if nep != None: - ne = nep + ep = [E A] element properties, + E: Young's modulus + A: cross section area + + ed = [u1 ... u4] element displacement vector - C = np.mat([ - [0., 0., 0., 1., 0., 0.], - [0., 0., 0., 0., 0., 1.], - [0., 6*alfa, 0., 0., 1., 0.], - [L, 0., 0., 1., 0., 0.], - [0., L**3, L**2, 0., L, 1.], - [0., 3*(L**2+2*alfa), 2*L, 0., 1., 0.] - ]) + nep : number of evaluation points ( default=2 ) - G = np.mat([ - [n[0], n[1], 0., 0., 0., 0.], - [-n[1], n[0], 0., 0., 0., 0.], - [0., 0., 1., 0., 0., 0.], - [0., 0., 0., n[0], n[1], 0.], - [0., 0., 0., -n[1], n[0], 0.], - [0., 0., 0., 0., 0., 1.] - ]) + OUTPUT: es = [N1 ; section forces, local directions, in + N2 ; nep points along the beam, dim(es)= nep x 1 + ...] + + QX: axial force - M = np.ravel(C.I*(G*np.asmatrix(ed).T-np.mat([0., 0., 0., -qx*L**2/( - 2*EA), qy*L**4/(24*EI)-qy*L**2/(2*GAK), qy*L**3/(6*EI)]).T)) - C2 = np.mat([M[0], M[3]]).T - C4 = np.mat([M[1], M[2], M[4], M[5]]).T + edi = [u1 ; element displacements, local directions, + u2 ; in n points along the bar, dim(edi)= nep x 1 + ...] - x = np.asmatrix(np.arange(0., L+L/(ne-1), L/(ne-1))).T - zero = np.asmatrix(np.zeros([len(x)])).T - one = np.asmatrix(np.ones([len(x)])).T + eci = [x1; evaluation points on the local x-axis, + x2; (x1=0 and xn=L) + ...] + ------------------------------------------------------------- - u = np.concatenate((x, one), 1)*C2-qx/(2*EA)*np.power(x, 2) - du = np.concatenate((one, zero), 1)*C2-qx*x/EA + LAST MODIFIED: O Dahlblom 2015-10-20 + O Dahlblom 2022-11-16 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A = ep + DEA = E*A + + ne=2 + if nep != None: + ne=nep - v = np.concatenate((np.power(x, 3), np.power(x, 2), x, one), 1) * \ - C4+qy/(24*EI)*np.np.power(x, 4)-qy/(2*GAK)*np.power(x, 2) - dv = np.concatenate((3*np.power(x, 2), 2*x, one, zero), - 1)*C4+qy*np.power(x, 3)/(6*EI)-qy*x/GAK + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) - teta = np.concatenate((3*(np.power(x, 2)+2*alfa*one), - 2*x, one, zero), 1)*C4+qy*np.power(x, 3)/(6*EI) - dteta = np.concatenate((6*x, 2*one, zero, zero), 1) * \ - C4+qy*np.power(x, 2)/(2*EI) + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L - N = EA*du - M = EI*dteta - V = GAK*(dv-teta) + G = np.array([ + [nxX, nyX, 0, 0], + [nxY, nyY, 0, 0], + [ 0, 0, nxX, nyX], + [ 0, 0, nxY, nyY] + ]) + + edl = G @ ed.reshape(4,1) + a1 = np.array([ + edl[0], + edl[2] + ]) + + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + C1a = C1 @ a1 - es = np.concatenate((N, V, M), 1) - edi = np.concatenate((u, v, teta), 1) - eci = x + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + + N = DEA*du + QX = N[0] + es = N + edi=u + eci=X - if nep != None: - return es, edi, eci + if nep == None: + return es, QX else: - return es + return es, QX, edi, eci -def beam2w(ex, ey, ep, eq=None): +def bar3e(ex, ey, ez, ep, eq=None): """ - Compute the stiffness matrix for a two dimensional beam element - on elastic foundation. + Ke = bar2e(ex, ey, ez, ep) + Ke, fe = bar2e(ex, ey, ez, ep, eq) + ---------------------------------------------------------------------- + PURPOSE + Compute the element stiffness matrix for three dimensional bar element. - Parameters: - - ex = [x1, x2] - ey = [y1, y2] element node coordinates - - ep = [E,A,I,ka,kt] element properties, - E: Young's modulus - A: cross section area - I: moment of inertia - ka: axial foundation stiffness - kt: transversal foundation stiffness + INPUT: ex = [x1 x2] element node coordinates + ey = [y1 y2] + ez = [z1 z2] - eq = [qx, qy] distributed loads, local directions + ep = [E A] element properties; + E: Young's modulus + A: cross section area - Returns: + eq = [qX] distributed load + + OUTPUT: Ke : bar stiffness matrix [6 x 6] + fe : element load vector [6 x 1] (if eq!=None) + ------------------------------------------------------------- - Ke beam stiffness matrix (6 x 6) - - fe element load vector (6 x 1) + LAST MODIFIED: O Dahlblom 2015-10-19 + O Dahlblom 2022-11-18 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b/L).reshape(2) - - E, A, I, ka, kt = ep + E, A = ep + DEA=E*A - qx = 0 - qy = 0 - if eq != None: - qx, qy = eq - - K1 = np.mat([ - [E*A/L, 0, 0, -E*A/L, 0, 0], - [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], - [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], - [-E*A/L, 0, 0, E*A/L, 0, 0], - [0, -12*E*I/L**3, -6*E*I/L**2, 0, 12*E*I/L**3, -6*E*I/L**2], - [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] - ]) + qX=0. + if not eq is None: + qX=eq[0] - K2 = L/420*np.mat([ - [140*ka, 0, 0, 70*ka, 0, 0], - [0, 156*kt, 22*kt*L, 0, 54*kt, -13*kt*L], - [0, 22*kt*L, 4*kt*L**2, 0, 13*kt*L, -3*kt*L**2], - [70*ka, 0, 0, 140*ka, 0, 0], - [0, 54*kt, 13*kt*L, 0, 156*kt, -22*kt*L], - [0, -13*kt*L, -3*kt*L**2, 0, -22*kt*L, 4*kt*L**2] + x1, x2 = ex + y1, y2 = ey + z1, z2 = ez + dx = x2-x1 + dy = y2-y1 + dz = z2-z1 + L = np.sqrt(dx*dx+dy*dy+dz*dz) + + Kle = DEA/L*np.array([ + [1, -1], + [-1, 1] ]) - Kle = K1+K2 - fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T - - G = np.mat([ - [n[0], n[1], 0, 0, 0, 0], - [-n[1], n[0], 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0], - [0, 0, 0, n[0], n[1], 0], - [0, 0, 0, -n[1], n[0], 0], - [0, 0, 0, 0, 0, 1] + fle = qX*L*np.array([1/2, 1/2]).reshape(2,1) + + nxX=dx/L + nyX=dy/L + nzX=dz/L + G = np.array([ + [nxX, nyX, nzX, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, nzX] ]) + + Ke = G.T @ Kle @ G + fe = G.T @ fle - Ke = G.T*Kle*G - fe = G.T*fle - - if eq != None: - return Ke, fe - else: + if eq is None: return Ke + else: + return Ke, fe -def beam2ws(ex, ey, ep, ed, eq=None): +def bar3s(ex, ey, ez, ep, ed, eq=None, nep=None): """ - Compute section forces in a two dimensional beam element - on elastic foundation. + es = bar3s(ex, ey, ez, ep, ed) + es = bar3s(ex, ey, ez, ep, ed, eq) + es, edi, eci = bar3s(ex, ey, ez, ep, ed, eq, nep) + ------------------------------------------------------------- + PURPOSE + Compute normal force in three dimensional bar element. - Parameters: + INPUT: ex = [x1 x2] element node coordinates + ey = [y1 y2] + ez = [z1 z2] + + ep = [E A] element properties, + E: Young's modulus + A: cross section area - ex = [x1, x2] - ey = [y1, y2] element node coordinates + ed = [u1 ... u4] element displacement vector - ep = [E,A,I,ka,kt] element properties, - E: Young's modulus - A: cross section area - I: moment of inertia - ka: axial foundation stiffness - kt: transversal foundation stiffness + eq = [qX] distributed load - ed = [u1, ... ,u6] element displacement vector + nep : number of evaluation points ( default=2 ) - eq = [qx, qy] distributed loads, local directions + OUTPUT: es = [N1 ; section forces, local directions, in + N2 ; nep points along the beam, dim(es)= nep x 1 + ...] + + edi = [u1 ; element displacements, local directions, + u2 ; in n points along the bar, dim(edi)= nep x 1 + ...] - Returns: + eci = [x1; evaluation points on the local x-axis, + x2; (x1=0 and xn=L) + ...] + ------------------------------------------------------------- - es = [[N1, V1, M1], - [N2, V2, M2]] element forces, local direction + LAST MODIFIED: O Dahlblom 2021-09-01 + O Dahlblom 2022-11-18 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - if np.asmatrix(ed).shape[0] > 1: - error("Only one row is allowed in the ed matrix !!!") - return + E, A = ep + DEA = E*A + + qX = 0. + if not eq is None: + qX = eq[0] + + ne = 2 + if nep != None: + ne = nep - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]] + x1, x2 = ex + y1, y2 = ey + z1, z2 = ez + dx = x2-x1 + dy = y2-y1 + dz = z2-z1 + L = np.sqrt(dx*dx+dy*dy+dz*dz) + + nxX = dx/L + nyX = dy/L + nzX =dz/L + + G = np.array([ + [nxX, nyX, nzX, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, nzX] ]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b/L).reshape(2,) + + a1 = G @ ed.reshape(6,1) - E, A, I, ka, kt = ep + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + + C1a = C1 @ a1 - qx = 0 - qy = 0 - if eq != None: - qx, qy = eq + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + + if DEA != 0: + u = u -(X**2-L*X)*qX/(2*DEA) + du = du -(2*X-L)*qX/(2*DEA) + + N = DEA*du + es = N + edi=u + eci=X - K1 = np.mat([ - [E*A/L, 0, 0, -E*A/L, 0, 0], - [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], - [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], - [-E*A/L, 0, 0, E*A/L, 0, 0], - [0, -12*E*I/L**3, -6*E*I/L**2, 0, 12*E*I/L**3, -6*E*I/L**2], - [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] + if nep == None: + return es + else: + return es, edi, eci + + +def beam1e(ex, ep, eq=None): + """ + Ke = beam1e(ex, ep) + Ke, fe = beam1e(ex, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a one dimensional beam element. + + INPUT: ex = [x1 x2] element node coordinates + + ep = [E I] element properties; + E: Young's modulus + I: moment of inertia + + eq = [qY] distributed load + + OUTPUT: Ke : beam stiffness matrix [4 x 4] + fe : element load vector [4 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2019-01-09 + O Dahlblom 2022-10-25 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, I = ep + DEI = E*I + + qY = 0. + if not eq is None: + qY = eq[0] + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + Ke = DEI/L**3*np.array([ + [12, 6*L, -12, 6*L], + [6*L, 4*L**2, -6*L, 2*L**2], + [-12, -6*L, 12, -6*L], + [6*L, 2*L**2, -6*L, 4*L**2] + ]) + + fe = qY*np.array([L/2, L**2/12, L/2, -L**2/12]).reshape(4,1) + + if eq is None: + return Ke + else: + return Ke, fe + + +def beam1s(ex, ep, ed, eq=None, nep=None): + """ + es = beam1s(ex, ep, ed) + es = beam1s(ex, ep, ed, eq) + es, ed, ec = beam1s(ex, ep, ed, eq, nep) + ------------------------------------------------------------- + PURPOSE + Compute section forces in one dimensional beam element (beam1e). + + INPUT ex = [x1 x2] element node coordinates + + ep = [E I] element properties, + E: Young's modulus + I: moment of inertia + + ed = [u1 ... u4] element displacements + + eq = [qy] distributed loads, local directions + + nep : number of evaluation points ( default=2 ) + + OUTPUT: es = [V1 M1 ; section forces, local directions, in + V2 M2 ; nep points along the beam, dim(es)= nep x 2 + ......] + + edi = [v1 ; element displacements, local directions, + v2 ; in nep points along the beam, dim(edi)= nep x 1 + ....] + + eci = [x1; evaluation points on the local x-axis + x2; + ..] + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2021-09-01 + O Dahlblom 2022-10-25 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + + E, I = ep + DEI = E*I + + qY=0. + + if not eq is None: + qY = eq[0] + + ne = 2 + if nep != None: + ne = nep + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + a2 = ed.reshape(4,1) + + C2 = np.array([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [-3/L**2, -2/L, 3/L**2, -1/L], + [2/L**3, 1/L**2, -2/L**3, 1/L**2] + ]) + + C2a = C2 @ a2 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a +# dv = np.concatenate((zero, one, 2*X, 3*X**2), 1) @ C2a + d2v = np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + d3v = np.concatenate((zero, zero, zero, 6*one), 1) @ C2a + + if DEI != 0: + v = v+(X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI) +# dv = dv+(2*X**3 - 3*L*X**2 + L**2*X)*qY/(12*DEI) + d2v = d2v+(6*X**2 - 6*L*X + L**2*one)*qY/(12*DEI) + d3v = d3v+(2*X - L*one)*qY/(2*DEI) + + M = DEI*d2v + V = -DEI*d3v + es = np.concatenate((V, M), 1) + edi = v + eci = X + + if nep == None: + return es + else: + return es, edi, eci + + +def beam1we(ex, ep, eq=None): + """ + Ke = beam1we(ex, ep) + Ke, fe = beam1we(ex, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a one dimensional beam element + on elastic foundation. + + INPUT: ex = [x1 x2] element node coordinates + + ep = [E I kY] element properties; + E: Young's modulus + I: moment of inertia + kY: transversal found. stiffness + + eq = [qY] distributed load + + OUTPUT: Ke: beam stiffness matrix [4 x 4] + fe: element load vector [4 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2016-02-17 + O Dahlblom 2022-10-18 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, I, kY =ep + DEI = E*I; + + qY = 0 + if not eq is None: + qY = eq[0] + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + K0 = DEI/L**3*np.array([ + [12, 6*L, -12, 6*L], + [6*L, 4*L**2, -6*L, 2*L**2], + [-12, -6*L, 12, -6*L], + [6*L, 2*L**2, -6*L, 4*L**2] + ]) + + Ks = kY*L/420*np.array([ + [156, 22*L, 54, -13*L], + [22*L, 4*L**2, 13*L, -3*L**2], + [54, 13*L, 156, -22*L], + [-13*L, -3*L**2, -22*L, 4*L**2] + ]) + + Ke = K0+Ks + + fe = qY*np.array([L/2, L**2/12, L/2, -L**2/12]).reshape(4,1) + if eq is None: + return Ke + else: + return Ke, fe + + +def beam1ws(ex, ep, ed, eq=None, nep=None): + """ + es = beam1ws(ex, ep, ed) + es = beam1ws(ex, ep, ed, eq) + es, ed, ec = beam1ws(ex, ep, ed, eq, nep) + ------------------------------------------------------------- + PURPOSE + Compute section forces in one dimensional beam element + on elastic foundation (beam1we). + + INPUT: ex = [x1 x2] element node coordinates + + ep = [E I kY] element properties, + E: Young's modulus + I: moment of inertia + kY: transversal foundation stiffness + + ed = [u1 ... u4] element displacements + + eq = [qy] distributed loads, local directions + + nep number of evaluation points ( default=2 ) + + OUTPUT: es = [V1 M1 ; section forces, local directions, in + V2 M2 ; nep points along the beam, dim(es)= n x 2 + ......] + + edi = [v1 ; element displacements, local directions, + v2 ; in nep points along the beam, dim(edi)= n x 1 + ...] + + eci = [x1 ; evaluation points on the local x-axis + x2 ; + ...] + + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2021-09-01 + O Dahlblom 2022-10-18 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, I, kY = ep + DEI = E*I + + qY = 0. + + if not eq is None: + qY = eq[0] + + ne = 2 + if nep != None: + ne = nep + + x1, x2 = ex + dx = x2-x1 + L = abs(dx) + + a2 = ed.reshape(4,1) + + C2 = np.array([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [-3/L**2, -2/L, 3/L**2, -1/L], + [2/L**3, 1/L**2, -2/L**3, 1/L**2] + ]) + + C2a = C2 @ a2 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a + d2v = np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + d3v = np.concatenate((zero, zero, zero, 6*one), 1) @ C2a + + if DEI != 0: + v = v - kY/DEI*np.concatenate(( + (X**4 - 2*L*X**3 + L**2*X**2)/24, + (X**5 - 3*L**2*X**3 + 2*L**3*X**2)/120, + (X**6 - 4*L**3*X**3 + 3*L**4*X**2)/360, + (X**7 - 5*L**4*X**3 + 4*L**5*X**2)/840), 1) @ C2a + \ + (X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI) + d2v = d2v - kY/DEI*np.concatenate(( + (6*X**2 - 6*L*X + L**2*one)/12, + (10*X**3 - 9*L**2*X + 2*L**3*one)/60, + (5*X**4 - 4*L**3*X + L**4*one)/60, + (21*X**5 - 15*L**4*X + 4*L**5*one)/420),1) @ C2a + \ + (6*X**2 - 6*L*X + L**2*one)*qY/(12*DEI) + d3v = d3v - kY/DEI*np.concatenate(( + (2*X - L*one)/2, + (10*X**2 - 3*L**2)/20, + (5*X**3 - L**3*one)/15, + (7*X**4 - L**4*one)/28), 1) @ C2a + \ + (2*X - L*one)*qY/(2*DEI) + M = DEI*d2v + V = -DEI*d3v + es = np.concatenate((V, M), 1) + edi = v + eci = X + + if nep == None: + return es + else: + return es, edi, eci + + +def beam2e(ex, ey, ep, eq=None): + """ + Ke = beam2e(ex, ey, ep) + Ke, fe = beam2e(ex, ey, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a two dimensional beam element. + + INPUT: ex = [x1 x2] element node coordinates + ey = [y1 y2] + + ep = [E A I] element properties; + E: Young's modulus + A: Cross section area + I: moment of inertia + + eq = [qX qY] distributed loads, local directions + + OUTPUT: Ke : element stiffness matrix [6 x 6] + fe : element load vector [6 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2015-08-17 + O Dahlblom 2022-11-21 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I = ep + DEA = E*A + DEI = E*I + + qX = 0. + qY = 0. + if not eq is None: + qX, qY = eq + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + Kle = np.array([ + [ DEA/L, 0., 0., -DEA/L, 0., 0.], + [ 0., 12*DEI/L**3, 6*DEI/L**2, 0., -12*DEI/L**3, 6*DEI/L**2], + [ 0., 6*DEI/L**2, 4*DEI/L, 0., -6*DEI/L**2, 2*DEI/L], + [-DEA/L, 0., 0., DEA/L, 0., 0.], + [ 0., -12*DEI/L**3, -6*DEI/L**2, 0., 12*DEI/L**3, -6*DEI/L**2], + [ 0., 6*DEI/L**2, 2*DEI/L, 0., -6*DEI/L**2, 4*DEI/L] + ]) + + fle = L*np.array([qX/2, qY/2, qY*L/12, qX/2, qY/2, -qY*L/12]).reshape(6,1) + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + Ke = G.T @ Kle @ G + fe = G.T @ fle + + if eq is None: + return Ke + else: + return Ke, fe + + +def beam2s(ex, ey, ep, ed, eq=None, nep=None): + """ + es = beam2s(ex, ey, ep, ed) + es = beam2s(ex, ey, ep, ed, eq) + es, edi, eci = beam2s(ex, ey, ep, ed, eq, nep) +--------------------------------------------------------------------- + PURPOSE + Compute section forces in two dimensional beam element (beam2e). + + INPUT: ex = [x1 x2] + ey = [y1 y2] element node coordinates + + ep = [E A I] element properties, + E: Young's modulus + A: cross section area + I: moment of inertia + + ed = [u1 ... u6] element displacements + + eq = [qx qy] distributed loads, local directions + + nep number of evaluation points ( default=2 ) + + OUTPUT: es = [ N1 V1 M1 section forces, local directions, in + N2 V2 M2 n points along the beam, dim(es)= n x 3 + ........] + + edi = [ u1 v1 element displacements, local directions, + u2 v2 in n points along the beam, dim(es)= n x 2 + .....] + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + + LAST MODIFIED: O Dahlblom 2021-09-08 + O Dahlblom 2022-11-21 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I = ep + DEA = E*A + DEI = E*I + + qX = 0. + qY = 0. + if not eq is None: + qX, qY = eq + + ne=2 + if nep != None: + ne=nep + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + edl = G @ ed.reshape(6,1) + + a1 = np.array([ + edl[0], + edl[3] + ]) + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + C1a = C1 @ a1 + + a2 = np.array([ + edl[1], + edl[2], + edl[4], + edl[5] + ]) + C2 = np.array([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [-3/L**2, -2/L, 3/L**2, -1/L], + [2/L**3, 1/L**2, -2/L**3, 1/L**2] + ]) + C2a = C2 @ a2 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + if DEA != 0: + u = u -(X**2-L*X)*qX/(2*DEA) + du = du -(2*X-L)*qX/(2*DEA) + + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a +# dv = np.concatenate((zero, one, 2*X, 3*X**2), 1) @ C2a + d2v=np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + d3v = np.concatenate((zero, zero, zero, 6*one), 1) @ C2a + if DEI != 0: + v = v+(X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI) +# dv = dv+(2*X**3 - 3*L*X**2 + L**2*X)*qY/(12*DEI) + d2v = d2v+(6*X**2 - 6*L*X + L**2*one)*qY/(12*DEI) + d3v = d3v+(2*X - L*one)*qY/(2*DEI) + + N = DEA*du + M = DEI*d2v + V = -DEI*d3v + es = np.concatenate((N, V, M), 1) + edi = np.concatenate((u, v), 1) + eci = X + + if nep == None: + return es + else: + return es, edi, eci + + +def beam2we(ex, ey, ep, eq=None): + """ + Ke = beam2we(ex, ey, ep) + Ke, fe = beam2we(ex, ey, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a two dimensional beam element + on elastic foundation. + + INPUT: ex = [x1 x2] element node coordinates + ey = [y1 y2] + + ep = [E,A,I,kX,kY] element properties; + E: Young's modulus + A: Cross section area + I: moment of inertia + kX: axial foundation stiffness + kY: transversal foundation stiffness + + eq = [qX qY] distributed loads, local directions + + OUTPUT: Ke : element stiffness matrix [6 x 6] + fe : element load vector [6 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2015-08-07 + O Dahlblom 2022-11-21 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I, kX, kY = ep + DEA = E*A + DEI = E*I + + qX = 0 + qY = 0 + if not eq is None: + qX, qY = eq + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + K0 = np.array([ + [ DEA/L, 0., 0., -DEA/L, 0., 0.], + [ 0., 12*DEI/L**3, 6*DEI/L**2, 0., -12*DEI/L**3, 6*DEI/L**2], + [ 0., 6*DEI/L**2, 4*DEI/L, 0., -6*DEI/L**2, 2*DEI/L], + [-DEA/L, 0., 0., DEA/L, 0., 0.], + [ 0., -12*DEI/L**3, -6*DEI/L**2, 0., 12*DEI/L**3, -6*DEI/L**2], + [ 0., 6*DEI/L**2., 2*DEI/L, 0., -6*DEI/L**2, 4*DEI/L] + ]) + + Ks = L/420*np.array([ + [140*kX, 0, 0, 70*kX, 0, 0], + [0, 156*kY, 22*kY*L, 0, 54*kY, -13*kY*L], + [0, 22*kY*L, 4*kY*L**2, 0, 13*kY*L, -3*kY*L**2], + [70*kX, 0, 0, 140*kX, 0, 0], + [0, 54*kY, 13*kY*L, 0, 156*kY, -22*kY*L], + [0, -13*kY*L, -3*kY*L**2, 0, -22*kY*L, 4*kY*L**2] + ]) + + Kle = K0+Ks + + fle = L*np.array([qX/2, qY/2, qY*L/12, qX/2, qY/2, -qY*L/12]).reshape(6,1) + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + Ke = G.T @ Kle @ G + fe = G.T @ fle + + if eq is None: + return Ke + else: + return Ke, fe + + +def beam2ws(ex, ey, ep, ed, eq=None, nep=None): + """ + es = beam2ws(ex, ey, ep, ed) + es = beam2ws(ex, ey, ep, ed, eq) + es, edi, eci = beam2ws(ex, ey, ep, ed, eq, nep) +--------------------------------------------------------------------- + PURPOSE + Compute section forces in a two dimensional beam element + on elastic foundation. + + INPUT: ex = [x1 x2] + ey = [y1 y2] element node coordinates + + ep = [E,A,I,kX,kY] element properties, + E: Young's modulus + A: cross section area + I: moment of inertia + kX: axial foundation stiffness + kY: transversal foundation stiffness + + ed = [u1 ... u6] element displacements + + eq = [qx qy] distributed loads, local directions + + nep number of evaluation points ( default=2 ) + + OUTPUT: es = [ N1 V1 M1 section forces, local directions, in + N2 V2 M2 n points along the beam, dim(es)= n x 3 + ........] + + edi = [ u1 v1 element displacements, local directions, + u2 v2 in n points along the beam, dim(es)= n x 2 + .....] + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2022-09-30 + O Dahlblom 2022-11-21 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I, kX, kY = ep + DEA = E*A + DEI = E*I + + qX = 0 + qY = 0 + if not eq is None: + qX, qY = eq + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + ne = 2 + if nep != None: + ne = nep + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + edl = G @ ed.reshape(6,1) + + a1 = np.array([ + edl[0], + edl[3] + ]) + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + C1a = C1 @ a1 + + a2 = np.array([ + edl[1], + edl[2], + edl[4], + edl[5] + ]) + C2 = np.array([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [-3/L**2, -2/L, 3/L**2, -1/L], + [2/L**3, 1/L**2, -2/L**3, 1/L**2] + ]) + C2a = C2 @ a2 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + if DEA != 0: + u = u +kX/DEA*np.concatenate(((X**2-L*X)/2, (X**3-L**2*X)/6),1) @ C1a-(X**2-L*X)*qX/(2*DEA) + du = du +kX/DEA*np.concatenate(((2*X-L)/2, (3*X**2-L**2)/6),1) @ C1a-(2*X-L)*qX/(2*DEA) + + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a +# dv = np.concatenate((zero, one, 2*X, 3*X**2), 1) @ C2a + d2v = np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + d3v = np.concatenate((zero, zero, zero, 6*one), 1) @ C2a + if DEI != 0: + v = v - kY/DEI*np.concatenate(( + (X**4 - 2*L*X**3 + L**2*X**2)/24, + (X**5 - 3*L**2*X**3 + 2*L**3*X**2)/120, + (X**6 - 4*L**3*X**3 + 3*L**4*X**2)/360, + (X**7 - 5*L**4*X**3 + 4*L**5*X**2)/840), 1) @ C2a + \ + (X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI) + d2v = d2v - kY/DEI*np.concatenate(( + (6*X**2 - 6*L*X + L**2*one)/12, + (10*X**3 - 9*L**2*X + 2*L**3*one)/60, + (5*X**4 - 4*L**3*X + L**4*one)/60, + (21*X**5 - 15*L**4*X + 4*L**5*one)/420),1) @ C2a + \ + (6*X**2 - 6*L*X + L**2*one)*qY/(12*DEI) + d3v = d3v - kY/DEI*np.concatenate(( + (2*X - L*one)/2, + (10*X**2 - 3*L**2)/20, + (5*X**3 - L**3*one)/15, + (7*X**4 - L**4*one)/28), 1) @ C2a + \ + (2*X - L*one)*qY/(2*DEI) + + N = DEA*du + M = DEI*d2v + V = -DEI*d3v + es = np.concatenate((N, V, M), 1) + edi = np.concatenate((u, v), 1) + eci = X + + if nep == None: + return es + else: + return es, edi, eci + + +def beam2ge(ex, ey, ep, QX, eq=None): + """ + Ke = beam2ge(ex, ey, ep, QX) + Ke, fe = beam2ge(ex, ey, ep, QX, eq) + ------------------------------------------------------------- + PURPOSE + Compute the element stiffness matrix for a two dimensional + beam element with respect to geometric nonlinearity. + + INPUT: ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E, A, I] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + + QX axial force in the beam + + eq = [qY] distributed transverse load + + OUTPUT: Ke : element stiffness matrix [6 x 6] + fe : element load vector [6 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2015-12-17 + O Dahlblom 2022-12-08 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I = ep + DEA = E*A + DEI = E*I + + if eq != None: + if np.size(eq) > 1: + error("eq should be a scalar !!!") + return + else: + qY = eq[0] + else: + qY = 0 + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + K0le = np.array([ + [ DEA/L, 0., 0., -DEA/L, 0., 0.], + [ 0., 12*DEI/L**3, 6*DEI/L**2, 0., -12*DEI/L**3, 6*DEI/L**2], + [ 0., 6*DEI/L**2, 4*DEI/L, 0., -6*DEI/L**2, 2*DEI/L], + [-DEA/L, 0., 0., DEA/L, 0., 0.], + [ 0., -12*DEI/L**3, -6*DEI/L**2, 0., 12*DEI/L**3, -6*DEI/L**2], + [ 0., 6*DEI/L**2, 2*DEI/L, 0., -6*DEI/L**2, 4*DEI/L] + ]) + + Ksle = QX/(30*L)*np.array([ + [ 0., 0., 0., 0., 0., 0.], + [ 0., 36., 3*L, 0., -36., 3*L], + [ 0., 3*L, 4*L**2, 0., -3*L, -L**2], + [ 0., 0., 0., 0., 0., 0.], + [ 0., -36., -3*L, 0., 36., -3*L], + [ 0., 3*L, -L**2, 0., -3*L, 4*L**2] + ]) + + fle = qY*L*np.array([0, 1/2, L/12, 0, 1/2, -L/12]).reshape(6,1) + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + Kle = K0le+Ksle + Ke = G.T @ Kle @ G + fe = G.T @ fle + + if eq is None: + return Ke + else: + return Ke, fe + + +def beam2gs(ex, ey, ep, ed, QX, eq=None, nep=None): + """ + es, QX = beam2gs(ex, ey, ep, ed, QX) + es, QX = beam2gs(ex, ey, ep, ed, QX, eq) + es, QX, edi, eci = beam2gs(ex, ey, ep, ed, QX, eq, nep) +--------------------------------------------------------------------- + PURPOSE + Calculate section forces in a two dimensional nonlinear + beam element (beam2ge). + + INPUT: ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E, A, I] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + + ed = [u1, ... ,u6] element displacement vector + + QX axial force + + eq = [qy] distributed transverse load + + nep number of evaluation points ( default=2 ) + + OUTPUT: es = [ N1 V1 M1 section forces, local directions, in + N2 V2 M2 n points along the beam, dim(es)= n x 3 + ........] + + QX axial force + + edi = [ u1 v1 element displacements, local directions, + u2 v2 in n points along the beam, dim(es)= n x 2 + .....] + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2021-09-01 + O Dahlblom 2022-12-06 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I = ep + DEA = E*A + DEI = E*I + + if eq != None: + if np.size(eq) > 1: + error("eq should be a scalar !!!") + return + else: + qY = eq[0] + else: + qY = 0 + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + ne = 2 + if nep != None: + ne = nep + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + edl = G @ ed.reshape(6,1) + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + a1 = np.array([ + edl[0], + edl[3] + ]) + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + C1a = C1 @ a1 + + a2 = np.array([ + edl[1], + edl[2], + edl[4], + edl[5] + ]) + C2 = np.array([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [-3/L**2, -2/L, 3/L**2, -1/L], + [2/L**3, 1/L**2, -2/L**3, 1/L**2] + ]) + C2a = C2 @ a2 + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a + dv = np.concatenate((zero, one, 2*X, 3*X**2), 1) @ C2a + d2v = np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + d3v = np.concatenate((zero, zero, zero, 6*one), 1) @ C2a + if DEI != 0: + v = v + QX/DEI*np.concatenate((zero, zero, (X**4-2*L*X**3+L**2*X**2)/12, (X**5-3*L**2*X**3+2*L**3*X**2)/20), 1) @ C2a + \ + (X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI) + dv = dv + QX/DEI*np.concatenate((zero, zero, (2*X**3-3*L*X**2+L**2*X)/6, (5*X**4-9*L**2*X**2+4*L**3*X)/20), 1) @ C2a + \ + (2*X**3 - 3*L*X**2 + L**2*X)*qY/(12*DEI) + d2v = d2v + QX/DEI*np.concatenate((zero, zero, (6*X**2-6*L*X+L**2*one)/6, (10*X**3-9*L**2*X+2*L**3*one)/10), 1) @ C2a + \ + (6*X**2 - 6*L*X + L**2*one)*qY/(12*DEI) + d3v = d3v + QX/DEI*np.concatenate((zero, zero, (2*X-L*one), (30*X**2-9*L**2*one)/10), 1) @ C2a + \ + (2*X - L*one)*qY/(2*DEI) + + QX = DEA*du.item(0) + M = DEI*d2v + V = -DEI*d3v + N=QX+dv*V + es = np.concatenate((N, V, M), 1) + edi = np.concatenate((u, v), 1) + eci = X + + if nep == None: + return es, QX + else: + return es, QX, edi, eci + + +def beam2gxe(ex, ey, ep, QX, eq=None): + """ + Ke = beam2gxe(ex, ey, ep, QX) + Ke, fe = beam2gxe(ex, ey, ep, QX, eq) + ------------------------------------------------------------- + PURPOSE + Compute the element stiffness matrix for a two dimensional + beam element with respect to geometric nonlinearity with exact solution. + + INPUT: ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E, A, I] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + + QX axial force in the beam + + eq distributed transverse load + + OUTPUT: Ke : element stiffness matrix [6 x 6] + fe : element load vector [6 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2021-06-21 + O Dahlblom 2022-12-06 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I = ep + DEA = E*A + DEI = E*I + + if eq != None: + if np.size(eq) > 1: + error("eq should be a scalar !!!") + return + else: + qY = eq[0] + else: + qY = 0 + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + eps = 1e-12 + + if QX < -eps*DEI/L**2: + kL = np.sqrt(-QX/DEI)*L + f1 = (kL/2)/np.tan(kL/2) + f2 = kL**2/(12*(1-f1)) + f3 = f1/4+3*f2/4 + f4 = -f1/2+3*f2/2 + f5 = f1*f2 + h = 6*(2/kL**2-(1+np.cos(kL))/(kL*np.sin(kL))) + elif QX > eps*DEI/L**2: + kL = np.sqrt(QX/DEI)*L + f1 = (kL/2)/np.tanh(kL/2) + f2 = -(1/12.)*kL**2/(1-f1) + f3 = f1/4+3*f2/4 + f4 = -f1/2+3*f2/2 + f5 = f1*f2 + h = -6*(2/kL**2-(1+np.cosh(kL))/(kL*np.sinh(kL))) + else: + f1 = f2 = f3 = f4 = f5 = h = 1 + + Kle = np.array([ + [DEA/L, 0., 0., -DEA/L, 0., 0.], + [ 0., 12*DEI*f5/L**3, 6*DEI*f2/L**2, 0., -12*DEI*f5/L**3, 6*DEI*f2/L**2], + [ 0., 6*DEI*f2/L**2, 4*DEI*f3/L, 0., -6*DEI*f2/L**2, 2*DEI*f4/L], + [-DEA/L, 0., 0., DEA/L, 0., 0.], + [ 0., -12*DEI*f5/L**3, -6*DEI*f2/L**2, 0., 12*DEI*f5/L**3, -6*DEI*f2/L**2], + [0., 6*DEI*f2/L**2, 2*DEI*f4/L, 0., -6*DEI*f2/L**2, 4*DEI*f3/L] + ]) + + fle = qY*L*np.array([0., 1/2., L*h/12, 0., 1/2., -L*h/12]).reshape(6,1) + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + Ke = G.T @ Kle @ G + fe = G.T @ fle + + if eq is None: + return Ke + else: + return Ke, fe + + +def beam2gxs(ex, ey, ep, ed, QX, eq=None, nep=None): + """ + es, QX = beam2gxs(ex, ey, ep, ed, QX) + es, QX = beam2gxs(ex, ey, ep, ed, QX, eq) + es, QX, edi, eci = beam2gxs(ex, ey, ep, ed, QX, eq, nep) +--------------------------------------------------------------------- + PURPOSE + Calculate section forces in a two dimensional nonlinear + beam element (beam2gxe). + + INPUT: ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E, A, I] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + + ed = [u1, ... ,u6] element displacement vector + + QX axial force + + eq = [qy] distributed transverse load + + nep number of evaluation points ( default=2 ) + + OUTPUT: es = [ N1 V1 M1 section forces, local directions, in + N2 V2 M2 n points along the beam, dim(es)= n x 3 + ........] + + QX axial force + + edi = [ u1 v1 element displacements, local directions, + u2 v2 in n points along the beam, dim(es)= n x 2 + .....] + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2021-09-17 + O Dahlblom 2022-12-06 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, A, I = ep + DEA = E*A + DEI = E*I + + if eq != None: + if np.size(eq) > 1: + error("eq should be a scalar !!!") + return + else: + qY = eq[0] + else: + qY = 0 + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + + ne = 2 + if nep != None: + ne = nep + + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) + + edl = G @ ed.reshape(6,1) + + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + a1 = np.array([ + edl[0], + edl[3] + ]) + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + C1a = C1 @ a1 + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + + a2 = np.array([ + edl[1], + edl[2], + edl[4], + edl[5] ]) - K2 = L/420*np.mat([ - [140*ka, 0, 0, 70*ka, 0, 0], - [0, 156*kt, 22*kt*L, 0, 54*kt, -13*kt*L], - [0, 22*kt*L, 4*kt*L**2, 0, 13*kt*L, -3*kt*L**2], - [70*ka, 0, 0, 140*ka, 0, 0], - [0, 54*kt, 13*kt*L, 0, 156*kt, -22*kt*L], - [0, -13*kt*L, -3*kt*L**2, 0, -22*kt*L, 4*kt*L**2] - ]) + eps = 1e-12 + + if QX < -eps*DEI/L**2: + k = np.sqrt(-QX/DEI) + kL = k*L + C2 = 1/(k*(-2*(1-np.cos(kL))+kL*np.sin(kL)))*np.array([ + [k*(kL*np.sin(kL)+np.cos(kL)-1), -kL*np.cos(kL)+np.sin(kL), -k*(1-np.cos(kL)), -np.sin(kL)+kL], + [-(k**2)*np.sin(kL), -k*(1-np.cos(kL)), (k**2)*np.sin(kL), -k*(1-np.cos(kL))], + [-k*(1-np.cos(kL)), kL*np.cos(kL)-np.sin(kL), k*(1-np.cos(kL)), np.sin(kL)-kL], + [k*np.sin(kL), (kL*np.sin(kL)+np.cos(kL)-1), -k*np.sin(kL), (1-np.cos(kL))] + ]) + + C2a = C2 @ a2 + v = np.concatenate((one, X, np.cos(k*X), np.sin(k*X)), 1) @ C2a + dv = np.concatenate((zero, one, -k*np.sin(k*X), k*np.cos(k*X)), 1) @ C2a + d2v = np.concatenate((zero, zero, -k**2*np.cos(k*X), -k**2*np.sin(k*X)), 1) @ C2a + d3v = np.concatenate((zero, zero, k**3*np.sin(k*X), -k**3*np.cos(k*X)), 1) @ C2a + if DEI != 0: + v = v+qY*L**4/(2*DEI)*((1+np.cos(kL))/(kL**3*np.sin(kL))*(-1+np.cos(k*X))+np.sin(k*X)/kL**3+X*(-1+X/L)/(kL**2*L)) + dv = dv+qY*L**3/(2*DEI)*((1+np.cos(kL))/(kL**2*np.sin(kL))*(-np.sin(k*X))+np.cos(k*X)/kL**2+(-1+2*X/L)/kL**2) + d2v = d2v+qY*L**2/(2*DEI)*((1+np.cos(kL))/(kL*np.sin(kL))*(-np.cos(k*X))-np.sin(k*X)/kL+2/(kL**2)) + d3v = d3v+qY*L/(2*DEI)*((1+np.cos(kL))/np.sin(kL)*(np.sin(k*X))-np.cos(k*X)) + elif QX > eps*DEI/L**2: + k = np.sqrt(QX/DEI) + kL = k*L + C2 = 1/(k*(-2*(1-np.cosh(kL))-kL*np.sinh(kL)))*np.array([ + [k*(-kL*np.sinh(kL)+np.cosh(kL)-1), -kL*np.cosh(kL)+np.sinh(kL), -k*(1-np.cosh(kL)), -np.sinh(kL)+kL], + [(k**2)*np.sinh(kL), -k*(1-np.cosh(kL)), -(k**2)*np.sinh(kL), -k*(1-np.cosh(kL))], + [-k*(1-np.cosh(kL)), kL*np.cosh(kL)-np.sinh(kL), k*(1-np.cosh(kL)), np.sinh(kL)-kL], + [-k*np.sinh(kL), (-kL*np.sinh(kL)+np.cosh(kL)-1), k*np.sinh(kL), (1-np.cosh(kL))] + ]) + C2a = C2 @ a2 + v = np.concatenate((one, X, np.cosh(k*X), np.sinh(k*X)), 1) @ C2a + dv = np.concatenate((zero, one, k*np.sinh(k*X), k*np.cosh(k*X)), 1) @ C2a + d2v = np.concatenate((zero, zero, k**2*np.cosh(k*X), k**2*np.sinh(k*X)), 1) @ C2a + d3v = np.concatenate((zero, zero, k**3*np.sinh(k*X), k**3*np.cosh(k*X)), 1) @ C2a + if DEI != 0: + v = v+qY*L**4/(2*DEI)*((1+np.cosh(kL))/(kL**3*np.sinh(kL))*(-1+np.cosh(k*X))-np.sinh(k*X)/kL**3+X*(1-X/L)/(kL**2*L)) + dv = dv+qY*L**3/(2*DEI)*((1+np.cosh(kL))/(kL**2*np.sinh(kL))*(np.sinh(k*X))-np.cosh(k*X)/kL**2+(1-2*X/L)/kL**2) + d2v = d2v+qY*L**2/(2*DEI)*((1+np.cosh(kL))/(kL*np.sinh(kL))*(np.cosh(k*X))-np.sinh(k*X)/kL-2/(kL**2)) + d3v = d3v+qY*L/(2*DEI)*((1+np.cosh(kL))/np.sinh(kL)*(np.sinh(k*X))-np.cosh(k*X)) + else: + C2 = np.array([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [-3/L**2, -2/L, 3/L**2, -1/L], + [2/L**3, 1/L**2, -2/L**3, 1/L**2] + ]) + C2a = C2 @ a2 + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a + dv = np.concatenate((zero, one, 2*X, 3*X**2), 1) @ C2a + d2v = np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + d3v = np.concatenate((zero, zero, zero, 6*one), 1) @ C2a + if DEI != 0: + v = v+(X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI) + dv = dv+(2*X**3 -3*L*X**2 +L**2*X)*qY/(12*DEI) + d2v = d2v +(6*X**2 - 6*L*X + L**2*one)*qY/(12*DEI) + d3v = d3v +(2*X - L*one)*qY/(2*DEI) + + QX = DEA*du.item(0) + M = DEI*d2v + V = -DEI*d3v + N=QX+dv*V + es = np.concatenate((N, V, M), 1) + edi = np.concatenate((u, v), 1) + eci = X + + if nep == None: + return es, QX + else: + return es, QX, edi, eci + + +def beam2te(ex, ey, ep, eq=None): + """ + Ke = beam2te(ex, ey, ep) + Ke, fe = beam2te(ex, ey, ep, eq) + ------------------------------------------------------------- + PURPOSE + Compute the stiffness matrix for a two dimensional Timoshenko + beam element. + + INPUT: ex = [x1 x2] element node coordinates + ey = [y1 y2] + + ep = [E Gm A I ks] element properties; + E: Young's modulus + G: shear modulus + A: Cross section area + I: moment of inertia + ks: shear correction factor + + eq = [qX qY] distributed loads, local directions + + OUTPUT: Ke : element stiffness matrix [6 x 6] + fe : element load vector [6 x 1] (if eq!=None) + ------------------------------------------------------------- + + LAST MODIFIED: O Dahlblom 2021-11-05 + O Dahlblom 2022-12-08 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, Gm, A, I, ks = ep + DEA = E*A + DEI = E*I + DGAks = Gm*A*ks + + qX = 0. + qY = 0. + if not eq is None: + qX, qY = eq + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) + m = (12*DEI)/(L**2*DGAks) + f1=1/(1+m) + f2=f1*(1+m/4) + f3=f1*(1-m/2) - Kle = K1+K2 - fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T - G = np.mat([ - [n[0], n[1], 0, 0, 0, 0], - [-n[1], n[0], 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0], - [0, 0, 0, n[0], n[1], 0], - [0, 0, 0, -n[1], n[0], 0], - [0, 0, 0, 0, 0, 1] + Kle = np.array([ + [ DEA/L, 0., 0., -DEA/L, 0., 0.], + [ 0., 12*DEI*f1/L**3, 6*DEI*f1/L**2, 0., -12*DEI*f1/L**3, 6*DEI*f1/L**2], + [ 0., 6*DEI*f1/L**2, 4*DEI*f2/L, 0., -6*DEI*f1/L**2, 2*DEI*f3/L], + [-DEA/L, 0., 0., DEA/L, 0., 0.], + [ 0., -12*DEI*f1/L**3, -6*DEI*f1/L**2, 0., 12*DEI*f1/L**3, -6*DEI*f1/L**2], + [ 0., 6*DEI*f1/L**2, 2*DEI*f3/L, 0., -6*DEI*f1/L**2, 4*DEI*f2/L] ]) - P = Kle*G*np.asmatrix(ed).T-fle + fle = L*np.array([qX/2, qY/2, qY*L/12, qX/2, qY/2, -qY*L/12]).reshape(6,1) - es = np.mat([ - [-P[0, 0], -P[1, 0], -P[2, 0]], - [P[3, 0], P[4, 0], P[5, 0]] + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] ]) - return es + Ke = G.T @ Kle @ G + fe = G.T @ fle + if eq is None: + return Ke + else: + return Ke, fe + -def beam2g(ex, ey, ep, N, eq=None): +def beam2ts(ex, ey, ep, ed, eq=None, nep=None): """ - Compute the element stiffness matrix for a two dimensional - beam element with respect to geometric nonlinearity. - - Parameters: - - ex = [x1, x2] - ey = [y1, y2] element node coordinates + es = beam2ts(ex, ey, ep, ed) + es = beam2ts(ex, ey, ep, ed, eq) + es, edi, eci = beam2s(ex, ey, ep, ed, eq, nep) +--------------------------------------------------------------------- + PURPOSE + Compute section forces in two dimensional Timoshenko beam + element (beam2te). - ep = [E,A,I] element properties; - E: Young's modulus - A: cross section area - I: moment of inertia + INPUT: ex = [x1 x2] + ey = [y1 y2] element node coordinates - N axial force in the beam + ep = [E G A I ks] element properties, + E: Young's modulus + G: shear modulus + A: cross section area + I: moment of inertia + ks: shear correction factor - eq distributed transverse load + ed = [u1 ... u6] element displacements - Returns: + eq = [qx qy] distributed loads, local directions - Ke element stiffness matrix (6 x 6) + nep number of evaluation points ( default=2 ) - fe element load vector (6 x 1) - """ - if eq != None: - if np.size(eq) > 1: - error("eq should be a scalar !!!") - return - else: - q = eq[0] - else: - q = 0 + OUTPUT: es = [ N1 V1 M1 section forces, local directions, in + N2 V2 M2 n points along the beam, dim(es)= n x 3 + ........] + + edi = [ u1 v1 teta1 element displacements, local directions, + u2 v2 teta2 in n points along the beam, dim(es)= n x 2 + ...........] + (Note! For Timoshenko beam element the rotation of the cross + section is not equal to dv/dx) + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + ------------------------------------------------------------- - b = np.mat([ - [ex[1]-ex[0]], - [ey[1]-ey[0]] - ]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b/L).reshape(2,) + LAST MODIFIED: O Dahlblom 2021-11-05 + O Dahlblom 2022-12-08 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + E, Gm, A, I, ks = ep + DEA = E*A + DEI = E*I + DGAks = Gm*A*ks + alpha=DEI/DGAks + + qX = 0. + qY = 0. + if not eq is None: + qX, qY = eq - E, A, I = ep + ne=2 + if nep != None: + ne=nep + + x1, x2 = ex + y1, y2 = ey + dx = x2-x1 + dy = y2-y1 + L = np.sqrt(dx*dx+dy*dy) - rho = -N*L**2/(np.pi**2*E*I) + nxX = dx/L + nyX = dy/L + nxY = -dy/L + nyY = dx/L + G = np.array([ + [nxX, nyX, 0, 0, 0, 0], + [nxY, nyY, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, nxX, nyX, 0], + [ 0, 0, 0, nxY, nyY, 0], + [ 0, 0, 0, 0, 0, 1] + ]) - kL = np.pi*np.sqrt(abs(rho))+np.finfo(float).eps + edl = G @ ed.reshape(6,1) - if rho > 0: - f1 = (kL/2)/np.tan(kL/2) - f2 = (1/12.)*kL**2/(1-f1) - f3 = f1/4+3*f2/4 - f4 = -f1/2+3*f2/2 - f5 = f1*f2 - h = 6*(2/kL**2-(1+np.cos(kL))/(kL*np.sin(kL))) - elif rho < 0: - f1 = (kL/2)/np.tanh(kL/2) - f2 = -(1/12.)*kL**2/(1-f1) - f3 = f1/4+3*f2/4 - f4 = -f1/2+3*f2/2 - f5 = f1*f2 - h = -6*(2/kL**2-(1+np.cosh(kL))/(kL*np.sinh(kL))) - else: - f1 = f2 = f3 = f4 = f5 = h = 1 + a1 = np.array([ + edl[0], + edl[3] + ]) + C1 = np.array([ + [1., 0.], + [-1/L, 1/L] + ]) + C1a = C1 @ a1 - Kle = np.mat([ - [E*A/L, 0., 0., -E*A/L, 0., 0.], - [0., 12*E*I*f5/L**3., 6*E*I*f2/L**2., - 0., -12*E*I*f5/L**3., 6*E*I*f2/L**2.], - [0., 6*E*I*f2/L**2., 4*E*I*f3/L, - 0., -6*E*I*f2/L**2., 2*E*I*f4/L], - [-E*A/L, 0., 0., E*A/L, 0., 0.], - [0., -12*E*I*f5/L**3., -6*E*I*f2/L**2., - 0., 12*E*I*f5/L**3., -6*E*I*f2/L**2.], - [0., 6*E*I*f2/L**2., 2*E*I*f4/L, - 0., -6*E*I*f2/L**2., 4*E*I*f3/L] + a2 = np.array([ + edl[1], + edl[2], + edl[4], + edl[5] ]) + C2 = 1/(L**2+12*alpha)*np.array([ + [L**2+12*alpha, 0., 0., 0.], + [ -12*alpha/L, L**2+6*alpha, 12*alpha/L, -6*alpha], + [ -3., -2*L-6*alpha/L, 3., -L+6*alpha/L], + [ 2/L, 1., -2/L, 1.] + ]) + C2a = C2 @ a2 - fle = q*L*np.mat([0., 1/2., L*h/12, 0., 1/2., -L*h/12]).T + X = np.arange(0., L+L/(ne-1), L/(ne-1)).reshape(ne,1) + zero = np.zeros(ne).reshape(ne,1) + one = np.ones(ne).reshape(ne,1) + + u = np.concatenate((one, X), 1) @ C1a + du = np.concatenate((zero, one), 1) @ C1a + if DEA != 0: + u = u -(X**2-L*X)*qX/(2*DEA) + du = du -(2*X-L)*qX/(2*DEA) - G = np.mat([ - [n[0], n[1], 0, 0, 0, 0], - [-n[1], n[0], 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0], - [0, 0, 0, n[0], n[1], 0], - [0, 0, 0, -n[1], n[0], 0], - [0, 0, 0, 0, 0, 1] - ]) + v = np.concatenate((one, X, X**2, X**3), 1) @ C2a + dv = np.concatenate((zero, one, 2*X, 3*X**2), 1) @ C2a + theta = np.concatenate((zero, one, 2*X, 3*X**2+6*alpha), 1) @ C2a + dtheta=np.concatenate((zero, zero, 2*one, 6*X), 1) @ C2a + if DEI != 0: + v = v+(X**4 - 2*L*X**3 + L**2*X**2)*qY/(24*DEI)+(-X**2/2+L*X/2)*qY/DGAks + dv = dv+(2*X**3 - 3*L*X**2 + L**2*X)*qY/(12*DEI)+(-X+L/2)*qY/DGAks + theta = theta+(2*X**3-3*L*X**2+L**2*X)*qY/(12*DEI) + dtheta = dtheta+(6*X**2-6*L*X+L**2)*qY/(12*DEI) - Ke = G.T*Kle*G - fe = G.T*fle + N = DEA*du + M = DEI*dtheta + V = DGAks*(dv-theta) + es = np.concatenate((N, V, M), 1) + edi = np.concatenate((u, v, theta), 1) + eci = X - if eq != None: - return Ke, fe + if nep == None: + return es else: - return Ke - + return es, edi, eci + -def beam2gs(ex, ey, ep, ed, N, eq=None): +def beam2de(ex, ey, ep): """ - Calculate section forces in a two dimensional nonlinear + Ke, Me = beam2de(ex, ey, ep) + Ke, Me, Ce = beam2de(ex, ey, ep) + ------------------------------------------------------------- + PURPOSE + Calculate the stiffness matrix Ke, the mass matrix Me + and the damping matrix Ce for a 2D elastic Bernoulli beam element. - Parameters: - - ex = [x1, x2] - ey = [y1, y2] element node coordinates - - ep = [E,A,I] element properties; - E: Young's modulus - A: cross section area - I: moment of inertia - - ed = [u1, ... ,u6] element displacement vector - - N axial force + INPUT: ex = [x1, x2] + ey = [y1, y2] element node coordinates - eq = [qy] distributed transverse load + ep = [E,A,I,m,(a,b)] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + m: mass per unit length + a,b: damping coefficients, + Ce=aMe+bKe - Returns: + OUTPUT: Ke element stiffness matrix (6 x 6) + Me element mass martix + Ce element damping matrix, optional + ------------------------------------------------------------- - es = [[N1,V1,M1], element forces, local directions - [N2,V2,M2]] + LAST MODIFIED: K Persson 1995-08-23 + O Dahlblom 2022-12-08 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - if eq != None: - eq = eq[0] - else: - eq = 0 - - b = np.mat([ + b = np.array([ [ex[1]-ex[0]], [ey[1]-ey[0]] ]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b/L).reshape(2,) + L = np.sqrt(b.T @ b).item(0) + n = np.array(b/L).reshape(2,) - E, A, I = ep + a = 0 + b = 0 + if np.size(ep) == 4: + E, A, I, m = ep + elif np.size(ep) == 6: + E, A, I, m, a, b = ep - rho = -N*L**2/(np.pi**2*E*I) + print ("E, A, I, m, a, b, L") + print (E, A, I, m, a, b, L) - eps = 2.2204e-16 - kL = np.pi*np.sqrt(abs(rho))+eps - if rho > 0: - f1 = (kL/2)/np.tan(kL/2) - f2 = (1/12.)*kL**2/(1-f1) - f3 = f1/4+3*f2/4 - f4 = -f1/2+3*f2/2 - f5 = f1*f2 - h = 6*(2/kL**2-(1+np.cos(kL))/(kL*np.sin(kL))) - elif rho < 0: - f1 = (kL/2)/np.tanh(kL/2) - f2 = -(1/12.)*kL**2/(1-f1) - f3 = f1/4+3*f2/4 - f4 = -f1/2+3*f2/2 - f5 = f1*f2 - h = -6*(2/kL**2-(1+np.cosh(kL))/(kL*np.sinh(kL))) - else: - f1 = f2 = f3 = f4 = f5 = h = 1 + Kle = np.array([ + [E*A/L, 0, 0, -E*A/L, 0, 0], + [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], + [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], + [-E*A/L, 0, 0, E*A/L, 0, 0], + [0, -12*E*I/L**3, -6*E*I/L**2, 0, 12*E*I/L**3, -6*E*I/L**2], + [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] + ]) - Kle = np.mat([ - [E*A/L, 0, 0, -E*A/L, 0, 0], - [0, 12*E*I*f5/L**3, 6*E*I*f2/L**2, - 0, -12*E*I*f5/L**3, 6*E*I*f2/L**2], - [0, 6*E*I*f2/L**2, 4*E*I*f3/L, 0, -6*E*I*f2/L**2, 2*E*I*f4/L], - [-E*A/L, 0, 0, E*A/L, 0, 0], - [0, -12*E*I*f5/L**3, -6*E*I*f2/L**2, - 0, 12*E*I*f5/L**3, -6*E*I*f2/L**2], - [0, 6*E*I*f2/L**2, 2*E*I*f4/L, 0, -6*E*I*f2/L**2, 4*E*I*f3/L] + Mle = m*L/420*np.array([ + [140, 0, 0, 70, 0, 0], + [0, 156, 22*L, 0, 54, -13*L], + [0, 22*L, 4*L**2, 0, 13*L, -3*L**2], + [70, 0, 0, 140, 0, 0], + [0, 54, 13*L, 0, 156, -22*L], + [0, -13*L, -3*L**2, 0, -22*L, 4*L**2] ]) - fle = eq*L*np.mat([0, 1/2., L*h/12, 0, 1/2., -L*h/12]).T + Cle = a*Mle+b*Kle - G = np.mat([ + G = np.array([ [n[0], n[1], 0, 0, 0, 0], [-n[1], n[0], 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], @@ -1097,48 +2534,59 @@ def beam2gs(ex, ey, ep, ed, N, eq=None): [0, 0, 0, 0, 0, 1] ]) - u = np.asmatrix(ed).T - P = Kle*G*u-fle - - es = np.mat([ - [-P[0, 0], -P[1, 0], -P[2, 0]], - [P[3, 0], P[4, 0], P[5, 0]] - ]) + Ke = G.T @ Kle @ G + Me = G.T @ Mle @ G + Ce = G.T @ Cle @ G - return es + if np.size(ep) == 4: + return Ke, Me + elif np.size(ep) == 6: + return Ke, Me, Ce -def beam2d(ex, ey, ep): +def beam2ds(ex, ey, ep, ed, ev, ea): """ - Calculate the stiffness matrix Ke, the mass matrix Me - and the damping matrix Ce for a 2D elastic Bernoulli - beam element. - - Parameters: - - ex = [x1, x2] - ey = [y1, y2] element node coordinates - - ep = [E,A,I,m,(a,b)] element properties; - E: Young's modulus - A: cross section area - I: moment of inertia - m: mass per unit length - a,b: damping coefficients, - Ce=aMe+bKe + es = beam2ds(ex, ey, ep, ed, ev, ea) + ------------------------------------------------------------- + PURPOSE + Calculate the element forces for a number of identical + (nie) 2D Bernoulli beam elements in dynamic analysis. + + INPUT: ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,A,I,m,(a,b)] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + m: mass per unit length + a,b: damping coefficients, + Ce=aMe+bKe + + ed : element displacement matrix + + ev : element velocity matrix + + ea : element acceleration matrix - Returns: + OUTPUT: es : element forces in local directions, + = [-N1 -V1 -M1 N2 V2 M2; + ....... ......] ; dim(es)= nie x 6 + ------------------------------------------------------------- - Ke element stiffness matrix (6 x 6) - Me element mass martix - Ce element damping matrix, optional + LAST MODIFIED: K Persson 1995-08-23 + O Dahlblom 2022-12-08 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- """ - b = np.mat([ + b = np.array([ [ex[1]-ex[0]], [ey[1]-ey[0]] ]) - L = np.sqrt(b.T*b).item() - n = np.asarray(b/L).reshape(2,) + L = np.sqrt(b.T @ b).item(0) + n = np.array(b/L).reshape(2,) a = 0 b = 0 @@ -1147,7 +2595,7 @@ def beam2d(ex, ey, ep): elif np.size(ep) == 6: E, A, I, m, a, b = ep - Kle = np.mat([ + Kle = np.array([ [E*A/L, 0, 0, -E*A/L, 0, 0], [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], @@ -1156,7 +2604,7 @@ def beam2d(ex, ey, ep): [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] ]) - Mle = m*L/420*np.mat([ + Mle = m*L/420*np.array([ [140, 0, 0, 70, 0, 0], [0, 156, 22*L, 0, 54, -13*L], [0, 22*L, 4*L**2, 0, 13*L, -3*L**2], @@ -1167,7 +2615,7 @@ def beam2d(ex, ey, ep): Cle = a*Mle+b*Kle - G = np.mat([ + G = np.array([ [n[0], n[1], 0, 0, 0, 0], [-n[1], n[0], 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], @@ -1176,14 +2624,22 @@ def beam2d(ex, ey, ep): [0, 0, 0, 0, 0, 1] ]) - Ke = G.T*Kle*G - Me = G.T*Mle*G - Ce = G.T*Cle*G + nie, ned = ed.shape + es = np.array(np.zeros((nie, 6))) + for i in range(nie): + d = ed[i,:].reshape(6,1) + v = ev[i,:].reshape(6,1) + a = ea[i,:].reshape(6,1) + es[i,:] = (Kle @ G @ d + Cle @ G @ v + Mle @ G @ a).T + +# [nie,ned]=size(ed); +# for i=1:nie +# d=ed(i,:)'; +# v=ev(i,:)'; +# a=ea(i,:)'; +# es(i,:)=(Kle*G*d+Cle*G*v+Mle*G*a)'; - if np.size(ep) == 4: - return Ke, Me - elif np.size(ep) == 6: - return Ke, Me, Ce + return es def beam3e(ex, ey, ez, eo, ep, eq=None): @@ -1363,7 +2819,6 @@ def beam3s(ex, ey, ez, eo, ep, ed, eq=None, nep=None): [xn]] ------------------------------------------------------------- - LAST MODIFIED: O Dahlblom 2015-10-19 O Dahlblom 2022-11-23 (Python version) Copyright (c) Division of Structural Mechanics and @@ -1519,7 +2974,7 @@ def beam3s(ex, ey, ez, eo, ep, ed, eq=None, nep=None): return es else: return es, edi, eci - + def flw2te(ex, ey, ep, D, eq=None): """ @@ -3983,6 +5438,412 @@ def eigen(K,M,b=None): return L, X +def gfunc(G,dt): + """ + Form vector with function values at equally spaced + points by linear interpolation + + Parameters: + + G = [t_i, g_i] t_i: time i, g_i: g(t_i) + dim(G) = np x 2, np = number of points + dt time step + + Returns: + + t 1-D vector with equally spaced time points + g 1-D vector with corresponding function values + """ + ti = np.arange(G[0,0],G[-1,0]+dt,dt) + g1 = np.interp(ti,G[:,0],G[:,1]) + return ti, g1 + + +def step1(K,C,f,a0,bc,ip,times,dofs): + """ + Algorithm for dynamic solution of first-order + FE equations considering boundary conditions. + + Parameters: + + K conductivity matrix, dim(K) = ndof x ndof + C capacity matrix, dim(C) = ndof x ndof + f load vector, dim(f) = ndof x (nstep + 1), + If dim(f) = ndof x 1, the values are kept constant + during time integration + a0 initial vector a(0), dim(a0) = ndof x 1 + bc boundary condition matrix, dim(bc) = nbc x (nstep + 2) + where nbc = number of prescribed degrees of freedom (either constant or time-dependent) + The first column contains the numbers of the prescribed degrees of freedom + and the subsequent columns contain the time history. + If dim(bc) = nbc x 2, the values from the second column are kept constant + during time integration + ip array [dt, tottime, alpha], where + dt is the size of the time increment, + tottime is the total time, + alpha is time integration constant. + Frequently used values of alpha are: + alpha=0: forward difference; forward Euler, + alpha=1/2: trapezoidal rule; Crank-Nicholson + alpha=1: backward difference; backward Euler + times array [t(i) ...] of times at which output should be written to a and da + dofs array [dof(i) ...] of degree of freedom numbers for which history output + should be written to ahist and dahist + + Returns: + + modelhist dictionary containing solution history for the whole model at following keys: + modelhist['a'] constains values of a at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['a']) = ndof x (nstep + 1) or ndof x ntimes + modelhist['da'] constains values of da at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['da']) = ndof x (nstep + 1) or ndof x ntimes + dofhist dictionary containing solution history for the degrees of freedom selected in 'dofs': + dofhist['a'] constains time history of a at the dofs specified in 'dofs' + dim(dofhist['ahist']) = ndof x (nstep + 1) + dofhist['da'] constains time history of daat the dofs specified in 'dofs' + dim(dofhist['dahist']) = ndof x (nstep + 1) + """ + ndof, _ = K.shape + dt, tottime, alpha = ip + a1 = (1-alpha)*dt + a2 = alpha*dt + + nstep = 1 + if np.array(f).any(): + _, ncf = f.shape + if ncf>1: + nstep = ncf-1 + + if np.array(bc).any(): + _, ncb = bc.shape + if ncb>2: + nstep = ncb-2 + bound = 1 + if not np.array(bc).any(): + bound = 0 + + ns = int(tottime/dt) + if (ns < nstep or nstep==1): + nstep=ns + + tf = np.zeros((ndof,nstep+1)) + if np.array(f).any(): + if ncf==1: + tf = f[:,0].reshape(-1,1)@np.ones((1,nstep+1)) + if ncf>1: + tf = np.copy(f) + + modelhist = {} + sa=0 + if not np.array(times).any(): + ntimes=0 + sa=1 + modelhist['a'] = np.zeros((ndof,nstep+1)) + modelhist['da'] = np.zeros((ndof,nstep+1)) + else: + ntimes = len(times) + if ntimes: + sa=2 + modelhist['a'] = np.zeros((ndof,ntimes)) + modelhist['da'] = np.zeros((ndof,ntimes)) + + dofhist = {} + if np.array(dofs).all(): + ndofs = len(dofs) + if ndofs: + dofhist['a'] = np.zeros((ndofs,nstep+1)) + dofhist['da'] = np.zeros((ndofs,nstep+1)) + else: + ndofs=0 + + itime = 0 + + # Calculate initial second time derivative d2a0 + da0 = np.linalg.solve(C,tf[:,0].reshape(-1,1) - K@a0) + # Save initial values + if sa==1: + modelhist['a'][:,0] = a0.ravel() + modelhist['da'][:,0] = da0.ravel() + elif sa==2: + if times[itime]==0: + modelhist['a'][:,itime] = a0.ravel() + modelhist['da'][:,itime] = da0.ravel() + itime += 1 + + if ndofs: + dofhist['a'][:,0] = a0[np.ix_(dofs-1)].ravel() + dofhist['da'][:,0] = da0[np.ix_(dofs-1)].ravel() + + # Reduce matrices due to bcs + tempa = np.zeros((ndof,1)) + tempda = np.zeros((ndof,1)) + fdof=np.arange(1,ndof+1).astype(int) + if bound: + nrb, ncb = bc.shape + if ncb==2: + pa = bc[:,1].reshape(-1,1)@np.ones((1,nstep+1)) + pda = np.zeros((nrb,nstep+1)) + elif ncb>2: + pa = np.copy(bc[:,1:]) + pda1 = (pa[:,1]-pa[:,0])/dt + pdarest = (pa[:,1:] - pa[:,0:-1])/dt + pda = np.hstack((pda1.reshape(-1,1),pdarest)) + pdof = np.copy(bc[:,0]).astype(int) + fdof = np.setdiff1d(fdof,pdof).astype(int) - 1 + pdof -= 1 #adjusting for indexing starting from 0 + Keff = C[np.ix_(fdof,fdof)] + a2*K[np.ix_(fdof,fdof)] + else: + fdof -= 1 #adjusting for indexing starting from 0 + Keff = C + a2*K + + L, U = lu(Keff,permute_l=True) + anew = a0[np.ix_(fdof)] + danew = da0[np.ix_(fdof)] + + # Iterate over time steps + for j in range(1,nstep+1): + time = dt*j + aold = np.copy(anew) + daold = np.copy(danew) + apred = aold + a1*daold + if not bound: + reff = tf[:,j].reshape(-1,1) - K@apred + else: + pdeff = C[np.ix_(fdof,pdof)]@pda[:,j].reshape(-1,1) + K[np.ix_(fdof,pdof)]@pa[:,j].reshape(-1,1) + reff = tf[np.ix_(fdof),j].reshape(-1,1) - K[np.ix_(fdof,fdof)]@apred - pdeff + y = np.linalg.solve(L,reff) + danew = np.linalg.solve(U,y) + anew = apred + a2*danew + # Save to modelhist and dofhist + if bound: + tempa[np.ix_(pdof)] = pa[:,j].reshape(-1,1) + tempda[np.ix_(pdof)] = pda[:,j].reshape(-1,1) + tempa[np.ix_(fdof)] = anew + tempda[np.ix_(fdof)] = danew + if sa==1: + modelhist['a'][:,j] = tempa.ravel() + modelhist['da'][:,j] = tempda.ravel() + elif sa==2: + if ntimes and itime < ntimes: + if time >= times[itime]: + modelhist['a'][:,itime] = tempa.ravel() + modelhist['da'][:,itime] = tempda.ravel() + itime += 1 + if ndofs: + dofhist['a'][:,j] = tempa[np.ix_(dofs-1)].ravel() + dofhist['da'][:,j] = tempda[np.ix_(dofs-1)].ravel() + + return modelhist, dofhist + + +def step2(K,C,M,f,a0,da0,bc,ip,times,dofs): + """ + Algorithm for dynamic solution of second-order + FE equations considering boundary conditions. + + Parameters: + + K global stiffness matrix, dim(K) = ndof x ndof + C global damping matrix, dim(C) = ndof x ndof + If there is no damping in the system, simply set C=[] + M global mass matrix, dim(M) = ndof x ndof + f global load vector, dim(f) = ndof x (nstep + 1), + If dim(f) = ndof x 1, the values are kept constant + during time integration + a0 initial displacement vector a(0), dim(a0) = ndof x 1 + da0 initial velocity vector v(0), dim(da0) = ndof x 1 + bc boundary condition matrix, dim(bc) = nbc x (nstep + 2) + where nbc = number of prescribed degrees of freedom (either constant or time-dependent) + The first column contains the numbers of the prescribed degrees of freedom + and the subsequent columns contain the time history. + If dim(bc) = nbc x 2, the values from the second column are kept constant + during time integration + ip array [dt, tottime, alpha, delta], where + dt is the size of the time increment, + tottime is the total time, + alpha and delta are time integration constants for the Newmark family of methods. + Frequently used values of alpha and delta are: + alpha=1/4, delta=1/2: average acceleration (trapezoidal) rule, + alpha=1/6, delta=1/2: linear acceleration + alpha=0, delta=1/2: central difference + times array [t(i) ...] of times at which output should be written to a, da and d2a + dofs array [dof(i) ...] of degree of freedom numbers for which history output + should be written to ahist, dahist and d2ahist + + Returns: + + modelhist dictionary containing solution history for the whole model at following keys: + modelhist['a'] constains displacement values at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['a']) = ndof x (nstep + 1) or ndof x ntimes + modelhist['da'] constains velocity values at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['da']) = ndof x (nstep + 1) or ndof x ntimes + modelhist['d2a'] constains acceleration values at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['d2a']) = ndof x (nstep + 1) or ndof x ntimes + dofhist dictionary containing solution history for the degrees of freedom selected in 'dofs': + dofhist['a'] constains displacement time history at the dofs specified in 'dofs' + dim(dofhist['ahist']) = ndof x (nstep + 1) + dofhist['da'] constains velocity time history at the dofs specified in 'dofs' + dim(dofhist['dahist']) = ndof x (nstep + 1) + dofhist['d2a'] constains acceleration time history at the dofs specified in 'dofs' + dim(dofhist['d2ahist']) = ndof x (nstep + 1) + """ + ndof, _ = K.shape + if not np.array(C).any(): + C = np.zeros((ndof,ndof)) + dt, tottime, alpha, delta = ip + b1 = dt*dt*0.5*(1-2*alpha) + b2 = (1-delta)*dt + b3 = delta*dt + b4 = alpha*dt*dt + + nstep = 1 + if np.array(f).any(): + _, ncf = f.shape + if ncf>1: + nstep = ncf-1 + + if np.array(bc).any(): + _, ncb = bc.shape + if ncb>2: + nstep = ncb-2 + bound = 1 + if not np.array(bc).any(): + bound = 0 + + ns = int(tottime/dt) + if (ns < nstep or nstep==1): + nstep=ns + + tf = np.zeros((ndof,nstep+1)) + if np.array(f).any(): + if ncf==1: + tf = f[:,0].reshape(-1,1)@np.ones((1,nstep+1)) + if ncf>1: + tf = np.copy(f) + + modelhist = {} + sa=0 + if not np.array(times).any(): + ntimes=0 + sa=1 + modelhist['a'] = np.zeros((ndof,nstep+1)) + modelhist['da'] = np.zeros((ndof,nstep+1)) + modelhist['d2a'] = np.zeros((ndof,nstep+1)) + else: + ntimes = len(times) + if ntimes: + sa=2 + modelhist['a'] = np.zeros((ndof,ntimes)) + modelhist['da'] = np.zeros((ndof,ntimes)) + modelhist['d2a'] = np.zeros((ndof,ntimes)) + + dofhist = {} + if np.array(dofs).all(): + ndofs = len(dofs) + if ndofs: + dofhist['a'] = np.zeros((ndofs,nstep+1)) + dofhist['da'] = np.zeros((ndofs,nstep+1)) + dofhist['d2a'] = np.zeros((ndofs,nstep+1)) + else: + ndofs=0 + + itime = 0 + + # Calculate initial second time derivative d2a0 + d2a0 = np.linalg.solve(M,tf[:,0].reshape(-1,1) - C@da0 - K@a0) + # Save initial values + if sa==1: + modelhist['a'][:,0] = a0.ravel() + modelhist['da'][:,0] = da0.ravel() + modelhist['d2a'][:,0] = d2a0.ravel() + elif sa==2: + if times[itime]==0: + modelhist['a'][:,itime] = a0.ravel() + modelhist['da'][:,itime] = da0.ravel() + modelhist['d2a'][:,itime] = d2a0.ravel() + itime += 1 + + if ndofs: + dofhist['a'][:,0] = a0[np.ix_(dofs-1)].ravel() + dofhist['da'][:,0] = da0[np.ix_(dofs-1)].ravel() + dofhist['d2a'][:,0] = d2a0[np.ix_(dofs-1)].ravel() + + # Reduce matrices due to bcs + tempa = np.zeros((ndof,1)) + tempda = np.zeros((ndof,1)) + tempd2a = np.zeros((ndof,1)) + fdof=np.arange(1,ndof+1).astype(int) + if bound: + nrb, ncb = bc.shape + if ncb==2: + pa = bc[:,1].reshape(-1,1)@np.ones((1,nstep+1)) + pda = np.zeros((nrb,nstep+1)) + elif ncb>2: + pa = np.copy(bc[:,1:]) + pda1 = (pa[:,1]-pa[:,0])/dt + pdarest = (pa[:,1:] - pa[:,0:-1])/dt + pda = np.hstack((pda1.reshape(-1,1),pdarest)) + pdof = np.copy(bc[:,0]).astype(int) + fdof = np.setdiff1d(fdof,pdof).astype(int) - 1 + pdof -= 1 #adjusting for indexing starting from 0 + Keff = M[np.ix_(fdof,fdof)] + b3*C[np.ix_(fdof,fdof)] +b4*K[np.ix_(fdof,fdof)] + else: + fdof -= 1 #adjusting for indexing starting from 0 + Keff = M + b3*C + b4*K + + L, U = lu(Keff,permute_l=True) + anew = a0[np.ix_(fdof)] + danew = da0[np.ix_(fdof)] + d2anew = d2a0[np.ix_(fdof)] + + # Iterate over time steps + for j in range(1,nstep+1): + time = dt*j + aold = np.copy(anew) + daold = np.copy(danew) + d2aold = np.copy(d2anew) + apred = aold + dt*daold + b1*d2aold + dapred = daold + b2*d2aold + if not bound: + reff = tf[:,j].reshape(-1,1) - C@dapred - K@apred + else: + pdeff = C[np.ix_(fdof,pdof)]@pda[:,j].reshape(-1,1) + K[np.ix_(fdof,pdof)]@pa[:,j].reshape(-1,1) + reff = tf[np.ix_(fdof),j].reshape(-1,1) - C[np.ix_(fdof,fdof)]@dapred - K[np.ix_(fdof,fdof)]@apred - pdeff + y = np.linalg.solve(L,reff) + d2anew = np.linalg.solve(U,y) + anew = apred + b4*d2anew + danew = dapred + b3*d2anew + # Save to modelhist and dofhist + if bound: + tempa[np.ix_(pdof)] = pa[:,j].reshape(-1,1) + tempda[np.ix_(pdof)] = pda[:,j].reshape(-1,1) + tempa[np.ix_(fdof)] = anew + tempda[np.ix_(fdof)] = danew + tempd2a[np.ix_(fdof)] = d2anew + if sa==1: + modelhist['a'][:,j] = tempa.ravel() + modelhist['da'][:,j] = tempda.ravel() + modelhist['d2a'][:,j] = tempd2a.ravel() + elif sa==2: + if ntimes and itime < ntimes: + if time >= times[itime]: + modelhist['a'][:,itime] = tempa.ravel() + modelhist['da'][:,itime] = tempda.ravel() + modelhist['d2a'][:,itime] = tempd2a.ravel() + itime += 1 + if ndofs: + dofhist['a'][:,j] = tempa[np.ix_(dofs-1)].ravel() + dofhist['da'][:,j] = tempda[np.ix_(dofs-1)].ravel() + dofhist['d2a'][:,j] = tempd2a[np.ix_(dofs-1)].ravel() + + return modelhist, dofhist + + def extract_eldisp(edof, a): """ Extract element displacements from the global displacement @@ -4466,4 +6327,4 @@ def beam2crd(ex=None, ey=None, ed=None, mag=None): excd[i, :] = xyc[0, :]+mag*cd[0, :] eycd[i, :] = xyc[1, :]+mag*cd[1, :] - return excd, eycd + return excd, eycd \ No newline at end of file diff --git a/calfem/core_compat.py b/calfem/core_compat.py new file mode 100644 index 0000000..901803b --- /dev/null +++ b/calfem/core_compat.py @@ -0,0 +1,4877 @@ +# -*- coding: iso-8859-15 -*- +""" +CALFEM Core module + +Contains all the functions implementing CALFEM standard functionality +""" + +from scipy.sparse.linalg import dsolve +from scipy.linalg import eig, lu +import numpy as np + +import logging as cflog +import sys +import traceback + +__prev_exception_hook = sys.excepthook + + +def exception_logging(exctype, value, tb): + """ + Log exception by using the root logger. + + Parameters + ---------- + exctype : type + value : NameError + tb : traceback + """ + write_val = {'exception_type': str(exctype), + 'message': str(traceback.format_tb(tb, 10))} + print('Error: %s \n in "%s", line %d' % + (value, tb.tb_frame.f_code.co_filename, tb.tb_lineno)) + + +def enable_friendly_errors(): + __prev_exception_hook = sys.excepthook + sys.excepthook = exception_logging + + +def disable_friendly_errors(): + sys.excepthook = __prev_exception_hook + + +easy_on = enable_friendly_errors +easy_off = disable_friendly_errors + + +def check_list_array(v, error_string): + + fname = sys._getframe(1).f_code.co_name + + if (type(v) != list) and (type(v) != np.ndarray): + raise TypeError("%s (%s)" % (error_string, fname)) + + +def check_length(v, length, error_string): + + fname = sys._getframe(1).f_code.co_name + + if len(v) != length: + raise ValueError("%s (%s)" % (error_string, fname)) + + +def user_warning(msg): + + fname = sys._getframe(1).f_code.co_name + + print("Warning: %s (%s)" % (msg, fname)) + + +def error(msg): + """Write ``msg`` to error log.""" + cflog.error(" calfem.core: "+msg) + + +def info(msg): + """Write ``msg`` to info log.""" + cflog.info(" calfem.core: "+msg) + + +def spring1e(ep): + """ + Compute element stiffness matrix for spring element. + + :param float ep: spring stiffness or analog quantity (ep = k). + :return mat Ke: stiffness matrix, dim(Ke)= 2 x 2 + """ + k = ep + return np.mat([[k, -k], [-k, k]], 'd') + + +def spring1s(ep, ed): + """ + Compute element force in spring element (spring1e). + + :param float ep: spring stiffness or analog quantity + :param list ed: element displacements [d0, d1] + :return float es: element force [N] + """ + k = ep + return k*(ed[1]-ed[0]) + + +def bar1e(ep): + """ + Compute element stiffness matrix for spring element. + + :param ep float: spring stiffness or analog quantity + :return mat Ke: stiffness matrix, dim(Ke)= 2 x 2 + """ + k = ep + return np.mat([[k, -k], [-k, k]], 'd') + + +def bar1s(ep, ed): + """ + Compute element force in spring element (spring1e). + + :param float ep: spring stiffness or analog quantity + :param list ed: element displacements [d0, d1] + :return float es: element force + """ + k = ep + return k*(ed[1]-ed[0]) + + +def bar2e(ex, ey, ep): + """ + Compute the element stiffness matrix for two dimensional bar element. + + :param list ex: element x coordinates [x1, x2] + :param list ey: element y coordinates [y1, y2] + :param list ep: [E, A]: E - Young's modulus, A - Cross section area + :return mat Ke: stiffness matrix, [4 x 4] + """ + E = ep[0] + A = ep[1] + + b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) + L = np.sqrt(b.T*b).item() + + Kle = np.mat([[1., -1.], [-1., 1.]])*E*A/L + + n = np.asarray(b.T/L).reshape(2,) + + G = np.mat([ + [n[0], n[1], 0., 0.], + [0., 0., n[0], n[1]] + ]) + + return G.T*Kle*G + + +def bar2g(ex, ey, ep, N): + """ + Compute element stiffness matrix for two dimensional geometric + nonlinear bar element. + + :param list ex: element x coordinates [x1, x2] + :param list ey: element y coordinates [y1, y2] + :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area + :param float N: normal force + :return mat Ke: stiffness matrix [4 x 4] + """ + E = ep[0] + A = ep[1] + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + + L = np.sqrt(b.T*b).item() + + n = np.asarray(b.T/L).reshape(2,) + + G = np.mat([ + [n[0], n[1], 0., 0.], + [-n[1], n[0], 0., 0.], + [0., 0., n[0], n[1]], + [0., 0., -n[1], n[0]] + ]) + + Kle = E*A/L*np.mat([ + [1, 0, -1, 0], + [0, 0, 0, 0], + [-1, 0, 1, 0], + [0, 0, 0, 0] + ])+N/L*np.mat([ + [0, 0, 0, 0], + [0, 1, 0, -1], + [0, 0, 0, 0], + [0, -1, 0, 1] + ]) + + return G.T*Kle*G + + +def bar2s(ex, ey, ep, ed): + """ + Compute normal force in two dimensional bar element. + + :param list ex: element x coordinates [x1, x2] + :param list ey: element y coordinates [y1, y2] + :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area + :param list ed: element displacements [u1, u2, u3, u4] + :return float N: element foce [N] + """ + E = ep[0] + A = ep[1] + + b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) + L = np.sqrt(b.T*b).item() + + #Kle = np.mat([[1.,-1.],[-1.,1.]])*E*A/L + + n = np.asarray(b.T/L).reshape(2,) + + G = np.mat([ + [n[0], n[1], 0., 0.], + [0., 0., n[0], n[1]] + ]) + + u = np.asmatrix(ed).T + N = E*A/L*np.mat([[-1., 1.]])*G*u + return N.item() + + +def bar2gs(ex, ey, ep, ed): + """ + Calculate section forces in a two dimensional geometric + nonlinear bar element (bar2g). + Parameters: + ex = [x1 x2] element node coordinates + ey = [y1 y2] + + ep = [E A] element properties; + E: Young's modulus + A: cross section area + + ed = [u1 ... u4] element displacement vector + + Returns: + es = [N1; + N2 ] section forces, local directions + + QX: axial force + + edi = [ u1 ; element displacements, local directions, + u2 ; in n points along the bar, dim(es)= n x 1 + ...] + + eci = [ x1 ; local x-coordinates of the evaluation + x2 ; points, (x1=0 and xn=L) + ...] + """ + EA = ep[0]*ep[1] + ne = 2 + + dx = ex[1] - ex[0] + dy = ey[1] - ey[0] + L = np.sqrt(dx**2 + dy**2) + + n = [dx/L, dy/L, -dy/L, dx/L] + G = np.array([ + [n[0], n[1], 0., 0.], + [n[2], n[3], 0., 0.], + [0., 0., n[0], n[1]], + [0., 0., n[2], n[3]] + ]) + + edl = G@ed.reshape(-1,1) + a1 = np.array([edl[0], edl[2]]).reshape(-1,1) + + C1 = np.array([[1., 0.,], + [-1/L, 1/L]]) + C1a = C1@a1 + + x = np.linspace(0,L,ne).reshape(-1,1) + zero = np.zeros(x.shape) + one = np.ones(x.shape) + + u = np.concatenate((one, x),axis=1)@C1a + du = np.concatenate((zero, one),axis=1)@C1a + + N = EA*du + return N, N[0].item(), u, x + + +def bar3e(ex, ey, ez, ep): + """ + Compute element stiffness matrix for three dimensional bar element. + + :param list ex: element x coordinates [x1, x2] + :param list ey: element y coordinates [y1, y2] + :param list ez: element z coordinates [z1, z2] + :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area + :return mat Ke: stiffness matrix, [6 x 6] + """ + E = ep[0] + A = ep[1] + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]], + [ez[1]-ez[0]] + ]) + L = np.sqrt(b.T*b).item() + + n = np.asarray(b.T/L).reshape(3) + + G = np.mat([ + [n[0], n[1], n[2], 0., 0., 0.], + [0., 0., 0., n[0], n[1], n[2]] + ]) + + Kle = E*A/L*np.mat([ + [1, -1], + [-1, 1] + ]) + + return G.T*Kle*G + + +def bar3s(ex, ey, ez, ep, ed): + """ + Compute normal force in three dimensional bar element. + + :param list ex: element x coordinates [x1, x2] + :param list ey: element y coordinates [y1, y2] + :param list ez: element z coordinates [z1, z2] + :param list ep: element properties [E, A], E - Young's modulus, A - Cross section area + :param list ed: element displacements [u1, ..., u6] + :return float N: normal force + """ + E = ep[0] + A = ep[1] + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]], + [ez[1]-ez[0]] + ]) + L = np.sqrt(b.T*b).item() + + n = np.asarray(b.T/L).reshape(3) + + G = np.mat([ + [n[0], n[1], n[2], 0., 0., 0.], + [0., 0., 0., n[0], n[1], n[2]] + ]) + + #Kle = E*A/L*np.mat([ + # [ 1,-1], + # [-1, 1] + #]) + + u = np.asmatrix(ed).T + N = E*A/L*np.mat([[-1., 1.]])*G*u + + return N.item() + +def beam1e(ex, ep, eq=None): + """ + Compute the stiffness matrix for a one dimensional beam element. + + :param list ex: element x coordinates [x1, x2] + :param list ep: element properties [E, I], E - Young's modulus, I - Moment of inertia + :param float eq: distributed load [qy] + :return mat Ke: element stiffness matrix [4 x 4] + :return mat fe: element load vector [4 x 1] (if eq!=None) + """ + L = ex[1]-ex[0] + + E = ep[0] + I = ep[1] + + qy = 0. + if eq: + qy = eq + + Ke = E*I/(L**3) * np.mat([ + [12, 6*L, -12, 6*L], + [6*L, 4*L**2, -6*L, 2*L**2], + [-12, -6*L, 12, -6*L], + [6*L, 2*L**2, -6*L, 4*L**2] + ]) + + fe = qy*np.mat([L/2, L**2/12, L/2, -L**2/12]).T + + if eq is None: + return Ke + else: + return Ke, fe + +def beam1s(ex, ep, ed, eq=None, nep=None): + """ + Compute section forces in one dimensional beam element (beam1e). + + Parameters: + + ex = [x1 x2] element node coordinates + + ep = [E I] element properties, + E: Young's modulus + I: moment of inertia + + ed = [u1 ... u4] element displacements + + eq = qy distributed load, local directions + + nep number of evaluation points ( default=2 ) + + Returns: + + es = [ V1 M1 section forces, local directions, in + V2 M2 n points along the beam, dim(es)= n x 2 + .........] + + edi = [ v1 element displacements, local directions, + v2 in n points along the beam, dim(es)= n x 1 + .......] + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + + """ + EI = ep[0]*ep[1] + L = ex[1]-ex[0] + + qy = 0. + + if eq: + qy = eq + + ne = 2 + + if nep != None: + ne = nep + + Cinv = np.mat([ + [1, 0, 0, 0], + [0, 1, 0, 0], + [-3/(L**2), -2/L, 3/(L**2), -1/L], + [2/(L**3), 1/(L**2), -2/(L**3), 1/(L**2)] + ]) + + Ca = (Cinv@ed).T + + x = np.asmatrix(np.linspace(0., L, nep)).T + zero = np.asmatrix(np.zeros([len(x)])).T + one = np.asmatrix(np.ones([len(x)])).T + + v = np.concatenate((one, x, np.power(x, 2), np.power(x, 3)), 1)@Ca \ + + qy/(24*EI)*(np.power(x,4) - 2*L*np.power(x,3) + (L**2)*np.power(x,2)) + d2v = np.concatenate((zero, zero, 2*one, 6*x), 1)@Ca \ + + qy/(12*EI)*(6*np.power(x,2) - 6*L*x + L**2) + d3v = np.concatenate((zero, zero, zero, 6*one), 1)@Ca + qy/(2*EI)*(2*x - L) + + M = EI*d2v + V = -EI*d3v + edi = v + eci = x + es = np.concatenate((V, M), 1) + + return (es, edi, eci) + + + +def beam2e(ex, ey, ep, eq=None): + """ + Compute the stiffness matrix for a two dimensional beam element. + + :param list ex: element x coordinates [x1, x2] + :param list ey: element y coordinates [y1, y2] + :param list ep: element properties [E, A, I], E - Young's modulus, A - Cross section area, I - Moment of inertia + :param list eq: distributed loads, local directions [qx, qy] + :return mat Ke: element stiffness matrix [6 x 6] + :return mat fe: element stiffness matrix [6 x 1] (if eq!=None) + """ + + b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b.T/L).reshape(2,) + + E = ep[0] + A = ep[1] + I = ep[2] + + qx = 0. + qy = 0. + if not eq is None: + qx = eq[0] + qy = eq[1] + + Kle = np.mat([ + [E*A/L, 0., 0., -E*A/L, 0., 0.], + [0., 12*E*I/L**3., 6*E*I/L**2., 0., -12*E*I/L**3., 6*E*I/L**2.], + [0., 6*E*I/L**2., 4*E*I/L, 0., -6*E*I/L**2., 2*E*I/L], + [-E*A/L, 0., 0., E*A/L, 0., 0.], + [0., -12*E*I/L**3., -6*E*I/L**2., 0., 12*E*I/L**3., -6*E*I/L**2.], + [0., 6*E*I/L**2., 2*E*I/L, 0., -6*E*I/L**2., 4*E*I/L] + ]) + + fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T + + G = np.mat([ + [n[0], n[1], 0., 0., 0., 0.], + [-n[1], n[0], 0., 0., 0., 0.], + [0., 0., 1., 0., 0., 0.], + [0., 0., 0., n[0], n[1], 0.], + [0., 0., 0., -n[1], n[0], 0.], + [0., 0., 0., 0., 0., 1.] + ]) + + Ke = G.T*Kle*G + fe = G.T*fle + + if eq is None: + return Ke + else: + return Ke, fe + + +def beam2s(ex, ey, ep, ed, eq=None, nep=None): + """ + Compute section forces in two dimensional beam element (beam2e). + + Parameters: + + ex = [x1 x2] + ey = [y1 y2] element node coordinates + + ep = [E A I] element properties, + E: Young's modulus + A: cross section area + I: moment of inertia + + ed = [u1 ... u6] element displacements + + eq = [qx qy] distributed loads, local directions + + nep number of evaluation points ( default=2 ) + + Returns: + + es = [ N1 V1 M1 section forces, local directions, in + N2 V2 M2 n points along the beam, dim(es)= n x 3 + .........] + + edi = [ u1 v1 element displacements, local directions, + u2 v2 in n points along the beam, dim(es)= n x 2 + .......] + + eci = [ x1 local x-coordinates of the evaluation + x2 points, (x1=0 and xn=L) + ...] + + """ + EA = ep[0]*ep[1] + EI = ep[0]*ep[2] + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + + L = np.sqrt(b.T*b).item() + n = np.asarray(b.T/L).reshape(2,) + + qx = 0. + qy = 0. + + if not eq is None: + qx = eq[0] + qy = eq[1] + + ne = 2 + + if nep != None: + ne = nep + + C = np.mat([ + [0., 0., 0., 1., 0., 0.], + [0., 0., 0., 0., 0., 1.], + [0., 0., 0., 0., 1., 0.], + [L, 0., 0., 1., 0., 0.], + [0., L**3, L**2, 0., L, 1.], + [0., 3*L**2, 2*L, 0., 1., 0.] + ]) + + G = np.mat([ + [n[0], n[1], 0., 0., 0., 0.], + [-n[1], n[0], 0., 0., 0., 0.], + [0., 0., 1., 0., 0., 0.], + [0., 0., 0., n[0], n[1], 0.], + [0., 0., 0., -n[1], n[0], 0.], + [0., 0., 0., 0., 0., 1.] + ]) + + M = np.ravel(C.I*(G*np.asmatrix(ed).T - + np.matrix([0., 0., 0., -qx*L**2/(2*EA), qy*L**4/(24*EI), qy*L**3/(6*EI)]).T)) + A = np.matrix([M[0], M[3]]).T + B = np.matrix([M[1], M[2], M[4], M[5]]).T + + x = np.asmatrix(np.arange(0., L+L/(ne-1), L/(ne-1))).T + zero = np.asmatrix(np.zeros([len(x)])).T + one = np.asmatrix(np.ones([len(x)])).T + + u = np.concatenate((x, one), 1)*A-np.power(x, 2)*qx/(2*EA) + du = np.concatenate((one, zero), 1)*A-x*qx/EA + v = np.concatenate((np.power(x, 3), np.power(x, 2), x, + one), 1)*B+np.power(x, 4)*qy/(24*EI) + d2v = np.concatenate((6*x, 2*one, zero, zero), 1) * \ + B+np.power(x, 2)*qy/(2*EI) + d3v = np.concatenate((6*one, zero, zero, zero), 1)*B+x*qy/EI + + N = EA*du + M = EI*d2v + V = -EI*d3v + edi = np.concatenate((u, v), 1) + eci = x + es = np.concatenate((N, V, M), 1) + + return (es, edi, eci) + + +def beam2t(ex, ey, ep, eq=None): + """ + Compute the stiffness matrix for a two dimensional elastic + Timoshenko beam element. + + Parameters: + + ex = [x1 x2] + ey = [y1 y2] element node coordinates + + ep = [E G A I ks] element properties + E: Young's modulus + G: Shear modulus + A: Cross section area + I: Moment of inertia + ks: Shear correction factor + + eq = [qx qy] distributed loads, local directions + + Returns: + + Ke element stiffness matrix (6 x 6) + + fe element load vector (6 x 1) + + """ + + b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b.T/L).reshape(2) + + E = ep[0] + Gm = ep[1] + A = ep[2] + I = ep[3] + ks = ep[4] + + qx = 0. + qy = 0. + if eq != None: + qx = eq[0] + qy = eq[1] + + m = (12/L**2)*(E*I/(Gm*A*ks)) + + Kle = E/(1+m)*np.mat([ + [A*(1+m)/L, 0., 0., -A*(1+m)/L, 0., 0.], + [0., 12*I/L**3., 6*I/L**2., 0., -12*I/L**3., 6*I/L**2.], + [0., 6*I/L**2., 4*I * + (1+m/4.)/L, 0., -6*I/L**2., 2*I*(1-m/2)/L], + [-A*(1+m)/L, 0., 0., + A*(1+m)/L, 0., 0.], + [0., -12*I/L**3., -6*I/L**2., + 0., 12*I/L**3., -6*I/L**2.], + [0., 6*I/L**2., 2*I * + (1-m/2)/L, 0., -6*I/L**2., 4*I*(1+m/4)/L] + ]) + + fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T + + G = np.mat([ + [n[0], n[1], 0., 0., 0., 0.], + [-n[1], n[0], 0., 0., 0., 0.], + [0., 0., 1., 0., 0., 0.], + [0., 0., 0., n[0], n[1], 0.], + [0., 0., 0., -n[1], n[0], 0.], + [0., 0., 0., 0., 0., 1.] + ]) + + Ke = G.T*Kle*G + fe = G.T*fle + + if eq == None: + return Ke + else: + return Ke, fe + + +def beam2ts(ex, ey, ep, ed, eq=None, nep=None): + """ + Compute section forces in two dimensional beam element (beam2e). + + Parameters: + + ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,G,A,I,ks] element properties, + E: Young's modulus + G: shear modulus + A: cross section area + I: moment of inertia + + ed = [u1, ... ,u6] element displacements + + eq = [qx, qy] distributed loads, local directions + + nep number of evaluation points ( default=2 ) + + Returns: + + es = [[N1,V1,M1], section forces, local directions, in + [N2,V2,M2], n points along the beam, dim(es)= n x 3 + ..........] + + edi = [[u1,v1,teta1], element displacements, local directions, + [u2,v2,teta2], and rotation of cross section at + .............] in n points along the beam, dim(es)= n x 2 + + (Note! Rotation of the cross section is not equal to dv/dx for Timoshenko beam element) + + eci = [[x1], local x-coordinates of the evaluation + [x2], points, (x1=0 and xn=L) + ....] + + """ + EA = ep[0]*ep[2] + EI = ep[0]*ep[3] + GAK = ep[1]*ep[2]*ep[4] + alfa = EI/GAK + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b.T/L).reshape(2) + + qx = 0. + qy = 0. + if eq != None: + qx = eq[0] + qy = eq[1] + + ne = 2 + + if nep != None: + ne = nep + + C = np.mat([ + [0., 0., 0., 1., 0., 0.], + [0., 0., 0., 0., 0., 1.], + [0., 6*alfa, 0., 0., 1., 0.], + [L, 0., 0., 1., 0., 0.], + [0., L**3, L**2, 0., L, 1.], + [0., 3*(L**2+2*alfa), 2*L, 0., 1., 0.] + ]) + + G = np.mat([ + [n[0], n[1], 0., 0., 0., 0.], + [-n[1], n[0], 0., 0., 0., 0.], + [0., 0., 1., 0., 0., 0.], + [0., 0., 0., n[0], n[1], 0.], + [0., 0., 0., -n[1], n[0], 0.], + [0., 0., 0., 0., 0., 1.] + ]) + + M = np.ravel(C.I*(G*np.asmatrix(ed).T-np.mat([0., 0., 0., -qx*L**2/( + 2*EA), qy*L**4/(24*EI)-qy*L**2/(2*GAK), qy*L**3/(6*EI)]).T)) + C2 = np.mat([M[0], M[3]]).T + C4 = np.mat([M[1], M[2], M[4], M[5]]).T + + x = np.asmatrix(np.arange(0., L+L/(ne-1), L/(ne-1))).T + zero = np.asmatrix(np.zeros([len(x)])).T + one = np.asmatrix(np.ones([len(x)])).T + + u = np.concatenate((x, one), 1)*C2-qx/(2*EA)*np.power(x, 2) + du = np.concatenate((one, zero), 1)*C2-qx*x/EA + + v = np.concatenate((np.power(x, 3), np.power(x, 2), x, one), 1) * \ + C4+qy/(24*EI)*np.np.power(x, 4)-qy/(2*GAK)*np.power(x, 2) + dv = np.concatenate((3*np.power(x, 2), 2*x, one, zero), + 1)*C4+qy*np.power(x, 3)/(6*EI)-qy*x/GAK + + teta = np.concatenate((3*(np.power(x, 2)+2*alfa*one), + 2*x, one, zero), 1)*C4+qy*np.power(x, 3)/(6*EI) + dteta = np.concatenate((6*x, 2*one, zero, zero), 1) * \ + C4+qy*np.power(x, 2)/(2*EI) + + N = EA*du + M = EI*dteta + V = GAK*(dv-teta) + + es = np.concatenate((N, V, M), 1) + edi = np.concatenate((u, v, teta), 1) + eci = x + + if nep != None: + return es, edi, eci + else: + return es + + +def beam2w(ex, ey, ep, eq=None): + """ + Compute the stiffness matrix for a two dimensional beam element + on elastic foundation. + + Parameters: + + ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,A,I,ka,kt] element properties, + E: Young's modulus + A: cross section area + I: moment of inertia + ka: axial foundation stiffness + kt: transversal foundation stiffness + + eq = [qx, qy] distributed loads, local directions + + Returns: + + Ke beam stiffness matrix (6 x 6) + + fe element load vector (6 x 1) + """ + b = np.mat([[ex[1]-ex[0]], [ey[1]-ey[0]]]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b/L).reshape(2) + + E, A, I, ka, kt = ep + + qx = 0 + qy = 0 + if eq != None: + qx, qy = eq + + K1 = np.mat([ + [E*A/L, 0, 0, -E*A/L, 0, 0], + [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], + [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], + [-E*A/L, 0, 0, E*A/L, 0, 0], + [0, -12*E*I/L**3, -6*E*I/L**2, 0, 12*E*I/L**3, -6*E*I/L**2], + [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] + ]) + + K2 = L/420*np.mat([ + [140*ka, 0, 0, 70*ka, 0, 0], + [0, 156*kt, 22*kt*L, 0, 54*kt, -13*kt*L], + [0, 22*kt*L, 4*kt*L**2, 0, 13*kt*L, -3*kt*L**2], + [70*ka, 0, 0, 140*ka, 0, 0], + [0, 54*kt, 13*kt*L, 0, 156*kt, -22*kt*L], + [0, -13*kt*L, -3*kt*L**2, 0, -22*kt*L, 4*kt*L**2] + ]) + + Kle = K1+K2 + fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T + + G = np.mat([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, -n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + Ke = G.T*Kle*G + fe = G.T*fle + + if eq != None: + return Ke, fe + else: + return Ke + + +def beam2ws(ex, ey, ep, ed, eq=None): + """ + Compute section forces in a two dimensional beam element + on elastic foundation. + + Parameters: + + ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,A,I,ka,kt] element properties, + E: Young's modulus + A: cross section area + I: moment of inertia + ka: axial foundation stiffness + kt: transversal foundation stiffness + + ed = [u1, ... ,u6] element displacement vector + + eq = [qx, qy] distributed loads, local directions + + Returns: + + es = [[N1, V1, M1], + [N2, V2, M2]] element forces, local direction + """ + if np.asmatrix(ed).shape[0] > 1: + error("Only one row is allowed in the ed matrix !!!") + return + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b/L).reshape(2,) + + E, A, I, ka, kt = ep + + qx = 0 + qy = 0 + if eq != None: + qx, qy = eq + + K1 = np.mat([ + [E*A/L, 0, 0, -E*A/L, 0, 0], + [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], + [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], + [-E*A/L, 0, 0, E*A/L, 0, 0], + [0, -12*E*I/L**3, -6*E*I/L**2, 0, 12*E*I/L**3, -6*E*I/L**2], + [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] + ]) + + K2 = L/420*np.mat([ + [140*ka, 0, 0, 70*ka, 0, 0], + [0, 156*kt, 22*kt*L, 0, 54*kt, -13*kt*L], + [0, 22*kt*L, 4*kt*L**2, 0, 13*kt*L, -3*kt*L**2], + [70*ka, 0, 0, 140*ka, 0, 0], + [0, 54*kt, 13*kt*L, 0, 156*kt, -22*kt*L], + [0, -13*kt*L, -3*kt*L**2, 0, -22*kt*L, 4*kt*L**2] + ]) + + Kle = K1+K2 + fle = L*np.mat([qx/2, qy/2, qy*L/12, qx/2, qy/2, -qy*L/12]).T + + G = np.mat([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, -n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + P = Kle*G*np.asmatrix(ed).T-fle + + es = np.mat([ + [-P[0, 0], -P[1, 0], -P[2, 0]], + [P[3, 0], P[4, 0], P[5, 0]] + ]) + + return es + + +def beam2g(ex, ey, ep, N, eq=None): + """ + Compute the element stiffness matrix for a two dimensional + beam element with respect to geometric nonlinearity. + + Parameters: + + ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,A,I] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + + N axial force in the beam + + eq distributed transverse load + + Returns: + + Ke element stiffness matrix (6 x 6) + + fe element load vector (6 x 1) + """ + if eq != None: + if np.size(eq) > 1: + error("eq should be a scalar !!!") + return + else: + q = eq[0] + else: + q = 0 + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b/L).reshape(2,) + + E, A, I = ep + + rho = -N*L**2/(np.pi**2*E*I) + + kL = np.pi*np.sqrt(abs(rho))+np.finfo(float).eps + + if rho > 0: + f1 = (kL/2)/np.tan(kL/2) + f2 = (1/12.)*kL**2/(1-f1) + f3 = f1/4+3*f2/4 + f4 = -f1/2+3*f2/2 + f5 = f1*f2 + h = 6*(2/kL**2-(1+np.cos(kL))/(kL*np.sin(kL))) + elif rho < 0: + f1 = (kL/2)/np.tanh(kL/2) + f2 = -(1/12.)*kL**2/(1-f1) + f3 = f1/4+3*f2/4 + f4 = -f1/2+3*f2/2 + f5 = f1*f2 + h = -6*(2/kL**2-(1+np.cosh(kL))/(kL*np.sinh(kL))) + else: + f1 = f2 = f3 = f4 = f5 = h = 1 + + Kle = np.mat([ + [E*A/L, 0., 0., -E*A/L, 0., 0.], + [0., 12*E*I*f5/L**3., 6*E*I*f2/L**2., + 0., -12*E*I*f5/L**3., 6*E*I*f2/L**2.], + [0., 6*E*I*f2/L**2., 4*E*I*f3/L, + 0., -6*E*I*f2/L**2., 2*E*I*f4/L], + [-E*A/L, 0., 0., E*A/L, 0., 0.], + [0., -12*E*I*f5/L**3., -6*E*I*f2/L**2., + 0., 12*E*I*f5/L**3., -6*E*I*f2/L**2.], + [0., 6*E*I*f2/L**2., 2*E*I*f4/L, + 0., -6*E*I*f2/L**2., 4*E*I*f3/L] + ]) + + fle = q*L*np.mat([0., 1/2., L*h/12, 0., 1/2., -L*h/12]).T + + G = np.mat([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, -n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + Ke = G.T*Kle*G + fe = G.T*fle + + if eq != None: + return Ke, fe + else: + return Ke + + +def beam2gs(ex, ey, ep, ed, N, eq=None): + """ + Calculate section forces in a two dimensional nonlinear + beam element. + + Parameters: + + ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,A,I] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + + ed = [u1, ... ,u6] element displacement vector + + N axial force + + eq = [qy] distributed transverse load + + Returns: + + es = [[N1,V1,M1], element forces, local directions + [N2,V2,M2]] + """ + if eq != None: + eq = eq[0] + else: + eq = 0 + + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b/L).reshape(2,) + + E, A, I = ep + + rho = -N*L**2/(np.pi**2*E*I) + + eps = 2.2204e-16 + kL = np.pi*np.sqrt(abs(rho))+eps + + if rho > 0: + f1 = (kL/2)/np.tan(kL/2) + f2 = (1/12.)*kL**2/(1-f1) + f3 = f1/4+3*f2/4 + f4 = -f1/2+3*f2/2 + f5 = f1*f2 + h = 6*(2/kL**2-(1+np.cos(kL))/(kL*np.sin(kL))) + elif rho < 0: + f1 = (kL/2)/np.tanh(kL/2) + f2 = -(1/12.)*kL**2/(1-f1) + f3 = f1/4+3*f2/4 + f4 = -f1/2+3*f2/2 + f5 = f1*f2 + h = -6*(2/kL**2-(1+np.cosh(kL))/(kL*np.sinh(kL))) + else: + f1 = f2 = f3 = f4 = f5 = h = 1 + + Kle = np.mat([ + [E*A/L, 0, 0, -E*A/L, 0, 0], + [0, 12*E*I*f5/L**3, 6*E*I*f2/L**2, + 0, -12*E*I*f5/L**3, 6*E*I*f2/L**2], + [0, 6*E*I*f2/L**2, 4*E*I*f3/L, 0, -6*E*I*f2/L**2, 2*E*I*f4/L], + [-E*A/L, 0, 0, E*A/L, 0, 0], + [0, -12*E*I*f5/L**3, -6*E*I*f2/L**2, + 0, 12*E*I*f5/L**3, -6*E*I*f2/L**2], + [0, 6*E*I*f2/L**2, 2*E*I*f4/L, 0, -6*E*I*f2/L**2, 4*E*I*f3/L] + ]) + + fle = eq*L*np.mat([0, 1/2., L*h/12, 0, 1/2., -L*h/12]).T + + G = np.mat([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, -n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + u = np.asmatrix(ed).T + P = Kle*G*u-fle + + es = np.mat([ + [-P[0, 0], -P[1, 0], -P[2, 0]], + [P[3, 0], P[4, 0], P[5, 0]] + ]) + + return es + + +def beam2d(ex, ey, ep): + """ + Calculate the stiffness matrix Ke, the mass matrix Me + and the damping matrix Ce for a 2D elastic Bernoulli + beam element. + + Parameters: + + ex = [x1, x2] + ey = [y1, y2] element node coordinates + + ep = [E,A,I,m,(a,b)] element properties; + E: Young's modulus + A: cross section area + I: moment of inertia + m: mass per unit length + a,b: damping coefficients, + Ce=aMe+bKe + + Returns: + + Ke element stiffness matrix (6 x 6) + Me element mass martix + Ce element damping matrix, optional + """ + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]] + ]) + L = np.sqrt(b.T*b).item() + n = np.asarray(b/L).reshape(2,) + + a = 0 + b = 0 + if np.size(ep) == 4: + E, A, I, m = ep + elif np.size(ep) == 6: + E, A, I, m, a, b = ep + + Kle = np.mat([ + [E*A/L, 0, 0, -E*A/L, 0, 0], + [0, 12*E*I/L**3, 6*E*I/L**2, 0, -12*E*I/L**3, 6*E*I/L**2], + [0, 6*E*I/L**2, 4*E*I/L, 0, -6*E*I/L**2, 2*E*I/L], + [-E*A/L, 0, 0, E*A/L, 0, 0], + [0, -12*E*I/L**3, -6*E*I/L**2, 0, 12*E*I/L**3, -6*E*I/L**2], + [0, 6*E*I/L**2, 2*E*I/L, 0, -6*E*I/L**2, 4*E*I/L] + ]) + + Mle = m*L/420*np.mat([ + [140, 0, 0, 70, 0, 0], + [0, 156, 22*L, 0, 54, -13*L], + [0, 22*L, 4*L**2, 0, 13*L, -3*L**2], + [70, 0, 0, 140, 0, 0], + [0, 54, 13*L, 0, 156, -22*L], + [0, -13*L, -3*L**2, 0, -22*L, 4*L**2] + ]) + + Cle = a*Mle+b*Kle + + G = np.mat([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, -n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + Ke = G.T*Kle*G + Me = G.T*Mle*G + Ce = G.T*Cle*G + + if np.size(ep) == 4: + return Ke, Me + elif np.size(ep) == 6: + return Ke, Me, Ce + + +def beam3e(ex, ey, ez, eo, ep, eq=None): + """ + Calculate the stiffness matrix for a 3D elastic Bernoulli + beam element. + + Parameters: + + ex = [x1 x2] + ey = [y1 y2] + ez = [z1 z2] element node coordinates + + eo = [xz yz zz] orientation of local z axis + + ep = [E G A Iy Iz Kv] element properties + E: Young's modulus + G: Shear modulus + A: Cross section area + Iy: Moment of inertia, local y-axis + Iz: Moment of inertia, local z-axis + Kv: Saint-Venant's torsion constant + + eq = [qx qy qz qw] distributed loads + + Returns: + + Ke beam stiffness matrix (12 x 12) + + fe equivalent nodal forces (12 x 1) + + """ + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]], + [ez[1]-ez[0]] + ]) + L = np.sqrt(b.T*b).item() + n1 = np.asarray(b.T/L).reshape(3,) + + eo = np.asmatrix(eo) + lc = np.sqrt(eo*eo.T).item() + n3 = np.asarray(eo/lc).reshape(3,) + + E, Gs, A, Iy, Iz, Kv = ep + + qx = 0. + qy = 0. + qz = 0. + qw = 0. + if eq != None: + qx, qy, qz, qw = eq + + a = E*A/L + b = 12*E*Iz/L**3 + c = 6*E*Iz/L**2 + d = 12*E*Iy/L**3 + e = 6*E*Iy/L**2 + f = Gs*Kv/L + g = 2*E*Iy/L + h = 2*E*Iz/L + + Kle = np.mat([ + [a, 0, 0, 0, 0, 0, -a, 0, 0, 0, 0, 0], + [0, b, 0, 0, 0, c, 0, -b, 0, 0, 0, c], + [0, 0, d, 0, -e, 0, 0, 0, -d, 0, -e, 0], + [0, 0, 0, f, 0, 0, 0, 0, 0, -f, 0, 0], + [0, 0, -e, 0, 2*g, 0, 0, 0, e, 0, g, 0], + [0, c, 0, 0, 0, 2*h, 0, -c, 0, 0, 0, h], + [-a, 0, 0, 0, 0, 0, a, 0, 0, 0, 0, 0], + [0, -b, 0, 0, 0, -c, 0, b, 0, 0, 0, -c], + [0, 0, -d, 0, e, 0, 0, 0, d, 0, e, 0], + [0, 0, 0, -f, 0, 0, 0, 0, 0, f, 0, 0], + [0, 0, -e, 0, g, 0, 0, 0, e, 0, 2*g, 0], + [0, c, 0, 0, 0, h, 0, -c, 0, 0, 0, 2*h] + ]) + + fle = L/2*np.mat([qx, qy, qz, qw, -qz*L/6, qy*L/6, + qx, qy, qz, qw, qz*L/6, -qy*L/6]).T + + n2 = np.array([0., 0., 0.]) + n2[0] = n3[1]*n1[2]-n3[2]*n1[1] + n2[1] = -n1[2]*n3[0]+n1[0]*n3[2] + n2[2] = n3[0]*n1[1]-n1[0]*n3[1] + + #An = np.append([n1,n2],[n3],0) + + G = np.mat([ + [n1[0], n1[1], n1[2], 0, 0, 0, 0, 0, 0, 0, 0, 0], + [n2[0], n2[1], n2[2], 0, 0, 0, 0, 0, 0, 0, 0, 0], + [n3[0], n3[1], n3[2], 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, n1[0], n1[1], n1[2], 0, 0, 0, 0, 0, 0], + [0, 0, 0, n2[0], n2[1], n2[2], 0, 0, 0, 0, 0, 0], + [0, 0, 0, n3[0], n3[1], n3[2], 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, n1[0], n1[1], n1[2], 0, 0, 0], + [0, 0, 0, 0, 0, 0, n2[0], n2[1], n2[2], 0, 0, 0], + [0, 0, 0, 0, 0, 0, n3[0], n3[1], n3[2], 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, n1[0], n1[1], n1[2]], + [0, 0, 0, 0, 0, 0, 0, 0, 0, n2[0], n2[1], n2[2]], + [0, 0, 0, 0, 0, 0, 0, 0, 0, n3[0], n3[1], n3[2]] + ]) + + Ke = G.T*Kle*G + fe = G.T*fle + + if eq == None: + return Ke + else: + return Ke, fe + + +def beam3s(ex, ey, ez, eo, ep, ed, eq=None, n=None): + """ + Calculate the variation of the section forces and displacements + along a three-dimensional beam element. + + Parameters: + + ex = [x1 x2] element node coordinates + ey = [y1 y2] + ez = [z1 z2] + + eo = [xz yz zz] orientation of local z axis + + ep = [E G A Iy Iz Kv] element properties + E: Young's modulus + G: Shear modulus + A: Cross section area + Iy: Moment of inertia, local y-axis + Iz: Moment of inertia, local z-axis + Kv: Saint-Venant's torsion constant + + ed the element displacement vector from the + global coordinate system + + eq = [qx qy qz qw] the disibuted axial, transversal and + torsional loads + + n the number of point in which displacements + and section forces are to be computed + + Returns: + + es = [[N1,Vy1,Vz1,T1,My1,Mz1], section forces in n points along + [N2,Vy2,Vz2,T2,My2,Mz2], the local x-axis + [..,...,...,..,...,...], + [Nn,Vyn,Vzn,Tn,Myn,Mzn]] + + edi = [[u1,v1,w1,fi1], displacements in n points along + [u2,v2,w2,fi2], the local x-axis + [..,..,..,...], + [un,vn,wn,fin]] + + eci = [[x1], local x-coordinates of the evaluation + [x2], points + [..], + [xn]] + + """ + b = np.mat([ + [ex[1]-ex[0]], + [ey[1]-ey[0]], + [ez[1]-ez[0]] + ]) + L = np.sqrt(b.T*b).item() + n1 = np.asarray(b.T/L).reshape(3,) + + eo = np.asmatrix(eo) + lc = np.sqrt(eo*eo.T).item() + n3 = np.asarray(eo/lc).reshape(3,) + + EA = ep[0]*ep[2] + EIy = ep[0]*ep[3] + EIz = ep[0]*ep[4] + GKv = ep[1]*ep[5] + + qx = 0. + qy = 0. + qz = 0. + qw = 0. + if eq != None: + qx, qy, qz, qw = eq + + ne = 2 + if n != None: + ne = n + + n2 = np.array([0., 0., 0.]) + n2[0] = n3[1]*n1[2]-n3[2]*n1[1] + n2[1] = -n1[2]*n3[0]+n1[0]*n3[2] + n2[2] = n3[0]*n1[1]-n1[0]*n3[1] + + G = np.mat([ + [n1[0], n1[1], n1[2], 0, 0, 0, + 0, 0, 0, 0, 0, 0], + [n2[0], n2[1], n2[2], 0, 0, 0, + 0, 0, 0, 0, 0, 0], + [n3[0], n3[1], n3[2], 0, 0, 0, + 0, 0, 0, 0, 0, 0], + [0, 0, 0, n1[0], n1[1], n1[2], + 0, 0, 0, 0, 0, 0], + [0, 0, 0, n2[0], n2[1], n2[2], + 0, 0, 0, 0, 0, 0], + [0, 0, 0, n3[0], n3[1], n3[2], + 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, + n1[0], n1[1], n1[2], 0, 0, 0], + [0, 0, 0, 0, 0, 0, + n2[0], n2[1], n2[2], 0, 0, 0], + [0, 0, 0, 0, 0, 0, + n3[0], n3[1], n3[2], 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, + 0, 0, n1[0], n1[1], n1[2]], + [0, 0, 0, 0, 0, 0, 0, + 0, 0, n2[0], n2[1], n2[2]], + [0, 0, 0, 0, 0, 0, + 0, 0, 0, n3[0], n3[1], n3[2]] + ]) + + u = G*np.asmatrix(ed).T-np.array([ # u is the local element displacement + [0], # vector minus the particular solution + [0], # to the beam's diff.eq:s + [0], + [0], + [0], + [0], + [-qx*L**2/(2*EA)], + [qy*L**4/(24*EIz)], + [qz*L**4/(24*EIy)], + [-qw*L**2/(2*GKv)], + [-qz*L**3/(6*EIy)], + [qy*L**3/(6*EIz)] + ]) + + C = np.mat([ + [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [L, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], + [0, 0, L**3, L**2, L, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, L**3, L**2, L, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L, 1], + [0, 0, 0, 0, 0, 0, -3*L**2, -2*L, -1, 0, 0, 0], + [0, 0, 3*L**2, 2*L, 1, 0, 0, 0, 0, 0, 0, 0], + ]) + + m = np.linalg.inv(C)*u + eci = np.zeros((ne, 1)) + es = np.zeros((ne, 6)) + edi = np.zeros((ne, 4)) + for i in np.arange(ne): + x = i*L/(ne-1) + eci[i, 0] = x + es[i, :] = (np.mat([ + [EA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, -6*EIz, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, -6*EIy, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GKv, 0], + [0, 0, 0, 0, 0, 0, -6*EIy*x, -2*EIy, 0, 0, 0, 0], + [0, 0, 6*EIz*x, 2*EIz, 0, 0, 0, 0, 0, 0, 0, 0] + ])*m+np.array([-qx*x, -qy*x, -qz*x, -qw*x, -qz*x**2/2, qy*x**2/2]).reshape(6, 1)).T + + edi[i, :] = (np.mat([ + [x, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, x**3, x**2, x, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, x**3, x**2, x, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x, 1] + ])*m+np.array([-qx*x**2/(2*EA), qy*x**4/(24*EIz), qz*x**4/(24*EIy), -qw*x**2/(2*GKv)]).reshape(4, 1)).T + + if n == None: + return es + else: + return es, edi, eci + + +def flw2te(ex, ey, ep, D, eq=None): + """ + Compute element stiffness (conductivity) matrix for a triangular field element. + + Parameters: + + ex = [x1 x2 x3] + ey = [y1 y2 y3] element coordinates + + ep = [t] element thickness + + D = [kxx kxy; + kyx kyy] constitutive matrix + + eq heat supply per unit volume + + Returns: + + Ke element 'stiffness' matrix (3 x 3) + + fe element load vector (3 x 1) + + """ + t = ep[0] + if eq == None: + eq = 0. + + exm = np.asmatrix(ex) + eym = np.asmatrix(ey) + C = np.asmatrix(np.hstack([np.ones((3, 1)), exm.T, eym.T])) + B = np.matrix([ + [0., 1., 0.], + [0., 0., 1.] + ])*C.I + A = 0.5*np.linalg.det(C) + + Ke = B.T*D*B*t*A + fe = np.matrix([[1., 1., 1.]]).T*eq*A*t/3 + + if eq == 0.: + return Ke + else: + return Ke, fe + + +def flw2ts(ex, ey, D, ed): + """ + Compute flows or corresponding quantities in the triangular field element. + + Parameters: + + ex = [x1 x2 x3] + ey = [y1 y2 y3] element coordinates + + D = [kxx kxy + kyx kyy] constitutive matrix + + ed =[u1 u2 u3] u1,u2,u3: nodal values + .. .. ..; + + Returns: + + es=[ qx qy ] + ... ..] element flows + + et=[ gx gy ] + ... ..] element gradients + + """ + + if len(ex.shape) > 1: + qs = np.zeros([ex.shape[0], 2]) + qt = np.zeros([ex.shape[0], 2]) + row = 0 + for exr, eyr, edr in zip(ex, ey, ed): + exm = np.asmatrix(exr) + eym = np.asmatrix(eyr) + edm = np.asmatrix(edr) + C = np.asmatrix(np.hstack([np.ones((3, 1)), exm.T, eym.T])) + B = np.matrix([ + [0., 1., 0.], + [0., 0., 1.] + ])*C.I + + qs[row, :] = (-D*B*edm.T).T + qt[row, :] = (B*edm.T).T + row += 1 + + return qs, qt + else: + exm = np.asmatrix(ex) + eym = np.asmatrix(ey) + edm = np.asmatrix(ed) + C = np.asmatrix(np.hstack([np.ones((3, 1)), exm.T, eym.T])) + B = np.matrix([ + [0., 1., 0.], + [0., 0., 1.] + ])*C.I + + qs = -D*B*edm.T + qt = B*edm.T + + return qs.T, qt.T + + +def flw2qe(ex, ey, ep, D, eq=None): + """ + Compute element stiffness (conductivity) matrix for a triangular field element. + + Parameters: + + ex = [x1, x2, x3, x4] + ey = [y1, y2, y3, y4] element coordinates + + ep = [t] element thickness + + D = [[kxx, kxy], + [kyx, kyy]] constitutive matrix + + eq heat supply per unit volume + + Returns: + + Ke element 'stiffness' matrix (4 x 4) + + fe element load vector (4 x 1) + + """ + xc = sum(ex)/4. + yc = sum(ey)/4. + + K = np.zeros((5, 5)) + f = np.zeros((5, 1)) + + if eq == None: + k1 = flw2te([ex[0], ex[1], xc], [ey[0], ey[1], yc], ep, D) + K = assem(np.array([1, 2, 5]), K, k1) + k1 = flw2te([ex[1], ex[2], xc], [ey[1], ey[2], yc], ep, D) + K = assem(np.array([2, 3, 5]), K, k1) + k1 = flw2te([ex[2], ex[3], xc], [ey[2], ey[3], yc], ep, D) + K = assem(np.array([3, 4, 5]), K, k1) + k1 = flw2te([ex[3], ex[0], xc], [ey[3], ey[0], yc], ep, D) + K = assem(np.array([4, 1, 5]), K, k1) + else: + k1, f1 = flw2te([ex[0], ex[1], xc], [ey[0], ey[1], yc], ep, D, eq) + K, f = assem(np.array([1, 2, 5]), K, k1, f, f1) + k1, f1 = flw2te([ex[1], ex[2], xc], [ey[1], ey[2], yc], ep, D, eq) + K, f = assem(np.array([2, 3, 5]), K, k1, f, f1) + k1, f1 = flw2te([ex[2], ex[3], xc], [ey[2], ey[3], yc], ep, D, eq) + K, f = assem(np.array([3, 4, 5]), K, k1, f, f1) + k1, f1 = flw2te([ex[3], ex[0], xc], [ey[3], ey[0], yc], ep, D, eq) + K, f = assem(np.array([4, 1, 5]), K, k1, f, f1) + Ke1, fe1 = statcon(K, f, np.array([5])) + + Ke = Ke1 + fe = fe1 + + if eq == None: + return Ke + else: + return Ke, fe + + +def flw2qs(ex, ey, ep, D, ed, eq=None): + """ + Compute flows or corresponding quantities in the + quadrilateral field element. + + Parameters: + + ex = [x1, x2, x3, x4] + ey = [y1, y2, y3, y4] element coordinates + + ep = [t] element thickness + + D = [[kxx, kxy], + [kyx, kyy]] constitutive matrix + + ed = [[u1, u2, u3, u4], + [.., .., .., ..]] u1,u2,u3,u4: nodal values + + eq heat supply per unit volume + + Returns: + + es = [[qx, qy], + [.., ..]] element flows + + et = [[gx, gy], + [.., ..]] element gradients + + """ + K = np.zeros((5, 5)) + f = np.zeros((5, 1)) + + xm = sum(ex)/4 + ym = sum(ey)/4 + + if eq == None: + q = 0 + else: + q = eq + + En = np.array([ + [1, 2, 5], + [2, 3, 5], + [3, 4, 5], + [4, 1, 5] + ]) + ex1 = np.array([ex[0], ex[1], xm]) + ey1 = np.array([ey[0], ey[1], ym]) + ex2 = np.array([ex[1], ex[2], xm]) + ey2 = np.array([ey[1], ey[2], ym]) + ex3 = np.array([ex[2], ex[3], xm]) + ey3 = np.array([ey[2], ey[3], ym]) + ex4 = np.array([ex[3], ex[0], xm]) + ey4 = np.array([ey[3], ey[0], ym]) + + if eq == None: + k1 = flw2te(ex1, ey1, ep, D) + K = assem(En[0], K, k1) + k1 = flw2te(ex2, ey2, ep, D) + K = assem(En[1], K, k1) + k1 = flw2te(ex3, ey3, ep, D) + K = assem(En[2], K, k1) + k1 = flw2te(ex4, ey4, ep, D) + K = assem(En[3], K, k1) + else: + k1, f1 = flw2te(ex1, ey1, ep, D, q) + K, f = assem(En[0], K, k1, f, f1) + k1, f1 = flw2te(ex2, ey2, ep, D, q) + K, f = assem(En[1], K, k1, f, f1) + k1, f1 = flw2te(ex3, ey3, ep, D, q) + K, f = assem(En[2], K, k1, f, f1) + k1, f1 = flw2te(ex4, ey4, ep, D, q) + K, f = assem(En[3], K, k1, f, f1) + + if ed.ndim == 1: + ed = np.array([ed]) + + ni, nj = np.shape(ed) + + a = np.zeros((5, ni)) + for i in range(ni): + a[np.ix_(range(5), [i])], r = np.asarray( + solveq(K, f, np.arange(1, 5), ed[i])) + + s1, t1 = flw2ts(ex1, ey1, D, a[np.ix_(En[0, :]-1, np.arange(ni))].T) + s2, t2 = flw2ts(ex2, ey2, D, a[np.ix_(En[1, :]-1, np.arange(ni))].T) + s3, t3 = flw2ts(ex3, ey3, D, a[np.ix_(En[2, :]-1, np.arange(ni))].T) + s4, t4 = flw2ts(ex4, ey4, D, a[np.ix_(En[3, :]-1, np.arange(ni))].T) + + es = (s1+s2+s3+s4)/4. + et = (t1+t2+t3+t4)/4. + + return es, et + + +def flw2i4e(ex, ey, ep, D, eq=None): + """ + Compute element stiffness (conductivity) + matrix for 4 node isoparametric field element + + Parameters: + + ex = [x1 x2 x3 x4] element coordinates + ey = [y1 y2 y3 y4] + + ep = [t ir] thickness and integration rule + + D = [[kxx kxy], + [kyx kyy]] constitutive matrix + + eq heat supply per unit volume + + Returns: + Ke element 'stiffness' matrix (4 x 4) + fe element load vector (4 x 1) + + """ + t = ep[0] + ir = ep[1] + ngp = ir*ir + + if eq == None: + q = 0 + else: + q = eq + + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.mat([g1, g1]) + w = np.mat([w1, w1]) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-g1, -g1], + [g1, -g1], + [-g1, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w1, w1], + [w1, w1], + [w1, w1] + ]) + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat([ + [-g1, -g1], + [-g2, -g1], + [g1, -g1], + [-g1, g2], + [g2, g2], + [g1, g2], + [-g1, g1], + [g2, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w2, w1], + [w1, w1], + [w1, w2], + [w2, w2], + [w1, w2], + [w1, w1], + [w2, w1], + [w1, w1] + ]) + else: + info("Used number of integration points not implemented") + wp = np.multiply(w[:, 0], w[:, 1]) + + xsi = gp[:, 0] + eta = gp[:, 1] + r2 = ngp*2 + + N = np.multiply((1-xsi), (1-eta))/4. + N = np.append(N, np.multiply((1+xsi), (1-eta))/4., axis=1) + N = np.append(N, np.multiply((1+xsi), (1+eta))/4., axis=1) + N = np.append(N, np.multiply((1-xsi), (1+eta))/4., axis=1) + + dNr = np.mat(np.zeros((r2, 4))) + dNr[0:r2:2, 0] = -(1-eta)/4. + dNr[0:r2:2, 1] = (1-eta)/4. + dNr[0:r2:2, 2] = (1+eta)/4. + dNr[0:r2:2, 3] = -(1+eta)/4. + dNr[1:r2+1:2, 0] = -(1-xsi)/4. + dNr[1:r2+1:2, 1] = -(1+xsi)/4. + dNr[1:r2+1:2, 2] = (1+xsi)/4. + dNr[1:r2+1:2, 3] = (1-xsi)/4. + + Ke1 = np.mat(np.zeros((4, 4))) + fe1 = np.mat(np.zeros((4, 1))) + JT = dNr*np.mat([ex, ey]).T + + for i in range(ngp): + indx = np.array([2*(i+1)-1, 2*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobi determinant == 0") + JTinv = np.linalg.inv(JT[indx-1, :]) + B = JTinv*dNr[indx-1, :] + Ke1 = Ke1+B.T*D*B*detJ*wp[i].item() + fe1 = fe1+N[i, :].T*detJ*wp[i] + + if eq == None: + return Ke1*t + else: + return Ke1*t, fe1*t*eq + + +def flw2i4s(ex, ey, ep, D, ed): + """ + Compute flows or corresponding quantities in the + 4 node isoparametric element. + + Parameters: + + ex = [x1 x2 x3 x4] element coordinates + ey = [y1 y2 y3 y4] + + ep = [t ir] thickness and integration rule + + D = [[kxx kxy], + [kyx kyy]] constitutive matrix + + ed = [u1, u2, u3, u4] u1,u2,u3,u4: nodal values + + Returns: + es = [[qx, qy], + [.., ..]] element flows + + et = [[qx, qy], + [... ..]] element gradients + + eci=[[ix1, iy1], Gauss point location vector + [... ...], nint: number of integration points + [ix(nint), iy(nint)] + + """ + t = ep[0] + ir = ep[1] + ngp = ir*ir + + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.mat([g1, g1]) + w = np.mat([w1, w1]) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-g1, -g1], + [g1, -g1], + [-g1, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w1, w1], + [w1, w1], + [w1, w1] + ]) + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat([ + [-g1, -g1], + [-g2, -g1], + [g1, -g1], + [-g1, g2], + [g2, g2], + [g1, g2], + [-g1, g1], + [g2, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w2, w1], + [w1, w1], + [w1, w2], + [w2, w2], + [w1, w2], + [w1, w1], + [w2, w1], + [w1, w1] + ]) + else: + info("Used number of integration points not implemented") + wp = np.multiply(w[:, 0], w[:, 1]) + + xsi = gp[:, 0] + eta = gp[:, 1] + r2 = ngp*2 + + N = np.multiply((1-xsi), (1-eta))/4. + N = np.append(N, np.multiply((1+xsi), (1-eta))/4., axis=1) + N = np.append(N, np.multiply((1+xsi), (1+eta))/4., axis=1) + N = np.append(N, np.multiply((1-xsi), (1+eta))/4., axis=1) + + dNr = np.mat(np.zeros((r2, 4))) + dNr[0:r2:2, 0] = -(1-eta)/4. + dNr[0:r2:2, 1] = (1-eta)/4. + dNr[0:r2:2, 2] = (1+eta)/4. + dNr[0:r2:2, 3] = -(1+eta)/4. + dNr[1:r2+1:2, 0] = -(1-xsi)/4. + dNr[1:r2+1:2, 1] = -(1+xsi)/4. + dNr[1:r2+1:2, 2] = (1+xsi)/4. + dNr[1:r2+1:2, 3] = (1-xsi)/4. + + eci = N*np.mat([ex, ey]).T + if ed.ndim == 1: + ed = np.array([ed]) + + red, ced = np.shape(ed) + JT = dNr*np.mat([ex, ey]).T + + es = np.mat(np.zeros((ngp*red, 2))) + et = np.mat(np.zeros((ngp*red, 2))) + for i in range(ngp): + indx = np.array([2*(i+1)-1, 2*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobi determinatn == 0") + JTinv = np.linalg.inv(JT[indx-1, :]) + B = JTinv*dNr[indx-1, :] + p1 = -D*B*ed.T + p2 = B*ed.T + es[i:ngp*red:ngp, :] = p1.T + et[i:ngp*red:ngp, :] = p2.T + + return es, et, eci + + +def flw2i8e(ex, ey, ep, D, eq=None): + """ + Compute element stiffness (conductivity) + matrix for 8 node isoparametric field element. + + Parameters: + + ex = [x1, ..., x8] element coordinates + ey = [y1, ..., y8] + + ep = [t, ir] thickness and integration rule + + D = [[kxx, kxy], + [kyx, kyy]] constitutive matrix + + eq heat supply per unit volume + + Returns: + + Ke element 'stiffness' matrix (8 x 8) + fe element load vector (8 x 1) + + """ + t = ep[0] + ir = ep[1] + ngp = ir*ir + + if eq == None: + q = 0 + else: + q = eq + + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.mat([g1, g1]) + w = np.mat([w1, w1]) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-g1, -g1], + [g1, -g1], + [-g1, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w1, w1], + [w1, w1], + [w1, w1] + ]) + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat([ + [-g1, -g1], + [-g2, -g1], + [g1, -g1], + [-g1, g2], + [g2, g2], + [g1, g2], + [-g1, g1], + [g2, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w2, w1], + [w1, w1], + [w1, w2], + [w2, w2], + [w1, w2], + [w1, w1], + [w2, w1], + [w1, w1] + ]) + else: + info("Used number of integration points not implemented") + wp = np.multiply(w[:, 0], w[:, 1]) + + xsi = gp[:, 0] + eta = gp[:, 1] + r2 = ngp*2 + + N = np.multiply(np.multiply(-(1-xsi), (1-eta)), (1+xsi+eta))/4. + N = np.append(N, np.multiply( + np.multiply(-(1+xsi), (1-eta)), (1-xsi+eta))/4., axis=1) + N = np.append(N, np.multiply( + np.multiply(-(1+xsi), (1+eta)), (1-xsi-eta))/4., axis=1) + N = np.append(N, np.multiply( + np.multiply(-(1-xsi), (1+eta)), (1+xsi-eta))/4., axis=1) + N = np.append(N, np.multiply( + (1-np.multiply(xsi, xsi)), (1-eta))/2., axis=1) + N = np.append(N, np.multiply( + (1+xsi), (1-np.multiply(eta, eta)))/2., axis=1) + N = np.append(N, np.multiply( + (1-np.multiply(xsi, xsi)), (1+eta))/2., axis=1) + N = np.append(N, np.multiply( + (1-xsi), (1-np.multiply(eta, eta)))/2., axis=1) + + dNr = np.mat(np.zeros((r2, 8))) + dNr[0:r2:2, 0] = -(-np.multiply((1-eta), (1+xsi+eta)) + + np.multiply((1-xsi), (1-eta)))/4. + dNr[0:r2:2, 1] = -(np.multiply((1-eta), (1-xsi+eta)) - + np.multiply((1+xsi), (1-eta)))/4. + dNr[0:r2:2, 2] = -(np.multiply((1+eta), (1-xsi-eta)) - + np.multiply((1+xsi), (1+eta)))/4. + dNr[0:r2:2, 3] = -(-np.multiply((1+eta), (1+xsi-eta)) + + np.multiply((1-xsi), (1+eta)))/4. + dNr[0:r2:2, 4] = -np.multiply(xsi, (1-eta)) + dNr[0:r2:2, 5] = (1-np.multiply(eta, eta))/2. + dNr[0:r2:2, 6] = -np.multiply(xsi, (1+eta)) + dNr[0:r2:2, 7] = -(1-np.multiply(eta, eta))/2. + dNr[1:r2+1:2, 0] = -(-np.multiply((1-xsi), (1+xsi+eta)) + + np.multiply((1-xsi), (1-eta)))/4. + dNr[1:r2+1:2, 1] = -(-np.multiply((1+xsi), (1-xsi+eta)) + + np.multiply((1+xsi), (1-eta)))/4. + dNr[1:r2+1:2, 2] = -(np.multiply((1+xsi), (1-xsi-eta)) - + np.multiply((1+xsi), (1+eta)))/4. + dNr[1:r2+1:2, 3] = -(np.multiply((1-xsi), (1+xsi-eta)) - + np.multiply((1-xsi), (1+eta)))/4. + dNr[1:r2+1:2, 4] = -(1-np.multiply(xsi, xsi))/2. + dNr[1:r2+1:2, 5] = -np.multiply(eta, (1+xsi)) + dNr[1:r2+1:2, 6] = (1-np.multiply(xsi, xsi))/2. + dNr[1:r2+1:2, 7] = -np.multiply(eta, (1-xsi)) + + Ke1 = np.mat(np.zeros((8, 8))) + fe1 = np.mat(np.zeros((8, 1))) + JT = dNr*np.mat([ex, ey]).T + + for i in range(ngp): + indx = np.array([2*(i+1)-1, 2*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobideterminanten lika med noll!") + JTinv = np.linalg.inv(JT[indx-1, :]) + B = JTinv*dNr[indx-1, :] + Ke1 = Ke1+B.T*D*B*detJ*wp[i].item() + fe1 = fe1+N[i, :].T*detJ*wp[i] + + if eq != None: + return Ke1*t, fe1*t*q + else: + return Ke1*t + + +def flw2i8s(ex, ey, ep, D, ed): + """ + Compute flows or corresponding quantities in the + 8 node isoparametric element. + + Parameters: + + ex = [x1,x2,x3....,x8] element coordinates + ey = [y1,y2,y3....,y8] + + ep = [t,ir] thickness and integration rule + + D = [[kxx,kxy], + [kyx,kyy]] constitutive matrix + + ed = [u1,....,u8] u1,....,u8: nodal values + + Returns: + es = [[qx,qy], + [..,..]] element flows + + et = [[qx,qy], + [..,..]] element gradients + + eci=[[ix1,iy1], Gauss point location vector + [...,...], nint: number of integration points + [ix(nint),iy(nint)]] + + """ + t = ep[0] + ir = ep[1] + ngp = ir*ir + + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.mat([g1, g1]) + w = np.mat([w1, w1]) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-g1, -g1], + [g1, -g1], + [-g1, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w1, w1], + [w1, w1], + [w1, w1] + ]) + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat([ + [-g1, -g1], + [-g2, -g1], + [g1, -g1], + [-g1, g2], + [g2, g2], + [g1, g2], + [-g1, g1], + [g2, g1], + [g1, g1] + ]) + w = np.mat([ + [w1, w1], + [w2, w1], + [w1, w1], + [w1, w2], + [w2, w2], + [w1, w2], + [w1, w1], + [w2, w1], + [w1, w1] + ]) + else: + info("Used number of integration points not implemented") + wp = np.multiply(w[:, 0], w[:, 1]) + + xsi = gp[:, 0] + eta = gp[:, 1] + r2 = ngp*2 + + N = np.multiply(np.multiply(-(1-xsi), (1-eta)), (1+xsi+eta))/4. + N = np.append(N, np.multiply( + np.multiply(-(1+xsi), (1-eta)), (1-xsi+eta))/4., axis=1) + N = np.append(N, np.multiply( + np.multiply(-(1+xsi), (1+eta)), (1-xsi-eta))/4., axis=1) + N = np.append(N, np.multiply( + np.multiply(-(1-xsi), (1+eta)), (1+xsi-eta))/4., axis=1) + N = np.append(N, np.multiply( + (1-np.multiply(xsi, xsi)), (1-eta))/2., axis=1) + N = np.append(N, np.multiply( + (1+xsi), (1-np.multiply(eta, eta)))/2., axis=1) + N = np.append(N, np.multiply( + (1-np.multiply(xsi, xsi)), (1+eta))/2., axis=1) + N = np.append(N, np.multiply( + (1-xsi), (1-np.multiply(eta, eta)))/2., axis=1) + + dNr = np.mat(np.zeros((r2, 8))) + dNr[0:r2:2, 0] = -(-np.multiply((1-eta), (1+xsi+eta)) + + np.multiply((1-xsi), (1-eta)))/4. + dNr[0:r2:2, 1] = -(np.multiply((1-eta), (1-xsi+eta)) - + np.multiply((1+xsi), (1-eta)))/4. + dNr[0:r2:2, 2] = -(np.multiply((1+eta), (1-xsi-eta)) - + np.multiply((1+xsi), (1+eta)))/4. + dNr[0:r2:2, 3] = -(-np.multiply((1+eta), (1+xsi-eta)) + + np.multiply((1-xsi), (1+eta)))/4. + dNr[0:r2:2, 4] = -np.multiply(xsi, (1-eta)) + dNr[0:r2:2, 5] = (1-np.multiply(eta, eta))/2. + dNr[0:r2:2, 6] = -np.multiply(xsi, (1+eta)) + dNr[0:r2:2, 7] = -(1-np.multiply(eta, eta))/2. + dNr[1:r2+1:2, 0] = -(-np.multiply((1-xsi), (1+xsi+eta)) + + np.multiply((1-xsi), (1-eta)))/4. + dNr[1:r2+1:2, 1] = -(-np.multiply((1+xsi), (1-xsi+eta)) + + np.multiply((1+xsi), (1-eta)))/4. + dNr[1:r2+1:2, 2] = -(np.multiply((1+xsi), (1-xsi-eta)) - + np.multiply((1+xsi), (1+eta)))/4. + dNr[1:r2+1:2, 3] = -(np.multiply((1-xsi), (1+xsi-eta)) - + np.multiply((1-xsi), (1+eta)))/4. + dNr[1:r2+1:2, 4] = -(1-np.multiply(xsi, xsi))/2. + dNr[1:r2+1:2, 5] = -np.multiply(eta, (1+xsi)) + dNr[1:r2+1:2, 6] = (1-np.multiply(xsi, xsi))/2. + dNr[1:r2+1:2, 7] = -np.multiply(eta, (1-xsi)) + + eci = N*np.mat([ex, ey]).T + if ed.ndim == 1: + ed = np.array([ed]) + red, ced = np.shape(ed) + JT = dNr*np.mat([ex, ey]).T + + es = np.mat(np.zeros((ngp*red, 2))) + et = np.mat(np.zeros((ngp*red, 2))) + + for i in range(ngp): + indx = np.array([2*(i+1)-1, 2*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobi determinant == 0") + JTinv = np.linalg.inv(JT[indx-1, :]) + B = JTinv*dNr[indx-1, :] + p1 = -D*B*ed.T + p2 = B*ed.T + es[i:ngp*red:ngp, :] = p1.T + et[i:ngp*red:ngp, :] = p2.T + + return es, et, eci + + +def flw3i8e(ex, ey, ez, ep, D, eq=None): + """ + Compute element stiffness (conductivity) + matrix for 8 node isoparametric field element. + + Parameters: + + ex = [x1,x2,x3,...,x8] + ey = [y1,y2,y3,...,y8] element coordinates + ez = [z1,z2,z3,...,z8] + + ep = [ir] Ir: Integration rule + + D = [[kxx,kxy,kxz], + [kyx,kyy,kyz], + [kzx,kzy,kzz]] constitutive matrix + + eq heat supply per unit volume + + Output: + + Ke element 'stiffness' matrix (8 x 8) + fe element load vector (8 x 1) + + """ + ir = ep[0] + ngp = ir*ir*ir + + if eq == None: + q = 0 + else: + q = eq + + if ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-1, -1, -1], + [1, -1, -1], + [1, 1, -1], + [-1, 1, -1], + [-1, -1, 1], + [1, -1, 1], + [1, 1, 1], + [-1, 1, 1] + ])*g1 + w = np.mat(np.ones((8, 3)))*w1 + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat(np.zeros((27, 3))) + w = np.mat(np.zeros((27, 3))) + I1 = np.array([-1, 0, 1, -1, 0, 1, -1, 0, 1]) + I2 = np.array([0, -1, 0, 0, 1, 0, 0, 1, 0]) + gp[:, 0] = np.mat([I1, I1, I1]).reshape(27, 1)*g1 + gp[:, 0] = np.mat([I2, I2, I2]).reshape(27, 1)*g2+gp[:, 0] + I1 = abs(I1) + I2 = abs(I2) + w[:, 0] = np.mat([I1, I1, I1]).reshape(27, 1)*w1 + w[:, 0] = np.mat([I2, I2, I2]).reshape(27, 1)*w2+w[:, 0] + I1 = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1]) + I2 = np.array([0, 0, 0, 1, 1, 1, 0, 0, 0]) + gp[:, 1] = np.mat([I1, I1, I1]).reshape(27, 1)*g1 + gp[:, 1] = np.mat([I2, I2, I2]).reshape(27, 1)*g2+gp[:, 1] + I1 = abs(I1) + I2 = abs(I2) + w[:, 1] = np.mat([I1, I1, I1]).reshape(27, 1)*w1 + w[:, 1] = np.mat([I2, I2, I2]).reshape(27, 1)*w2+w[:, 1] + I1 = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1]) + I2 = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]) + I3 = abs(I1) + gp[:, 2] = np.mat([I1, I2, I3]).reshape(27, 1)*g1 + gp[:, 2] = np.mat([I2, I3, I2]).reshape(27, 1)*g2+gp[:, 2] + w[:, 2] = np.mat([I3, I2, I3]).reshape(27, 1)*w1 + w[:, 2] = np.mat([I2, I3, I2]).reshape(27, 1)*w2+w[:, 2] + else: + info("Used number of integration points not implemented") + return + + wp = np.multiply(np.multiply(w[:, 0], w[:, 1]), w[:, 2]) + + xsi = gp[:, 0] + eta = gp[:, 1] + zet = gp[:, 2] + r2 = ngp*3 + + N = np.multiply(np.multiply((1-xsi), (1-eta)), (1-zet))/8. + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1-eta)), (1-zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1+eta)), (1-zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1-xsi), (1+eta)), (1-zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1-xsi), (1-eta)), (1+zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1-eta)), (1+zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1+eta)), (1+zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1-xsi), (1+eta)), (1+zet))/8., axis=1) + + dNr = np.mat(np.zeros((r2, 8))) + dNr[0:r2:3, 0] = np.multiply(-(1-eta), (1-zet)) + dNr[0:r2:3, 1] = np.multiply((1-eta), (1-zet)) + dNr[0:r2:3, 2] = np.multiply((1+eta), (1-zet)) + dNr[0:r2:3, 3] = np.multiply(-(1+eta), (1-zet)) + dNr[0:r2:3, 4] = np.multiply(-(1-eta), (1+zet)) + dNr[0:r2:3, 5] = np.multiply((1-eta), (1+zet)) + dNr[0:r2:3, 6] = np.multiply((1+eta), (1+zet)) + dNr[0:r2:3, 7] = np.multiply(-(1+eta), (1+zet)) + dNr[1:r2+1:3, 0] = np.multiply(-(1-xsi), (1-zet)) + dNr[1:r2+1:3, 1] = np.multiply(-(1+xsi), (1-zet)) + dNr[1:r2+1:3, 2] = np.multiply((1+xsi), (1-zet)) + dNr[1:r2+1:3, 3] = np.multiply((1-xsi), (1-zet)) + dNr[1:r2+1:3, 4] = np.multiply(-(1-xsi), (1+zet)) + dNr[1:r2+1:3, 5] = np.multiply(-(1+xsi), (1+zet)) + dNr[1:r2+1:3, 6] = np.multiply((1+xsi), (1+zet)) + dNr[1:r2+1:3, 7] = np.multiply((1-xsi), (1+zet)) + dNr[2:r2+2:3, 0] = np.multiply(-(1-xsi), (1-eta)) + dNr[2:r2+2:3, 1] = np.multiply(-(1+xsi), (1-eta)) + dNr[2:r2+2:3, 2] = np.multiply(-(1+xsi), (1+eta)) + dNr[2:r2+2:3, 3] = np.multiply(-(1-xsi), (1+eta)) + dNr[2:r2+2:3, 4] = np.multiply((1-xsi), (1-eta)) + dNr[2:r2+2:3, 5] = np.multiply((1+xsi), (1-eta)) + dNr[2:r2+2:3, 6] = np.multiply((1+xsi), (1+eta)) + dNr[2:r2+2:3, 7] = np.multiply((1-xsi), (1+eta)) + dNr = dNr/8. + + Ke1 = np.mat(np.zeros((8, 8))) + fe1 = np.mat(np.zeros((8, 1))) + JT = dNr*np.mat([ex, ey, ez]).T + + for i in range(ngp): + indx = np.array([3*(i+1)-2, 3*(i+1)-1, 3*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobi determinant == 0") + JTinv = np.linalg.inv(JT[indx-1, :]) + B = JTinv*dNr[indx-1, :] + Ke1 = Ke1+B.T*D*B*detJ*wp[i].item() + fe1 = fe1+N[i, :].T*detJ*wp[i] + + if eq != None: + return Ke1, fe1*q + else: + return Ke1 + + +def flw3i8s(ex, ey, ez, ep, D, ed): + """ + Compute flows or corresponding quantities in the + 8 node (3-dim) isoparametric field element. + + Parameters: + + ex = [x1,x2,x3,...,x8] + ey = [y1,y2,y3,...,y8] element coordinates + ez = [z1,z2,z3,...,z8] + + ep = [ir] Ir: Integration rule + + D = [[kxx,kxy,kxz], + [kyx,kyy,kyz], + [kzx,kzy,kzz]] constitutive matrix + + ed = [[u1,....,u8], element nodal values + [..,....,..]] + + Output: + + es = [[qx,qy,qz], + [..,..,..]] element flows(s) + + et = [[qx,qy,qz], element gradients(s) + [..,..,..]] + + eci = [[ix1,ix1,iz1], location vector + [...,...,...], nint: number of integration points + [ix(nint),iy(nint),iz(nint)]] + + """ + ir = ep[0] + ngp = ir*ir*ir + + if ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-1, -1, -1], + [1, -1, -1], + [1, 1, -1], + [-1, 1, -1], + [-1, -1, 1], + [1, -1, 1], + [1, 1, 1], + [-1, 1, 1] + ])*g1 + w = np.mat(np.ones((8, 3)))*w1 + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat(np.zeros((27, 3))) + w = np.mat(np.zeros((27, 3))) + I1 = np.array([-1, 0, 1, -1, 0, 1, -1, 0, 1]) + I2 = np.array([0, -1, 0, 0, 1, 0, 0, 1, 0]) + gp[:, 0] = np.mat([I1, I1, I1]).reshape(27, 1)*g1 + gp[:, 0] = np.mat([I2, I2, I2]).reshape(27, 1)*g2+gp[:, 0] + I1 = abs(I1) + I2 = abs(I2) + w[:, 0] = np.mat([I1, I1, I1]).reshape(27, 1)*w1 + w[:, 0] = np.mat([I2, I2, I2]).reshape(27, 1)*w2+w[:, 0] + I1 = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1]) + I2 = np.array([0, 0, 0, 1, 1, 1, 0, 0, 0]) + gp[:, 1] = np.mat([I1, I1, I1]).reshape(27, 1)*g1 + gp[:, 1] = np.mat([I2, I2, I2]).reshape(27, 1)*g2+gp[:, 1] + I1 = abs(I1) + I2 = abs(I2) + w[:, 1] = np.mat([I1, I1, I1]).reshape(27, 1)*w1 + w[:, 1] = np.mat([I2, I2, I2]).reshape(27, 1)*w2+w[:, 1] + I1 = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1]) + I2 = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]) + I3 = abs(I1) + gp[:, 2] = np.mat([I1, I2, I3]).reshape(27, 1)*g1 + gp[:, 2] = np.mat([I2, I3, I2]).reshape(27, 1)*g2+gp[:, 2] + w[:, 2] = np.mat([I3, I2, I3]).reshape(27, 1)*w1 + w[:, 2] = np.mat([I2, I3, I2]).reshape(27, 1)*w2+w[:, 2] + else: + info("Used number of integration points not implemented") + return + + wp = np.multiply(np.multiply(w[:, 0], w[:, 1]), w[:, 2]) + + xsi = gp[:, 0] + eta = gp[:, 1] + zet = gp[:, 2] + r2 = ngp*3 + + N = np.multiply(np.multiply((1-xsi), (1-eta)), (1-zet))/8. + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1-eta)), (1-zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1+eta)), (1-zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1-xsi), (1+eta)), (1-zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1-xsi), (1-eta)), (1+zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1-eta)), (1+zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1+xsi), (1+eta)), (1+zet))/8., axis=1) + N = np.append(N, np.multiply(np.multiply( + (1-xsi), (1+eta)), (1+zet))/8., axis=1) + + dNr = np.mat(np.zeros((r2, 8))) + dNr[0:r2:3, 0] = np.multiply(-(1-eta), (1-zet)) + dNr[0:r2:3, 1] = np.multiply((1-eta), (1-zet)) + dNr[0:r2:3, 2] = np.multiply((1+eta), (1-zet)) + dNr[0:r2:3, 3] = np.multiply(-(1+eta), (1-zet)) + dNr[0:r2:3, 4] = np.multiply(-(1-eta), (1+zet)) + dNr[0:r2:3, 5] = np.multiply((1-eta), (1+zet)) + dNr[0:r2:3, 6] = np.multiply((1+eta), (1+zet)) + dNr[0:r2:3, 7] = np.multiply(-(1+eta), (1+zet)) + dNr[1:r2+1:3, 0] = np.multiply(-(1-xsi), (1-zet)) + dNr[1:r2+1:3, 1] = np.multiply(-(1+xsi), (1-zet)) + dNr[1:r2+1:3, 2] = np.multiply((1+xsi), (1-zet)) + dNr[1:r2+1:3, 3] = np.multiply((1-xsi), (1-zet)) + dNr[1:r2+1:3, 4] = np.multiply(-(1-xsi), (1+zet)) + dNr[1:r2+1:3, 5] = np.multiply(-(1+xsi), (1+zet)) + dNr[1:r2+1:3, 6] = np.multiply((1+xsi), (1+zet)) + dNr[1:r2+1:3, 7] = np.multiply((1-xsi), (1+zet)) + dNr[2:r2+2:3, 0] = np.multiply(-(1-xsi), (1-eta)) + dNr[2:r2+2:3, 1] = np.multiply(-(1+xsi), (1-eta)) + dNr[2:r2+2:3, 2] = np.multiply(-(1+xsi), (1+eta)) + dNr[2:r2+2:3, 3] = np.multiply(-(1-xsi), (1+eta)) + dNr[2:r2+2:3, 4] = np.multiply((1-xsi), (1-eta)) + dNr[2:r2+2:3, 5] = np.multiply((1+xsi), (1-eta)) + dNr[2:r2+2:3, 6] = np.multiply((1+xsi), (1+eta)) + dNr[2:r2+2:3, 7] = np.multiply((1-xsi), (1+eta)) + dNr = dNr/8. + + eci = N*np.mat([ex, ey, ez]).T + if ed.ndim == 1: + ed = np.array([ed]) + red, ced = np.shape(ed) + JT = dNr*np.mat([ex, ey, ez]).T + + es = np.mat(np.zeros((ngp*red, 3))) + et = np.mat(np.zeros((ngp*red, 3))) + for i in range(ngp): + indx = np.array([3*(i+1)-2, 3*(i+1)-1, 3*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobideterminanten lika med noll!") + JTinv = np.linalg.inv(JT[indx-1, :]) + B = JTinv*dNr[indx-1, :] + p1 = -D*B*ed.T + p2 = B*ed.T + es[i:ngp*red:ngp, :] = p1.T + et[i:ngp*red:ngp, :] = p2.T + + return es, et, eci + + +def plante(ex, ey, ep, D, eq=None): + """ + Calculate the stiffness matrix for a triangular plane stress or plane strain element. + + Parameters: + + ex = [x1,x2,x3] element coordinates + ey = [y1,y2,y3] + + ep = [ptype,t] ptype: analysis type + t: thickness + + D constitutive matrix + + eq = [[bx], bx: body force x-dir + [by]] by: body force y-dir + + Returns: + + Ke element stiffness matrix (6 x 6) + fe equivalent nodal forces (6 x 1) (if eq is given) + + """ + + ptype, t = ep + + bx = 0.0 + by = 0.0 + + if not eq is None: + bx = eq[0] + by = eq[1] + + C = np.mat([ + [1, ex[0], ey[0], 0, 0, 0], + [0, 0, 0, 1, ex[0], ey[0]], + [1, ex[1], ey[1], 0, 0, 0], + [0, 0, 0, 1, ex[1], ey[1]], + [1, ex[2], ey[2], 0, 0, 0], + [0, 0, 0, 1, ex[2], ey[2]] + ]) + + A = 0.5*np.linalg.det(np.mat([ + [1, ex[0], ey[0]], + [1, ex[1], ey[1]], + [1, ex[2], ey[2]] + ])) + + # --------- plane stress -------------------------------------- + + if ptype == 1: + B = np.mat([ + [0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, 1, 0, 1, 0] + ])*np.linalg.inv(C) + + colD = D.shape[1] + + if colD > 3: + Cm = np.linalg.inv(D) + Dm = np.linalg.inv(Cm[np.ix_((0, 1, 3), (0, 1, 3))]) + else: + Dm = D + + Ke = B.T*Dm*B*A*t + fe = A/3*np.mat([bx, by, bx, by, bx, by]).T*t + + if eq is None: + return Ke + else: + return Ke, fe.T + + #--------- plane strain -------------------------------------- + + elif ptype == 2: + B = np.mat([ + [0, 1, 0, 0, 0, 0, ], + [0, 0, 0, 0, 0, 1, ], + [0, 0, 1, 0, 1, 0, ] + ])*np.linalg.inv(C) + + colD = D.shape[1] + + if colD > 3: + Dm = D[np.ix_((0, 1, 3), (0, 1, 3))] + else: + Dm = D + + Ke = B.T*Dm*B*A*t + fe = A/3*np.mat([bx, by, bx, by, bx, by]).T*t + + if eq == None: + return Ke + else: + return Ke, fe.T + + else: + info("Error ! Check first argument, ptype=1 or 2 allowed") + if eq == None: + return None + else: + return None, None + + +def plants(ex, ey, ep, D, ed): + """ + Calculate element normal and shear stress for a + triangular plane stress or plane strain element. + + INPUT: ex = [x1 x2 x3] element coordinates + ey = [y1 y2 y3] + + ep = [ptype t ] ptype: analysis type + t: thickness + + D constitutive matrix + + ed =[u1 u2 ...u6 element displacement vector + ...... ] one row for each element + + OUTPUT: es = [ sigx sigy [sigz] tauxy element stress matrix + ...... ] one row for each element + + et = [ epsx epsy [epsz] gamxy element strain matrix + ...... ] one row for each element + """ + + ptype = ep[0] + + if np.ndim(ex) == 1: + ex = np.array([ex]) + if np.ndim(ey) == 1: + ey = np.array([ey]) + if np.ndim(ed) == 1: + ed = np.array([ed]) + + rowed = ed.shape[0] + rowex = ex.shape[0] + + # --------- plane stress -------------------------------------- + + if ptype == 1: + + colD = D.shape[1] + + if colD > 3: + Cm = np.linalg.inv(D) + Dm = np.linalg.inv(Cm[np.ix_((0, 1, 3), (0, 1, 3))]) + else: + Dm = D + + incie = 0 + + if rowex == 1: + incie = 0 + else: + incie = 1 + + et = np.zeros([rowed, colD]) + es = np.zeros([rowed, colD]) + + ie = 0 + + for i in range(rowed): + C = np.matrix( + [[1, ex[ie, 0], ey[ie, 0], 0, 0, 0], + [0, 0, 0, 1, ex[ie, 0], ey[ie, 0]], + [1, ex[ie, 1], ey[ie, 1], 0, 0, 0], + [0, 0, 0, 1, ex[ie, 1], ey[ie, 1]], + [1, ex[ie, 2], ey[ie, 2], 0, 0, 0], + [0, 0, 0, 1, ex[ie, 2], ey[ie, 2]]] + ) + + B = np.matrix([ + [0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, 1, 0, 1, 0]])*np.linalg.inv(C) + + ee = B*np.asmatrix(ed[ie, :]).T + + if colD > 3: + ss = np.zeros([colD, 1]) + ss[[0, 1, 3]] = Dm*ee + ee = Cm*ss + else: + ss = Dm*ee + + et[ie, :] = ee.T + es[ie, :] = ss.T + + ie = ie + incie + + return es, et + + # --------- plane strain -------------------------------------- + elif ptype == 2: # Implementation by LAPM + colD = D.shape[1] + incie = 0 + + if rowex == 1: + incie = 0 + else: + incie = 1 + + et = np.zeros([rowed, colD]) + es = np.zeros([rowed, colD]) + + ie = 0 + + ee = np.zeros([colD, 1]) + + for i in range(rowed): + C = np.matrix( + [[1, ex[ie, 0], ey[ie, 0], 0, 0, 0], + [0, 0, 0, 1, ex[ie, 0], ey[ie, 0]], + [1, ex[ie, 1], ey[ie, 1], 0, 0, 0], + [0, 0, 0, 1, ex[ie, 1], ey[ie, 1]], + [1, ex[ie, 2], ey[ie, 2], 0, 0, 0], + [0, 0, 0, 1, ex[ie, 2], ey[ie, 2]]] + ) + + B = np.matrix([ + [0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, 1, 0, 1, 0]])*np.linalg.inv(C) + + e = B*np.asmatrix(ed[ie, :]).T + + if colD > 3: + ee[[0, 1, 3]] = e + else: + ee = e + + et[ie, :] = ee.T + es[ie, :] = (D*ee).T + + ie = ie + incie + + return es, et + + else: + print("Error ! Check first argument, ptype=1 or 2 allowed") + return None + + +def plantf(ex, ey, ep, es): + """ + Compute internal element force vector in a triangular element + in plane stress or plane strain. + + Parameters: + + ex = [x1,x2,x3] node coordinates + ey = [y1,y2,y3] + + ep = [ptype,t] ptype: analysis type + t: thickness + + es = [[sigx,sigy,[sigz],tauxy] element stress matrix + [ ...... ]] one row for each element + + OUTPUT: + + fe = [[f1],[f2],...,[f8]] internal force vector + + """ + + ptype, t = ep + + colD = es.shape[1] + + #--------- plane stress -------------------------------------- + + if ptype == 1: + + C = np.mat([ + [1, ex[0], ey[0], 0, 0, 0], + [0, 0, 0, 1, ex[0], ey[0]], + [1, ex[1], ey[1], 0, 0, 0], + [0, 0, 0, 1, ex[1], ey[1]], + [1, ex[2], ey[2], 0, 0, 0], + [0, 0, 0, 1, ex[2], ey[2]] + ]) + + A = 0.5*np.linalg.det(np.mat([ + [1, ex[0], ey[0]], + [1, ex[1], ey[1]], + [1, ex[2], ey[2]] + ])) + + B = np.mat([ + [0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, 1, 0, 1, 0] + ])*np.linalg.inv(C) + + if colD > 3: + stress = np.asmatrix(es[np.ix_((0, 1, 3))]) + else: + stress = np.asmatrix(es) + + ef = (A*t*B.T*stress.T).T + + return np.reshape(np.asarray(ef), 6) + + #--------- plane strain -------------------------------------- + + elif ptype == 2: + + C = np.mat([ + [1, ex[0], ey[0], 0, 0, 0], + [0, 0, 0, 1, ex[0], ey[0]], + [1, ex[1], ey[1], 0, 0, 0], + [0, 0, 0, 1, ex[1], ey[1]], + [1, ex[2], ey[2], 0, 0, 0], + [0, 0, 0, 1, ex[2], ey[2]] + ]) + + A = 0.5*np.linalg.det(np.mat([ + [1, ex[0], ey[0]], + [1, ex[1], ey[1]], + [1, ex[2], ey[2]] + ])) + + B = np.mat([ + [0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, 1, 0, 1, 0] + ])*np.linalg.inv(C) + + if colD > 3: + stress = np.asmatrix(es[np.ix_((1, 2, 4))]) + else: + stress = np.asmatrix(es) + + ef = (A*t*B.T*stress.T).T + + return np.reshape(np.asarray(ef), 6) + + else: + info("Error ! Check first argument, ptype=1 or 2 allowed") + return None + + +def platre(ex, ey, ep, D, eq=None): + """ + Calculate the stiffness matrix for a rectangular plate element. + NOTE! Element sides must be parallel to the coordinate axis. + + Parameters: + + ex = [x1,x2,x3,x4] element coordinates + ey = [y1,y2,y3,y4] + + ep = [t] thicknes + + D constitutive matrix for + plane stress + + eq = [qz] load/unit area + Returns: + + Ke element stiffness matrix (12 x 12) + fe equivalent nodal forces (12 x 1) + + """ + Lx = (ex[2]-ex[0]).astype(float) + Ly = (ey[2]-ey[0]).astype(float) + t = ep[0] + + D = t**3/12.*D + + A1 = Ly/(Lx**3) + A2 = Lx/(Ly**3) + A3 = 1/Lx/Ly + A4 = Ly/(Lx**2) + A5 = Lx/(Ly**2) + A6 = 1/Lx + A7 = 1/Ly + A8 = Ly/Lx + A9 = Lx/Ly + + C1 = 4*A1*D[0, 0]+4*A2*D[1, 1]+2*A3*D[0, 1]+5.6*A3*D[2, 2] + C2 = -4*A1*D[0, 0]+2*A2*D[1, 1]-2*A3*D[0, 1]-5.6*A3*D[2, 2] + C3 = 2*A1*D[0, 0]-4*A2*D[1, 1]-2*A3*D[0, 1]-5.6*A3*D[2, 2] + C4 = -2*A1*D[0, 0]-2*A2*D[1, 1]+2*A3*D[0, 1]+5.6*A3*D[2, 2] + C5 = 2*A5*D[1, 1]+A6*D[0, 1]+0.4*A6*D[2, 2] + C6 = 2*A4*D[0, 0]+A7*D[0, 1]+0.4*A7*D[2, 2] + + C7 = 2*A5*D[1, 1]+0.4*A6*D[2, 2] + C8 = 2*A4*D[0, 0]+0.4*A7*D[2, 2] + C9 = A5*D[1, 1]-A6*D[0, 1]-0.4*A6*D[2, 2] + C10 = A4*D[0, 0]-A7*D[0, 1]-0.4*A7*D[2, 2] + C11 = A5*D[1, 1]-0.4*A6*D[2, 2] + C12 = A4*D[0, 0]-0.4*A7*D[2, 2] + + C13 = 4/3.*A9*D[1, 1]+8/15.*A8*D[2, 2] + C14 = 4/3.*A8*D[0, 0]+8/15.*A9*D[2, 2] + C15 = 2/3.*A9*D[1, 1]-8/15.*A8*D[2, 2] + C16 = 2/3.*A8*D[0, 0]-8/15.*A9*D[2, 2] + C17 = 2/3.*A9*D[1, 1]-2/15.*A8*D[2, 2] + C18 = 2/3.*A8*D[0, 0]-2/15.*A9*D[2, 2] + C19 = 1/3.*A9*D[1, 1]+2/15.*A8*D[2, 2] + C20 = 1/3.*A8*D[0, 0]+2/15.*A9*D[2, 2] + C21 = D[0, 1] + + Keq = np.mat(np.zeros((12, 12))) + Keq[0, 0:13] = C1, C5, -C6, C2, C9, -C8, C4, C11, -C12, C3, C7, -C10 + Keq[1, 1:13] = C13, -C21, C9, C15, 0, -C11, C19, 0, -C7, C17, 0 + Keq[2, 2:13] = C14, C8, 0, C18, C12, 0, C20, -C10, 0, C16 + Keq[3, 3:13] = C1, C5, C6, C3, C7, C10, C4, C11, C12 + Keq[4, 4:13] = C13, C21, -C7, C17, 0, -C11, C19, 0 + Keq[5, 5:13] = C14, C10, 0, C16, -C12, 0, C20 + Keq[6, 6:13] = C1, -C5, C6, C2, -C9, C8 + Keq[7, 7:13] = C13, -C21, -C9, C15, 0 + Keq[8, 8:13] = C14, -C8, 0, C18 + Keq[9, 9:13] = C1, -C5, -C6 + Keq[10, 10:13] = C13, C21 + Keq[11, 11] = C14 + Keq = Keq.T+Keq-np.diag(np.diag(Keq)) + + if eq != None: + q = eq + R1 = q*Lx*Ly/4 + R2 = q*Lx*Ly**2/24 + R3 = q*Ly*Lx**2/24 + + feq = np.mat([R1, R2, -R3, R1, R2, R3, R1, -R2, R3, R1, -R2, -R3]) + + if eq != None: + return Keq, feq + else: + return Keq + + +def planqe(ex, ey, ep, D, eq=None): + """ + Calculate the stiffness matrix for a quadrilateral + plane stress or plane strain element. + + Parameters: + ex=[x1 x2 x3 x4] element coordinates + ey=[y1 y2 y3 y4] + + ep = [ptype, t] ptype: analysis type + t: element thickness + + D constitutive matrix + + eq = [bx; bx: body force in x direction + by] by: body force in y direction + + OUTPUT: Ke : element stiffness matrix (8 x 8) + fe : equivalent nodal forces (row array) + """ + K = np.zeros((10, 10)) + f = np.zeros((10, 1)) + + xm = sum(ex)/4. + ym = sum(ey)/4. + + b1 = eq if eq is not None else np.array([[0], [0]]) + + ke1, fe1 = plante(np.array([ex[0], ex[1], xm]), + np.array([ey[0], ey[1], ym]), ep, D, b1) + K, f = assem(np.array([1, 2, 3, 4, 9, 10]), K, ke1, f, fe1) + ke1, fe1 = plante(np.array([ex[1], ex[2], xm]), + np.array([ey[1], ey[2], ym]), ep, D, b1) + K, f = assem(np.array([3, 4, 5, 6, 9, 10]), K, ke1, f, fe1) + ke1, fe1 = plante(np.array([ex[2], ex[3], xm]), + np.array([ey[2], ey[3], ym]), ep, D, b1) + K, f = assem(np.array([5, 6, 7, 8, 9, 10]), K, ke1, f, fe1) + ke1, fe1 = plante(np.array([ex[3], ex[0], xm]), + np.array([ey[3], ey[0], ym]), ep, D, b1) + K, f = assem(np.array([7, 8, 1, 2, 9, 10]), K, ke1, f, fe1) + Ke, fe = statcon(K, f, np.array([[9], [10]])) + + if eq == None: + return Ke + else: + return Ke, fe + + +def planqs(ex, ey, ep, D, ed, eq=None): + """ + Calculate element normal and shear stress for a quadrilateral + plane stress or plane strain element. + + Parameters: + ex = [x1 x2 x3 x4] element coordinates + ey = [y1 y2 y3 y4] + + ep = [ptype, t] ptype: analysis type + t: thickness + + D constitutive matrix + + ed = [u1 u2 ..u8] element displacement vector + + eq = [[bx] bx: body force in x direction + [by]] by: body force in y direction + + OUTPUT: es = [ sigx sigy (sigz) tauxy] element stress array + et = [ epsx epsy (epsz) gamxy] element strain array + """ + + if ex.shape != (4,) or ey.shape != (4,) or ed.shape != (8,): + raise ValueError( + 'Error ! PLANQS: only one element at the time (ex, ey, ed must be a row arrays)') + + K = np.zeros((10, 10)) + f = np.zeros((10, 1)) + + xm = sum(ex)/4. + ym = sum(ey)/4. + + b1 = eq if eq is not None else np.array([[0], [0]]) + + ex1 = np.array([ex[0], ex[1], xm]) + ey1 = np.array([ey[0], ey[1], ym]) + ex2 = np.array([ex[1], ex[2], xm]) + ey2 = np.array([ey[1], ey[2], ym]) + ex3 = np.array([ex[2], ex[3], xm]) + ey3 = np.array([ey[2], ey[3], ym]) + ex4 = np.array([ex[3], ex[0], xm]) + ey4 = np.array([ey[3], ey[0], ym]) + + ke1, fe1 = plante(ex1, ey1, ep, D, b1) + K, f = assem(np.array([1, 2, 3, 4, 9, 10]), K, ke1, f, fe1) + ke1, fe1 = plante(ex2, ey2, ep, D, b1) + K, f = assem(np.array([3, 4, 5, 6, 9, 10]), K, ke1, f, fe1) + ke1, fe1 = plante(ex3, ey3, ep, D, b1) + K, f = assem(np.array([5, 6, 7, 8, 9, 10]), K, ke1, f, fe1) + ke1, fe1 = plante(ex4, ey4, ep, D, b1) + K, f = assem(np.array([7, 8, 1, 2, 9, 10]), K, ke1, f, fe1) + + A1 = 0.5 * \ + np.linalg.det( + np.hstack([np.ones((3, 1)), np.mat(ex1).T, np.mat(ey1).T])) + A2 = 0.5 * \ + np.linalg.det( + np.hstack([np.ones((3, 1)), np.mat(ex2).T, np.mat(ey2).T])) + A3 = 0.5 * \ + np.linalg.det( + np.hstack([np.ones((3, 1)), np.mat(ex3).T, np.mat(ey3).T])) + A4 = 0.5 * \ + np.linalg.det( + np.hstack([np.ones((3, 1)), np.mat(ex4).T, np.mat(ey4).T])) + Atot = A1+A2+A3+A4 + + a, _ = solveq(K, f, np.array(range(1, 9)), ed) + +# ni = ed.shape[0] +# a = np.mat(empty((10,ni))) +# for i in range(ni): +# a[:,i] = solveq(K, f, np.array(range(1,9)), ed[i,:])[0] +# #a = np.hstack([a, solveq(K, f, np.hstack([matrix(range(1,9)).T, ed[i,:].T]) ) ]) + + s1, t1 = plants(ex1, ey1, ep, D, np.hstack([a[[0, 1, 2, 3, 8, 9], :].T])) + s2, t2 = plants(ex2, ey2, ep, D, np.hstack([a[[2, 3, 4, 5, 8, 9], :].T])) + s3, t3 = plants(ex3, ey3, ep, D, np.hstack([a[[4, 5, 6, 7, 8, 9], :].T])) + s4, t4 = plants(ex4, ey4, ep, D, np.hstack([a[[6, 7, 0, 1, 8, 9], :].T])) + + es = (s1*A1+s2*A2+s3*A3+s4*A4)/Atot + et = (t1*A1+t2*A2+t3*A3+t4*A4)/Atot + + # [0] because these are 1-by-3 arrays and we want row arrays out. + return es[0], et[0] + + +def plani4e(ex, ey, ep, D, eq=None): + """ + Calculate the stiffness matrix for a 4 node isoparametric + element in plane strain or plane stress. + + Parameters: + ex = [x1 ... x4] element coordinates. Row array + ey = [y1 ... y4] + + ep =[ptype, t, ir] ptype: analysis type + t : thickness + ir: integration rule + + D constitutive matrix + + eq = [bx; by] bx: body force in x direction + by: body force in y direction + Any array with 2 elements acceptable + + Returns: + Ke : element stiffness matrix (8 x 8) + fe : equivalent nodal forces (8 x 1) + """ + ptype = ep[0] + t = ep[1] + ir = ep[2] + ngp = ir*ir + if eq == None: + q = np.zeros((2, 1)) + else: + q = np.reshape(eq, (2, 1)) +#--------- gauss points -------------------------------------- + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.mat([g1, g1]) + w = np.mat([w1, w1]) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.mat([ + [-g1, -g1], + [g1, -g1], + [-g1, g1], + [g1, g1]]) + w = np.mat([ + [w1, w1], + [w1, w1], + [w1, w1], + [w1, w1]]) + elif ir == 3: + g1 = 0.774596669241483 + g2 = 0. + w1 = 0.555555555555555 + w2 = 0.888888888888888 + gp = np.mat([ + [-g1, -g1], + [-g2, -g1], + [g1, -g1], + [-g1, g2], + [g2, g2], + [g1, g2], + [-g1, g1], + [g2, g1], + [g1, g1]]) + w = np.mat([ + [w1, w1], + [w2, w1], + [w1, w1], + [w1, w2], + [w2, w2], + [w1, w2], + [w1, w1], + [w2, w1], + [w1, w1]]) + else: + info("Used number of integrat ion points not implemented") + wp = np.multiply(w[:, 0], w[:, 1]) + xsi = gp[:, 0] + eta = gp[:, 1] + r2 = ngp*2 + # Shape Functions + N = np.multiply((1-xsi), (1-eta))/4. + N = np.append(N, np.multiply((1+xsi), (1-eta))/4., axis=1) + N = np.append(N, np.multiply((1+xsi), (1+eta))/4., axis=1) + N = np.append(N, np.multiply((1-xsi), (1+eta))/4., axis=1) + + dNr = np.mat(np.zeros((r2, 4))) + dNr[0:r2:2, 0] = -(1-eta)/4. + dNr[0:r2:2, 1] = (1-eta)/4. + dNr[0:r2:2, 2] = (1+eta)/4. + dNr[0:r2:2, 3] = -(1+eta)/4. + dNr[1:r2+1:2, 0] = -(1-xsi)/4. + dNr[1:r2+1:2, 1] = -(1+xsi)/4. + dNr[1:r2+1:2, 2] = (1+xsi)/4. + dNr[1:r2+1:2, 3] = (1-xsi)/4. + +# + Ke1 = np.mat(np.zeros((8, 8))) + fe1 = np.mat(np.zeros((8, 1))) + JT = dNr*np.mat([ex, ey]).T + # --------- plane stress -------------------------------------- + if ptype == 1: + colD = np.shape(D)[0] + if colD > 3: + Cm = np.linalg.inv(D) + Dm = np.linalg.inv(Cm[np.ix_([0, 1, 3], [0, 1, 3])]) + else: + Dm = D +# + B = np.matrix(np.zeros((3, 8))) + N2 = np.matrix(np.zeros((2, 8))) + for i in range(ngp): + indx = np.array([2*(i+1)-1, 2*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobi determinant equal or less than zero!") + JTinv = np.linalg.inv(JT[indx-1, :]) + dNx = JTinv*dNr[indx-1, :] +# + index_array_even = np.array([0, 2, 4, 6]) + index_array_odd = np.array([1, 3, 5, 7]) +# + counter = 0 + for index in index_array_even: + B[0, index] = dNx[0, counter] + B[2, index] = dNx[1, counter] + N2[0, index] = N[i, counter] + counter = counter+1 +# + counter = 0 + for index in index_array_odd: + B[1, index] = dNx[1, counter] + B[2, index] = dNx[0, counter] + N2[1, index] = N[i, counter] + counter = counter+1 +# + Ke1 = Ke1+B.T*Dm*B*detJ*wp[i].item()*t + fe1 = fe1 + N2.T * q * detJ * wp[i].item() * t + + return Ke1, fe1 +#--------- plane strain -------------------------------------- + elif ptype == 2: + # + colD = np.shape(D)[0] + if colD > 3: + Dm = D[np.ix_([0, 1, 3], [0, 1, 3])] + else: + Dm = D +# + B = np.matrix(np.zeros((3, 8))) + N2 = np.matrix(np.zeros((2, 8))) + for i in range(ngp): + indx = np.array([2*(i+1)-1, 2*(i+1)]) + detJ = np.linalg.det(JT[indx-1, :]) + if detJ < 10*np.finfo(float).eps: + info("Jacobideterminant equal or less than zero!") + JTinv = np.linalg.inv(JT[indx-1, :]) + dNx = JTinv*dNr[indx-1, :] +# + index_array_even = np.array([0, 2, 4, 6]) + index_array_odd = np.array([1, 3, 5, 7]) +# + counter = 0 + for index in index_array_even: + # + B[0, index] = dNx[0, counter] + B[2, index] = dNx[1, counter] + N2[0, index] = N[i, counter] +# + counter = counter+1 +# + counter = 0 + for index in index_array_odd: + B[1, index] = dNx[1, counter] + B[2, index] = dNx[0, counter] + N2[1, index] = N[i, counter] + counter = counter+1 +# + Ke1 = Ke1 + B.T * Dm * B * detJ * np.asscalar(wp[i]) * t + fe1 = fe1+N2.T*q*detJ*np.asscalar(wp[i])*t + return Ke1, fe1 + else: + info("Error ! Check first argument, ptype=1 or 2 allowed") + + +def soli8e(ex, ey, ez, ep, D, eqp=None): + """ + Ke=soli8e(ex,ey,ez,ep,D) + [Ke,fe]=soli8e(ex,ey,ez,ep,D,eq) + ------------------------------------------------------------- + PURPOSE + Calculate the stiffness matrix for a 8 node (brick) + isoparametric element. + + INPUT: ex = [x1 x2 x3 ... x8] + ey = [y1 y2 y3 ... y8] element coordinates + ez = [z1 z2 z3 ... z8] + + ep = [ir] ir integration rule + + D constitutive matrix + + eq = [bx; by; bz] bx: body force in x direction + by: body force in y direction + bz: body force in z direction + + OUTPUT: Ke : element stiffness matrix + fe : equivalent nodal forces + ------------------------------------------------------------- + + LAST MODIFIED: M Ristinmaa 1995-10-25 + J Lindemann 2022-01-24 (Python version) + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + ir = ep[0] + ngp = ir*ir*ir + + if eqp == None: + eq = np.zeros((3, 1)) + else: + eq = eqp + + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.array([g1, g1, g1]).reshape(1, 3) + w = np.array([w1, w1, w1]).reshape(1, 3) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.zeros((8, 3)) + w = np.zeros((8, 3)) + gp[:, 0] = np.array([-1, 1, 1, -1, -1, 1, 1, -1])*g1 + w[:, 0] = np.array([1, 1, 1, 1, 1, 1, 1, 1])*w1 + gp[:, 1] = np.array([-1, -1, 1, 1, -1, -1, 1, 1])*g1 + w[:, 1] = np.array([1, 1, 1, 1, 1, 1, 1, 1])*w1 + gp[:, 2] = np.array([-1, -1, -1, -1, 1, 1, 1, 1])*g1 + w[:, 2] = np.array([1, 1, 1, 1, 1, 1, 1, 1])*w1 + else: + g1 = 0.774596669241483, + g2 = 0.0 + w1 = 0.555555555555555 + w2 = 0.888888888888888 + + gp = np.zeros((27, 3)) + w = np.zeros((27, 3)) + + I1 = np.array([-1, 0, 1, -1, 0, 1, -1, 0, 1]).reshape(1, 9) + I2 = np.array([0, -1, 0, 0, 1, 0, 0, 1, 0]).reshape(1, 9) + + gp[:, 0] = np.concatenate((I1, I1, I1), axis=1)*g1 + gp[:, 0] = np.concatenate((I2, I2, I2), axis=1)*g2 + gp[:, 0] + + I1 = np.abs(I1) + I2 = np.abs(I2) + + w[:, 0] = np.concatenate((I1, I1, I1), axis=1)*w1 + w[:, 0] = np.concatenate((I2, I2, I2), axis=1)*w2 + w[:, 0] + + I1 = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1]).reshape(1, 9) + I2 = np.array([0, 0, 0, 1, 1, 1, 0, 0, 0]).reshape(1, 9) + + gp[:, 1] = np.concatenate((I1, I1, I1), axis=1)*g1 + gp[:, 1] = np.concatenate((I2, I2, I2), axis=1)*g2 + gp[:, 1] + + I1 = np.abs(I1) + I2 = np.abs(I2) + + w[:, 1] = np.concatenate((I1, I1, I1), axis=1)*w1 + w[:, 1] = np.concatenate((I2, I2, I2), axis=1)*w2 + w[:, 1] + + I1 = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1]).reshape(1, 9) + I2 = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]).reshape(1, 9) + I3 = np.abs(I1) + + gp[:, 2] = np.concatenate((I1, I2, I3), axis=1)*g1 + gp[:, 2] = np.concatenate((I2, I3, I2), axis=1)*g2 + gp[:, 2] + + w[:, 2] = np.concatenate((I3, I2, I3), axis=1)*w1 + w[:, 2] = np.concatenate((I2, I3, I2), axis=1)*w2 + w[:, 2] + + wp = w[:, 0]*w[:, 1]*w[:, 2] + + xsi = gp[:, 0] + eta = gp[:, 1] + zet = gp[:, 2] + r2 = ngp*3 + + N = np.zeros((ngp, 8)) + dNr = np.zeros((r2, 8)) + + N[:, 0] = (1-xsi)*(1-eta)*(1-zet)/8 + N[:, 1] = (1+xsi)*(1-eta)*(1-zet)/8 + N[:, 2] = (1+xsi)*(1+eta)*(1-zet)/8 + N[:, 3] = (1-xsi)*(1+eta)*(1-zet)/8 + N[:, 4] = (1-xsi)*(1-eta)*(1+zet)/8 + N[:, 5] = (1+xsi)*(1-eta)*(1+zet)/8 + N[:, 6] = (1+xsi)*(1+eta)*(1+zet)/8 + N[:, 7] = (1-xsi)*(1+eta)*(1+zet)/8 + + dNr[0:r2+1:3, 0] = -(1-eta)*(1-zet) + dNr[0:r2+1:3, 1] = (1-eta)*(1-zet) + dNr[0:r2+1:3, 2] = (1+eta)*(1-zet) + dNr[0:r2+1:3, 3] = -(1+eta)*(1-zet) + dNr[0:r2+1:3, 4] = -(1-eta)*(1+zet) + dNr[0:r2+1:3, 5] = (1-eta)*(1+zet) + dNr[0:r2+1:3, 6] = (1+eta)*(1+zet) + dNr[0:r2+1:3, 7] = -(1+eta)*(1+zet) + dNr[1:r2+2:3, 0] = -(1-xsi)*(1-zet) + dNr[1:r2+2:3, 1] = -(1+xsi)*(1-zet) + dNr[1:r2+2:3, 2] = (1+xsi)*(1-zet) + dNr[1:r2+2:3, 3] = (1-xsi)*(1-zet) + dNr[1:r2+2:3, 4] = -(1-xsi)*(1+zet) + dNr[1:r2+2:3, 5] = -(1+xsi)*(1+zet) + dNr[1:r2+2:3, 6] = (1+xsi)*(1+zet) + dNr[1:r2+2:3, 7] = (1-xsi)*(1+zet) + dNr[2:r2+3:3, 0] = -(1-xsi)*(1-eta) + dNr[2:r2+3:3, 1] = -(1+xsi)*(1-eta) + dNr[2:r2+3:3, 2] = -(1+xsi)*(1+eta) + dNr[2:r2+3:3, 3] = -(1-xsi)*(1+eta) + dNr[2:r2+3:3, 4] = (1-xsi)*(1-eta) + dNr[2:r2+3:3, 5] = (1+xsi)*(1-eta) + dNr[2:r2+3:3, 6] = (1+xsi)*(1+eta) + dNr[2:r2+3:3, 7] = (1-xsi)*(1+eta) + + dNr = dNr/8.0 + + Ke = np.zeros((24, 24)) + fe = np.zeros((24, 1)) + + ex = np.asarray(ex).reshape((8, 1)) + ey = np.asarray(ey).reshape((8, 1)) + ez = np.asarray(ez).reshape((8, 1)) + + JT = dNr@np.concatenate((ex, ey, ez), axis=1) + + eps = np.finfo(float).eps + + for i in range(ngp): + indx = [i*3, i*3+1, i*3+2] + detJ = np.linalg.det(JT[indx, :]) + if detJ < 10*eps: + print('Jacobideterminant equal or less than zero!') + JTinv = np.linalg.inv(JT[indx, :]) + dNx = JTinv@dNr[indx, :] + + B = np.zeros((6, 24)) + N2 = np.zeros((3, 24)) + + B[0, 0:24:3] = dNx[0, :] + B[1, 1:25:3] = dNx[1, :] + B[2, 2:26:3] = dNx[2, :] + B[3, 0:24:3] = dNx[1, :] + B[3, 1:25:3] = dNx[0, :] + B[4, 0:24:3] = dNx[2, :] + B[4, 2:26:3] = dNx[0, :] + B[5, 1:25:3] = dNx[2, :] + B[5, 2:26:3] = dNx[1, :] + + N2[0, 0:24:3] = N[i, :] + N2[1, 1:25:3] = N[i, :] + N2[2, 2:26:3] = N[i, :] + + Ke = Ke + (np.transpose(B)@D@B)*detJ*wp[i] + fe = fe + (np.transpose(N2)@eq)*detJ*wp[i] + + if eqp != None: + return Ke, fe + else: + return Ke + + +def soli8s(ex, ey, ez, ep, D, ed): + """ + [es,et]=soli8s(ex,ey,ez,ep,D,ed) + ------------------------------------------------------------- + PURPOSE + Calculate element normal and shear stress for a + 8 node (brick) isoparametric element. + + INPUT: ex = [x1 x2 x3 ... x8] + ey = [y1 y2 y3 ... y8] element coordinates + ez = [z1 z2 z3 ... z8] + + ep = [Ir] Ir: integration rule + + D constitutive matrix + + ed = [u1 u2 ..u24] element displacement vector + + OUTPUT: es = [ sigx sigy sigz sigxy sigyz sigxz ; + ...... ... ] + element stress matrix, one row for each + integration point + + es = [ eps epsy epsz epsxy epsyz epsxz ; + ...... ... ] + element strain matrix, one row for each + integration point + ------------------------------------------------------------- + + LAST MODIFIED: M Ristinmaa 1995-10-25 + J Lindemann 2022-02-23 (Python version) + + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + + ir = ep[0] + ngp = ir*ir*ir + + ir = ep[0] + ngp = ir*ir*ir + + if ir == 1: + g1 = 0.0 + w1 = 2.0 + gp = np.array([g1, g1, g1]).reshape(1, 3) + w = np.array([w1, w1, w1]).reshape(1, 3) + elif ir == 2: + g1 = 0.577350269189626 + w1 = 1 + gp = np.zeros((8, 3)) + w = np.zeros((8, 3)) + gp[:, 0] = np.array([-1, 1, 1, -1, -1, 1, 1, -1])*g1 + w[:, 0] = np.array([1, 1, 1, 1, 1, 1, 1, 1])*w1 + gp[:, 1] = np.array([-1, -1, 1, 1, -1, -1, 1, 1])*g1 + w[:, 1] = np.array([1, 1, 1, 1, 1, 1, 1, 1])*w1 + gp[:, 2] = np.array([-1, -1, -1, -1, 1, 1, 1, 1])*g1 + w[:, 2] = np.array([1, 1, 1, 1, 1, 1, 1, 1])*w1 + else: + g1 = 0.774596669241483, + g2 = 0.0 + w1 = 0.555555555555555 + w2 = 0.888888888888888 + + gp = np.zeros((27, 3)) + w = np.zeros((27, 3)) + + I1 = np.array([-1, 0, 1, -1, 0, 1, -1, 0, 1]).reshape(1, 9) + I2 = np.array([0, -1, 0, 0, 1, 0, 0, 1, 0]).reshape(1, 9) + + gp[:, 0] = np.concatenate((I1, I1, I1), axis=1)*g1 + gp[:, 0] = np.concatenate((I2, I2, I2), axis=1)*g2 + gp[:, 0] + + I1 = np.abs(I1) + I2 = np.abs(I2) + + w[:, 0] = np.concatenate((I1, I1, I1), axis=1)*w1 + w[:, 0] = np.concatenate((I2, I2, I2), axis=1)*w2 + w[:, 0] + + I1 = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1]).reshape(1, 9) + I2 = np.array([0, 0, 0, 1, 1, 1, 0, 0, 0]).reshape(1, 9) + + gp[:, 1] = np.concatenate((I1, I1, I1), axis=1)*g1 + gp[:, 1] = np.concatenate((I2, I2, I2), axis=1)*g2 + gp[:, 1] + + I1 = np.abs(I1) + I2 = np.abs(I2) + + w[:, 1] = np.concatenate((I1, I1, I1), axis=1)*w1 + w[:, 1] = np.concatenate((I2, I2, I2), axis=1)*w2 + w[:, 1] + + I1 = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1]).reshape(1, 9) + I2 = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]).reshape(1, 9) + I3 = np.abs(I1) + + gp[:, 2] = np.concatenate((I1, I2, I3), axis=1)*g1 + gp[:, 2] = np.concatenate((I2, I3, I2), axis=1)*g2 + gp[:, 2] + + w[:, 2] = np.concatenate((I3, I2, I3), axis=1)*w1 + w[:, 2] = np.concatenate((I2, I3, I2), axis=1)*w2 + w[:, 2] + + wp = w[:, 0]*w[:, 1]*w[:, 2] + + xsi = gp[:, 0] + eta = gp[:, 1] + zet = gp[:, 2] + r2 = ngp*3 + + N = np.zeros((ngp, 8)) + dNr = np.zeros((r2, 8)) + + N[:, 0] = (1-xsi)*(1-eta)*(1-zet)/8 + N[:, 1] = (1+xsi)*(1-eta)*(1-zet)/8 + N[:, 2] = (1+xsi)*(1+eta)*(1-zet)/8 + N[:, 3] = (1-xsi)*(1+eta)*(1-zet)/8 + N[:, 4] = (1-xsi)*(1-eta)*(1+zet)/8 + N[:, 5] = (1+xsi)*(1-eta)*(1+zet)/8 + N[:, 6] = (1+xsi)*(1+eta)*(1+zet)/8 + N[:, 7] = (1-xsi)*(1+eta)*(1+zet)/8 + + dNr[0:r2+1:3, 0] = -(1-eta)*(1-zet) + dNr[0:r2+1:3, 1] = (1-eta)*(1-zet) + dNr[0:r2+1:3, 2] = (1+eta)*(1-zet) + dNr[0:r2+1:3, 3] = -(1+eta)*(1-zet) + dNr[0:r2+1:3, 4] = -(1-eta)*(1+zet) + dNr[0:r2+1:3, 5] = (1-eta)*(1+zet) + dNr[0:r2+1:3, 6] = (1+eta)*(1+zet) + dNr[0:r2+1:3, 7] = -(1+eta)*(1+zet) + dNr[1:r2+2:3, 0] = -(1-xsi)*(1-zet) + dNr[1:r2+2:3, 1] = -(1+xsi)*(1-zet) + dNr[1:r2+2:3, 2] = (1+xsi)*(1-zet) + dNr[1:r2+2:3, 3] = (1-xsi)*(1-zet) + dNr[1:r2+2:3, 4] = -(1-xsi)*(1+zet) + dNr[1:r2+2:3, 5] = -(1+xsi)*(1+zet) + dNr[1:r2+2:3, 6] = (1+xsi)*(1+zet) + dNr[1:r2+2:3, 7] = (1-xsi)*(1+zet) + dNr[2:r2+3:3, 0] = -(1-xsi)*(1-eta) + dNr[2:r2+3:3, 1] = -(1+xsi)*(1-eta) + dNr[2:r2+3:3, 2] = -(1+xsi)*(1+eta) + dNr[2:r2+3:3, 3] = -(1-xsi)*(1+eta) + dNr[2:r2+3:3, 4] = (1-xsi)*(1-eta) + dNr[2:r2+3:3, 5] = (1+xsi)*(1-eta) + dNr[2:r2+3:3, 6] = (1+xsi)*(1+eta) + dNr[2:r2+3:3, 7] = (1-xsi)*(1+eta) + + dNr = dNr/8.0 + + ex = np.asarray(ex).reshape((8, 1)) + ey = np.asarray(ey).reshape((8, 1)) + ez = np.asarray(ez).reshape((8, 1)) + + JT = dNr@np.concatenate((ex, ey, ez), axis=1) + + eps = np.finfo(float).eps + + eci = N@np.concatenate((ex, ey, ez), axis=1) + et = np.zeros((ngp, 6)) + es = np.zeros((ngp, 6)) + + ed = ed.reshape(1, 24) + + for i in range(ngp): + indx = [i*3, i*3+1, i*3+2] + detJ = np.linalg.det(JT[indx, :]) + if detJ < 10*eps: + print('Jacobideterminant equal or less than zero!') + JTinv = np.linalg.inv(JT[indx, :]) + dNx = JTinv@dNr[indx, :] + + B = np.zeros((6, 24)) + N2 = np.zeros((3, 24)) + + B[0, 0:24:3] = dNx[0, :] + B[1, 1:25:3] = dNx[1, :] + B[2, 2:26:3] = dNx[2, :] + B[3, 0:24:3] = dNx[1, :] + B[3, 1:25:3] = dNx[0, :] + B[4, 0:24:3] = dNx[2, :] + B[4, 2:26:3] = dNx[0, :] + B[5, 1:25:3] = dNx[2, :] + B[5, 2:26:3] = dNx[1, :] + + N2[0, 0:24:3] = N[i, :] + N2[1, 1:25:3] = N[i, :] + N2[2, 2:26:3] = N[i, :] + + # [6x24] x [24,1] + ee = B@np.transpose(ed) + + et[i, :] = ee.reshape(6,) + es[i, :] = (D@ee).reshape(6,) + + return et, es, eci + + +def assem(edof, K, Ke, f=None, fe=None): + """ + Assemble element matrices Ke ( and fe ) into the global + stiffness matrix K ( and the global force vector f ) + according to the topology matrix edof. + + Parameters: + + edof dof topology array + K the global stiffness matrix + Ke element stiffness matrix + f the global force vector + fe element force vector + + Output parameters: + + K the new global stiffness matrix + f the new global force vector + fe element force vector + + """ + + if edof.ndim == 1: + idx = edof-1 + K[np.ix_(idx, idx)] = K[np.ix_(idx, idx)] + Ke + if (not f is None) and (not fe is None): + f[np.ix_(idx)] = f[np.ix_(idx)] + fe + else: + for row in edof: + idx = row-1 + K[np.ix_(idx, idx)] = K[np.ix_(idx, idx)] + Ke + if (not f is None) and (not fe is None): + f[np.ix_(idx)] = f[np.ix_(idx)] + fe + + if f is None: + return K + else: + return K, f + + +def solveq(K, f, bcPrescr, bcVal=None): + """ + Solve static FE-equations considering boundary conditions. + + Parameters: + + K global stiffness matrix, dim(K)= nd x nd + f global load vector, dim(f)= nd x 1 + + bcPrescr 1-dim integer array containing prescribed dofs. + bcVal 1-dim float array containing prescribed values. + If not given all prescribed dofs are assumed 0. + + Returns: + + a solution including boundary values + Q reaction force vector + dim(a)=dim(Q)= nd x 1, nd : number of dof's + + """ + + nDofs = K.shape[0] + nPdofs = bcPrescr.shape[0] + + if bcVal is None: + bcVal = np.zeros([nPdofs], 'd') + + bc = np.ones(nDofs, 'bool') + bcDofs = np.arange(nDofs) + + bc[np.ix_(bcPrescr-1)] = False + bcDofs = bcDofs[bc] + + fsys = f[bcDofs]-K[np.ix_((bcDofs), (bcPrescr-1))] * \ + np.asmatrix(bcVal).reshape(nPdofs, 1) + asys = np.linalg.solve(K[np.ix_((bcDofs), (bcDofs))], fsys) + + a = np.zeros([nDofs, 1]) + a[np.ix_(bcPrescr-1)] = np.asmatrix(bcVal).reshape(nPdofs, 1) + a[np.ix_(bcDofs)] = asys + + Q = K*np.asmatrix(a)-f + + return (np.asmatrix(a), Q) + + +def spsolveq(K, f, bcPrescr, bcVal=None): + """ + Solve static FE-equations considering boundary conditions. + + Parameters: + + K global stiffness matrix, dim(K)= nd x nd + f global load vector, dim(f)= nd x 1 + + bcPrescr 1-dim integer array containing prescribed dofs. + bcVal 1-dim float array containing prescribed values. + If not given all prescribed dofs are assumed 0. + + Returns: + + a solution including boundary values + Q reaction force vector + dim(a)=dim(Q)= nd x 1, nd : number of dof's + + """ + + nDofs = K.shape[0] + nPdofs = bcPrescr.shape[0] + + if bcVal is None: + bcVal = np.zeros([nPdofs], 'd') + + bc = np.ones(nDofs, 'bool') + bcDofs = np.arange(nDofs) + + bc[np.ix_(bcPrescr-1)] = False + bcDofs = bcDofs[bc] + + bcVal_m = np.asmatrix(bcVal).reshape(nPdofs, 1) + + info("Preparing system matrix...") + + mask = np.ones(K.shape[0], dtype=bool) + mask[bcDofs] = False + + info("step 1... converting K->CSR") + Kcsr = K.asformat("csr") + info("step 2... Kt") + #Kt1 = K[bcDofs] + #Kt = Kt1[:,bcPrescr] + Kt = K[np.ix_((bcDofs), (bcPrescr-1))] + info("step 3... fsys") + fsys = f[bcDofs]-Kt*bcVal_m + info("step 4... Ksys") + Ksys1 = Kcsr[bcDofs] + Ksys = Ksys1[:, bcDofs] + #Ksys = Kcsr[np.ix_((bcDofs),(bcDofs))] + info("done...") + + info("Solving system...") + asys = dsolve.spsolve(Ksys, fsys) + + info("Reconstructing full a...") + a = np.zeros([nDofs, 1]) + a[np.ix_(bcPrescr-1)] = bcVal_m + a[np.ix_(bcDofs)] = np.asmatrix(asys).transpose() + + a_m = np.asmatrix(a) + Q = K*a_m-f + info("done...") + return (a_m, Q) + + +def eigen(K,M,b=None): + """ + Solve the generalized eigenvalue problem + |K-LM|X = 0, considering boundary conditions + + Parameters: + + K global stiffness matrix, dim(K) = ndof x ndof + M global mass matrix, dim(M) = ndof x ndof + b boundary condition vector, dim(b) = nbc x 1 + + Returns: + + L eigenvalue vector, dim(L) = (ndof-nbc) x 1 + X eigenvectors, dim(X) = ndof x (ndof-nbc) + """ + nd, _ = K.shape + if b is not None: + fdof = np.setdiff1d(np.arange(nd), b-1) + D, X1 = eig(K[np.ix_(fdof,fdof)], M[np.ix_(fdof,fdof)]) + D = np.real(D) + nfdof, _ = X1.shape + for j in range(nfdof): + mnorm = np.sqrt(X1[:,j].T@M[np.ix_(fdof,fdof)]@X1[:,j]) + X1[:,j] /= mnorm + s_order = np.argsort(D) + L = np.sort(D) + X2 = np.zeros(X1.shape) + for ind,j in enumerate(s_order): + X2[:,ind] = X1[:,j] + X = np.zeros((nd,nfdof)) + X[fdof,:] = X2 + return L, X + else: + D, X1 = eig(K, M) + D = np.real(D) + for j in range(nd): + mnorm = np.sqrt(X1[:,j].T@M@X1[:,j]) + X1[:,j] /= mnorm + s_order = np.argsort(D) + L = np.sort(D) + X = np.copy(X1) + for ind,j in enumerate(s_order): + X[:,ind] = X1[:,j] + return L, X + + +def gfunc(G,dt): + """ + Form vector with function values at equally spaced + points by linear interpolation + + Parameters: + + G = [t_i, g_i] t_i: time i, g_i: g(t_i) + dim(G) = np x 2, np = number of points + dt time step + + Returns: + + t 1-D vector with equally spaced time points + g 1-D vector with corresponding function values + """ + ti = np.arange(G[0,0],G[-1,0]+dt,dt) + g1 = np.interp(ti,G[:,0],G[:,1]) + return ti, g1 + + +def step1(K,C,f,a0,bc,ip,times,dofs): + """ + Algorithm for dynamic solution of first-order + FE equations considering boundary conditions. + + Parameters: + + K conductivity matrix, dim(K) = ndof x ndof + C capacity matrix, dim(C) = ndof x ndof + f load vector, dim(f) = ndof x (nstep + 1), + If dim(f) = ndof x 1, the values are kept constant + during time integration + a0 initial vector a(0), dim(a0) = ndof x 1 + bc boundary condition matrix, dim(bc) = nbc x (nstep + 2) + where nbc = number of prescribed degrees of freedom (either constant or time-dependent) + The first column contains the numbers of the prescribed degrees of freedom + and the subsequent columns contain the time history. + If dim(bc) = nbc x 2, the values from the second column are kept constant + during time integration + ip array [dt, tottime, alpha], where + dt is the size of the time increment, + tottime is the total time, + alpha is time integration constant. + Frequently used values of alpha are: + alpha=0: forward difference; forward Euler, + alpha=1/2: trapezoidal rule; Crank-Nicholson + alpha=1: backward difference; backward Euler + times array [t(i) ...] of times at which output should be written to a and da + dofs array [dof(i) ...] of degree of freedom numbers for which history output + should be written to ahist and dahist + + Returns: + + modelhist dictionary containing solution history for the whole model at following keys: + modelhist['a'] constains values of a at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['a']) = ndof x (nstep + 1) or ndof x ntimes + modelhist['da'] constains values of da at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['da']) = ndof x (nstep + 1) or ndof x ntimes + dofhist dictionary containing solution history for the degrees of freedom selected in 'dofs': + dofhist['a'] constains time history of a at the dofs specified in 'dofs' + dim(dofhist['ahist']) = ndof x (nstep + 1) + dofhist['da'] constains time history of daat the dofs specified in 'dofs' + dim(dofhist['dahist']) = ndof x (nstep + 1) + """ + ndof, _ = K.shape + dt, tottime, alpha = ip + a1 = (1-alpha)*dt + a2 = alpha*dt + + nstep = 1 + if np.array(f).any(): + _, ncf = f.shape + if ncf>1: + nstep = ncf-1 + + if np.array(bc).any(): + _, ncb = bc.shape + if ncb>2: + nstep = ncb-2 + bound = 1 + if not np.array(bc).any(): + bound = 0 + + ns = int(tottime/dt) + if (ns < nstep or nstep==1): + nstep=ns + + tf = np.zeros((ndof,nstep+1)) + if np.array(f).any(): + if ncf==1: + tf = f[:,0].reshape(-1,1)@np.ones((1,nstep+1)) + if ncf>1: + tf = np.copy(f) + + modelhist = {} + sa=0 + if not np.array(times).any(): + ntimes=0 + sa=1 + modelhist['a'] = np.zeros((ndof,nstep+1)) + modelhist['da'] = np.zeros((ndof,nstep+1)) + else: + ntimes = len(times) + if ntimes: + sa=2 + modelhist['a'] = np.zeros((ndof,ntimes)) + modelhist['da'] = np.zeros((ndof,ntimes)) + + dofhist = {} + if np.array(dofs).all(): + ndofs = len(dofs) + if ndofs: + dofhist['a'] = np.zeros((ndofs,nstep+1)) + dofhist['da'] = np.zeros((ndofs,nstep+1)) + else: + ndofs=0 + + itime = 0 + + # Calculate initial second time derivative d2a0 + da0 = np.linalg.solve(C,tf[:,0].reshape(-1,1) - K@a0) + # Save initial values + if sa==1: + modelhist['a'][:,0] = a0.ravel() + modelhist['da'][:,0] = da0.ravel() + elif sa==2: + if times[itime]==0: + modelhist['a'][:,itime] = a0.ravel() + modelhist['da'][:,itime] = da0.ravel() + itime += 1 + + if ndofs: + dofhist['a'][:,0] = a0[np.ix_(dofs-1)].ravel() + dofhist['da'][:,0] = da0[np.ix_(dofs-1)].ravel() + + # Reduce matrices due to bcs + tempa = np.zeros((ndof,1)) + tempda = np.zeros((ndof,1)) + fdof=np.arange(1,ndof+1).astype(int) + if bound: + nrb, ncb = bc.shape + if ncb==2: + pa = bc[:,1].reshape(-1,1)@np.ones((1,nstep+1)) + pda = np.zeros((nrb,nstep+1)) + elif ncb>2: + pa = np.copy(bc[:,1:]) + pda1 = (pa[:,1]-pa[:,0])/dt + pdarest = (pa[:,1:] - pa[:,0:-1])/dt + pda = np.hstack((pda1.reshape(-1,1),pdarest)) + pdof = np.copy(bc[:,0]).astype(int) + fdof = np.setdiff1d(fdof,pdof).astype(int) - 1 + pdof -= 1 #adjusting for indexing starting from 0 + Keff = C[np.ix_(fdof,fdof)] + a2*K[np.ix_(fdof,fdof)] + else: + fdof -= 1 #adjusting for indexing starting from 0 + Keff = C + a2*K + + L, U = lu(Keff,permute_l=True) + anew = a0[np.ix_(fdof)] + danew = da0[np.ix_(fdof)] + + # Iterate over time steps + for j in range(1,nstep+1): + time = dt*j + aold = np.copy(anew) + daold = np.copy(danew) + apred = aold + a1*daold + if not bound: + reff = tf[:,j].reshape(-1,1) - K@apred + else: + pdeff = C[np.ix_(fdof,pdof)]@pda[:,j].reshape(-1,1) + K[np.ix_(fdof,pdof)]@pa[:,j].reshape(-1,1) + reff = tf[np.ix_(fdof),j].reshape(-1,1) - K[np.ix_(fdof,fdof)]@apred - pdeff + y = np.linalg.solve(L,reff) + danew = np.linalg.solve(U,y) + anew = apred + a2*danew + # Save to modelhist and dofhist + if bound: + tempa[np.ix_(pdof)] = pa[:,j].reshape(-1,1) + tempda[np.ix_(pdof)] = pda[:,j].reshape(-1,1) + tempa[np.ix_(fdof)] = anew + tempda[np.ix_(fdof)] = danew + if sa==1: + modelhist['a'][:,j] = tempa.ravel() + modelhist['da'][:,j] = tempda.ravel() + elif sa==2: + if ntimes and itime < ntimes: + if time >= times[itime]: + modelhist['a'][:,itime] = tempa.ravel() + modelhist['da'][:,itime] = tempda.ravel() + itime += 1 + if ndofs: + dofhist['a'][:,j] = tempa[np.ix_(dofs-1)].ravel() + dofhist['da'][:,j] = tempda[np.ix_(dofs-1)].ravel() + + return modelhist, dofhist + + +def step2(K,C,M,f,a0,da0,bc,ip,times,dofs): + """ + Algorithm for dynamic solution of second-order + FE equations considering boundary conditions. + + Parameters: + + K global stiffness matrix, dim(K) = ndof x ndof + C global damping matrix, dim(C) = ndof x ndof + If there is no damping in the system, simply set C=[] + M global mass matrix, dim(M) = ndof x ndof + f global load vector, dim(f) = ndof x (nstep + 1), + If dim(f) = ndof x 1, the values are kept constant + during time integration + a0 initial displacement vector a(0), dim(a0) = ndof x 1 + da0 initial velocity vector v(0), dim(da0) = ndof x 1 + bc boundary condition matrix, dim(bc) = nbc x (nstep + 2) + where nbc = number of prescribed degrees of freedom (either constant or time-dependent) + The first column contains the numbers of the prescribed degrees of freedom + and the subsequent columns contain the time history. + If dim(bc) = nbc x 2, the values from the second column are kept constant + during time integration + ip array [dt, tottime, alpha, delta], where + dt is the size of the time increment, + tottime is the total time, + alpha and delta are time integration constants for the Newmark family of methods. + Frequently used values of alpha and delta are: + alpha=1/4, delta=1/2: average acceleration (trapezoidal) rule, + alpha=1/6, delta=1/2: linear acceleration + alpha=0, delta=1/2: central difference + times array [t(i) ...] of times at which output should be written to a, da and d2a + dofs array [dof(i) ...] of degree of freedom numbers for which history output + should be written to ahist, dahist and d2ahist + + Returns: + + modelhist dictionary containing solution history for the whole model at following keys: + modelhist['a'] constains displacement values at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['a']) = ndof x (nstep + 1) or ndof x ntimes + modelhist['da'] constains velocity values at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['da']) = ndof x (nstep + 1) or ndof x ntimes + modelhist['d2a'] constains acceleration values at all timesteps, + alternatively at times specified in 'times' + dim(modelhist['d2a']) = ndof x (nstep + 1) or ndof x ntimes + dofhist dictionary containing solution history for the degrees of freedom selected in 'dofs': + dofhist['a'] constains displacement time history at the dofs specified in 'dofs' + dim(dofhist['ahist']) = ndof x (nstep + 1) + dofhist['da'] constains velocity time history at the dofs specified in 'dofs' + dim(dofhist['dahist']) = ndof x (nstep + 1) + dofhist['d2a'] constains acceleration time history at the dofs specified in 'dofs' + dim(dofhist['d2ahist']) = ndof x (nstep + 1) + """ + ndof, _ = K.shape + if not np.array(C).any(): + C = np.zeros((ndof,ndof)) + dt, tottime, alpha, delta = ip + b1 = dt*dt*0.5*(1-2*alpha) + b2 = (1-delta)*dt + b3 = delta*dt + b4 = alpha*dt*dt + + nstep = 1 + if np.array(f).any(): + _, ncf = f.shape + if ncf>1: + nstep = ncf-1 + + if np.array(bc).any(): + _, ncb = bc.shape + if ncb>2: + nstep = ncb-2 + bound = 1 + if not np.array(bc).any(): + bound = 0 + + ns = int(tottime/dt) + if (ns < nstep or nstep==1): + nstep=ns + + tf = np.zeros((ndof,nstep+1)) + if np.array(f).any(): + if ncf==1: + tf = f[:,0].reshape(-1,1)@np.ones((1,nstep+1)) + if ncf>1: + tf = np.copy(f) + + modelhist = {} + sa=0 + if not np.array(times).any(): + ntimes=0 + sa=1 + modelhist['a'] = np.zeros((ndof,nstep+1)) + modelhist['da'] = np.zeros((ndof,nstep+1)) + modelhist['d2a'] = np.zeros((ndof,nstep+1)) + else: + ntimes = len(times) + if ntimes: + sa=2 + modelhist['a'] = np.zeros((ndof,ntimes)) + modelhist['da'] = np.zeros((ndof,ntimes)) + modelhist['d2a'] = np.zeros((ndof,ntimes)) + + dofhist = {} + if np.array(dofs).all(): + ndofs = len(dofs) + if ndofs: + dofhist['a'] = np.zeros((ndofs,nstep+1)) + dofhist['da'] = np.zeros((ndofs,nstep+1)) + dofhist['d2a'] = np.zeros((ndofs,nstep+1)) + else: + ndofs=0 + + itime = 0 + + # Calculate initial second time derivative d2a0 + d2a0 = np.linalg.solve(M,tf[:,0].reshape(-1,1) - C@da0 - K@a0) + # Save initial values + if sa==1: + modelhist['a'][:,0] = a0.ravel() + modelhist['da'][:,0] = da0.ravel() + modelhist['d2a'][:,0] = d2a0.ravel() + elif sa==2: + if times[itime]==0: + modelhist['a'][:,itime] = a0.ravel() + modelhist['da'][:,itime] = da0.ravel() + modelhist['d2a'][:,itime] = d2a0.ravel() + itime += 1 + + if ndofs: + dofhist['a'][:,0] = a0[np.ix_(dofs-1)].ravel() + dofhist['da'][:,0] = da0[np.ix_(dofs-1)].ravel() + dofhist['d2a'][:,0] = d2a0[np.ix_(dofs-1)].ravel() + + # Reduce matrices due to bcs + tempa = np.zeros((ndof,1)) + tempda = np.zeros((ndof,1)) + tempd2a = np.zeros((ndof,1)) + fdof=np.arange(1,ndof+1).astype(int) + if bound: + nrb, ncb = bc.shape + if ncb==2: + pa = bc[:,1].reshape(-1,1)@np.ones((1,nstep+1)) + pda = np.zeros((nrb,nstep+1)) + elif ncb>2: + pa = np.copy(bc[:,1:]) + pda1 = (pa[:,1]-pa[:,0])/dt + pdarest = (pa[:,1:] - pa[:,0:-1])/dt + pda = np.hstack((pda1.reshape(-1,1),pdarest)) + pdof = np.copy(bc[:,0]).astype(int) + fdof = np.setdiff1d(fdof,pdof).astype(int) - 1 + pdof -= 1 #adjusting for indexing starting from 0 + Keff = M[np.ix_(fdof,fdof)] + b3*C[np.ix_(fdof,fdof)] +b4*K[np.ix_(fdof,fdof)] + else: + fdof -= 1 #adjusting for indexing starting from 0 + Keff = M + b3*C + b4*K + + L, U = lu(Keff,permute_l=True) + anew = a0[np.ix_(fdof)] + danew = da0[np.ix_(fdof)] + d2anew = d2a0[np.ix_(fdof)] + + # Iterate over time steps + for j in range(1,nstep+1): + time = dt*j + aold = np.copy(anew) + daold = np.copy(danew) + d2aold = np.copy(d2anew) + apred = aold + dt*daold + b1*d2aold + dapred = daold + b2*d2aold + if not bound: + reff = tf[:,j].reshape(-1,1) - C@dapred - K@apred + else: + pdeff = C[np.ix_(fdof,pdof)]@pda[:,j].reshape(-1,1) + K[np.ix_(fdof,pdof)]@pa[:,j].reshape(-1,1) + reff = tf[np.ix_(fdof),j].reshape(-1,1) - C[np.ix_(fdof,fdof)]@dapred - K[np.ix_(fdof,fdof)]@apred - pdeff + y = np.linalg.solve(L,reff) + d2anew = np.linalg.solve(U,y) + anew = apred + b4*d2anew + danew = dapred + b3*d2anew + # Save to modelhist and dofhist + if bound: + tempa[np.ix_(pdof)] = pa[:,j].reshape(-1,1) + tempda[np.ix_(pdof)] = pda[:,j].reshape(-1,1) + tempa[np.ix_(fdof)] = anew + tempda[np.ix_(fdof)] = danew + tempd2a[np.ix_(fdof)] = d2anew + if sa==1: + modelhist['a'][:,j] = tempa.ravel() + modelhist['da'][:,j] = tempda.ravel() + modelhist['d2a'][:,j] = tempd2a.ravel() + elif sa==2: + if ntimes and itime < ntimes: + if time >= times[itime]: + modelhist['a'][:,itime] = tempa.ravel() + modelhist['da'][:,itime] = tempda.ravel() + modelhist['d2a'][:,itime] = tempd2a.ravel() + itime += 1 + if ndofs: + dofhist['a'][:,j] = tempa[np.ix_(dofs-1)].ravel() + dofhist['da'][:,j] = tempda[np.ix_(dofs-1)].ravel() + dofhist['d2a'][:,j] = tempd2a[np.ix_(dofs-1)].ravel() + + return modelhist, dofhist + + +def extract_eldisp(edof, a): + """ + Extract element displacements from the global displacement + vector according to the topology matrix edof. + + Parameters: + + a the global displacement vector + edof dof topology array + + Returns: + + ed: element displacement array + + """ + + ed = None + + if edof.ndim == 1: + nDofs = len(edof) + ed = np.zeros([nDofs]) + idx = edof-1 + ed[:] = a[np.ix_(idx)].T + else: + nElements = edof.shape[0] + nDofs = edof.shape[1] + ed = np.zeros([nElements, nDofs]) + i = 0 + for row in edof: + idx = row-1 + ed[i, :] = a[np.ix_(idx)].T + i += 1 + + return ed + + +extractEldisp = extract_eldisp +extract_ed = extract_eldisp + + +def statcon(K, f, cd): + """ + Condensation of static FE-equations according to the vector cd. + + Parameters: + + K global stiffness matrix, dim(K) = nd x nd + f global load vector, dim(f)= nd x 1 + + cd vector containing dof's to be eliminated + dim(cd)= nc x 1, nc: number of condensed dof's + Returns: + + K1 condensed stiffness matrix, + dim(K1)= (nd-nc) x (nd-nc) + f1 condensed load vector, dim(f1)= (nd-nc) x 1 + """ + nd, nd = np.shape(K) + cd = (cd-1).flatten() + + aindx = np.arange(nd) + aindx = np.delete(aindx, cd, 0) + bindx = cd + + Kaa = np.mat(K[np.ix_(aindx, aindx)]) + Kab = np.mat(K[np.ix_(aindx, bindx)]) + Kbb = np.mat(K[np.ix_(bindx, bindx)]) + + fa = np.mat(f[aindx]) + fb = np.mat(f[bindx]) + + K1 = Kaa-Kab*Kbb.I*Kab.T + f1 = fa-Kab*Kbb.I*fb + + return K1, f1 + + +def c_mul(a, b): + return eval(hex((np.long(a) * b) & 0xFFFFFFFF)[:-1]) + + +def dofHash(dof): + if len(dof) == 1: + return dof[0] + value = 0x345678 + for item in dof: + value = c_mul(1000003, value) ^ hash(item) + value = value ^ len(dof) + if value == -1: + value = -2 + return value + + +def create_dofs(nCoords, nDof): + """ + Create dof array [nCoords x nDof] + """ + return np.arange(nCoords*nDof).reshape(nCoords, nDof)+1 + + +createdofs = create_dofs + + +def coordxtr(edof, coords, dofs, nen=-1): + """ + Create element coordinate matrices ex, ey, ez from edof + coord and dofs matrices. + + Parameters: + + edof [nel x (nen * nnd)], nnd = number of node dofs + coords [ncoords x ndims], ndims = node dimensions + dofs [ncoords x nnd] + + Returns: + + ex if ndims = 1 + ex, ey if ndims = 2 + ex, ey, ez if ndims = 3 + """ + + # Create dictionary with dof indices + + dofDict = {} + nDofs = np.size(dofs, 1) + nElements = np.size(edof, 0) + n_element_dofs = np.size(edof, 1) + nDimensions = np.size(coords, 1) + nElementDofs = np.size(edof, 1) + + if nen == -1: + nElementNodes = int(nElementDofs/nDofs) + else: + nElementNodes = nen + + if nElementNodes*nDofs != n_element_dofs: + nDofs = nElementNodes*nDofs - n_element_dofs + user_warning( + "dofs/edof mismatch. Using %d dofs per node when indexing." % nDofs) + + idx = 0 + for dof in dofs: + #dofDict[dofHash(dof)] = idx + dofDict[hash(tuple(dof[0:nDofs]))] = idx + idx += 1 + + # Loop over edof and extract element coords + + ex = np.zeros((nElements, nElementNodes)) + ey = np.zeros((nElements, nElementNodes)) + ez = np.zeros((nElements, nElementNodes)) + + elementIdx = 0 + for etopo in edof: + for i in range(nElementNodes): + i0 = i*nDofs + i1 = i*nDofs+nDofs-1 + dof = [] + if i0 == i1: + dof = [etopo[i*nDofs]] + else: + dof = etopo[i*nDofs:(i*nDofs+nDofs)] + + nodeCoord = coords[dofDict[hash(tuple(dof[0:nDofs]))]] + + if nDimensions >= 1: + ex[elementIdx, i] = nodeCoord[0] + if nDimensions >= 2: + ey[elementIdx, i] = nodeCoord[1] + if nDimensions >= 3: + ez[elementIdx, i] = nodeCoord[2] + + elementIdx += 1 + + if nDimensions == 1: + return ex + + if nDimensions == 2: + return ex, ey + + if nDimensions == 3: + return ex, ey, ez + + +coord_extract = coordxtr + + +def hooke(ptype, E, v): + """ + Calculate the material matrix for a linear + elastic and isotropic material. + + Parameters: + + ptype= 1: plane stress + 2: plane strain + 3: axisymmetry + 4: three dimensional + + E Young's modulus + v Poissons const. + + Returns: + + D material matrix + + """ + + if ptype == 1: + D = E*np.matrix( + [[1, v, 0], + [v, 1, 0], + [0, 0, (1-v)/2]] + )/(1-v**2) + elif ptype == 2: + D = E/(1+v)*np.matrix( + [[1-v, v, v, 0], + [v, 1-v, v, 0], + [v, v, 1-v, 0], + [0, 0, 0, (1-2*v)/2]] + )/(1-2*v) + elif ptype == 3: + D = E/(1+v)*np.matrix( + [[1-v, v, v, 0], + [v, 1-v, v, 0], + [v, v, 1-v, 0], + [0, 0, 0, (1-2*v)/2]] + )/(1-2*v) + elif ptype == 4: + D = E*np.matrix( + [[1-v, v, v, 0, 0, 0], + [v, 1-v, v, 0, 0, 0], + [v, v, 1-v, 0, 0, 0], + [0, 0, 0, (1-2*v)/2, 0, 0], + [0, 0, 0, 0, (1-2*v)/2, 0], + [0, 0, 0, 0, 0, (1-2*v)/2]] + )/(1+v)/(1-2*v) + else: + info("ptype not supported.") + + return D + + +def effmises(es, ptype): + """ + Calculate effective von mises stresses. + + Parameters: + + es + + ptype= 1: plane stress + 2: plane strain + 3: axisymmetry + 4: three dimensional + + es = [[sigx,sigy,[sigz],tauxy] element stress matrix + [ ...... ]] one row for each element + + Returns: + + eseff = [eseff_0 .. eseff_nel-1] + + """ + + nel = np.size(es, 0) + escomps = np.size(es, 1) + + eseff = np.zeros([nel]) + + if ptype == 1: + sigxx = es[:, 0] + sigyy = es[:, 1] + sigxy = es[:, 2] + eseff = np.sqrt(sigxx*sigxx+sigyy*sigyy-sigxx*sigyy+3*sigxy*sigxy) + return eseff + + +def stress2nodal(eseff, edof): + """ + Convert element effective stresses to nodal effective + stresses. + + Parameters: + + eseff = [eseff_0 .. eseff_nel-1] + edof = [dof topology array] + + Returns: + + ev: element value array [[ev_0_0 ev_0_1 ev_0_nen-1 ] + .. + ev_nel-1_0 ev_nel-1_1 ev_nel-1_nen-1] + + """ + + values = np.zeros(edof.max()) + elnodes = int(np.size(edof, 1) / 2) + + for etopo, eleseff in zip(edof, eseff): + values[etopo-1] = values[etopo-1] + eleseff / elnodes + + evtemp = extractEldisp(edof, values) + ev = evtemp[:, range(0, elnodes*2, 2)] + + return ev + + +def beam2crd_old(ex, ey, ed, mag): + """ + ------------------------------------------------------------- + PURPOSE + Calculate the element continous displacements for a + number of identical 2D Bernoulli beam elements. + + INPUT: ex,ey, + ed, + mag + + OUTPUT: excd,eycd + ------------------------------------------------------------- + + LAST MODIFIED: P-E AUSTRELL 1993-10-15 + J Lindemann 2021-12-30 (Python) + + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + nie, ned = ed.shape + + excd = np.zeros([nie, 20]) + eycd = np.zeros([nie, 20]) + + for i in range(nie): + + b = np.array([ex[i, 1]-ex[i, 0], ey[i, 1]-ey[i, 0]]) + L = np.asscalar(np.sqrt(b@np.transpose(b))) + n = b/L + + G = np.array([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, -n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + d = ed[i, :] + dl = G @ d + + xl = np.linspace(0.0, L, 20) + one = np.ones(xl.shape) + + Cis = np.array([ + [-1.0, 1.0], + [L, 0.0] + ]) / L + + ds = np.array([dl[0], dl[3]]).reshape(2, 1) + + xl_one = np.transpose(np.vstack((xl, one))) + + ul = np.transpose(xl_one@Cis@ds) # [20x1][2] + + Cib = np.array([ + [12, 6*L, -12, 6*L], + [-6*L, -4*L**2, 6*L, -2*L**2], + [0, L**3, 0, 0], + [L**3, 0, 0, 0] + ])/L**3 + + db = np.array([dl[1], dl[2], dl[4], dl[5]]).reshape(4, 1) + vl = np.transpose(np.transpose( + np.vstack((xl**3/6, xl**2/2, xl, one)))@Cib@db) + + cld = np.vstack((ul, vl)) + A = np.array([ + [n[0], -n[1]], + [n[1], n[0]] + ]) + cd = A@cld + + # [2,1] x [1,20] + [2 x 1] x [1 x 20] + # [2 x 20] + [2 x 20] + + AA = A[:, 0].reshape(2, 1) + XL = xl.reshape(1, 20) + xyc = AA@XL + np.array([[ex[i, 0]], [ey[i, 0]]])@one.reshape(1, 20) + + excd[i, :] = xyc[0, :]+mag*cd[0, :] + eycd[i, :] = xyc[1, :]+mag*cd[1, :] + + return excd, eycd + + +def beam2crd(ex=None, ey=None, ed=None, mag=None): + """ + ------------------------------------------------------------- + PURPOSE + Calculate the element continous displacements for a + number of identical 2D Bernoulli beam elements. + + INPUT: ex,ey, + ed, + mag + + OUTPUT: excd,eycd + ------------------------------------------------------------- + + LAST MODIFIED: P-E AUSTRELL 1993-10-15 + Copyright (c) Division of Structural Mechanics and + Division of Solid Mechanics. + Lund University + ------------------------------------------------------------- + """ + + nie, ned = ed.shape + + n_coords = 21 + + excd = np.zeros([nie, n_coords]) + eycd = np.zeros([nie, n_coords]) + + for i in range(nie): + b = np.array([ex[i, 1] - ex[i, 0], ey[i, 1] - ey[i, 0]]) + L = np.sqrt(b @ np.transpose(b)) + n = b / L + + G = np.array([ + [n[0], n[1], 0, 0, 0, 0], + [-n[1], n[0], 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, n[0], n[1], 0], + [0, 0, 0, - n[1], n[0], 0], + [0, 0, 0, 0, 0, 1] + ]) + + d = np.transpose(ed[i, :]) + dl = G @ d + xl = np.transpose(np.linspace(0, L, n_coords)) + one = np.ones(xl.shape) + + Cis = np.array([ + [-1, 1], + [L, 0] + ]) / L + + ds = np.array([dl[0], dl[3]]).reshape(2, 1) + xl_one = np.transpose(np.vstack((xl, one))) + ul = np.transpose(xl_one@Cis@ds) # [20x1][2] + + Cib = np.array([ + [12, 6 * L, - 12, 6 * L], + [- 6 * L, - 4 * L ** 2, 6 * L, - 2 * L ** 2], + [0, L ** 3, 0, 0], + [L ** 3, 0, 0, 0] + ]) / L ** 3 + + db = np.array([dl[1], dl[2], dl[4], dl[5]]).reshape(4, 1) + vl = np.transpose(np.transpose( + np.vstack((xl**3/6, xl**2/2, xl, one)))@Cib@db) + + cld = np.vstack((ul, vl)) + A = np.array([ + [n[0], -n[1]], + [n[1], n[0]] + ]) + cd = A@cld + + # [2,1] x [1,20] + [2 x 1] x [1 x 20] + # [2 x 20] + [2 x 20] + + AA = A[:, 0].reshape(2, 1) + XL = xl.reshape(1, n_coords) + xyc = AA@XL + np.array([[ex[i, 0]], [ey[i, 0]]] + )@one.reshape(1, n_coords) + + excd[i, :] = xyc[0, :]+mag*cd[0, :] + eycd[i, :] = xyc[1, :]+mag*cd[1, :] + + return excd, eycd \ No newline at end of file diff --git a/calfem/editor.py b/calfem/editor.py index 4b270e5..7bf4ab5 100644 --- a/calfem/editor.py +++ b/calfem/editor.py @@ -20,6 +20,7 @@ import calfem.geometry as cfg import calfem.vis_mpl as cfv import calfem.editor_scene as editor_scene +import calfem.editor_ui as editor_ui app = None @@ -31,8 +32,11 @@ def __init__(self): super(QMainWindow, self).__init__() self.app = app - root = os.path.dirname(os.path.realpath(__file__)) - loadUi(os.path.join(root, 'editor.ui'), self) + #root = os.path.dirname(os.path.realpath(__file__)) + #loadUi(os.path.join(root, 'editor.ui'), self) + + ui = editor_ui.Ui_MainWindow() + ui.setupUi(self) # loadUi('editor.ui', self) loadUI kan ladd ui-fil och lägga till objekt direkt i klassen. self.setWindowTitle("CALFEM Geometry Editor") diff --git a/calfem/editor_ui.py b/calfem/editor_ui.py new file mode 100644 index 0000000..a8293bc --- /dev/null +++ b/calfem/editor_ui.py @@ -0,0 +1,1208 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'editor.ui' +# +# Created by: PyQt5 UI code generator 5.9.2 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1493, 785) + MainWindow.setStyleSheet("") + MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.centralwidget = QtWidgets.QWidget(MainWindow) + MainWindow.centralwidget.setStyleSheet("QWidget{\n" +"background: rgb(220, 220, 220);\n" +"}") + MainWindow.centralwidget.setObjectName("centralwidget") + MainWindow.verticalLayout_2 = QtWidgets.QVBoxLayout(MainWindow.centralwidget) + MainWindow.verticalLayout_2.setObjectName("verticalLayout_2") + MainWindow.tabWidget = QtWidgets.QTabWidget(MainWindow.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.tabWidget.sizePolicy().hasHeightForWidth()) + MainWindow.tabWidget.setSizePolicy(sizePolicy) + MainWindow.tabWidget.setMinimumSize(QtCore.QSize(0, 120)) + MainWindow.tabWidget.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + MainWindow.tabWidget.setStyleSheet("QTabWidget::pane { /* The tab widget frame */\n" +" border-bottom: 6px solid;\n" +" border-bottom-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgb(200, 200, 200), stop:1 rgba(220,220,220));\n" +" border-top: 8px solid rgb(0,0,128);\n" +" /*border-radius: 4px;*/\n" +"}\n" +"\n" +"\n" +"QTabWidget::tab-bar {\n" +" left: 20px; /* move to the right by 5px */\n" +" bottom: -8px;\n" +"}\n" +"\n" +"QTabBar::tab {\n" +" /*border-bottom-color: transparent;\n" +" border-top-left-radius: 4px;*/\n" +" min-width: 18ex;\n" +" padding: 4px;\n" +"}\n" +"\n" +"QTabBar::tab:selected {\n" +" background: rgb(240,240,240);\n" +" border: 2px solid rgb(200,200,200);\n" +" border-bottom: 0 px solid;\n" +" border-top-left-radius: 6px;\n" +" border-top-right-radius: 6px;\n" +"}\n" +"\n" +"QTabBar::tab:!selected {\n" +" border: 2px solid rgb(200,200,200);\n" +" margin-top: 4px; /* make non-selected tabs look smaller */\n" +" border-top-left-radius: 6px;\n" +" border-top-right-radius: 6px;\n" +"}") + MainWindow.tabWidget.setObjectName("tabWidget") + MainWindow.tab_2 = QtWidgets.QWidget() + MainWindow.tab_2.setStyleSheet("QWidget{\n" +" background-color: rgb(240, 240, 240);\n" +"} ") + MainWindow.tab_2.setObjectName("tab_2") + MainWindow.layoutWidget = QtWidgets.QWidget(MainWindow.tab_2) + MainWindow.layoutWidget.setGeometry(QtCore.QRect(0, 0, 1100, 81)) + MainWindow.layoutWidget.setObjectName("layoutWidget") + MainWindow.horizontalLayout_2 = QtWidgets.QHBoxLayout(MainWindow.layoutWidget) + MainWindow.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + MainWindow.horizontalLayout_2.setObjectName("horizontalLayout_2") + spacerItem = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + MainWindow.horizontalLayout_2.addItem(spacerItem) + MainWindow.gridLayout = QtWidgets.QGridLayout() + MainWindow.gridLayout.setObjectName("gridLayout") + MainWindow.zoomOutButtonSurface = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.zoomOutButtonSurface.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/Images/zoom_out.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.zoomOutButtonSurface.setIcon(icon) + MainWindow.zoomOutButtonSurface.setIconSize(QtCore.QSize(24, 24)) + MainWindow.zoomOutButtonSurface.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.zoomOutButtonSurface.setObjectName("zoomOutButtonSurface") + MainWindow.gridLayout.addWidget(MainWindow.zoomOutButtonSurface, 0, 1, 1, 1) + MainWindow.arrowButtonSurface = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.arrowButtonSurface.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + MainWindow.arrowButtonSurface.setFocusPolicy(QtCore.Qt.TabFocus) + MainWindow.arrowButtonSurface.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/Images/select.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.arrowButtonSurface.setIcon(icon1) + MainWindow.arrowButtonSurface.setIconSize(QtCore.QSize(24, 24)) + MainWindow.arrowButtonSurface.setCheckable(False) + MainWindow.arrowButtonSurface.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.arrowButtonSurface.setObjectName("arrowButtonSurface") + MainWindow.gridLayout.addWidget(MainWindow.arrowButtonSurface, 0, 0, 1, 1) + MainWindow.panningButtonSurface = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.panningButtonSurface.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(":/Images/pan.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.panningButtonSurface.setIcon(icon2) + MainWindow.panningButtonSurface.setIconSize(QtCore.QSize(24, 24)) + MainWindow.panningButtonSurface.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.panningButtonSurface.setObjectName("panningButtonSurface") + MainWindow.gridLayout.addWidget(MainWindow.panningButtonSurface, 1, 0, 1, 1) + MainWindow.zoomInButtonSurface = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.zoomInButtonSurface.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon3 = QtGui.QIcon() + icon3.addPixmap(QtGui.QPixmap(":/Images/zoom_in.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.zoomInButtonSurface.setIcon(icon3) + MainWindow.zoomInButtonSurface.setIconSize(QtCore.QSize(24, 24)) + MainWindow.zoomInButtonSurface.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.zoomInButtonSurface.setObjectName("zoomInButtonSurface") + MainWindow.gridLayout.addWidget(MainWindow.zoomInButtonSurface, 1, 1, 1, 1) + MainWindow.horizontalLayout_2.addLayout(MainWindow.gridLayout) + MainWindow.line_2 = QtWidgets.QFrame(MainWindow.layoutWidget) + MainWindow.line_2.setMinimumSize(QtCore.QSize(15, 0)) + MainWindow.line_2.setFrameShadow(QtWidgets.QFrame.Plain) + MainWindow.line_2.setLineWidth(1) + MainWindow.line_2.setFrameShape(QtWidgets.QFrame.VLine) + MainWindow.line_2.setObjectName("line_2") + MainWindow.horizontalLayout_2.addWidget(MainWindow.line_2) + MainWindow.verticalLayout_7 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_7.setObjectName("verticalLayout_7") + MainWindow.polyButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.polyButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon4 = QtGui.QIcon() + icon4.addPixmap(QtGui.QPixmap(":/Images/polygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.polyButton.setIcon(icon4) + MainWindow.polyButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.polyButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.polyButton.setObjectName("polyButton") + MainWindow.verticalLayout_7.addWidget(MainWindow.polyButton) + MainWindow.rectButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.rectButton.setEnabled(True) + MainWindow.rectButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon5 = QtGui.QIcon() + icon5.addPixmap(QtGui.QPixmap(":/Images/rectangle.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.rectButton.setIcon(icon5) + MainWindow.rectButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.rectButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.rectButton.setObjectName("rectButton") + MainWindow.verticalLayout_7.addWidget(MainWindow.rectButton) + MainWindow.horizontalLayout_2.addLayout(MainWindow.verticalLayout_7) + MainWindow.verticalLayout_10 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_10.setObjectName("verticalLayout_10") + MainWindow.addPolyHoleButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.addPolyHoleButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon6 = QtGui.QIcon() + icon6.addPixmap(QtGui.QPixmap(":/Images/polygon_hole.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.addPolyHoleButton.setIcon(icon6) + MainWindow.addPolyHoleButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.addPolyHoleButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.addPolyHoleButton.setObjectName("addPolyHoleButton") + MainWindow.verticalLayout_10.addWidget(MainWindow.addPolyHoleButton) + MainWindow.addRectHoleButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.addRectHoleButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon7 = QtGui.QIcon() + icon7.addPixmap(QtGui.QPixmap(":/Images/rectangle_hole.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.addRectHoleButton.setIcon(icon7) + MainWindow.addRectHoleButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.addRectHoleButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.addRectHoleButton.setObjectName("addRectHoleButton") + MainWindow.verticalLayout_10.addWidget(MainWindow.addRectHoleButton) + MainWindow.horizontalLayout_2.addLayout(MainWindow.verticalLayout_10) + MainWindow.verticalLayout_12 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_12.setObjectName("verticalLayout_12") + MainWindow.mergeButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.mergeButton.sizePolicy().hasHeightForWidth()) + MainWindow.mergeButton.setSizePolicy(sizePolicy) + MainWindow.mergeButton.setLayoutDirection(QtCore.Qt.LeftToRight) + MainWindow.mergeButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon8 = QtGui.QIcon() + icon8.addPixmap(QtGui.QPixmap(":/Images/merge.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.mergeButton.setIcon(icon8) + MainWindow.mergeButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.mergeButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.mergeButton.setAutoRaise(False) + MainWindow.mergeButton.setObjectName("mergeButton") + MainWindow.verticalLayout_12.addWidget(MainWindow.mergeButton) + MainWindow.deleteButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.deleteButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon9 = QtGui.QIcon() + icon9.addPixmap(QtGui.QPixmap(":/Images/erase.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.deleteButton.setIcon(icon9) + MainWindow.deleteButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.deleteButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.deleteButton.setObjectName("deleteButton") + MainWindow.verticalLayout_12.addWidget(MainWindow.deleteButton) + MainWindow.horizontalLayout_2.addLayout(MainWindow.verticalLayout_12) + MainWindow.line_5 = QtWidgets.QFrame(MainWindow.layoutWidget) + MainWindow.line_5.setMinimumSize(QtCore.QSize(15, 0)) + MainWindow.line_5.setFrameShadow(QtWidgets.QFrame.Plain) + MainWindow.line_5.setLineWidth(1) + MainWindow.line_5.setFrameShape(QtWidgets.QFrame.VLine) + MainWindow.line_5.setObjectName("line_5") + MainWindow.horizontalLayout_2.addWidget(MainWindow.line_5) + MainWindow.verticalLayout_9 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_9.setObjectName("verticalLayout_9") + MainWindow.gridSnapButtonSurface = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.gridSnapButtonSurface.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:checked {\n" +" background-color: rgb(191, 184, 175);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgb(223, 219, 215);\n" +"}\n" +"") + icon10 = QtGui.QIcon() + icon10.addPixmap(QtGui.QPixmap(":/Images/grid_snap.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.gridSnapButtonSurface.setIcon(icon10) + MainWindow.gridSnapButtonSurface.setIconSize(QtCore.QSize(24, 24)) + MainWindow.gridSnapButtonSurface.setCheckable(True) + MainWindow.gridSnapButtonSurface.setChecked(True) + MainWindow.gridSnapButtonSurface.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.gridSnapButtonSurface.setObjectName("gridSnapButtonSurface") + MainWindow.verticalLayout_9.addWidget(MainWindow.gridSnapButtonSurface) + MainWindow.gridButtonSurface = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.gridButtonSurface.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:checked {\n" +" background-color: rgb(191, 184, 175);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgb(223, 219, 215);\n" +"}\n" +"") + icon11 = QtGui.QIcon() + icon11.addPixmap(QtGui.QPixmap(":/Images/grid.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.gridButtonSurface.setIcon(icon11) + MainWindow.gridButtonSurface.setIconSize(QtCore.QSize(24, 24)) + MainWindow.gridButtonSurface.setCheckable(True) + MainWindow.gridButtonSurface.setChecked(True) + MainWindow.gridButtonSurface.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.gridButtonSurface.setObjectName("gridButtonSurface") + MainWindow.verticalLayout_9.addWidget(MainWindow.gridButtonSurface) + MainWindow.horizontalLayout_2.addLayout(MainWindow.verticalLayout_9) + MainWindow.verticalLayout_8 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_8.setObjectName("verticalLayout_8") + MainWindow.gridSpacingSpinBox = QtWidgets.QSpinBox(MainWindow.layoutWidget) + MainWindow.gridSpacingSpinBox.setMinimum(5) + MainWindow.gridSpacingSpinBox.setMaximum(1000) + MainWindow.gridSpacingSpinBox.setSingleStep(10) + MainWindow.gridSpacingSpinBox.setProperty("value", 20) + MainWindow.gridSpacingSpinBox.setObjectName("gridSpacingSpinBox") + MainWindow.verticalLayout_8.addWidget(MainWindow.gridSpacingSpinBox) + MainWindow.gridSpacingButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.gridSpacingButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(191, 184, 175);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgb(223, 219, 215);\n" +"}\n" +"") + icon12 = QtGui.QIcon() + icon12.addPixmap(QtGui.QPixmap(":/Images/grid_settings.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.gridSpacingButton.setIcon(icon12) + MainWindow.gridSpacingButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.gridSpacingButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.gridSpacingButton.setObjectName("gridSpacingButton") + MainWindow.verticalLayout_8.addWidget(MainWindow.gridSpacingButton) + MainWindow.horizontalLayout_2.addLayout(MainWindow.verticalLayout_8) + MainWindow.line_6 = QtWidgets.QFrame(MainWindow.layoutWidget) + MainWindow.line_6.setMinimumSize(QtCore.QSize(15, 0)) + MainWindow.line_6.setFrameShadow(QtWidgets.QFrame.Plain) + MainWindow.line_6.setLineWidth(1) + MainWindow.line_6.setFrameShape(QtWidgets.QFrame.VLine) + MainWindow.line_6.setObjectName("line_6") + MainWindow.horizontalLayout_2.addWidget(MainWindow.line_6) + MainWindow.verticalLayout_11 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_11.setObjectName("verticalLayout_11") + MainWindow.loadGeometryButton = QtWidgets.QToolButton(MainWindow.layoutWidget) + MainWindow.loadGeometryButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon13 = QtGui.QIcon() + icon13.addPixmap(QtGui.QPixmap(":/Images/open.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.loadGeometryButton.setIcon(icon13) + MainWindow.loadGeometryButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.loadGeometryButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.loadGeometryButton.setObjectName("loadGeometryButton") + MainWindow.verticalLayout_11.addWidget(MainWindow.loadGeometryButton) + MainWindow.horizontalLayout_2.addLayout(MainWindow.verticalLayout_11) + MainWindow.tabWidget.addTab(MainWindow.tab_2, "") + MainWindow.tab = QtWidgets.QWidget() + MainWindow.tab.setStyleSheet("QWidget{\n" +" background-color: rgb(240, 240, 240);\n" +"} ") + MainWindow.tab.setObjectName("tab") + MainWindow.horizontalLayoutWidget_2 = QtWidgets.QWidget(MainWindow.tab) + MainWindow.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(0, 0, 464, 81)) + MainWindow.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2") + MainWindow.horizontalLayout_3 = QtWidgets.QHBoxLayout(MainWindow.horizontalLayoutWidget_2) + MainWindow.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + MainWindow.horizontalLayout_3.setObjectName("horizontalLayout_3") + spacerItem1 = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + MainWindow.horizontalLayout_3.addItem(spacerItem1) + MainWindow.gridLayout_2 = QtWidgets.QGridLayout() + MainWindow.gridLayout_2.setObjectName("gridLayout_2") + MainWindow.arrowButtonBorder = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.arrowButtonBorder.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + MainWindow.arrowButtonBorder.setFocusPolicy(QtCore.Qt.TabFocus) + MainWindow.arrowButtonBorder.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.arrowButtonBorder.setIcon(icon1) + MainWindow.arrowButtonBorder.setIconSize(QtCore.QSize(24, 24)) + MainWindow.arrowButtonBorder.setCheckable(True) + MainWindow.arrowButtonBorder.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.arrowButtonBorder.setObjectName("arrowButtonBorder") + MainWindow.gridLayout_2.addWidget(MainWindow.arrowButtonBorder, 0, 0, 1, 1) + MainWindow.zoomOutButtonBorder = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.zoomOutButtonBorder.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.zoomOutButtonBorder.setIcon(icon) + MainWindow.zoomOutButtonBorder.setIconSize(QtCore.QSize(24, 24)) + MainWindow.zoomOutButtonBorder.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.zoomOutButtonBorder.setObjectName("zoomOutButtonBorder") + MainWindow.gridLayout_2.addWidget(MainWindow.zoomOutButtonBorder, 0, 1, 1, 1) + MainWindow.zoomInButtonBorder = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.zoomInButtonBorder.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.zoomInButtonBorder.setIcon(icon3) + MainWindow.zoomInButtonBorder.setIconSize(QtCore.QSize(24, 24)) + MainWindow.zoomInButtonBorder.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.zoomInButtonBorder.setObjectName("zoomInButtonBorder") + MainWindow.gridLayout_2.addWidget(MainWindow.zoomInButtonBorder, 1, 1, 1, 1) + MainWindow.panningButtonBorder = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.panningButtonBorder.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.panningButtonBorder.setIcon(icon2) + MainWindow.panningButtonBorder.setIconSize(QtCore.QSize(24, 24)) + MainWindow.panningButtonBorder.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.panningButtonBorder.setObjectName("panningButtonBorder") + MainWindow.gridLayout_2.addWidget(MainWindow.panningButtonBorder, 1, 0, 1, 1) + MainWindow.horizontalLayout_3.addLayout(MainWindow.gridLayout_2) + MainWindow.line = QtWidgets.QFrame(MainWindow.horizontalLayoutWidget_2) + MainWindow.line.setMinimumSize(QtCore.QSize(15, 0)) + MainWindow.line.setFrameShadow(QtWidgets.QFrame.Plain) + MainWindow.line.setFrameShape(QtWidgets.QFrame.VLine) + MainWindow.line.setObjectName("line") + MainWindow.horizontalLayout_3.addWidget(MainWindow.line) + MainWindow.verticalLayout_6 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_6.setObjectName("verticalLayout_6") + MainWindow.setMarkerButton = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.setMarkerButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon14 = QtGui.QIcon() + icon14.addPixmap(QtGui.QPixmap(":/Images/add_marker.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.setMarkerButton.setIcon(icon14) + MainWindow.setMarkerButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.setMarkerButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.setMarkerButton.setObjectName("setMarkerButton") + MainWindow.verticalLayout_6.addWidget(MainWindow.setMarkerButton) + MainWindow.splitEdgeButton = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.splitEdgeButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon15 = QtGui.QIcon() + icon15.addPixmap(QtGui.QPixmap(":/Images/split_edge.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.splitEdgeButton.setIcon(icon15) + MainWindow.splitEdgeButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.splitEdgeButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.splitEdgeButton.setObjectName("splitEdgeButton") + MainWindow.verticalLayout_6.addWidget(MainWindow.splitEdgeButton) + MainWindow.horizontalLayout_3.addLayout(MainWindow.verticalLayout_6) + MainWindow.line_3 = QtWidgets.QFrame(MainWindow.horizontalLayoutWidget_2) + MainWindow.line_3.setFrameShadow(QtWidgets.QFrame.Plain) + MainWindow.line_3.setFrameShape(QtWidgets.QFrame.VLine) + MainWindow.line_3.setObjectName("line_3") + MainWindow.horizontalLayout_3.addWidget(MainWindow.line_3) + MainWindow.verticalLayout_13 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_13.setObjectName("verticalLayout_13") + MainWindow.gridSnapButtonBorder = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.gridSnapButtonBorder.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:checked {\n" +" background-color: rgb(191, 184, 175);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgb(223, 219, 215);\n" +"}\n" +"") + MainWindow.gridSnapButtonBorder.setIcon(icon10) + MainWindow.gridSnapButtonBorder.setIconSize(QtCore.QSize(24, 24)) + MainWindow.gridSnapButtonBorder.setCheckable(True) + MainWindow.gridSnapButtonBorder.setChecked(True) + MainWindow.gridSnapButtonBorder.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.gridSnapButtonBorder.setObjectName("gridSnapButtonBorder") + MainWindow.verticalLayout_13.addWidget(MainWindow.gridSnapButtonBorder) + MainWindow.gridButtonBorder = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget_2) + MainWindow.gridButtonBorder.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:checked {\n" +" background-color: rgb(191, 184, 175);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgb(223, 219, 215);\n" +"}\n" +"") + MainWindow.gridButtonBorder.setIcon(icon11) + MainWindow.gridButtonBorder.setIconSize(QtCore.QSize(24, 24)) + MainWindow.gridButtonBorder.setCheckable(True) + MainWindow.gridButtonBorder.setChecked(True) + MainWindow.gridButtonBorder.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.gridButtonBorder.setObjectName("gridButtonBorder") + MainWindow.verticalLayout_13.addWidget(MainWindow.gridButtonBorder) + MainWindow.horizontalLayout_3.addLayout(MainWindow.verticalLayout_13) + MainWindow.tabWidget.addTab(MainWindow.tab, "") + MainWindow.tab_4 = QtWidgets.QWidget() + MainWindow.tab_4.setStyleSheet("QWidget{\n" +" background-color: rgb(240, 240, 240);\n" +"} ") + MainWindow.tab_4.setObjectName("tab_4") + MainWindow.saveGeomButton = QtWidgets.QToolButton(MainWindow.tab_4) + MainWindow.saveGeomButton.setGeometry(QtCore.QRect(10, 30, 141, 21)) + MainWindow.saveGeomButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon16 = QtGui.QIcon() + icon16.addPixmap(QtGui.QPixmap(":/Images/save.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.saveGeomButton.setIcon(icon16) + MainWindow.saveGeomButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.saveGeomButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.saveGeomButton.setObjectName("saveGeomButton") + MainWindow.tabWidget.addTab(MainWindow.tab_4, "") + MainWindow.tab_3 = QtWidgets.QWidget() + MainWindow.tab_3.setStyleSheet("QWidget{\n" +" background-color: rgb(240, 240, 240);\n" +"} ") + MainWindow.tab_3.setObjectName("tab_3") + MainWindow.horizontalLayoutWidget = QtWidgets.QWidget(MainWindow.tab_3) + MainWindow.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 0, 351, 71)) + MainWindow.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") + MainWindow.horizontalLayout_5 = QtWidgets.QHBoxLayout(MainWindow.horizontalLayoutWidget) + MainWindow.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + MainWindow.horizontalLayout_5.setSpacing(0) + MainWindow.horizontalLayout_5.setObjectName("horizontalLayout_5") + MainWindow.label_9 = QtWidgets.QLabel(MainWindow.horizontalLayoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.label_9.sizePolicy().hasHeightForWidth()) + MainWindow.label_9.setSizePolicy(sizePolicy) + MainWindow.label_9.setText("") + MainWindow.label_9.setPixmap(QtGui.QPixmap(":/Images/save.png")) + MainWindow.label_9.setObjectName("label_9") + MainWindow.horizontalLayout_5.addWidget(MainWindow.label_9) + MainWindow.line_4 = QtWidgets.QFrame(MainWindow.horizontalLayoutWidget) + MainWindow.line_4.setFrameShape(QtWidgets.QFrame.VLine) + MainWindow.line_4.setFrameShadow(QtWidgets.QFrame.Sunken) + MainWindow.line_4.setObjectName("line_4") + MainWindow.horizontalLayout_5.addWidget(MainWindow.line_4) + MainWindow.verticalLayout_19 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_19.setSpacing(0) + MainWindow.verticalLayout_19.setObjectName("verticalLayout_19") + MainWindow.saveMeshButton = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget) + MainWindow.saveMeshButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + icon17 = QtGui.QIcon() + icon17.addPixmap(QtGui.QPixmap(":/Images/blank.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.saveMeshButton.setIcon(icon17) + MainWindow.saveMeshButton.setIconSize(QtCore.QSize(12, 12)) + MainWindow.saveMeshButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.saveMeshButton.setObjectName("saveMeshButton") + MainWindow.verticalLayout_19.addWidget(MainWindow.saveMeshButton) + MainWindow.saveArraysButton = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget) + MainWindow.saveArraysButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.saveArraysButton.setIcon(icon17) + MainWindow.saveArraysButton.setIconSize(QtCore.QSize(12, 12)) + MainWindow.saveArraysButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.saveArraysButton.setObjectName("saveArraysButton") + MainWindow.verticalLayout_19.addWidget(MainWindow.saveArraysButton) + MainWindow.saveArraysMatlabButton = QtWidgets.QToolButton(MainWindow.horizontalLayoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.saveArraysMatlabButton.sizePolicy().hasHeightForWidth()) + MainWindow.saveArraysMatlabButton.setSizePolicy(sizePolicy) + MainWindow.saveArraysMatlabButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.saveArraysMatlabButton.setIcon(icon17) + MainWindow.saveArraysMatlabButton.setIconSize(QtCore.QSize(12, 12)) + MainWindow.saveArraysMatlabButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + MainWindow.saveArraysMatlabButton.setObjectName("saveArraysMatlabButton") + MainWindow.verticalLayout_19.addWidget(MainWindow.saveArraysMatlabButton) + MainWindow.horizontalLayout_5.addLayout(MainWindow.verticalLayout_19) + MainWindow.tabWidget.addTab(MainWindow.tab_3, "") + MainWindow.verticalLayout_2.addWidget(MainWindow.tabWidget) + MainWindow.horizontalLayout_4 = QtWidgets.QHBoxLayout() + MainWindow.horizontalLayout_4.setObjectName("horizontalLayout_4") + spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + MainWindow.horizontalLayout_4.addItem(spacerItem2) + MainWindow.labelTooltip = QtWidgets.QLabel(MainWindow.centralwidget) + MainWindow.labelTooltip.setStyleSheet("QLabel{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.labelTooltip.setText("") + MainWindow.labelTooltip.setObjectName("labelTooltip") + MainWindow.horizontalLayout_4.addWidget(MainWindow.labelTooltip) + spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + MainWindow.horizontalLayout_4.addItem(spacerItem3) + MainWindow.label = QtWidgets.QLabel(MainWindow.centralwidget) + MainWindow.label.setStyleSheet("QLabel{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.label.setObjectName("label") + MainWindow.horizontalLayout_4.addWidget(MainWindow.label) + MainWindow.labelX = QtWidgets.QLabel(MainWindow.centralwidget) + MainWindow.labelX.setStyleSheet("QLabel{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.labelX.setObjectName("labelX") + MainWindow.horizontalLayout_4.addWidget(MainWindow.labelX) + MainWindow.label_3 = QtWidgets.QLabel(MainWindow.centralwidget) + MainWindow.label_3.setStyleSheet("QLabel{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.label_3.setObjectName("label_3") + MainWindow.horizontalLayout_4.addWidget(MainWindow.label_3) + MainWindow.labelY = QtWidgets.QLabel(MainWindow.centralwidget) + MainWindow.labelY.setStyleSheet("QLabel{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.labelY.setObjectName("labelY") + MainWindow.horizontalLayout_4.addWidget(MainWindow.labelY) + spacerItem4 = QtWidgets.QSpacerItem(220, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + MainWindow.horizontalLayout_4.addItem(spacerItem4) + MainWindow.verticalLayout_2.addLayout(MainWindow.horizontalLayout_4) + MainWindow.horizontalLayout = QtWidgets.QHBoxLayout() + MainWindow.horizontalLayout.setSpacing(0) + MainWindow.horizontalLayout.setObjectName("horizontalLayout") + MainWindow.stackedWidget = QtWidgets.QStackedWidget(MainWindow.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.stackedWidget.sizePolicy().hasHeightForWidth()) + MainWindow.stackedWidget.setSizePolicy(sizePolicy) + MainWindow.stackedWidget.setMinimumSize(QtCore.QSize(661, 420)) + MainWindow.stackedWidget.setStyleSheet("QStackedWidget{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.stackedWidget.setObjectName("stackedWidget") + MainWindow.page = QtWidgets.QWidget() + MainWindow.page.setStyleSheet("QWidget{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.page.setObjectName("page") + MainWindow.verticalLayout_4 = QtWidgets.QVBoxLayout(MainWindow.page) + MainWindow.verticalLayout_4.setObjectName("verticalLayout_4") + MainWindow.verticalLayout = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout.setObjectName("verticalLayout") + MainWindow.verticalLayout_4.addLayout(MainWindow.verticalLayout) + MainWindow.stackedWidget.addWidget(MainWindow.page) + MainWindow.page_2 = QtWidgets.QWidget() + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.page_2.sizePolicy().hasHeightForWidth()) + MainWindow.page_2.setSizePolicy(sizePolicy) + MainWindow.page_2.setStyleSheet("QWidget{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.page_2.setObjectName("page_2") + MainWindow.verticalLayout_3 = QtWidgets.QVBoxLayout(MainWindow.page_2) + MainWindow.verticalLayout_3.setObjectName("verticalLayout_3") + MainWindow.graphicsView = QtWidgets.QGraphicsView(MainWindow.page_2) + MainWindow.graphicsView.setMinimumSize(QtCore.QSize(661, 401)) + MainWindow.graphicsView.viewport().setProperty("cursor", QtGui.QCursor(QtCore.Qt.ArrowCursor)) + MainWindow.graphicsView.setMouseTracking(True) + MainWindow.graphicsView.setStyleSheet("QGraphicsView{\n" +" background: rgb(255,255,255);\n" +" border: 2px solid rgb(0,0,128);\n" +"}") + MainWindow.graphicsView.setObjectName("graphicsView") + MainWindow.verticalLayout_3.addWidget(MainWindow.graphicsView) + MainWindow.stackedWidget.addWidget(MainWindow.page_2) + MainWindow.horizontalLayout.addWidget(MainWindow.stackedWidget) + MainWindow.stackedWidgetRight = QtWidgets.QStackedWidget(MainWindow.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.stackedWidgetRight.sizePolicy().hasHeightForWidth()) + MainWindow.stackedWidgetRight.setSizePolicy(sizePolicy) + MainWindow.stackedWidgetRight.setMinimumSize(QtCore.QSize(200, 401)) + MainWindow.stackedWidgetRight.setStyleSheet("QStackedWidget{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.stackedWidgetRight.setObjectName("stackedWidgetRight") + MainWindow.page_5 = QtWidgets.QWidget() + MainWindow.page_5.setStyleSheet("QWidget{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.page_5.setObjectName("page_5") + MainWindow.verticalLayout_14 = QtWidgets.QVBoxLayout(MainWindow.page_5) + MainWindow.verticalLayout_14.setObjectName("verticalLayout_14") + MainWindow.verticalLayout_15 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_15.setObjectName("verticalLayout_15") + MainWindow.widget = QtWidgets.QWidget(MainWindow.page_5) + MainWindow.widget.setStyleSheet("QWidget{\n" +" background: rgb(255,255,255);\n" +" border: 2px solid rgb(0,0,128);\n" +"}") + MainWindow.widget.setObjectName("widget") + MainWindow.gridLayout_3 = QtWidgets.QGridLayout(MainWindow.widget) + MainWindow.gridLayout_3.setObjectName("gridLayout_3") + MainWindow.label_4 = QtWidgets.QLabel(MainWindow.widget) + MainWindow.label_4.setStyleSheet("QLabel{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.label_4.setObjectName("label_4") + MainWindow.gridLayout_3.addWidget(MainWindow.label_4, 5, 0, 1, 1) + MainWindow.elSizeSpinBox = QtWidgets.QDoubleSpinBox(MainWindow.widget) + MainWindow.elSizeSpinBox.setStyleSheet("QDoubleSpinBox{\n" +" background: rgb(255,255,255);\n" +" border: 1px solid rgb(0,0,128);\n" +"}") + MainWindow.elSizeSpinBox.setDecimals(1) + MainWindow.elSizeSpinBox.setMinimum(0.0) + MainWindow.elSizeSpinBox.setMaximum(1000.0) + MainWindow.elSizeSpinBox.setSingleStep(5.0) + MainWindow.elSizeSpinBox.setProperty("value", 25.0) + MainWindow.elSizeSpinBox.setObjectName("elSizeSpinBox") + MainWindow.gridLayout_3.addWidget(MainWindow.elSizeSpinBox, 5, 1, 1, 1) + MainWindow.radioButtonQuadrangle = QtWidgets.QRadioButton(MainWindow.widget) + MainWindow.radioButtonQuadrangle.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonQuadrangle.setChecked(False) + MainWindow.radioButtonQuadrangle.setObjectName("radioButtonQuadrangle") + MainWindow.gridLayout_3.addWidget(MainWindow.radioButtonQuadrangle, 2, 1, 1, 1) + spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + MainWindow.gridLayout_3.addItem(spacerItem5, 10, 0, 1, 1) + MainWindow.label_5 = QtWidgets.QLabel(MainWindow.widget) + MainWindow.label_5.setStyleSheet("QLabel{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.label_5.setObjectName("label_5") + MainWindow.gridLayout_3.addWidget(MainWindow.label_5, 7, 0, 1, 1) + MainWindow.DOFSpinBox = QtWidgets.QSpinBox(MainWindow.widget) + MainWindow.DOFSpinBox.setStyleSheet("QSpinBox{\n" +" background: rgb(255,255,255);\n" +" border: 1px solid rgb(0,0,128);\n" +"}") + MainWindow.DOFSpinBox.setMinimum(1) + MainWindow.DOFSpinBox.setObjectName("DOFSpinBox") + MainWindow.gridLayout_3.addWidget(MainWindow.DOFSpinBox, 7, 1, 1, 1) + MainWindow.radioButtonTriangle = QtWidgets.QRadioButton(MainWindow.widget) + MainWindow.radioButtonTriangle.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonTriangle.setChecked(True) + MainWindow.radioButtonTriangle.setObjectName("radioButtonTriangle") + MainWindow.gridLayout_3.addWidget(MainWindow.radioButtonTriangle, 0, 1, 1, 1) + spacerItem6 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + MainWindow.gridLayout_3.addItem(spacerItem6, 4, 1, 1, 1) + spacerItem7 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + MainWindow.gridLayout_3.addItem(spacerItem7, 6, 1, 1, 1) + MainWindow.label_2 = QtWidgets.QLabel(MainWindow.widget) + MainWindow.label_2.setStyleSheet("QLabel{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.label_2.setObjectName("label_2") + MainWindow.gridLayout_3.addWidget(MainWindow.label_2, 0, 0, 1, 1) + spacerItem8 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + MainWindow.gridLayout_3.addItem(spacerItem8, 8, 1, 1, 1) + MainWindow.refreshMeshButton = QtWidgets.QPushButton(MainWindow.widget) + MainWindow.refreshMeshButton.setObjectName("refreshMeshButton") + MainWindow.gridLayout_3.addWidget(MainWindow.refreshMeshButton, 9, 1, 1, 1) + MainWindow.verticalLayout_15.addWidget(MainWindow.widget) + MainWindow.verticalLayout_14.addLayout(MainWindow.verticalLayout_15) + MainWindow.stackedWidgetRight.addWidget(MainWindow.page_5) + MainWindow.page_6 = QtWidgets.QWidget() + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.page_6.sizePolicy().hasHeightForWidth()) + MainWindow.page_6.setSizePolicy(sizePolicy) + MainWindow.page_6.setStyleSheet("QWidget{\n" +" background: rgba(255,255,255,0);\n" +"}") + MainWindow.page_6.setObjectName("page_6") + MainWindow.verticalLayout_16 = QtWidgets.QVBoxLayout(MainWindow.page_6) + MainWindow.verticalLayout_16.setObjectName("verticalLayout_16") + MainWindow.scrollArea = QtWidgets.QScrollArea(MainWindow.page_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(MainWindow.scrollArea.sizePolicy().hasHeightForWidth()) + MainWindow.scrollArea.setSizePolicy(sizePolicy) + MainWindow.scrollArea.setMinimumSize(QtCore.QSize(200, 300)) + MainWindow.scrollArea.setStyleSheet("QScrollArea{\n" +" background: rgb(255,255,255);\n" +" border: 2px solid rgb(0,0,128);\n" +"}") + MainWindow.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored) + MainWindow.scrollArea.setWidgetResizable(True) + MainWindow.scrollArea.setObjectName("scrollArea") + MainWindow.scrollAreaWidgetContents_2 = QtWidgets.QWidget() + MainWindow.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 196, 296)) + MainWindow.scrollAreaWidgetContents_2.setStyleSheet("QWidget{\n" +" background: rgb(255,255,255);\n" +"}") + MainWindow.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2") + MainWindow.scrollArea.setWidget(MainWindow.scrollAreaWidgetContents_2) + MainWindow.verticalLayout_16.addWidget(MainWindow.scrollArea) + spacerItem9 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + MainWindow.verticalLayout_16.addItem(spacerItem9) + MainWindow.stackedWidgetRight.addWidget(MainWindow.page_6) + MainWindow.page_7 = QtWidgets.QWidget() + MainWindow.page_7.setObjectName("page_7") + MainWindow.verticalLayout_5 = QtWidgets.QVBoxLayout(MainWindow.page_7) + MainWindow.verticalLayout_5.setObjectName("verticalLayout_5") + MainWindow.widget_2 = QtWidgets.QWidget(MainWindow.page_7) + MainWindow.widget_2.setStyleSheet("QWidget{\n" +" background: rgb(255,255,255);\n" +" border: 2px solid rgb(0,0,128);\n" +"}") + MainWindow.widget_2.setObjectName("widget_2") + MainWindow.gridLayout_4 = QtWidgets.QGridLayout(MainWindow.widget_2) + MainWindow.gridLayout_4.setObjectName("gridLayout_4") + spacerItem10 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + MainWindow.gridLayout_4.addItem(spacerItem10, 2, 1, 1, 1) + MainWindow.radioButtonDisplayPointLabelsTrue = QtWidgets.QRadioButton(MainWindow.widget_2) + MainWindow.radioButtonDisplayPointLabelsTrue.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonDisplayPointLabelsTrue.setChecked(True) + MainWindow.radioButtonDisplayPointLabelsTrue.setObjectName("radioButtonDisplayPointLabelsTrue") + MainWindow.buttonGroupDisplayPointLabels = QtWidgets.QButtonGroup(MainWindow) + MainWindow.buttonGroupDisplayPointLabels.setObjectName("buttonGroupDisplayPointLabels") + MainWindow.buttonGroupDisplayPointLabels.addButton(MainWindow.radioButtonDisplayPointLabelsTrue) + MainWindow.gridLayout_4.addWidget(MainWindow.radioButtonDisplayPointLabelsTrue, 3, 1, 1, 1) + MainWindow.radioButtonDisplayEdgeLabelsTrue = QtWidgets.QRadioButton(MainWindow.widget_2) + MainWindow.radioButtonDisplayEdgeLabelsTrue.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonDisplayEdgeLabelsTrue.setChecked(True) + MainWindow.radioButtonDisplayEdgeLabelsTrue.setObjectName("radioButtonDisplayEdgeLabelsTrue") + MainWindow.buttonGroupDOFsPerNode = QtWidgets.QButtonGroup(MainWindow) + MainWindow.buttonGroupDOFsPerNode.setObjectName("buttonGroupDOFsPerNode") + MainWindow.buttonGroupDOFsPerNode.addButton(MainWindow.radioButtonDisplayEdgeLabelsTrue) + MainWindow.gridLayout_4.addWidget(MainWindow.radioButtonDisplayEdgeLabelsTrue, 6, 1, 1, 1) + MainWindow.radioButtonDisplayPointLabelsFalse = QtWidgets.QRadioButton(MainWindow.widget_2) + MainWindow.radioButtonDisplayPointLabelsFalse.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonDisplayPointLabelsFalse.setObjectName("radioButtonDisplayPointLabelsFalse") + MainWindow.buttonGroupDisplayPointLabels.addButton(MainWindow.radioButtonDisplayPointLabelsFalse) + MainWindow.gridLayout_4.addWidget(MainWindow.radioButtonDisplayPointLabelsFalse, 4, 1, 1, 1) + MainWindow.radioButtonDrawPointFalse = QtWidgets.QRadioButton(MainWindow.widget_2) + MainWindow.radioButtonDrawPointFalse.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonDrawPointFalse.setObjectName("radioButtonDrawPointFalse") + MainWindow.buttonGroupDrawPoints = QtWidgets.QButtonGroup(MainWindow) + MainWindow.buttonGroupDrawPoints.setObjectName("buttonGroupDrawPoints") + MainWindow.buttonGroupDrawPoints.addButton(MainWindow.radioButtonDrawPointFalse) + MainWindow.gridLayout_4.addWidget(MainWindow.radioButtonDrawPointFalse, 1, 1, 1, 1) + MainWindow.radioButtonDrawPointTrue = QtWidgets.QRadioButton(MainWindow.widget_2) + MainWindow.radioButtonDrawPointTrue.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonDrawPointTrue.setChecked(True) + MainWindow.radioButtonDrawPointTrue.setObjectName("radioButtonDrawPointTrue") + MainWindow.buttonGroupDrawPoints.addButton(MainWindow.radioButtonDrawPointTrue) + MainWindow.gridLayout_4.addWidget(MainWindow.radioButtonDrawPointTrue, 0, 1, 1, 1) + MainWindow.label_8 = QtWidgets.QLabel(MainWindow.widget_2) + MainWindow.label_8.setStyleSheet("QLabel{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.label_8.setObjectName("label_8") + MainWindow.gridLayout_4.addWidget(MainWindow.label_8, 3, 0, 1, 1) + MainWindow.label_6 = QtWidgets.QLabel(MainWindow.widget_2) + MainWindow.label_6.setStyleSheet("QLabel{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.label_6.setObjectName("label_6") + MainWindow.gridLayout_4.addWidget(MainWindow.label_6, 0, 0, 1, 1) + MainWindow.label_7 = QtWidgets.QLabel(MainWindow.widget_2) + MainWindow.label_7.setStyleSheet("QLabel{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.label_7.setObjectName("label_7") + MainWindow.gridLayout_4.addWidget(MainWindow.label_7, 6, 0, 1, 1) + spacerItem11 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + MainWindow.gridLayout_4.addItem(spacerItem11, 8, 0, 1, 1) + MainWindow.radioButtonDisplayEdgeLabelsFalse = QtWidgets.QRadioButton(MainWindow.widget_2) + MainWindow.radioButtonDisplayEdgeLabelsFalse.setStyleSheet("QRadioButton{\n" +" background: rgb(255,255,255);\n" +" border: 0px solid rgb(0,0,128);\n" +"}") + MainWindow.radioButtonDisplayEdgeLabelsFalse.setObjectName("radioButtonDisplayEdgeLabelsFalse") + MainWindow.buttonGroupDOFsPerNode.addButton(MainWindow.radioButtonDisplayEdgeLabelsFalse) + MainWindow.gridLayout_4.addWidget(MainWindow.radioButtonDisplayEdgeLabelsFalse, 7, 1, 1, 1) + spacerItem12 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + MainWindow.gridLayout_4.addItem(spacerItem12, 5, 1, 1, 1) + MainWindow.verticalLayout_5.addWidget(MainWindow.widget_2) + MainWindow.stackedWidgetRight.addWidget(MainWindow.page_7) + MainWindow.horizontalLayout.addWidget(MainWindow.stackedWidgetRight) + MainWindow.verticalLayout_2.addLayout(MainWindow.horizontalLayout) + MainWindow.horizontalLayout_7 = QtWidgets.QHBoxLayout() + MainWindow.horizontalLayout_7.setObjectName("horizontalLayout_7") + spacerItem13 = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + MainWindow.horizontalLayout_7.addItem(spacerItem13) + MainWindow.verticalLayout_17 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_17.setObjectName("verticalLayout_17") + MainWindow.textBrowser = QtWidgets.QTextBrowser(MainWindow.centralwidget) + MainWindow.textBrowser.setMaximumSize(QtCore.QSize(16777215, 150)) + MainWindow.textBrowser.setStyleSheet("QTextBrowser{\n" +"border: 2px solid rgb(0,0,128);\n" +"background: rgb(255,255,255);\n" +"}") + MainWindow.textBrowser.setObjectName("textBrowser") + MainWindow.verticalLayout_17.addWidget(MainWindow.textBrowser) + MainWindow.horizontalLayout_7.addLayout(MainWindow.verticalLayout_17) + MainWindow.verticalLayout_18 = QtWidgets.QVBoxLayout() + MainWindow.verticalLayout_18.setObjectName("verticalLayout_18") + MainWindow.hideTextBrowserButton = QtWidgets.QToolButton(MainWindow.centralwidget) + MainWindow.hideTextBrowserButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}") + MainWindow.hideTextBrowserButton.setText("") + icon18 = QtGui.QIcon() + icon18.addPixmap(QtGui.QPixmap(":/Images/minus.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.hideTextBrowserButton.setIcon(icon18) + MainWindow.hideTextBrowserButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.hideTextBrowserButton.setObjectName("hideTextBrowserButton") + MainWindow.verticalLayout_18.addWidget(MainWindow.hideTextBrowserButton) + MainWindow.showTextBrowserButton = QtWidgets.QToolButton(MainWindow.centralwidget) + MainWindow.showTextBrowserButton.setEnabled(True) + MainWindow.showTextBrowserButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}") + MainWindow.showTextBrowserButton.setText("") + icon19 = QtGui.QIcon() + icon19.addPixmap(QtGui.QPixmap(":/Images/plus.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.showTextBrowserButton.setIcon(icon19) + MainWindow.showTextBrowserButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.showTextBrowserButton.setObjectName("showTextBrowserButton") + MainWindow.verticalLayout_18.addWidget(MainWindow.showTextBrowserButton) + MainWindow.clearTextBrowserButton = QtWidgets.QToolButton(MainWindow.centralwidget) + MainWindow.clearTextBrowserButton.setStyleSheet("QToolButton{\n" +" border: 0px;\n" +"}\n" +"\n" +"QToolButton:pressed {\n" +" background-color: rgb(185, 211, 220);\n" +"}\n" +"\n" +"QToolButton:hover {\n" +" background-color: rgba(185, 211, 220,100);\n" +"}\n" +"") + MainWindow.clearTextBrowserButton.setText("") + MainWindow.clearTextBrowserButton.setIcon(icon9) + MainWindow.clearTextBrowserButton.setIconSize(QtCore.QSize(24, 24)) + MainWindow.clearTextBrowserButton.setObjectName("clearTextBrowserButton") + MainWindow.verticalLayout_18.addWidget(MainWindow.clearTextBrowserButton) + MainWindow.horizontalLayout_7.addLayout(MainWindow.verticalLayout_18) + MainWindow.verticalLayout_2.addLayout(MainWindow.horizontalLayout_7) + MainWindow.setCentralWidget(MainWindow.centralwidget) + MainWindow.menubar = QtWidgets.QMenuBar(MainWindow) + MainWindow.menubar.setGeometry(QtCore.QRect(0, 0, 1493, 21)) + MainWindow.menubar.setObjectName("menubar") + MainWindow.setMenuBar(MainWindow.menubar) + MainWindow.statusbar = QtWidgets.QStatusBar(MainWindow) + MainWindow.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(MainWindow.statusbar) + + self.retranslateUi(MainWindow) + MainWindow.tabWidget.setCurrentIndex(0) + MainWindow.stackedWidget.setCurrentIndex(1) + MainWindow.stackedWidgetRight.setCurrentIndex(1) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + MainWindow.zoomOutButtonSurface.setText(_translate("MainWindow", "Zoom Out")) + MainWindow.arrowButtonSurface.setText(_translate("MainWindow", "Arrow")) + MainWindow.panningButtonSurface.setText(_translate("MainWindow", "Panning")) + MainWindow.zoomInButtonSurface.setText(_translate("MainWindow", "Zoom In")) + MainWindow.polyButton.setText(_translate("MainWindow", "Draw Polygon")) + MainWindow.rectButton.setText(_translate("MainWindow", "Draw Rectangle")) + MainWindow.addPolyHoleButton.setText(_translate("MainWindow", "Draw Polygon Hole")) + MainWindow.addRectHoleButton.setText(_translate("MainWindow", "Draw Rectangle Hole")) + MainWindow.mergeButton.setText(_translate("MainWindow", "Merge Overlapping Geometries")) + MainWindow.deleteButton.setText(_translate("MainWindow", "Delete Item")) + MainWindow.gridSnapButtonSurface.setText(_translate("MainWindow", "Toggle Gridsnap")) + MainWindow.gridButtonSurface.setText(_translate("MainWindow", "Toggle Grid")) + MainWindow.gridSpacingButton.setText(_translate("MainWindow", "Set Grid Spacing")) + MainWindow.loadGeometryButton.setText(_translate("MainWindow", "Load Geometry")) + MainWindow.tabWidget.setTabText(MainWindow.tabWidget.indexOf(MainWindow.tab_2), _translate("MainWindow", "Page")) + MainWindow.arrowButtonBorder.setText(_translate("MainWindow", "Arrow")) + MainWindow.zoomOutButtonBorder.setText(_translate("MainWindow", "Zoom Out")) + MainWindow.zoomInButtonBorder.setText(_translate("MainWindow", "Zoom In")) + MainWindow.panningButtonBorder.setText(_translate("MainWindow", "Panning")) + MainWindow.setMarkerButton.setText(_translate("MainWindow", "Set Marker")) + MainWindow.splitEdgeButton.setText(_translate("MainWindow", "Split Edge")) + MainWindow.gridSnapButtonBorder.setText(_translate("MainWindow", "Toggle Gridsnap")) + MainWindow.gridButtonBorder.setText(_translate("MainWindow", "Toggle Grid")) + MainWindow.tabWidget.setTabText(MainWindow.tabWidget.indexOf(MainWindow.tab), _translate("MainWindow", "Tab 1")) + MainWindow.saveGeomButton.setText(_translate("MainWindow", "Save Geometry")) + MainWindow.tabWidget.setTabText(MainWindow.tabWidget.indexOf(MainWindow.tab_4), _translate("MainWindow", "Page")) + MainWindow.saveMeshButton.setText(_translate("MainWindow", "Save Mesh")) + MainWindow.saveArraysButton.setText(_translate("MainWindow", "Save Mesh Arrays")) + MainWindow.saveArraysMatlabButton.setText(_translate("MainWindow", "Save Mesh Arrays to Matlab")) + MainWindow.tabWidget.setTabText(MainWindow.tabWidget.indexOf(MainWindow.tab_3), _translate("MainWindow", "Page")) + MainWindow.label.setText(_translate("MainWindow", "x: ")) + MainWindow.labelX.setText(_translate("MainWindow", "TextLabel")) + MainWindow.label_3.setText(_translate("MainWindow", "y:")) + MainWindow.labelY.setText(_translate("MainWindow", "TextLabel")) + MainWindow.label_4.setText(_translate("MainWindow", "Element Size:")) + MainWindow.radioButtonQuadrangle.setText(_translate("MainWindow", "Quadrangle")) + MainWindow.label_5.setText(_translate("MainWindow", "DOFs per Node:")) + MainWindow.radioButtonTriangle.setText(_translate("MainWindow", "Triangle")) + MainWindow.label_2.setText(_translate("MainWindow", "Element Type:")) + MainWindow.refreshMeshButton.setText(_translate("MainWindow", "Refresh Mesh")) + MainWindow.radioButtonDisplayPointLabelsTrue.setText(_translate("MainWindow", "True")) + MainWindow.radioButtonDisplayEdgeLabelsTrue.setText(_translate("MainWindow", "True")) + MainWindow.radioButtonDisplayPointLabelsFalse.setText(_translate("MainWindow", "False")) + MainWindow.radioButtonDrawPointFalse.setText(_translate("MainWindow", "False")) + MainWindow.radioButtonDrawPointTrue.setText(_translate("MainWindow", "True")) + MainWindow.label_8.setText(_translate("MainWindow", "Display Point Labels:")) + MainWindow.label_6.setText(_translate("MainWindow", "Draw Points:")) + MainWindow.label_7.setText(_translate("MainWindow", "Display Edge Labels")) + MainWindow.radioButtonDisplayEdgeLabelsFalse.setText(_translate("MainWindow", "False")) + MainWindow.textBrowser.setHtml(_translate("MainWindow", "\n" +"
\n" +"