In [1]:
    
from pint import UnitRegistry
import sympy
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import sys
%matplotlib inline
from IPython.display import display
    
Import Section class, which contains all calculations
In [2]:
    
from Section import Section
    
Initialization of sympy symbolic tool and pint for dimension analysis (not really implemented rn as not directly compatible with sympy)
In [3]:
    
ureg = UnitRegistry()
sympy.init_printing()
    
Define sympy parameters used for geometric description of sections
In [4]:
    
A, A0, t, t0, a, b, h, L, E, G = sympy.symbols('A A_0 t t_0 a b h L E G', positive=True)
    
We also define numerical values for each symbol in order to plot scaled section and perform calculations
In [5]:
    
values = [(A, 150 * ureg.millimeter**2),(A0, 250  * ureg.millimeter**2),(a, 80 * ureg.millimeter), \
          (b, 20 * ureg.millimeter),(h, 200 * ureg.millimeter),(L, 2000 * ureg.millimeter), \
          (t, 1.3 *ureg.millimeter),(E, 72e3 * ureg.MPa), (G, 27e3 * ureg.MPa)]
datav = [(v[0],v[1].magnitude) for v in values]
    
Define graph describing the section:
1) stringers are nodes with parameters:
2) panels are oriented edges with parameters:
In [6]:
    
stringers = {1:[(a+2*b,h),A],
             2:[(b+sympy.Rational(1,2)*a,h),A],
             3:[(sympy.Integer(0),h),A],
             4:[(b,sympy.Integer(0)),A],
             5:[(b+a,sympy.Integer(0)),A]}
             #5:[(sympy.Rational(1,2)*a,h),A]}
panels = {(1,2):t,
          (2,3):t,
          (3,4):t,
          (4,5):t,
          (5,1):t}
    
Define section and perform first calculations
In [7]:
    
S1 = Section(stringers, panels)
    
In [8]:
    
S1.cycles
    
    Out[8]:
Define a dictionary of coordinates used by Networkx to plot section as a Directed graph. Note that arrows are actually just thicker stubs
In [9]:
    
start_pos={ii: [float(S1.g.node[ii]['ip'][i].subs(datav)) for i in range(2)] for ii in S1.g.nodes() }
    
In [10]:
    
plt.figure(figsize=(12,8),dpi=300)
nx.draw(S1.g,with_labels=True, arrows= True, pos=start_pos)
plt.arrow(0,0,20,0)
plt.arrow(0,0,0,20)
#plt.text(0,0, 'CG', fontsize=24)
plt.axis('equal')
plt.title("Section in starting reference Frame",fontsize=16);
    
    
Section is plotted wrt center of gravity and rotated (if necessary) so that x and y are principal axes. Center of Gravity and Shear Center are drawn
In [11]:
    
positions={ii: [float(S1.g.node[ii]['pos'][i].subs(datav)) for i in range(2)] for ii in S1.g.nodes() }
    
In [12]:
    
x_ct, y_ct = S1.ct.subs(datav)
plt.figure(figsize=(12,8),dpi=300)
nx.draw(S1.g,with_labels=True, pos=positions)
plt.plot([0],[0],'o',ms=12,label='CG')
plt.plot([x_ct],[y_ct],'^',ms=12, label='SC')
#plt.text(0,0, 'CG', fontsize=24)
#plt.text(x_ct,y_ct, 'SC', fontsize=24)
plt.legend(loc='lower right', shadow=True)
plt.axis('equal')
plt.title("Section in pricipal reference Frame",fontsize=16);
    
    
In [13]:
    
Tx, Ty, Nz, Mx, My, Mz, F, ry, ry, mz = sympy.symbols('T_x T_y N_z M_x M_y M_z F r_y r_x m_z')
    
In [14]:
    
S1.set_loads(_Tx=0, _Ty=Ty, _Nz=0, _Mx=Mx, _My=0, _Mz=Mz)
    
In [15]:
    
S1.compute_stringer_actions()
S1.compute_panel_fluxes();
    
In [16]:
    
S1.N
    
    Out[16]:
In [17]:
    
S1.q
    
    Out[17]:
Compute L matrix: with 5 nodes we expect 2 dofs, one with symmetric load and one with antisymmetric load
In [18]:
    
S1.compute_L()
    
In [19]:
    
S1.L.subs(datav)
    
    Out[19]:
Compute H matrix
In [20]:
    
S1.compute_H()
    
In [23]:
    
S1.H.subs(datav)
    
    Out[23]:
Compute $\tilde{K}$ and $\tilde{M}$ as:
$$\tilde{K} = L^T \cdot \left[ \frac{A}{A_0} \right] \cdot L$$$$\tilde{M} = H^T \cdot \left[ \frac{l}{l_0}\frac{t_0}{t} \right] \cdot L$$
In [24]:
    
S1.compute_KM(A,b,t)
    
In [25]:
    
S1.Ktilde.subs(datav)
    
    Out[25]:
In [26]:
    
S1.Mtilde.subs(datav)
    
    Out[26]:
Compute eigenvalues and eigenvectors as:
$$\left| \mathbf{I} \cdot \beta^2 - \mathbf{\tilde{K}}^{-1} \cdot \mathbf{\tilde{M}} \right| = 0$$We substitute some numerical values to simplify the expressions
In [28]:
    
sol_data = (sympy.N(S1.Ktilde.subs(datav).inv())*(sympy.N(S1.Mtilde.subs(datav)))).eigenvects()
    
Eigenvalues correspond to $\beta^2$
In [29]:
    
β2 = [sol[0] for sol in sol_data]
β2
    
    Out[29]:
Eigenvectors are orthogonal as expected
In [30]:
    
X = [sol[2][0] for sol in sol_data]
X
    
    Out[30]:
From $\beta_i^2$ we compute: $$\lambda_i = \sqrt{\frac{E A_0 l_0}{G t_0} \beta_i^2}$$
substuting numerical values
In [32]:
    
λ = [sympy.N(sympy.sqrt(E*A*b/(G*t)*βi).subs(datav)) for βi in β2]
λ
    
    Out[32]:
In [ ]: