# Rectangular Plate Bending Element

This derivation follows the procedure given in Chapter 12 of "A First Course in the Finite Element Method, 4th Edition" by Daryl L. Logan. Logan's method has been improved upon to allow for orthotropic behavior. Closed form solutions for stiffness and load matrices are provided.

We'll start by importing a few Python libraries that are useful for symbolic math, and initializing "pretty" printing.

```python
from sympy import symbols, Matrix, diff, integrate, simplify, factor, latex, init_printing
from IPython.display import display, Math
init_printing()
```

The plate width will be defined as $2b$, and the height will be $2c$ to be consistent with Figure 12-1. We'll set up some Sympy symbols to represent $b$ and $c$.

```python
b, c = symbols('b, c')
```

The plate is defined by four nodes specified in counter-clockwise order: i, j, m, and n. The local x-axis runs from node i toward node j, and the local y-axis runs from node i toward node n. Next we'll define the element's local displacement vector, $[d]$, at each node. There are 3 degrees of freedom at each node: $w$, $\theta_x$, and $\theta_y$.

```python
wi, theta_xi, theta_yi = symbols('w_i, theta_x_i, theta_yi')
wj, theta_xj, theta_yj = symbols('w_j, theta_xj, theta_yj')
wm, theta_xm, theta_ym = symbols('w_m, theta_xm, theta_ym')
wn, theta_xn, theta_yn = symbols('w_n, theta_xn, theta_yn')
d = Matrix([wi, theta_xi, theta_yi, wj, theta_xj, theta_yj, wm, theta_xm, theta_ym, wn, theta_xn, theta_yn])
display(Math('[d] = ' + latex(d)))
```

$\displaystyle [d] = \left[\begin{matrix}w_{i}\\\theta_{x i}\\\theta_{yi}\\w_{j}\\\theta_{xj}\\\theta_{yj}\\w_{m}\\\theta_{xm}\\\theta_{ym}\\w_{n}\\\theta_{xn}\\\theta_{yn}\end{matrix}\right]$

A 12-term polynomial displacement function will be assumed to define the out-of-plane displacement, w, at any point (x, y) in the plate's local coordinate system. The rotations about each axis are derivatives of this displacement:

```python
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 = symbols('a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, a_10, a_11, a_12')
x, y, w, theta_x, theta_y = symbols('x, y, w, theta_x, theta_y')

w = a1 + a2*x + a3*y + a4*x**2 + a5*x*y + a6*y**2 + a7*x**3 + a8*x**2*y + a9*x*y**2 + a10*y**3 + a11*x**3*y + a12*x*y**3
theta_x = diff(w, y)
theta_y = -diff(w, x)

display(Math('w = ' + latex(w)))
display(Math('\\theta_x = ' + latex(theta_x)))
display(Math('\\theta_y = ' + latex(theta_y)))
```

$\displaystyle w = a_{1} + a_{10} y^{3} + a_{11} x^{3} y + a_{12} x y^{3} + a_{2} x + a_{3} y + a_{4} x^{2} + a_{5} x y + a_{6} y^{2} + a_{7} x^{3} + a_{8} x^{2} y + a_{9} x y^{2}$

$\displaystyle \theta_x = 3 a_{10} y^{2} + a_{11} x^{3} + 3 a_{12} x y^{2} + a_{3} + a_{5} x + 2 a_{6} y + a_{8} x^{2} + 2 a_{9} x y$

$\displaystyle \theta_y = - 3 a_{11} x^{2} y - a_{12} y^{3} - a_{2} - 2 a_{4} x - a_{5} y - 3 a_{7} x^{2} - 2 a_{8} x y - a_{9} y^{2}$

The negative sign on $\frac{dw}{dx}$ is required to be consistent with the right hand rule. These equations can be rewritten in matrix form as follows:

$[\psi] = [P][a]$

where $[\psi]$ is shorthand for  $\begin{bmatrix} w \\ \theta_x \\ \theta_y \end{bmatrix}$ and $[P]$ is defined as follows:

```python
P = Matrix([[1, x, y, x**2, x*y, y**2, x**3, x**2*y, x*y**2, y**3, x**3*y, x*y**3],
            [0, 0, 1, 0, x, 2*y, 0, x**2, 2*x*y, 3*y**2, x**3, 3*x*y**2],
            [0, -1, 0, -2*x, -y, 0, -3*x**2, -2*x*y, -y**2, 0, -3*x**2*y, -y**3]])

display(Math('P = ' + latex(P)))
```

$\displaystyle P = \left[\begin{array}{cccccccccccc}1 & x & y & x^{2} & x y & y^{2} & x^{3} & x^{2} y & x y^{2} & y^{3} & x^{3} y & x y^{3}\\0 & 0 & 1 & 0 & x & 2 y & 0 & x^{2} & 2 x y & 3 y^{2} & x^{3} & 3 x y^{2}\\0 & -1 & 0 & - 2 x & - y & 0 & - 3 x^{2} & - 2 x y & - y^{2} & 0 & - 3 x^{2} y & - y^{3}\end{array}\right]$

This general equation for $[P]$ will be evaluated at each node to give us a larger set of equations:

$[d] = [C][a]$

where $[C]$ is merely $[P]$ evaluated at each node, and $[d]$ is correpsondingly $[\psi]$ at each node. Knowing that the plate width is $2b$ and the plate height is $2c$, we can obtain the matrix $[C]$.

```python
C = Matrix([P, P, P, P])
C[0:3, 0:12] = C[0:3, 0:12].subs(x, 0).subs(y, 0)      # i-node @ x = 0, y = 0
C[3:6, 0:12] = C[3:6, 0:12].subs(x, 2*b).subs(y, 0)    # j-node @ x = 2b, y = 0
C[6:9, 0:12] = C[6:9, 0:12].subs(x, 2*b).subs(y, 2*c)  # m-node @ x = 2b, y = 2c
C[9:12, 0:12] = C[9:12, 0:12].subs(x, 0).subs(y, 2*c)  # n-node @ x = 0, y = 2c
display(Math('[C] = ' + latex(C)))
print(C)
```

$\displaystyle [C] = \left[\begin{array}{cccccccccccc}1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\1 & 2 b & 0 & 4 b^{2} & 0 & 0 & 8 b^{3} & 0 & 0 & 0 & 0 & 0\\0 & 0 & 1 & 0 & 2 b & 0 & 0 & 4 b^{2} & 0 & 0 & 8 b^{3} & 0\\0 & -1 & 0 & - 4 b & 0 & 0 & - 12 b^{2} & 0 & 0 & 0 & 0 & 0\\1 & 2 b & 2 c & 4 b^{2} & 4 b c & 4 c^{2} & 8 b^{3} & 8 b^{2} c & 8 b c^{2} & 8 c^{3} & 16 b^{3} c & 16 b c^{3}\\0 & 0 & 1 & 0 & 2 b & 4 c & 0 & 4 b^{2} & 8 b c & 12 c^{2} & 8 b^{3} & 24 b c^{2}\\0 & -1 & 0 & - 4 b & - 2 c & 0 & - 12 b^{2} & - 8 b c & - 4 c^{2} & 0 & - 24 b^{2} c & - 8 c^{3}\\1 & 0 & 2 c & 0 & 0 & 4 c^{2} & 0 & 0 & 0 & 8 c^{3} & 0 & 0\\0 & 0 & 1 & 0 & 0 & 4 c & 0 & 0 & 0 & 12 c^{2} & 0 & 0\\0 & -1 & 0 & 0 & - 2 c & 0 & 0 & 0 & - 4 c^{2} & 0 & 0 & - 8 c^{3}\end{array}\right]$

    Matrix([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 2*b, 0, 4*b**2, 0, 0, 8*b**3, 0, 0, 0, 0, 0], [0, 0, 1, 0, 2*b, 0, 0, 4*b**2, 0, 0, 8*b**3, 0], [0, -1, 0, -4*b, 0, 0, -12*b**2, 0, 0, 0, 0, 0], [1, 2*b, 2*c, 4*b**2, 4*b*c, 4*c**2, 8*b**3, 8*b**2*c, 8*b*c**2, 8*c**3, 16*b**3*c, 16*b*c**3], [0, 0, 1, 0, 2*b, 4*c, 0, 4*b**2, 8*b*c, 12*c**2, 8*b**3, 24*b*c**2], [0, -1, 0, -4*b, -2*c, 0, -12*b**2, -8*b*c, -4*c**2, 0, -24*b**2*c, -8*c**3], [1, 0, 2*c, 0, 0, 4*c**2, 0, 0, 0, 8*c**3, 0, 0], [0, 0, 1, 0, 0, 4*c, 0, 0, 0, 12*c**2, 0, 0], [0, -1, 0, 0, -2*c, 0, 0, 0, -4*c**2, 0, 0, -8*c**3]])

An important matrix that we will come back to later is the shape function matrix $[N]$, defined as:

$[N] = [P][C]^{-1}$

The closed form solution of $[N]$ for a rectangular plate is:

```python
N = P*C.inv()
display(Math('[N] = ' + latex(simplify(N))))
```

$\displaystyle [N] = \left[\begin{array}{cccccccccccc}1 - \frac{3 y^{2}}{4 c^{2}} + \frac{y^{3}}{4 c^{3}} - \frac{x y}{4 b c} + \frac{3 x y^{2}}{8 b c^{2}} - \frac{x y^{3}}{8 b c^{3}} - \frac{3 x^{2}}{4 b^{2}} + \frac{3 x^{2} y}{8 b^{2} c} + \frac{x^{3}}{4 b^{3}} - \frac{x^{3} y}{8 b^{3} c} & y - \frac{y^{2}}{c} + \frac{y^{3}}{4 c^{2}} - \frac{x y}{2 b} + \frac{x y^{2}}{2 b c} - \frac{x y^{3}}{8 b c^{2}} & - x + \frac{x y}{2 c} + \frac{x^{2}}{b} - \frac{x^{2} y}{2 b c} - \frac{x^{3}}{4 b^{2}} + \frac{x^{3} y}{8 b^{2} c} & \frac{x \left(2 b^{2} c^{2} y - 3 b^{2} c y^{2} + b^{2} y^{3} + 6 b c^{3} x - 3 b c^{2} x y - 2 c^{3} x^{2} + c^{2} x^{2} y\right)}{8 b^{3} c^{3}} & \frac{x y \left(4 c^{2} - 4 c y + y^{2}\right)}{8 b c^{2}} & \frac{x^{2} \left(4 b c - 2 b y - 2 c x + x y\right)}{8 b^{2} c} & \frac{x y \left(- 2 b^{2} c^{2} + 3 b^{2} c y - b^{2} y^{2} + 3 b c^{2} x - c^{2} x^{2}\right)}{8 b^{3} c^{3}} & \frac{x y^{2} \left(- 2 c + y\right)}{8 b c^{2}} & \frac{x^{2} y \left(2 b - x\right)}{8 b^{2} c} & \frac{y \left(6 b^{3} c y - 2 b^{3} y^{2} + 2 b^{2} c^{2} x - 3 b^{2} c x y + b^{2} x y^{2} - 3 b c^{2} x^{2} + c^{2} x^{3}\right)}{8 b^{3} c^{3}} & \frac{y^{2} \left(- 4 b c + 2 b y + 2 c x - x y\right)}{8 b c^{2}} & \frac{x y \left(- 4 b^{2} + 4 b x - x^{2}\right)}{8 b^{2} c}\\\frac{- 12 b^{3} c y + 6 b^{3} y^{2} - 2 b^{2} c^{2} x + 6 b^{2} c x y - 3 b^{2} x y^{2} + 3 b c^{2} x^{2} - c^{2} x^{3}}{8 b^{3} c^{3}} & 1 - \frac{2 y}{c} + \frac{3 y^{2}}{4 c^{2}} - \frac{x}{2 b} + \frac{x y}{b c} - \frac{3 x y^{2}}{8 b c^{2}} & \frac{x \left(4 b^{2} - 4 b x + x^{2}\right)}{8 b^{2} c} & \frac{x \left(2 b^{2} c^{2} - 6 b^{2} c y + 3 b^{2} y^{2} - 3 b c^{2} x + c^{2} x^{2}\right)}{8 b^{3} c^{3}} & \frac{x \left(4 c^{2} - 8 c y + 3 y^{2}\right)}{8 b c^{2}} & \frac{x^{2} \left(- 2 b + x\right)}{8 b^{2} c} & \frac{x \left(- 2 b^{2} c^{2} + 6 b^{2} c y - 3 b^{2} y^{2} + 3 b c^{2} x - c^{2} x^{2}\right)}{8 b^{3} c^{3}} & \frac{x y \left(- 4 c + 3 y\right)}{8 b c^{2}} & \frac{x^{2} \left(2 b - x\right)}{8 b^{2} c} & \frac{12 b^{3} c y - 6 b^{3} y^{2} + 2 b^{2} c^{2} x - 6 b^{2} c x y + 3 b^{2} x y^{2} - 3 b c^{2} x^{2} + c^{2} x^{3}}{8 b^{3} c^{3}} & \frac{y \left(- 8 b c + 6 b y + 4 c x - 3 x y\right)}{8 b c^{2}} & \frac{x \left(- 4 b^{2} + 4 b x - x^{2}\right)}{8 b^{2} c}\\\frac{2 b^{2} c^{2} y - 3 b^{2} c y^{2} + b^{2} y^{3} + 12 b c^{3} x - 6 b c^{2} x y - 6 c^{3} x^{2} + 3 c^{2} x^{2} y}{8 b^{3} c^{3}} & \frac{y \left(4 c^{2} - 4 c y + y^{2}\right)}{8 b c^{2}} & 1 - \frac{y}{2 c} - \frac{2 x}{b} + \frac{x y}{b c} + \frac{3 x^{2}}{4 b^{2}} - \frac{3 x^{2} y}{8 b^{2} c} & \frac{- 2 b^{2} c^{2} y + 3 b^{2} c y^{2} - b^{2} y^{3} - 12 b c^{3} x + 6 b c^{2} x y + 6 c^{3} x^{2} - 3 c^{2} x^{2} y}{8 b^{3} c^{3}} & \frac{y \left(- 4 c^{2} + 4 c y - y^{2}\right)}{8 b c^{2}} & \frac{x \left(- 8 b c + 4 b y + 6 c x - 3 x y\right)}{8 b^{2} c} & \frac{y \left(2 b^{2} c^{2} - 3 b^{2} c y + b^{2} y^{2} - 6 b c^{2} x + 3 c^{2} x^{2}\right)}{8 b^{3} c^{3}} & \frac{y^{2} \left(2 c - y\right)}{8 b c^{2}} & \frac{x y \left(- 4 b + 3 x\right)}{8 b^{2} c} & \frac{y \left(- 2 b^{2} c^{2} + 3 b^{2} c y - b^{2} y^{2} + 6 b c^{2} x - 3 c^{2} x^{2}\right)}{8 b^{3} c^{3}} & \frac{y^{2} \left(- 2 c + y\right)}{8 b c^{2}} & \frac{y \left(4 b^{2} - 8 b x + 3 x^{2}\right)}{8 b^{2} c}\end{array}\right]$

We can now solve for the $[a]$ matrix in terms of the nodal displacements:

```python
a = simplify(C.inv()*d)
display(Math('[a] = ' + latex(a)))
```

$\displaystyle [a] = \left[\begin{matrix}w_{i}\\- \theta_{yi}\\\theta_{x i}\\\frac{2 b \left(2 \theta_{yi} + \theta_{yj}\right) - 3 w_{i} + 3 w_{j}}{4 b^{2}}\\\frac{2 b \left(\theta_{yi} - \theta_{yn}\right) + 2 c \left(- \theta_{x i} + \theta_{xj}\right) - w_{i} + w_{j} - w_{m} + w_{n}}{4 b c}\\\frac{- 2 c \left(2 \theta_{x i} + \theta_{xn}\right) - 3 w_{i} + 3 w_{n}}{4 c^{2}}\\\frac{- b \left(\theta_{yi} + \theta_{yj}\right) + w_{i} - w_{j}}{4 b^{3}}\\\frac{2 b \left(- 2 \theta_{yi} - \theta_{yj} + \theta_{ym} + 2 \theta_{yn}\right) + 3 w_{i} - 3 w_{j} + 3 w_{m} - 3 w_{n}}{8 b^{2} c}\\\frac{2 c \left(2 \theta_{x i} - 2 \theta_{xj} - \theta_{xm} + \theta_{xn}\right) + 3 w_{i} - 3 w_{j} + 3 w_{m} - 3 w_{n}}{8 b c^{2}}\\\frac{c \left(\theta_{x i} + \theta_{xn}\right) + w_{i} - w_{n}}{4 c^{3}}\\\frac{b \left(\theta_{yi} + \theta_{yj} - \theta_{ym} - \theta_{yn}\right) - w_{i} + w_{j} - w_{m} + w_{n}}{8 b^{3} c}\\\frac{c \left(- \theta_{x i} + \theta_{xj} + \theta_{xm} - \theta_{xn}\right) - w_{i} + w_{j} - w_{m} + w_{n}}{8 b c^{3}}\end{matrix}\right]$

The next step is to define the curvature matrix:

$[\kappa] = \begin{bmatrix} -\frac{d^2w}{dx^2} \\ -\frac{d^2w}{dy^2} \\ -\frac{2d^2w}{dxdy} \end{bmatrix} = [Q][a]$

It should be recognized that $w/[a]$ is simply the first row of our $[P]$ matrix. Evaluating the derivatives in this expression gives $[Q]$ as follows:

```python
Q = Matrix([-diff(diff(P[0, :], x), x),
            -diff(diff(P[0, :], y), y),
            -2*diff(diff(P[0, :], x), y)])
display(Math('[Q] = ' + latex(Q)))
print(Q)
```

$\displaystyle [Q] = \left[\begin{array}{cccccccccccc}0 & 0 & 0 & -2 & 0 & 0 & - 6 x & - 2 y & 0 & 0 & - 6 x y & 0\\0 & 0 & 0 & 0 & 0 & -2 & 0 & 0 & - 2 x & - 6 y & 0 & - 6 x y\\0 & 0 & 0 & 0 & -2 & 0 & 0 & - 4 x & - 4 y & 0 & - 6 x^{2} & - 6 y^{2}\end{array}\right]$

    Matrix([[0, 0, 0, -2, 0, 0, -6*x, -2*y, 0, 0, -6*x*y, 0], [0, 0, 0, 0, 0, -2, 0, 0, -2*x, -6*y, 0, -6*x*y], [0, 0, 0, 0, -2, 0, 0, -4*x, -4*y, 0, -6*x**2, -6*y**2]])

With $[Q]$ in hand we can now solve for the $[B]$ matrix which is essential for formulating the stiffness matrix $[k]$

```python
B = simplify(Q*C.inv())
display(Math('[B] = ' + latex(B)))
```

$\displaystyle [B] = \left[\begin{array}{cccccccccccc}\frac{3 \left(2 b c - b y - 2 c x + x y\right)}{4 b^{3} c} & 0 & \frac{- 8 b c + 4 b y + 6 c x - 3 x y}{4 b^{2} c} & \frac{3 \left(- 2 b c + b y + 2 c x - x y\right)}{4 b^{3} c} & 0 & \frac{- 4 b c + 2 b y + 6 c x - 3 x y}{4 b^{2} c} & \frac{3 y \left(- b + x\right)}{4 b^{3} c} & 0 & \frac{y \left(- 2 b + 3 x\right)}{4 b^{2} c} & \frac{3 y \left(b - x\right)}{4 b^{3} c} & 0 & \frac{y \left(- 4 b + 3 x\right)}{4 b^{2} c}\\\frac{3 \left(2 b c - 2 b y - c x + x y\right)}{4 b c^{3}} & \frac{8 b c - 6 b y - 4 c x + 3 x y}{4 b c^{2}} & 0 & \frac{3 x \left(c - y\right)}{4 b c^{3}} & \frac{x \left(4 c - 3 y\right)}{4 b c^{2}} & 0 & \frac{3 x \left(- c + y\right)}{4 b c^{3}} & \frac{x \left(2 c - 3 y\right)}{4 b c^{2}} & 0 & \frac{3 \left(- 2 b c + 2 b y + c x - x y\right)}{4 b c^{3}} & \frac{4 b c - 6 b y - 2 c x + 3 x y}{4 b c^{2}} & 0\\\frac{2 b^{2} c^{2} - 6 b^{2} c y + 3 b^{2} y^{2} - 6 b c^{2} x + 3 c^{2} x^{2}}{4 b^{3} c^{3}} & \frac{c^{2} - 2 c y + \frac{3 y^{2}}{4}}{b c^{2}} & \frac{- b^{2} + 2 b x - \frac{3 x^{2}}{4}}{b^{2} c} & \frac{- 2 b^{2} c^{2} + 6 b^{2} c y - 3 b^{2} y^{2} + 6 b c^{2} x - 3 c^{2} x^{2}}{4 b^{3} c^{3}} & \frac{- c^{2} + 2 c y - \frac{3 y^{2}}{4}}{b c^{2}} & \frac{x \left(4 b - 3 x\right)}{4 b^{2} c} & \frac{2 b^{2} c^{2} - 6 b^{2} c y + 3 b^{2} y^{2} - 6 b c^{2} x + 3 c^{2} x^{2}}{4 b^{3} c^{3}} & \frac{y \left(4 c - 3 y\right)}{4 b c^{2}} & \frac{x \left(- 4 b + 3 x\right)}{4 b^{2} c} & \frac{- 2 b^{2} c^{2} + 6 b^{2} c y - 3 b^{2} y^{2} + 6 b c^{2} x - 3 c^{2} x^{2}}{4 b^{3} c^{3}} & \frac{y \left(- 4 c + 3 y\right)}{4 b c^{2}} & \frac{b^{2} - 2 b x + \frac{3 x^{2}}{4}}{b^{2} c}\end{array}\right]$

Now we form the constitutive matrix for orthotropic materials, [D]. This matrix is analagous to the flexural stiffness of a beam EI.

```python
Ex, Ey, nu_xy, nu_yx, G, t = symbols('E_x, E_y, \\nu_{xy}, \\nu_{yx}, G, t')

D = 1/(1 - nu_xy*nu_yx)*Matrix([[   Ex,    nu_yx*Ex,          0         ],
                                [nu_xy*Ey,    Ey,             0         ],
                                [   0,        0,     (1 - nu_xy*nu_yx)*G]])

display(Math('[D] = \\frac{t^3}{12}' + latex(D)))

print(t**3/12*D)
```

$\displaystyle [D] = \frac{t^3}{12}\left[\begin{matrix}\frac{E_{x}}{- \nu_{xy} \nu_{yx} + 1} & \frac{E_{x} \nu_{yx}}{- \nu_{xy} \nu_{yx} + 1} & 0\\\frac{E_{y} \nu_{xy}}{- \nu_{xy} \nu_{yx} + 1} & \frac{E_{y}}{- \nu_{xy} \nu_{yx} + 1} & 0\\0 & 0 & G\end{matrix}\right]$

    Matrix([[E_x*t**3/(12*(-\nu_{xy}*\nu_{yx} + 1)), E_x*\nu_{yx}*t**3/(12*(-\nu_{xy}*\nu_{yx} + 1)), 0], [E_y*\nu_{xy}*t**3/(12*(-\nu_{xy}*\nu_{yx} + 1)), E_y*t**3/(12*(-\nu_{xy}*\nu_{yx} + 1)), 0], [0, 0, G*t**3/12]])

Now we can calculate the stiffness matrix:

$[k] = \int_0^{2c} \int_0^{2b} [B]^T[D][B] dx dy$

```python
k = simplify(integrate(integrate(B.T*D*B, (x, 0, 2*b)), (y, 0, 2*c)))

display(Math('[k] = \\frac{t^3}{12}' + latex(k)))

# Uncomment the line below for a version that can be copied/pasted
# Be sure to multiply by t**3/12
print(k)
```

$\displaystyle [k] = \frac{t^3}{12}\left[\begin{array}{cccccccccccc}\frac{- \frac{E_{x} \nu_{yx} b^{2} c^{2}}{4} - E_{x} c^{4} - \frac{E_{y} \nu_{xy} b^{2} c^{2}}{4} - E_{y} b^{4} + \frac{7 G \nu_{xy} \nu_{yx} b^{2} c^{2}}{5} - \frac{7 G b^{2} c^{2}}{5}}{b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} c^{2}}{2} - E_{y} b^{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{x} c^{2} + \frac{E_{y} \nu_{xy} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} + \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} \nu_{yx} b^{2} c^{2} + 20 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} - 10 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} c^{2}}{2} - \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} c^{2} - G \nu_{xy} \nu_{yx} b^{2} + G b^{2}}{5 b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{x} \nu_{yx} b^{2} c^{2} + 10 E_{x} c^{4} - 5 E_{y} \nu_{xy} b^{2} c^{2} + 10 E_{y} b^{4} + 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} - 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} \nu_{yx} b^{2} c^{2} - 10 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} + 20 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{y} b^{2} + G \nu_{xy} \nu_{yx} c^{2} - G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} c^{2}}{2} - \frac{E_{y} \nu_{xy} b^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{- \frac{E_{y} \nu_{xy} c^{2}}{2} - E_{y} b^{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{4 \left(- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{y} \nu_{xy}}{\nu_{xy} \nu_{yx} - 1} & \frac{\frac{E_{y} \nu_{xy} c^{2}}{2} - \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - 4 G \nu_{xy} \nu_{yx} c^{2} + 4 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{\frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0\\\frac{\frac{E_{x} \nu_{yx} b^{2}}{2} + E_{x} c^{2} - \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} + \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{x} \nu_{yx}}{\nu_{xy} \nu_{yx} - 1} & \frac{4 \left(- 5 E_{x} c^{2} + 2 G \nu_{xy} \nu_{yx} b^{2} - 2 G b^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{x} c^{2} + G \nu_{xy} \nu_{yx} b^{2} - G b^{2}}{5 b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{2 \left(- 5 E_{x} c^{2} - G \nu_{xy} \nu_{yx} b^{2} + G b^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- 5 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} b^{2}}{2} + \frac{E_{x} c^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} - \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & - \frac{10 E_{x} c^{2} + 8 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{5 E_{x} \nu_{yx} b^{2} c^{2} + 20 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} - 10 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} c^{2}}{2} - \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{x} c^{2} + G \nu_{xy} \nu_{yx} b^{2} - G b^{2}}{5 b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} b^{2} c^{2}}{4} - E_{x} c^{4} - \frac{E_{y} \nu_{xy} b^{2} c^{2}}{4} - E_{y} b^{4} + \frac{7 G \nu_{xy} \nu_{yx} b^{2} c^{2}}{5} - \frac{7 G b^{2} c^{2}}{5}}{b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} c^{2}}{2} - E_{y} b^{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- E_{x} c^{2} - \frac{E_{y} \nu_{xy} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} - \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} \nu_{yx} b^{2} c^{2} - 10 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} + 20 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{y} b^{2} + G \nu_{xy} \nu_{yx} c^{2} - G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} c^{2}}{2} + \frac{E_{y} \nu_{xy} b^{2}}{2} - \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{x} \nu_{yx} b^{2} c^{2} + 10 E_{x} c^{4} - 5 E_{y} \nu_{xy} b^{2} c^{2} + 10 E_{y} b^{4} + 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} - 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{\frac{E_{y} \nu_{xy} c^{2}}{2} - \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - 4 G \nu_{xy} \nu_{yx} c^{2} + 4 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- \frac{E_{y} \nu_{xy} c^{2}}{2} - E_{y} b^{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{4 \left(- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{E_{y} \nu_{xy}}{\nu_{xy} \nu_{yx} - 1} & \frac{5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{\frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0\\\frac{5 E_{x} c^{2} - G \nu_{xy} \nu_{yx} b^{2} + G b^{2}}{5 b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{2 \left(- 5 E_{x} c^{2} - G \nu_{xy} \nu_{yx} b^{2} + G b^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} b^{2}}{2} - E_{x} c^{2} + \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} - \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{E_{x} \nu_{yx}}{\nu_{xy} \nu_{yx} - 1} & \frac{4 \left(- 5 E_{x} c^{2} + 2 G \nu_{xy} \nu_{yx} b^{2} - 2 G b^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} b^{2}}{2} - \frac{E_{x} c^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} + \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & - \frac{10 E_{x} c^{2} + 8 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- 5 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{- 5 E_{x} \nu_{yx} b^{2} c^{2} + 10 E_{x} c^{4} - 5 E_{y} \nu_{xy} b^{2} c^{2} + 10 E_{y} b^{4} + 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} - 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} \nu_{yx} b^{2} c^{2} - 10 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} + 20 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{x} c^{2} - 25 E_{y} \nu_{xy} b^{2} + 2 b^{2} \left(15 E_{y} \nu_{xy} - G \nu_{xy} \nu_{yx} + G\right)}{10 b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} b^{2} c^{2}}{4} - E_{x} c^{4} - \frac{E_{y} \nu_{xy} b^{2} c^{2}}{4} - E_{y} b^{4} + \frac{7 G \nu_{xy} \nu_{yx} b^{2} c^{2}}{5} - \frac{7 G b^{2} c^{2}}{5}}{b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} c^{2}}{2} + E_{y} b^{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- E_{x} c^{2} - \frac{E_{y} \nu_{xy} b^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} \nu_{yx} b^{2} c^{2} + 20 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} - 10 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} c^{2}}{2} + \frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- E_{x} c^{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{- \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- 5 E_{y} b^{2} + G \nu_{xy} \nu_{yx} c^{2} - G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{\frac{E_{y} \nu_{xy} c^{2}}{2} + E_{y} b^{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{4 \left(- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{y} \nu_{xy}}{\nu_{xy} \nu_{yx} - 1} & \frac{- \frac{E_{y} \nu_{xy} c^{2}}{2} + \frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - 4 G \nu_{xy} \nu_{yx} c^{2} + 4 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0\\\frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- 5 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} b^{2}}{2} - \frac{E_{x} c^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} + \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & - \frac{10 E_{x} c^{2} + 8 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} b^{2}}{2} - E_{x} c^{2} + \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} - \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{x} \nu_{yx}}{\nu_{xy} \nu_{yx} - 1} & \frac{4 \left(- 5 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{x} c^{2} - \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & - \frac{10 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{5 E_{x} \nu_{yx} b^{2} c^{2} - 10 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} + 20 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} c^{2} + 25 E_{y} \nu_{xy} b^{2} - 2 b^{2} \left(15 E_{y} \nu_{xy} - G \nu_{xy} \nu_{yx} + G\right)}{10 b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{x} \nu_{yx} b^{2} c^{2} + 10 E_{x} c^{4} - 5 E_{y} \nu_{xy} b^{2} c^{2} + 10 E_{y} b^{4} + 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} - 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{5 E_{x} \nu_{yx} b^{2} c^{2} + 20 E_{x} c^{4} + 5 E_{y} \nu_{xy} b^{2} c^{2} - 10 E_{y} b^{4} - 28 G \nu_{xy} \nu_{yx} b^{2} c^{2} + 28 G b^{2} c^{2}}{20 b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} c^{2}}{2} + \frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{x} c^{2} - \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- \frac{E_{x} \nu_{yx} b^{2} c^{2}}{4} - E_{x} c^{4} - \frac{E_{y} \nu_{xy} b^{2} c^{2}}{4} - E_{y} b^{4} + \frac{7 G \nu_{xy} \nu_{yx} b^{2} c^{2}}{5} - \frac{7 G b^{2} c^{2}}{5}}{b^{3} c^{3} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} c^{2}}{2} + E_{y} b^{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{E_{x} c^{2} + \frac{E_{y} \nu_{xy} b^{2}}{2} - \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)}\\\frac{- 5 E_{y} b^{2} + G \nu_{xy} \nu_{yx} c^{2} - G c^{2}}{5 b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - G \nu_{xy} \nu_{yx} c^{2} + G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- \frac{E_{y} b^{2}}{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- \frac{E_{y} \nu_{xy} c^{2}}{2} + \frac{E_{y} b^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} - \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{2 \left(- 5 E_{y} b^{2} - 4 G \nu_{xy} \nu_{yx} c^{2} + 4 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{\frac{E_{y} \nu_{xy} c^{2}}{2} + E_{y} b^{2} - \frac{G \nu_{xy} \nu_{yx} c^{2}}{5} + \frac{G c^{2}}{5}}{b c^{2} \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{4 \left(- 5 E_{y} b^{2} + 2 G \nu_{xy} \nu_{yx} c^{2} - 2 G c^{2}\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{E_{y} \nu_{xy}}{\nu_{xy} \nu_{yx} - 1}\\\frac{- \frac{E_{x} \nu_{yx} b^{2}}{2} + \frac{E_{x} c^{2}}{2} + \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} - \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & - \frac{10 E_{x} c^{2} + 8 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{\frac{E_{x} c^{2}}{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & \frac{- 5 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{- E_{x} c^{2} + \frac{G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & 0 & - \frac{10 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)} & \frac{\frac{E_{x} \nu_{yx} b^{2}}{2} + E_{x} c^{2} - \frac{G \nu_{xy} \nu_{yx} b^{2}}{5} + \frac{G b^{2}}{5}}{b^{2} c \left(\nu_{xy} \nu_{yx} - 1\right)} & - \frac{E_{x} \nu_{yx}}{\nu_{xy} \nu_{yx} - 1} & \frac{4 \left(- 5 E_{x} c^{2} + 2 G b^{2} \left(\nu_{xy} \nu_{yx} - 1\right)\right)}{15 b c \left(\nu_{xy} \nu_{yx} - 1\right)}\end{array}\right]$

    Matrix([[(-E_x*\nu_{yx}*b**2*c**2/4 - E_x*c**4 - E_y*\nu_{xy}*b**2*c**2/4 - E_y*b**4 + 7*G*\nu_{xy}*\nu_{yx}*b**2*c**2/5 - 7*G*b**2*c**2/5)/(b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*c**2/2 - E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2 + E_y*\nu_{xy}*b**2/2 - G*\nu_{xy}*\nu_{yx}*b**2/5 + G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*\nu_{yx}*b**2*c**2 + 20*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 - 10*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*c**2/2 - E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*c**2 - G*\nu_{xy}*\nu_{yx}*b**2 + G*b**2)/(5*b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_x*\nu_{yx}*b**2*c**2 + 10*E_x*c**4 - 5*E_y*\nu_{xy}*b**2*c**2 + 10*E_y*b**4 + 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 - 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*\nu_{yx}*b**2*c**2 - 10*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 + 20*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2 - G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2/2 - E_y*\nu_{xy}*b**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1))], [(-E_y*\nu_{xy}*c**2/2 - E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 4*(-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), E_y*\nu_{xy}/(\nu_{xy}*\nu_{yx} - 1), (E_y*\nu_{xy}*c**2/2 - E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - 4*G*\nu_{xy}*\nu_{yx}*c**2 + 4*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0], [(E_x*\nu_{yx}*b**2/2 + E_x*c**2 - G*\nu_{xy}*\nu_{yx}*b**2/5 + G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), E_x*\nu_{yx}/(\nu_{xy}*\nu_{yx} - 1), 4*(-5*E_x*c**2 + 2*G*\nu_{xy}*\nu_{yx}*b**2 - 2*G*b**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_x*c**2 + G*\nu_{xy}*\nu_{yx}*b**2 - G*b**2)/(5*b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, 2*(-5*E_x*c**2 - G*\nu_{xy}*\nu_{yx}*b**2 + G*b**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), -(E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-5*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*b**2/2 + E_x*c**2/2 + G*\nu_{xy}*\nu_{yx}*b**2/5 - G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, -(10*E_x*c**2 + 8*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1))], [(5*E_x*\nu_{yx}*b**2*c**2 + 20*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 - 10*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*c**2/2 - E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_x*c**2 + G*\nu_{xy}*\nu_{yx}*b**2 - G*b**2)/(5*b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*b**2*c**2/4 - E_x*c**4 - E_y*\nu_{xy}*b**2*c**2/4 - E_y*b**4 + 7*G*\nu_{xy}*\nu_{yx}*b**2*c**2/5 - 7*G*b**2*c**2/5)/(b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*c**2/2 - E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*c**2 - E_y*\nu_{xy}*b**2/2 + G*\nu_{xy}*\nu_{yx}*b**2/5 - G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*\nu_{yx}*b**2*c**2 - 10*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 + 20*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2 - G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*c**2/2 + E_y*\nu_{xy}*b**2/2 - G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_x*\nu_{yx}*b**2*c**2 + 10*E_x*c**4 - 5*E_y*\nu_{xy}*b**2*c**2 + 10*E_y*b**4 + 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 - 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), -(E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1))], [(E_y*\nu_{xy}*c**2/2 - E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - 4*G*\nu_{xy}*\nu_{yx}*c**2 + 4*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-E_y*\nu_{xy}*c**2/2 - E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 4*(-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), -E_y*\nu_{xy}/(\nu_{xy}*\nu_{yx} - 1), (5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0], [(5*E_x*c**2 - G*\nu_{xy}*\nu_{yx}*b**2 + G*b**2)/(5*b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, 2*(-5*E_x*c**2 - G*\nu_{xy}*\nu_{yx}*b**2 + G*b**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*b**2/2 - E_x*c**2 + G*\nu_{xy}*\nu_{yx}*b**2/5 - G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), -E_x*\nu_{yx}/(\nu_{xy}*\nu_{yx} - 1), 4*(-5*E_x*c**2 + 2*G*\nu_{xy}*\nu_{yx}*b**2 - 2*G*b**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*b**2/2 - E_x*c**2/2 - G*\nu_{xy}*\nu_{yx}*b**2/5 + G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, -(10*E_x*c**2 + 8*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-5*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1))], [(-5*E_x*\nu_{yx}*b**2*c**2 + 10*E_x*c**4 - 5*E_y*\nu_{xy}*b**2*c**2 + 10*E_y*b**4 + 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 - 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), -(E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*\nu_{yx}*b**2*c**2 - 10*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 + 20*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_x*c**2 - 25*E_y*\nu_{xy}*b**2 + 2*b**2*(15*E_y*\nu_{xy} - G*\nu_{xy}*\nu_{yx} + G))/(10*b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*b**2*c**2/4 - E_x*c**4 - E_y*\nu_{xy}*b**2*c**2/4 - E_y*b**4 + 7*G*\nu_{xy}*\nu_{yx}*b**2*c**2/5 - 7*G*b**2*c**2/5)/(b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*c**2/2 + E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*c**2 - E_y*\nu_{xy}*b**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*\nu_{yx}*b**2*c**2 + 20*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 - 10*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*c**2/2 + E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*c**2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1))], [(-E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-5*E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2 - G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (E_y*\nu_{xy}*c**2/2 + E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 4*(-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), E_y*\nu_{xy}/(\nu_{xy}*\nu_{yx} - 1), (-E_y*\nu_{xy}*c**2/2 + E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - 4*G*\nu_{xy}*\nu_{yx}*c**2 + 4*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0], [(E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-5*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*b**2/2 - E_x*c**2/2 - G*\nu_{xy}*\nu_{yx}*b**2/5 + G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, -(10*E_x*c**2 + 8*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*b**2/2 - E_x*c**2 + G*\nu_{xy}*\nu_{yx}*b**2/5 - G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), E_x*\nu_{yx}/(\nu_{xy}*\nu_{yx} - 1), 4*(-5*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2 - G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, -(10*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1))], [(5*E_x*\nu_{yx}*b**2*c**2 - 10*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 + 20*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*c**2 + 25*E_y*\nu_{xy}*b**2 - 2*b**2*(15*E_y*\nu_{xy} - G*\nu_{xy}*\nu_{yx} + G))/(10*b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_x*\nu_{yx}*b**2*c**2 + 10*E_x*c**4 - 5*E_y*\nu_{xy}*b**2*c**2 + 10*E_y*b**4 + 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 - 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (5*E_x*\nu_{yx}*b**2*c**2 + 20*E_x*c**4 + 5*E_y*\nu_{xy}*b**2*c**2 - 10*E_y*b**4 - 28*G*\nu_{xy}*\nu_{yx}*b**2*c**2 + 28*G*b**2*c**2)/(20*b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*c**2/2 + E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2 - G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*\nu_{yx}*b**2*c**2/4 - E_x*c**4 - E_y*\nu_{xy}*b**2*c**2/4 - E_y*b**4 + 7*G*\nu_{xy}*\nu_{yx}*b**2*c**2/5 - 7*G*b**2*c**2/5)/(b**3*c**3*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*c**2/2 + E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (E_x*c**2 + E_y*\nu_{xy}*b**2/2 - G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1))], [(-5*E_y*b**2 + G*\nu_{xy}*\nu_{yx}*c**2 - G*c**2)/(5*b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2 + G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-E_y*b**2/2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), (-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-E_y*\nu_{xy}*c**2/2 + E_y*b**2/2 + G*\nu_{xy}*\nu_{yx}*c**2/5 - G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 2*(-5*E_y*b**2 - 4*G*\nu_{xy}*\nu_{yx}*c**2 + 4*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (E_y*\nu_{xy}*c**2/2 + E_y*b**2 - G*\nu_{xy}*\nu_{yx}*c**2/5 + G*c**2/5)/(b*c**2*(\nu_{xy}*\nu_{yx} - 1)), 4*(-5*E_y*b**2 + 2*G*\nu_{xy}*\nu_{yx}*c**2 - 2*G*c**2)/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), -E_y*\nu_{xy}/(\nu_{xy}*\nu_{yx} - 1)], [(-E_x*\nu_{yx}*b**2/2 + E_x*c**2/2 + G*\nu_{xy}*\nu_{yx}*b**2/5 - G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, -(10*E_x*c**2 + 8*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), -(E_x*c**2/2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, (-5*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (-E_x*c**2 + G*b**2*(\nu_{xy}*\nu_{yx} - 1)/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), 0, -(10*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1)), (E_x*\nu_{yx}*b**2/2 + E_x*c**2 - G*\nu_{xy}*\nu_{yx}*b**2/5 + G*b**2/5)/(b**2*c*(\nu_{xy}*\nu_{yx} - 1)), -E_x*\nu_{yx}/(\nu_{xy}*\nu_{yx} - 1), 4*(-5*E_x*c**2 + 2*G*b**2*(\nu_{xy}*\nu_{yx} - 1))/(15*b*c*(\nu_{xy}*\nu_{yx} - 1))]])

The surface force matrix $[F_s]$ can be obtained from the shape function matrix. Since we're interested in the surface force matrix for uniform pressures in the direction of w,

```python
q = symbols('q')

Fs = integrate(integrate(N[0, :].T*q, (x, 0, 2*b)), (y, 0, 2*c))

display(Math('[F_s] = 4qcb' + latex(Fs/(4*q*c*b))))

# Uncomment the line below for a version that can be copied/pasted
print(Fs)
```

$\displaystyle [F_s] = 4qcb\left[\begin{matrix}\frac{1}{4}\\\frac{c}{12}\\- \frac{b}{12}\\\frac{1}{4}\\\frac{c}{12}\\\frac{b}{12}\\\frac{1}{4}\\- \frac{c}{12}\\\frac{b}{12}\\\frac{1}{4}\\- \frac{c}{12}\\- \frac{b}{12}\end{matrix}\right]$

    Matrix([[b*c*q], [b*c**2*q/3], [-b**2*c*q/3], [b*c*q], [b*c**2*q/3], [b**2*c*q/3], [b*c*q], [-b*c**2*q/3], [b**2*c*q/3], [b*c*q], [-b*c**2*q/3], [-b**2*c*q/3]])

## Membrane Action

### Shape Functions

```python
from sympy import factor, symbols
r, s = symbols('r, s')
h1 = factor(1/4*(1-r)*(1-s))
h2 = factor(1/4*(1+r)*(1-s))
h3 = factor(1/4*(1+r)*(1+s))
h4 = factor(1/4*(1-r)*(1+s))
```

```python
x1, y1, x2, y2, x3, y3, x4, y4 = symbols('x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4')
x = h1*x1 + h2*x2 + h3*x3 + h4*x4
y = h1*y1 + h2*y2 + h3*y3 + h4*y4
```

```python
J = Matrix([[diff(x, r), diff(y, r)],
            [diff(x, s), diff(y, s)]])

display(Math('J = (1/4)' + latex(factor(J*4))))
print(J*4)
```

$\displaystyle J = (1/4)\left[\begin{matrix}x_{1} \left(s - 1\right) - 1.0 x_{2} \left(s - 1\right) + x_{3} \left(s + 1\right) - 1.0 x_{4} \left(s + 1\right) & y_{1} \left(s - 1\right) - 1.0 y_{2} \left(s - 1\right) + y_{3} \left(s + 1\right) - 1.0 y_{4} \left(s + 1\right)\\x_{1} \left(r - 1\right) - 1.0 x_{2} \left(r + 1\right) + x_{3} \left(r + 1\right) - 1.0 x_{4} \left(r - 1\right) & y_{1} \left(r - 1\right) - 1.0 y_{2} \left(r + 1\right) + y_{3} \left(r + 1\right) - 1.0 y_{4} \left(r - 1\right)\end{matrix}\right]$

    Matrix([[x_1*(s - 1) - 1.0*x_2*(s - 1) + x_3*(s + 1) - 1.0*x_4*(s + 1), y_1*(s - 1) - 1.0*y_2*(s - 1) + y_3*(s + 1) - 1.0*y_4*(s + 1)], [x_1*(r - 1) - 1.0*x_2*(r + 1) + x_3*(r + 1) - 1.0*x_4*(r - 1), y_1*(r - 1) - 1.0*y_2*(r + 1) + y_3*(r + 1) - 1.0*y_4*(r - 1)]])

```python
print(4*diff(h1, r))
print(4*diff(h2, r))
print(4*diff(h3, r))
print(4*diff(h4, r))
```

    s - 1.0
    1.0 - 1.0*s
    s + 1.0
    -1.0*s - 1.0

```python

```


# Further information

## Why is some code in separate libraries?

When we run the `import sympy` command we are telling Python that we want to use
a specific set of tools. We will see other examples of this throughout this
course.

One of the advantages of having code in libraries is that it is more efficient
for Python to only use what is needed.

There are two types of Python libraries:

- Those that are part of the so called "standard library": these are part of
  Python itself.
- Those that are completely separate: `sympy` is one such example of this.

This separation allows for the development of tools to be not dependent on each
others. The developers of `sympy` do not need to coordinate with the developers
of Python to make new releases of the software.

## Why do we need to use sympy?

`sympy` is the library for symbolic mathematics. There are other python libraries
for carrying out mathematics in Python.

For example, let us compute the value of the following expression:

$$
    (\sqrt{2} + 2) ^ 2 - 2
$$

We could compute this using the `math` library (for the square root tool):

```python
import math

(math.sqrt(2) + 2) ** 2 - 2
```

    9.65685424949238

We could also make use of the fact that we do not need a square root tool at all:

$$
    (\sqrt{2} + 2) ^ 2 - 2 = (2 ^ {1 / 2} + 2) ^ 2 - 2
$$

```python
(2 ** (1 / 2) + 2) ** 2 - 2
```

    9.65685424949238

We see that in both those instances, we have a numeric value for the expression
that seems to be precise up to 14 decimal places.

However, that is **not** the exact value of that expression. The exact value of
the expression needs to be computed symbolically:

```python
import sympy

expression = (sympy.sqrt(2) + 2) ** 2 - 2
sympy.expand(expression)
```

$\displaystyle 4 + 4 \sqrt{2}$

This is one example of why `sympy` is an effective tool for mathematicians.
The other one seen in this chapter is being able to compute expressions with no
numerical value at all:

```python
a = sympy.Symbol("a")
b = sympy.Symbol("b")
sympy.factor(a ** 2 - b ** 2)
```

$\displaystyle \left(a - b\right) \left(a + b\right)$

## Why do I sometimes see `from sympy import *`?

There a number of resources available from which you can learn to use `sympy`. In
some instances you will not see `import sympy` but instead you will see `from sympy import *`.

**This it not a good way to do it.**

What this does is taking all the tools inside of sympy and putting it at the
same level of all the other tools available to you.

The problem with doing this is that it no longer makes your code clear.

An example of this are trigonometric functions. These exist in a number of
libraries:

```python
import math
```

```python
import sympy
```

```python
sympy.cos(0)
```

$\displaystyle 1$

```python
math.cos(0)
```

    1.0

One however allows us to carry out exact computations:

```python
sympy.cos(sympy.pi / 4)
```

$\displaystyle \frac{\sqrt{2}}{2}$

```python
math.cos(math.pi / 4)
```

    0.7071067811865476

If we chose to import all the functionality using `from sympy import *` then we
cannot tell immediately which function we are using (except from its output):

```python
from sympy import *
```

```python
from math import *
```

```python
cos(pi / 4)
```

    0.7071067811865476

In that case the second import has overwritten the first.

```{warning}
**It is never recommended to use** `import *` this makes your code less clear
and you are more likely to make mistakes when your code is not clear.
```

## Why do I sometimes see `import sympy as sym`?

In some resources you will see that instead of `import sympy` people use:
`import sympy as sym`. This is called **aliasing**. This is common and takes
advantage of the fact that Python can import a library and give it an
alias/nickname at the same time:

```
import <library> as <nickname>
```

So with sympy we can use:

```python
import sympy as sym

sym.cos(sym.pi / 4)
```

$\displaystyle \frac{\sqrt{2}}{2}$

There is nothing stopping you using whatever alias you want:

```python
import sympy as a_poor_name_choice

a_poor_name_choice.cos(a_poor_name_choice.pi / 4)
```

$\displaystyle \frac{\sqrt{2}}{2}$

```{attention}
**It is important** when aliasing to use accepted conventions for these
nicknames. For `sympy`, an accepted convention is indeed `import sympy as sym`.
```

## Are there other resources for learning sympy?

There are a large number of resources for learning `sympy`. Not all concentrate
on the algebra that we have considered in this chapter, and we will be covering
further `sympy` functionality in the next chapters.

Here are some resources:

- The main `sympy` documentation: <https://docs.sympy.org/latest/index.html>
- The scientific python lecture notes chapter on `sympy`:
  <https://scipy-lectures.org/packages/sympy.html>
- A short tutorial:
  <https://github.com/drvinceknight/Python-Mathematics-Handbook/>


# Model Analysis Project

In this project we analyse the Solow model. We want to examine how a higher labor supply will affect the level of productivity. Thus we extend the Solow model with $\lambda$ which indicades the fraction of the population in the labor force.

Furthermore, we adjust the model such that the level of technology increases within every period, and we analyse how this will affect the economy and the level of productivity.

Import and set magics:

```python
import numpy as np
from scipy import optimize
import sympy as sm

from IPython.display import display

%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib import cm
plt.style.use('seaborn-whitegrid')
plt.rcParams.update({'font.size': 12})

%matplotlib inline
import matplotlib.pyplot as plt # baseline modul
from mpl_toolkits.mplot3d import Axes3D # for 3d figures
plt.style.use('seaborn-whitegrid') # whitegrid nice with 3d
```

# The Solow model with labor supply

We consider the Solow model with an adjustable supply of labor. The model consists of the following equations:

$$Y_t = BK_t^{\alpha}L_t^{1-\alpha}, 0<\alpha<1$$
$$S_t = sY_t, 0 < s < 1$$
$$K_{t+1}-K_t = S_t\delta K_t, 0<\delta<1$$

where $K_t$ is capital today, $K_{t+1}$ is capital tomorrow, $S_t$ is savings and $Y_t$ is the output of the economy.

We also have $L_t$ which is the supply of labor, and $N_t$ which is the size of the population today, which are defined by the following:

$$L_t=\lambda N_t, 0<\lambda<1$$
$$N_{t+1}=(1+n)N_t$$

where lambda is the share of the population in work. The population is growing with a constant rate of $n$ in every period.

We consider capital, labor and output pr. capita (not pr. worker):

$$y_t = \frac{Y_t}{N_t} = \lambda^{(1-\alpha)}Bk_t^{\alpha}$$ with $$k_t = \frac{K_t}{N_t}$$

This will give us the following transformation equation of capital:

$$k_{t+1} = \frac{1}{(1+n)}(sB\lambda^{1-\alpha}k_t^{\alpha}+(1-\delta)k_t)$$

## Solving the model

The first step in solving the model is to find steady state of capital. This means solving for $k_t = k_{t+1} = k^{*}$

First we define all of the necessary symbols and equations of our model:

```python
k = sm.symbols('k')
n = sm.symbols('n')
s = sm.symbols('s')
B = sm.symbols('B')
lam = sm.symbols('lambda')
delta = sm.symbols('delta')
alpha = sm.symbols('alpha')

steadystateK = sm.Eq(k,(s*B*lam**(1-alpha)*k**(alpha)+(1-delta)*k)/((1+n)))
```

We solve this using sympy:

```python
steadystateKstar = sm.solve(steadystateK,k)[0]
steadystateKstar
```

$\displaystyle \left(\frac{B \lambda^{1 - \alpha} s}{\delta + n}\right)^{- \frac{1}{\alpha - 1}}$

We see that the level of capital in steady state is positively dependent of the savings $s$, $B$ and the share of the population that is working. The level of capital in steady state is negatively dependent of the growth in population as well as the rate of attrition of capital $\delta$, with the condition of stability of $\delta+n>0$.

We also want to find the steady state of the output of the economy $y^{*}$.
We know that $y_t = \lambda^{(1-\alpha)}Bk_t^{\alpha}$.
To solve for $y^{*}$ we need to insert $k^{*}$ into the equation.

```python
#saving the steady state for k
ssk = sm.lambdify((B,lam,alpha,delta,n,s),steadystateKstar)

y = sm.symbols('y')
steadystateY = sm.Eq(y,lam**(1-alpha)*B*steadystateKstar**alpha)
steadystateYstar = sm.solve(steadystateY,y)[0]
steadystateYstar
```

$\displaystyle B \lambda^{1 - \alpha} \left(\left(\frac{B \lambda^{1 - \alpha} s}{\delta + n}\right)^{- \frac{1}{\alpha - 1}}\right)^{\alpha}$

We note that output is positively dependent of the same parameters as capital.

### How will the supply of labor affect the output of the economy? (Theoretically)

To show how the supply of labor affects the output in steady state we need to take a look at lambda - the share of population in work. First we look at the elasticity of lambda. To do this we need to rewrite the steady state for $y^{*}$:

$$y^{*} = B\lambda^{(1-\alpha)}(\frac{B\lambda^{(1-\alpha)}s}{(\delta + n)})^{\frac{\alpha}{(1-\alpha)}}$$

$$y^{*} = \frac{B\lambda^{(1-\alpha)}B^{\frac{\alpha}{(1-\alpha)}}\lambda^{\alpha}s^{\frac{\alpha}{(1-\alpha)}}}{(\delta + n)^\frac{\alpha}{{(1-\alpha)}}}$$

$$y^{*} = \frac{B^{\frac{1}{(1-\alpha)}}\lambda s^{\frac{\alpha}{(1-\alpha)}}}{(\delta + n)^\frac{\alpha}{{(1-\alpha)}}}$$

$$y^{*} = B^{\frac{1}{(1-\alpha)}}\lambda(\frac{s}{(\delta + n)})^{\frac{\alpha}{(1-\alpha)}}$$

```python
ely = sm.Eq(y,B**(1/(1-alpha))*lam*(s/(delta+n))**(alpha/(1-alpha)))
ely
```

$\displaystyle y = B^{\frac{1}{1 - \alpha}} \lambda \left(\frac{s}{\delta + n}\right)^{\frac{\alpha}{1 - \alpha}}$

To find the elasticity of $y^{*}$ with respect to lambda we take the log on both sides:

$$ln(y^{*}) = \frac{1}{1-\alpha}ln(B) + ln(\lambda) + \frac{\alpha}{1-\alpha}(ln(s) - ln(n+\delta)) $$

We also find the elasticity of $y^{*}$ with respect to lambda with sympy:

```python
y_eq = B**(1/(1-alpha))*lam*(s/(delta+n))**(alpha/(1-alpha))

print(f'The elasticity is {sm.diff(y_eq,lam)*lam/y_eq}')
```

    The elasticity is 1

We find that the elasticity of $y^{*}$ with respect to lambda is 1. This means that an increase in $\lambda$ with 1 pct. will result in an increase in $y^{*}$ with 1 pct.

### How will the supply of labor affect the output of the economy? (Example)

To give an example of what the outcome of the steady state could be, we have tried to insert plausible values of the parameters. To see the effect of an increase in lambda, we have calculated the steady state value of capital two times given a share of workers being 0.6 and 0.75 which leads to the following two results:

```python
print(f'The first solution with lampda = 0.6 is: {ssk(1,0.6,1/3,0.1,0.25,0.2):.3f}')
print(f'The second solution with lampda = 0.75 is: {ssk(1,0.75,1/3,0.1,0.25,0.2):.3f}')
```

    The first solution with lampda = 0.6 is: 0.259
    The second solution with lampda = 0.75 is: 0.324

As expected we get a higher level of capital the higher the share of workers relative to the population. We will illustrate this relationship between $y^{*}$ and $\lambda$:

```python
alpha=1/3
delta=0.1
g=0.02
n=0.25
s=0.2
B=1
lam_plot = np.linspace(0,1,100)
yss_plot = (B**(1/(1-alpha))*lam_plot*(s/(delta+n))**(alpha/(1-alpha)))

#Plotting different value of lambda from 0 to 1 against the value of tecnolegy adjusted capital steady state
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_xlabel("Share of population in the laborforce")
ax.set_ylabel("$y^\star$")

ax.set_title('Figure 1: The effect of $\lambda$ on the steady state output', fontsize=13)
ax.plot(lam_plot,yss_plot)
plt.show;
```

From this we clearly see the 1:1 relationship between an incease in $\lambda$ and the output pr. capita of the economy in steady state. Outside of steady state the relationship between the share of the population in the labor force ($\lambda$) and the output will be different.
The output (outside ss) in the economy in pr. capita is:
$y_t = \lambda^{(1-\alpha)}Bk_t^{\alpha}$

We calculate the elasticity of $y_t$ with respect to $\lambda$ with sympy:

```python
y_t = B*lam**(1-alpha)*k**(alpha)

print(f'The elasticity is {sm.diff(y_t,lam)*lam/y_t}')
```

    The elasticity is 0.666666666666667

This means that an increase in $\lambda$ by 1 pct. will result in an increase in $y^{*}$ with 0.667 pct. The elasticity is now smaller than in steady state, since some of the production will be used as savings in the capital.

## Visualization of the two solutions

### The transition to steady state in a phase diagram

We want to show the transition to steady state in a phase diagram with the two different share of workers. We do this by simulating two different transations from time 0 to steady state.

```python
#Transformation equation of capital
def k_trans(alpha,delta,lam,B,s,n,k_t):
    return 1/(1+n)*(s*B*lam**(1-alpha)*k_t**alpha+(1-delta)*k_t)

#Steady state for k
def ss_k(alpha,delta,lam,B,s,n):
    return (B*lam**(1-alpha)*s/(delta+n))**(1/(1-alpha))

# Setting the parameters
alpha=1/3
delta=0.1
lam_one=0.6
lam_two=0.75
B=1
n=0.25
s=0.2
k0 = 0.01

#Time periods
T = 20
index = range(T)

# Number of values in the grid
N = 1000

# Capital in period t
k_tone = np.linspace(0,0.4,N)
k_ttwo = np.linspace(0,0.4,N)

# Capital in period t+1
k_trans_one = np.zeros(N)
k_trans_two = np.zeros(N)

for i,k in enumerate(k_tone):
    k_trans_one[i] = k_trans(alpha,delta,lam_one,B,s,n,k)

for i,k in enumerate(k_ttwo):
    k_trans_two[i] = k_trans(alpha,delta,lam_two,B,s,n,k)

fig, axes = plt.subplots(1, 2, sharex='col', figsize=(13, 4))
ax1 = axes[0]
ax2 = axes[1]

#Phase diagram 1:

ax1.plot(k_tone,k_trans_one, color='0.3',label=r'$k_{t+1} = f(k_t)$')
ax1.plot(k_tone,k_tone,color='0.3',linestyle=':', label=r'$45^{\circ}$ degree line')

ax1.set_ylabel('$k_{t+1}$')
ax1.set_xlabel('$k_t$')
ax1.set_xlim(0,0.35)
ax1.set_ylim(0,0.35)
ax1.legend(loc=4,frameon=True)

ax1.set_title('Figure 2.a: Phase diagram with $\lambda$ = 0.6', fontsize=13)

#Phase diagram 2:

ax2.plot(k_ttwo,k_trans_two, color='0.3',label=r'$k_{t+1} = f(k_t)$')
ax2.plot(k_ttwo,k_ttwo,color='0.3',linestyle=':', label=r'$45^{\circ}$ degree line')

ax2.set_ylabel('$k_{t+1}$')
ax2.set_xlabel('$k_t$')
ax2.set_xlim(0,0.35)
ax2.set_ylim(0,0.35)
ax2.legend(loc=4,frameon=True)

ax2.set_title('Figure 2.b: Phase diagram with $\lambda$ = 0.75', fontsize=13)

plt.show()
```

In the two phase diagrams we see the transations from time 0 to steady state with two different values for $\lambda$. We clearly see that the steady state value of capital pr. capita is higher with a higher share of workers. An increase in $\lambda$ will not just benefit the economy temporarily but also in the long run.

### A simulation of convergence of capital to steady state

```python
#Graph 3
k_level_one = np.zeros(len(index))
k_level_one[0] = k0

for t in index[1:]:
    k_level_one[t] = k_trans(alpha,delta,lam_one,B,s,n,k_level_one[t-1])

k_level_two = np.zeros(len(index))
k_level_two[0] = k0

for t in index[1:]:
    k_level_two[t] = k_trans(alpha,delta,lam_two,B,s,n,k_level_two[t-1])

fig, ax = plt.subplots(sharex='col', figsize=(6.5, 4))
ax.plot(k_level_one, color='0.3',label=r'lambda = 0.6')
ax.plot(k_level_two,color='0.3',linestyle=':', label=r'lambda = 0.75')
ax.set_ylabel('$k_{t}$')
ax.set_xlabel('t')
ax.legend(loc=4,frameon=True)

ax.set_title('Figure 3: Simulated convergence of capital to steady state', fontsize=13)

plt.show()
```

Figure 3 illustrates how capital converges to steady state with $\lambda$ being 0.6 and 0.75. Not only is the steady state level of $\lambda = 0.75$ higher, the level of capital in this economy is also higher during the time it converges to steady state. We see that in $t = 15$ the level of capital with $\lambda = 0.75$ is approximately 0.06 larger than the level of capital with $\lambda = 0.6$.

# The Solow model with labor supply and exogeneous technological progress

Instead of a fixed level of technology we now consider an economy with growing technology. The level of technology increases in every period beacuse of more R&D. The model changes such that

$$Y_t = K_t^{\alpha}(A_tL_t)^{1-\alpha}, 0<\alpha<1$$
$$A_{t+1}=(1+g)A_t$$

We note that the level of technology increases by $g$ in every period. Other than this the model is the same as earlier.

Now we consider technologically adjusted capital, labor and output pr. capita:

$$\tilde{y}_t = \frac{Y_t}{A_tN_t} = \lambda^{(1-\alpha)}\tilde{k}_t^{\alpha}$$ with $$\tilde{k}_t = \frac{K_t}{A_tN_t}$$

This gives us the following transformation equation of capital:

$$\tilde{k}_{t+1} = \frac{1}{(1+n)(1+g)}(s\lambda^{1-\alpha}\tilde{k}_t^{\alpha}+(1-\delta)\tilde{k}_t)$$

## Solving the model analytically

The analytic solution of steady state of capital is solved:

```python
k = sm.symbols('k')
n = sm.symbols('n')
s = sm.symbols('s')
lam = sm.symbols('lambda')
delta = sm.symbols('delta')
alpha = sm.symbols('alpha')
g = sm.symbols('g')

steadystateK_tilde = sm.Eq(k,(s*lam**(1-alpha)*k**(alpha)+(1-delta)*k)/((1+n)*(1+g)))
```

```python
kss = sm.solve(steadystateK_tilde,k)[0]
kss
```

$\displaystyle \left(\frac{\lambda^{1 - \alpha} s}{\delta + g n + g + n}\right)^{- \frac{1}{\alpha - 1}}$

## Solving the model numerically

The numerical solution of steady state of capital is solved:

```python
# Setting the parameters again
alpha=1/3
delta=0.1
lam_one=0.6
lam_two=0.75
g=0.02
n=0.25
s=0.2
```

```python
def solver(lam,s,g,n,alpha,delta):
    func = lambda k: k**alpha
    k_tilde_func = lambda k_tilde: k_tilde - (s*lam**(1-alpha)*func(k_tilde)+(1-delta)*k_tilde)/((1+n)*(1+g))
    solve = optimize.root_scalar(k_tilde_func,bracket=[0.1,100],method='bisect')
    return solve

solution1 = solver(lam_one,s,g,n,alpha,delta)
solution2 = solver(lam_two,s,g,n,alpha,delta)

print(f'The numerical solution with lambda = 0.6 is : {solution1.root:.3f}')
print(f'The numerical solution with lambda = 0.75 is : {solution2.root:.3f}')
```

    The numerical solution with $\lambda$ = 0.6 is : 0.234
    The numerical solution with lambda = 0.75 is : 0.292

The steady state level of capital is now smaller in both cases since we look at technologically adjusted capital pr. capita and not just capital pr. capita as we did earlier. We notice that the increase in capital given an increase in $\lambda$ is smaller in this economy.

## Visualization of the second model

To get a better idea of the impact on the steady state value from the parameters, we plot the share of the population in the labor force against the technologically adjusted capital pr. capita:

```python
lam_plot = np.linspace(0,1,100)
kss_plot = (lam_plot**(1-alpha)*s/(delta+g*n+g+n))**1/(1-alpha)

#Plotting different value of lambda from 0 to 1 against the value of tecnolegy adjusted capital steady state
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_xlabel("Share of population in the laborforce")
ax.set_ylabel("$k_{tilde}^\star$")

ax.set_title('Figure 4: The effect of $\lambda$ on the steady state of capital', fontsize=13)
ax.plot(lam_plot,kss_plot)
plt.show;
```

We find that a higher value of $\lambda$ also increases technologically adjusted capital pr. capita.

We combine this with different values for the populations growth:

```python
def kss_plot(lam,n,alpha=1/3,delta=0.1,g=0.02,s=0.2):
    ksteady = (lam**(1-alpha)*s/(delta+g*n+g+n))**1/(1-alpha)
    return ksteady

n_plot = np.linspace(0,1,100)
lam_plot = np.linspace(0,1,100)
x1_values_alt,x2_values_alt = np.meshgrid(lam_plot,n_plot,indexing='ij')
u_values_alt = kss_plot(x1_values_alt,x2_values_alt,alpha=1/3,delta=0.1,g=0.02,s=0.2)

fig = plt.figure()
ax = fig.add_subplot(1,1,1,projection='3d')
ax.plot_surface(x2_values_alt,x1_values_alt,u_values_alt,cmap=cm.jet)
ax.set_xlabel("n")
ax.set_ylabel("$lambda$")
ax.set_zlabel("$k_{tilde}^\star$")

ax.set_title('Figure 5: The effect of $n$ and $\lambda$ on the steady state of capital', fontsize=13);
```

As we expected the highest level of technologically adjusted capital pr. capita is found with a high level og $\lambda$ and no population growth. Since we look at the capital pr. capita an increase in the population will result in more pepole to "share" the capital with.

# Conclusion

The conclusion of this project is that a higher share of workers will result in a higher level of capital in steady state. In steady state we find a 1:1 relationship between an incease in $\lambda$ and the output pr. capita of the economy. This applies to both an economy with a fixed level of technology and an economy with an increasing development of technology over time. The difference is however, that an economy with a fixed level of technology will see a larger positive effect on capital pr. capita than an economy with an increasing development of technology will see on technologically adjusted capital pr. capita. This is primarily because of the fact that the level of technology is adjusted.

Thus if an economy is in a crisis where they have problems with a decreasing level of productivity which leads to no economic growth, a possible solution to this could be to raise the supply of labor. The supply of labor could be increased through lower taxation on income or if the unemployment benefits were lowered.


```python
%matplotlib inline
```

```python
import numpy as np
import matplotlib.pyplot as plt
from sympy.physics.hydrogen import R_nl
from numerov import radial_wf
```

```python
n, l = 15, 1
```

```python
offset = 0.002

#plot
fig, ax = plt.subplots(1, 2, figsize=(10, 4))

# numerov
for i, step in enumerate([0.001, 0.01, 0.05]):
    r, y = radial_wf(n, l, step=step)
    ax[0].plot(r, offset * (i + 1) + y, label=step)
    ax[1].plot(r, offset * (i + 1) + (r * y)**2.0, label=step)

# textbook
num_points = 500
r0 = np.linspace(0, r.max(), num_points)
y0 = np.array([R_nl(n, l, x) for x in r0])
ax[0].plot(r0, y0, label='sympy')
ax[1].plot(r0, (r0 * y0)**2.0, label='sympy')

ax[0].set_xlabel(r'$r$')
ax[0].set_ylabel(r'$R_{n, l}$')
ax[1].set_xlabel(r'$r$')
ax[1].set_ylabel(r'$r^2 |R_{n, l} |^2$')
ax[1].legend()
plt.tight_layout()
plt.show()
```

```python
n = 15; l = 2
offset = 0.002

#plot
fig, ax = plt.subplots()

# numerov
r, y = radial_wf(n, l, step=0.001)
ax.plot(r, (r * y)**2.0, label="numerov")

# textbook
y0 = np.array([R_nl(n, l, x) for x in r])
ax.plot(r, (r * y0)**2.0, label='sympy')

ax.set_xlabel(r'$r$')
ax.set_ylabel(r'$r^2 |R_{n, l} |^2$')
ax.legend()
plt.show()
```

```python
# sympy
%timeit np.array([R_nl(n, l, x) for x in r])
```

    19.7 s ± 1.19 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

```python
# numerov
%timeit radial_wf(n, l, step=0.001)
```

    1.56 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

```python
%timeit radial_wf(n, l, step=0.0001)
```

    15.9 ms ± 63.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

```python

```


## Point Collocation

This tutorial uses the same example as the [example introduction](./example_introduction.ipynb).
In other words:

```python
import numpy
from matplotlib import pyplot
import chaospy
from chaospy.example import (
    coordinates, exponential_model, distribution)
```

Point collection method is a broad term, as it covers multiple approaches.
But in a nutshell:

* Generate $Q_1, ..., Q_N = (I_1, R_1), ..., (I_N, R_N)$, using (pseudo-)random samples or otherwise.
* Evaluate model predictor $U_1, ..., U_N$ for each sample.
* Select an expansion or polynomials $P_1, ..., P_M$, typically orthogonal (with respect to the probability distribution).
* Define the linear regression problem: $U_n = \sum_m c_m(t) P_m(I_n, R_n)$ and solve for $c_1, ..., c_M$.
* Analyze model approximation $u(t; I, R) = \sum_m c_m(t) P_n(I, R)$ instead of actual model solver.

This approach does not require the samples to follow any distribution, nor does it require the polynomial expansion to have any particular properties, like e.g. orthogonality.
In practice however, when focusing on statistical properties (like mean and variance), it makes sense to have the number of samples in an area roughly proportional to the probability density function.
This can be achieved in a few ways, but most common is to either use random samples/low discrepancy sequences, or abscissas from a quadrature scheme.
And in the same way, even though the polynomials do not have to be orthogonal, in practice using orthogonal polynomials are shown to be more numerical stable.

Below, we will compare the [Halton sequence](https://en.wikipedia.org/wiki/Halton_sequence) and compare it to [optimal Gaussian quadrature](https://en.wikipedia.org/wiki/Gaussian_quadrature).

### Generating samples

In chaospy, creating low-discrepancy sequences can be done using the `distribution.sample` method.
Creating quadrature points can be done using `chaospy.generate_quadrature`.

```python
# Sampling schemes we want to include
rules = ["halton", "gaussian"]

# Generate samples for different orders:
quadrature_order = 10
number_of_samples = (quadrature_order+1)**2
samples = {
    "halton": distribution.sample(
        number_of_samples, rule="halton"),
    "gaussian": chaospy.generate_quadrature(
        quadrature_order, distribution, rule="gaussian")[0],
}

assert samples["halton"].shape ==  (len(distribution), number_of_samples)
assert samples["gaussian"].shape == (len(distribution), number_of_samples)
```

The two schemes represents two different approaches.
One is meant to mimic random samples, while the other is designed for quadrature.

```python
# increase figure width to better fit two plots
pyplot.rc("figure", figsize=[15, 6])

for fig_idx, rule in enumerate(rules, start=1):
    pyplot.subplot(1, 2, fig_idx)

    pyplot.scatter(*samples[rule])

    pyplot.xlabel("init (normal)")
    pyplot.ylabel("rate (uniform)") if fig_idx == 1 else None
    pyplot.axis([0.9, 2.1, 0.1, 0.2])
    pyplot.title(rule)

pyplot.show()
```

### Evaluating model predictor

Creating model predictions is fairly straight forward.
Just note that the (random) samples generated has shape `(len(distribution), number_of_samples)`.
As such, it is important to transpose when iterating over samples.

```python
evaluations = {}
for rule in rules:
    evaluations[rule] = numpy.array(
        [exponential_model(sample)
         for sample in samples[rule].T])

assert evaluations["halton"].shape == (number_of_samples, len(coordinates))
assert evaluations["gaussian"].shape == (number_of_samples, len(coordinates))
```

These model evaluations can be visualized, however ti is hard to observe the difference between the two schemes from these plots.

```python
for fig_idx, rule in enumerate(rules, start=1):
    pyplot.subplot(1, 2, fig_idx)

    pyplot.plot(coordinates, evaluations[rule][::3].T, alpha=0.3)

    pyplot.xlabel("coordinates $t$")
    pyplot.ylabel("model evaluations $u$")
    pyplot.title(rule)
    pyplot.axis([0, 10, 0, 2])

pyplot.show()
```

### Select expansion of Polynomials

Creating polynomial expansion can be done using the _three terms recursion_ algorithm:

```python
polynomial_order = 4
polynomial_expansion = chaospy.generate_expansion(
    polynomial_order, distribution)
polynomial_expansion[:6].round(5)
```

    polynomial([1.0, q1-0.15, q0-1.5, q1**2-0.3*q1+0.02167,
                q0*q1-1.5*q1-0.15*q0+0.225, q0**2-3.0*q0+2.21])

Here the polynomials are function of two variables: $q_0, q_1$, which in the context of the order of `distribution` refer to respectively $I$ and $a$ in the original problem.

The created expansion is orthogonal with respect to each other in a weighted Hilbert space:

$$
    \langle \Phi_n, \Phi_m \rangle = \mbox E(\Phi_n\Phi_m) = \delta_{nm} \|\Phi_n\|^2 \qquad
    \|\Phi_n\| = \sqrt{\langle\Phi_n, \Phi_n\rangle}
$$

where $\delta_{nm}$ is the Kronecker's delta.

In other words:

```python
outer_product = chaospy.outer(
    polynomial_expansion[:6], polynomial_expansion[:6])
normed_inner_products = (
    chaospy.E(outer_product, distribution)/
    chaospy.E(polynomial_expansion[:6]**2, distribution)
)
normed_inner_products.round(10)
```

    array([[ 1.,  0.,  0.,  0.,  0.,  0.],
           [ 0.,  1.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  1.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  1., -0.,  0.],
           [ 0.,  0.,  0., -0.,  1.,  0.],
           [ 0.,  0.,  0.,  0.,  0.,  1.]])

It is worth noting that scaling upwards, calculating $\mathbb E[\Phi_n^2]$ is known to tend to be numerically unstable.
It is more accurately calculated either using some quadrature scheme, or using the coefficients from the three terms recursion.
The latter can be retrieved by passing the flag `retall=True` to `chaospy.generate_quadrature`.

```python
_, norms = chaospy.generate_expansion(
    polynomial_order, distribution, retall=True)
(norms[:3].round(3),
 chaospy.E(polynomial_expansion[:3]**2, distribution).round(3))
```

    (array([1.   , 0.001, 0.04 ]), array([1.   , 0.001, 0.04 ]))

### Solve linear problem

With all samples $Q_1, ..., Q_N$, model evaluations $U_1, ..., U_N$ and polynomial expansion $\Phi_1, ..., \Phi_M$, we can put everything together to solve the equations:

$$
    U_n = \sum_{m=1}^M c_m(t) \Phi_m(Q_n) \qquad n = 1, ..., N
$$

with respect to the coefficients $c_1, ..., c_M$.

This can be done using the helper function `chaospy.fit_regression`:

```python
model_approximations = {
    rule: chaospy.fit_regression(
        polynomial_expansion, samples[rule], evaluations[rule])
    for rule in rules
}
(model_approximations["halton"][:4].round(3),
 model_approximations["gaussian"][:4].round(3))
```

    (polynomial([q0, -0.01*q0*q1+q0, -0.02*q0*q1+q0, -0.03*q0*q1+q0]),
     polynomial([q0, -0.01*q0*q1+q0, -0.02*q0*q1+q0, -0.03*q0*q1+q0]))

As a sidenote, the basic regression method can also be done manually using the least squares formula:

$$
    C = \left(P^T P\right)^{-1} P^T U
$$

where

$$
\begin{align}
    C &= [\hat c_m]_m &
    P &= [\Phi_m(Q_n)]_{mn} &
    U &= [U_n]_n
\end{align}
$$

Or using code:

```python
P = polynomial_expansion(*samples["halton"]).T
c_hat = numpy.linalg.inv(P.T @ P) @ P.T @ evaluations["halton"]
assert c_hat.shape == (15, len(coordinates))
```

The coefficients can then be combined together with the original polynomial expansion:

```python
# NBVAL_CHECK_OUTPUT
alternative_approximation = chaospy.sum(
    c_hat.T*polynomial_expansion, axis=1).T
alternative_approximation[:4].round(3)
```

    polynomial([q0, -0.01*q0*q1+q0, -0.02*q0*q1+q0, -0.03*q0*q1+q0])

### Assess Statistics

Since we have a direct approximation of the model function in the form of a polynomial, we can assess statistical properties from the polynomial, and use them as a proxy for the real statistics. For example, for mean and variance:

```python
for fig_idx, rule in enumerate(rules, start=1):
    pyplot.subplot(1, 2, fig_idx)

    mean = chaospy.E(
        model_approximations[rule], distribution)
    var = chaospy.Var(
        model_approximations[rule], distribution)

    pyplot.fill_between(coordinates, mean-numpy.sqrt(var),
                        mean+numpy.sqrt(var), alpha=0.3)
    pyplot.plot(coordinates, mean, "k-")

    pyplot.xlabel("coordinates $t$")
    pyplot.ylabel("Model evaluations $u$")
    pyplot.axis([0, 10, 0, 2])
    pyplot.title(rule)

pyplot.show()
```

### Error Analysis

It is hard to assess how well these models are doing from the final estimation alone.
They look about the same.
So to compare results, we do error analysis.
To do so, we use the reference analytical solution and error function as defined in  [example introduction](./example_introduction.ipynb).

```python
# NBVAL_CHECK_OUTPUT
from chaospy.example import error_mean, error_variance

assert abs(error_mean(mean)) < 1e-9
assert abs(error_variance(var)) < 1e-7
```

To illustrate the difference in a common format, we plot error as a function of the number of samples used in a logarithmic plot.

```python
# Estimate mean and variance for various number of samples
polynomial_orders = list(range(2, 6))
for idx, rule in enumerate(rules):
    pyplot.subplot(1, 2, idx+1)

    sample_sizes = []
    errors_mean = []
    errors_variance = []
    for order in polynomial_orders:

        # Perform analysis for a specific order
        samples = (
            distribution.sample((order+1)**2, rule="halton")
            if rule == "halton"
            else chaospy.generate_quadrature(
                order, distribution, rule="gaussian")[0]
        )
        evaluations = [exponential_model(sample)
                       for sample in samples.T]
        polynomial_expansion = chaospy.generate_expansion(
            order, distribution)
        model_approximation = chaospy.fit_regression(
            polynomial_expansion, samples, evaluations)

        # Store results
        sample_sizes.append((order+1)**2)
        errors_mean.append(error_mean(
            chaospy.E(model_approximation, distribution)))
        errors_variance.append(error_variance(
            chaospy.Var(model_approximation, distribution)))

    # Error plot for mean
    pyplot.loglog(sample_sizes, errors_mean, label="mean")

    # Error plot for variance
    pyplot.loglog(sample_sizes, errors_variance, label="variance")

    # Make plot pretty
    pyplot.axis([
        min(sample_sizes), max(sample_sizes), 1e-15, 1e-3])
    pyplot.title(rule)
    pyplot.xlabel("Number of samples")
    pyplot.legend() if idx else pyplot.ylabel("Error")

pyplot.show()
```

It is worth noting that Halton is not doing poorly, as much as the Gaussian approach doing so much better.
Though this can be the case some times, the effect most often drops drastically with the number of dimensions.


# Spectral Analysis of Deterministic Signals

*This jupyter notebook is part of a [collection of notebooks](../index.ipynb) on various topics of Digital Signal Processing.

## Zero-Padding

### Concept

Let's assume a signal $x_N[k]$ of finite length $N$, for instance a windowed signal $x_N[k] = x[k] \cdot \text{rect}_N[k]$. The discrete Fourier transformation (DFT) of $x_N[k]$ reads

\begin{equation}
X_N[\mu] = \sum_{k=0}^{N-1} x_N[k] \; w_N^{\mu k}
\end{equation}

where $w_N = \mathrm{e}^{-\mathrm{j} \frac{2 \pi}{N}}$ denotes the kernel of the DFT. For a sampled time-domain signal, the distance in frequency between two neighboring coefficients is given as $\Delta f = \frac{f_s}{N}$, where $f_s = \frac{1}{T}$ denotes the sampling frequency. Hence, if $N$ is increased the distance between neighboring frequencies is decreased. This leads to the concept of zero-padding in spectral analysis. Here the signal $x_N[k]$ of finite length is filled up with (M-N) zero values to a total length $M \geq N$

\begin{equation}
x_M[k] = \begin{cases}
x_N[k] & \mathrm{for} \; k=0,1,\dots,N-1 \\
0 & \mathrm{for} \; k=N,N+1,\dots,M-1
\end{cases}
\end{equation}

Appending zeros does not change the contents of the signal itself. However, the DFT $X_M[\mu]$ of $x_M[k]$ has now a decreased distance between neighboring frequencies $\Delta f = \frac{f_s}{M}$.

The question arises what influence zero-padding has on the spectrum and if it can enhance spectral analysis. On first sight it seems that the frequency resolution is higher, however do we get more information on the signal? In order to discuss this, a short numerical example is evaluated followed by a derivation of the mathematical relations between the spectrum $X_M[k]$ with zero-padding and $X_N[k]$ without zero-padding.

#### Example - Zero-Padding

The following example computes and plots the magnitude spectra $|X[\mu]|$ of a truncated complex exponential signal $x_N[k] = \mathrm{e}^{\,\mathrm{j}\,\Omega_0\,k} \cdot \text{rect}_N[k]$ and its zero-padded version $x_M[k]$.

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

N = 16  # length of the signal
M = 32  # length of zero-padded signal
Om0 = 5.33*(2*np.pi/N)  # frequency of exponential signal

# DFT of the exponential signal
xN = np.exp(1j*Om0*np.arange(N))
XN = np.fft.fft(xN)
# DFT of the zero-padded exponential signal
xM = np.concatenate((xN, np.zeros(M-N)))
XM = np.fft.fft(xM)

# plot spectra
plt.figure(figsize = (10, 6))

plt.subplot(121)
plt.stem(np.arange(N),np.abs(XN))
plt.title(r'DFT$_{%d}$ of $e^{j \Omega_0 k}$ without zero-padding' %N)
plt.xlabel(r'$\mu$')
plt.ylabel(r'$|X_N[\mu]|$')
plt.axis([0, N, 0, 18])
plt.grid()

plt.subplot(122)
plt.stem(np.arange(M),np.abs(XM))
plt.title(r'DFT$_{%d}$ of $e^{j \Omega_0 k}$ with zero-padding' %M)
plt.xlabel(r'$\mu$')
plt.ylabel(r'$|X_M[\mu]|$')
plt.axis([0, M, 0, 18])
plt.grid()
```

**Exercise**

* Check the two spectra carefully for relations. Are there common coefficients for the case $M = 2 N$?
* Increase the length `M` of the zero-padded signal $x_M[k]$. Can you gain additional information from the spectrum?

Solution: Every second (because the DFT length has been doubled) coefficient has been added, the other coefficients stay the same. With longer zero-padding, the maximum of the main lobe of the window gets closer to its true maximum.

### Interpolation of the Discrete Fourier Transformation

Lets step back to the discrete-time Fourier transformation (DTFT) of the finite-length signal $x_N[k]$ without zero-padding

\begin{equation}
X_N(\mathrm{e}^{\,\mathrm{j}\,\Omega}) = \sum_{k = -\infty}^{\infty} x_N[k] \, \mathrm{e}^{\,-\mathrm{j}\,\Omega\,k} = \sum_{k=0}^{N-1} x_N[k] \,\mathrm{e}^{-\,\mathrm{j}\,\Omega\,k}
\end{equation}

The discrete Fourier transformation (DFT) is derived by sampling $X_N(\mathrm{e}^{\mathrm{j}\,\Omega})$ at $\Omega = \mu \frac{2 \pi}{N}$

\begin{equation}
X_N[\mu] = X_N(\mathrm{e}^{\,\mathrm{j}\, \Omega}) \big\vert_{\Omega = \mu \frac{2 \pi}{N}} = \sum_{k=0}^{N-1} x_N[k] \, \mathrm{e}^{\,-\mathrm{j}\, \mu \frac{2\pi}{N}\,k}
\end{equation}

Since the DFT coefficients $X_N[\mu]$ are sampled equidistantly from the DTFT $X_N(\mathrm{e}^{\,\mathrm{j}\, \Omega})$, we can reconstruct the DTFT of $x_N[k]$ from the DFT coefficients by interpolation. Introduce the inverse DFT of $X_N[\mu]$

\begin{equation}
x_N[k] = \frac{1}{N} \sum_{\mu = 0}^{N-1} X_N[\mu] \; \mathrm{e}^{\,\mathrm{j}\,\frac{2 \pi}{N} \mu \,k}
\end{equation}

into the DTFT

\begin{equation}
X_N(\mathrm{e}^{\,\mathrm{j}\,\Omega}) = \sum_{k=0}^{N-1} x_N[k] \; \mathrm{e}^{-\,\mathrm{j}\, \Omega\, k} =
\sum_{\mu=0}^{N-1} X_N[\mu] \cdot \frac{1}{N} \sum_{k=0}^{N-1} \mathrm{e}^{-\mathrm{j}\, k \,(\Omega - \frac{2 \pi}{N} \mu)}
\end{equation}

reveals the relation between $X_N(\mathrm{e}^{\,\mathrm{j}\,\Omega})$ and $X_N[\mu]$. The last sum over $k$ constitutes a [geometric series](https://en.wikipedia.org/wiki/Geometric_series) and can be rearranged to

\begin{equation}
X_N(\mathrm{e}^{\,\mathrm{j}\,\Omega}) = \sum_{\mu=0}^{N-1} X_N[\mu] \cdot \frac{1}{N} \cdot \frac{1-\mathrm{e}^{-\mathrm{j}(\Omega-\frac{2\pi}{N}\mu)N}}{1-\mathrm{e}^{-\mathrm{j}(\Omega-\frac{2\pi}{N}\mu)}}
\end{equation}

By factorizing the last fraction to

\begin{equation}
X_N(\mathrm{e}^{\,\mathrm{j}\,\Omega}) = \sum_{\mu=0}^{N-1} X_N[\mu] \cdot \frac{1}{N} \cdot \frac{\mathrm{e}^{-\mathrm{j}\frac{(\Omega-\frac{2\pi}{N}\mu)N}{2}}}{\mathrm{e}^{-\mathrm{j}\frac{\Omega-\frac{2\pi}{N}\mu}{2}}} \cdot \frac{\mathrm{e}^{\mathrm{j}\frac{(\Omega-\frac{2\pi}{N}\mu)N}{2}}-\mathrm{e}^{-\mathrm{j}\frac{(\Omega-\frac{2\pi}{N}\mu)N}{2}}}{\mathrm{e}^{\mathrm{j}\frac{\Omega-\frac{2\pi}{N}\mu}{2}}-\mathrm{e}^{-\mathrm{j}\frac{\Omega-\frac{2\pi}{N}\mu}{2}}}
\end{equation}

and making use of [Euler's identity](https://en.wikipedia.org/wiki/Euler%27s_identity) $2\mathrm{j}\cdot\sin(x)=\mathrm{e}^{\mathrm{j} x}-\mathrm{e}^{-\mathrm{j} x}$ this can be simplified to

\begin{equation}
X_N(\mathrm{e}^{\,\mathrm{j}\,\Omega}) = \sum_{\mu=0}^{N-1} X_N[\mu] \cdot \mathrm{e}^{-\mathrm{j}\frac{(\Omega-\frac{2\pi}{N}\mu)(N-1)}{2}} \cdot \frac{1}{N} \cdot \frac{\sin(N\frac{\Omega-\frac{2\pi}{N}\mu}{2})}{\sin(\frac{\Omega-\frac{2\pi}{N}\mu}{2})}
\end{equation}

The last fraction can be written in terms of the $N$-th order periodic sinc function (aliased sinc function, [Dirichlet kernel](https://en.wikipedia.org/wiki/Dirichlet_kernel)), which is defined as

\begin{equation}
\text{psinc}_N (\Omega) = \frac{1}{N} \frac{\sin(\frac{N}{2} \Omega)}{  \sin(\frac{1}{2} \Omega)}
\end{equation}

According to this definition, the periodic sinc function is not defined at $\Omega = 2 \pi \,n$ for $n \in \mathbb{Z}$. This is resolved by applying [L'Hôpital's rule](https://en.wikipedia.org/wiki/L%27H%C3%B4pital%27s_rule) which results in $\text{psinc}_N (2 \pi \,n) = 1$ for $n \in \mathbb{Z}$.

Using the periodic sinc function, the DTFT $X_N(\mathrm{e}^{\,\mathrm{j}\, \Omega})$ of a finite-length signal $x_N[k]$ can be derived from its DFT $X_N[\mu]$ by

\begin{equation}
X_N(\mathrm{e}^{\,\mathrm{j}\, \Omega}) =  \sum_{\mu=0}^{N-1} X_N[\mu] \cdot \mathrm{e}^{-\,\mathrm{j}\, \frac{( \Omega - \frac{2 \pi}{N} \mu ) (N-1)}{2}} \cdot \text{psinc}_N ( \Omega - \frac{2 \pi}{N} \mu )
\end{equation}

#### Example - Periodic sinc function

This example illustrates the

1. periodic sinc function, and
2. interpolation of $X_N(\mathrm{e}^{\,\mathrm{j}\, \Omega})$ from $X_N[\mu]$ for an exponential signal using above relation.

```python
N = 16  # order of periodic sinc function
M = 1024  # number of frequency points
Om = np.linspace(-np.pi, np.pi, M)

# definition of periodic sinc function
def psinc(x, N):
    x = np.asanyarray(x)
    y = np.where(x == 0, 1.0e-20, x)
    return 1/N * np.sin(N/2*y)/np.sin(1/2*y)

# plot psinc
plt.figure(figsize = (10, 8))
plt.plot(Om, psinc(Om, 16))
plt.xlabel(r'$\Omega$')
plt.ylabel(r'$\mathrm{psinc}_N (\Omega)$')
plt.grid()
```

```python
N = 16  # length of the signal
M = 1024  # number of frequency points for DTFT
Om0 = 5.33*(2*np.pi/N)  # frequency of exponential signal

# DFT of the exponential signal
xN = np.exp(1j*Om0*np.arange(N))
XN = np.fft.fft(xN)

# interpolation of DTFT from DFT coefficients
Xi = np.asarray(np.zeros(M), dtype=complex)
for mu in np.arange(M):
    Omd = 2*np.pi/M*mu-2*np.pi*np.arange(N)/N
    interpolator = psinc(Omd, N) * np.exp(-1j*Omd*(N-1)/2)
    Xi[mu] = np.sum(XN * interpolator)

# plot spectra
plt.figure(figsize = (10, 8))
ax1 = plt.gca()

plt.plot(np.arange(M)*2*np.pi/M, abs(Xi), 'r', label=r'$|X_N(e^{j \Omega})|$')
plt.stem(np.arange(N)*2*np.pi/N, abs(XN), basefmt = ' ', label=r'$|X_N[\mu]|$')
plt.title(r'DFT $X_N[\mu]$ and interpolated DTFT $X_N(e^{j \Omega})$', y=1.08)
plt.ylim([-0.5, N+2]);
plt.legend()

ax1.set_xlabel(r'$\Omega$')
ax1.set_xlim([0, 2*np.pi])
ax1.grid()

ax2 = ax1.twiny()
ax2.set_xlim([0, N])
ax2.set_xlabel(r'$\mu$', color='C0')
ax2.tick_params('x', colors='C0')
```

### Relation between Discrete Fourier Transformations with and without Zero-Padding

It was already outlined above that the DFT is related to the DTFT by sampling. Hence, the DFT $X_M[\mu]$ is given by sampling the DTFT $X_M(\mathrm{e}^{\mathrm{j}\, \Omega})$ at $\Omega = \frac{2 \pi}{M} \mu$. Since the zero-padded signal $x_M[k]$ differs from $x_N[k]$ only with respect to the additional zeros, the DTFTs of both are equal

\begin{equation}
X_M(\mathrm{e}^{\mathrm{j}\, \Omega}) = X_N(\mathrm{e}^{\mathrm{j}\, \Omega})
\end{equation}

The desired relation between the DFTs $X_N[\mu]$ and $X_M[\mu]$ of the signal $x_N[k]$ and its zero-padded version $x_M[k]$ can be found by sampling the interpolated DTFT $X_N(\mathrm{e}^{\mathrm{j}\, \Omega})$ at $\Omega = \frac{2 \pi}{M} \mu$

\begin{equation}
X_M[\mu] =  \sum_{\eta=0}^{N-1} X_N[\eta] \cdot \mathrm{e}^{\,-\mathrm{j}\, \frac{( \frac{2 \pi}{M} \mu - \frac{2 \pi}{N} \eta ) (N-1)}{2}} \cdot \text{psinc}_N \left( \frac{2 \pi}{M} \mu - \frac{2 \pi}{N} \eta \right)
\end{equation}

for $\mu = 0, 1, \dots, M-1$.

Above equation relates the spectrum $X_N[\mu]$ of the original signal $x_N[k]$ to the spectrum $X_M[\mu]$ of the zero-padded signal $x_M[k]$. It essentially constitutes a bandlimited interpolation of the coefficients $X_N[\mu]$.

All spectral information of a signal of finite length $N$ is already contained in its spectrum derived from a DFT of length $N$. By applying zero-padding and a longer DFT, the frequency resolution is only virtually increased. The additional coefficients are related to the original ones by bandlimited interpolation. In general, zero-padding does not bring additional insights in spectral analysis. It may bring a benefit in special applications, for instance when estimating the frequency of an isolated harmonic signal from its spectrum. This is illustrated in the following example.

Zero-padding is also used to make a circular convolution equivalent to a linear convolution. However, there is a different reasoning behind this. Details are discussed in a [later section](../nonrecursive_filters/fast_convolution.ipynb#Linear-Convolution-by-Periodic-Convolution).

#### Example - Interpolation of the DFT

The following example shows that the coefficients $X_M[\mu]$ of the spectrum of the zero-padded signal $x_M[k]$ can be derived by interpolation from the spectrum $X_N[\mu]$.

```python
N = 16  # length of the signal
M = 32  # number of points for interpolated DFT
Om0 = 5.33*(2*np.pi/N)  # frequency of exponential signal

# periodic sinc function
def psinc(x, N):
    x = np.asanyarray(x)
    y = np.where(x == 0, 1.0e-20, x)
    return 1/N * np.sin(N/2*y)/np.sin(1/2*y)

# DFT of the exponential signal
xN = np.exp(1j*Om0*np.arange(N))
XN = np.fft.fft(xN)

# interpolation of DFT coefficients
XM = np.asarray(np.zeros(M), dtype=complex)
for mu in np.arange(M):
    Omd = 2*np.pi/M*mu-2*np.pi*np.arange(N)/N
    interpolator = psinc(Omd, N) * np.exp(-1j*Omd*(N-1)/2)
    XM[mu] = np.sum(XN * interpolator)

# plot spectra
plt.figure(figsize = (10, 6))

plt.subplot(121)
plt.stem(np.arange(N),np.abs(XN))
plt.title(r'DFT of $e^{j \Omega_0 k}$ without zero-padding')
plt.xlabel(r'$\mu$')
plt.ylabel(r'$|X_N[\mu]|$')
plt.axis([0, N, 0, 18])
plt.grid()

plt.subplot(122)
plt.stem(np.arange(M),np.abs(XM))
plt.title(r'Interpolated spectrum')
plt.xlabel(r'$\mu$')
plt.ylabel(r'$|X_M[\mu]|$')
plt.axis([0, M, 0, 18])
plt.grid()
```

**Exercise**

* Compare the interpolated spectrum to the spectrum with zero padding from the first example.
* Estimate the frequency $\Omega_0$ of the exponential signal from the interpolated spectrum. How could you further increase the accuracy of your estimate?

Solution: The interpolated spectrum is the same as the spectrum with zero padding from the first example. The estimated frequency from the interpolated spectrum is $\Omega_0=\frac{2\pi}{M}\mu=\frac{2\pi}{32}\cdot11$. A better estimate can be obtained by increasing the number of points for the interpolated DFT or by further zero-padding of the time domain signal.

#### Example - Estimation of Frequency and Amplitude of a Harmonic Signal

The estimation of the normalized frequency $\Omega_0$ and amplitude $A$ of a single exponential signal $x_N[k] = A \cdot e^{j \Omega_0 k}$ by the DFT of the zero-padded signal (or interpolated DFT) is illustrated in the following example. The frequency is estimated from the DFT of the zero-padded signal by finding the maximum in the magnitude spectrum

\begin{equation}
\hat{\mu_0} = \underset{\mu}{\mathrm{argmax}} \{ |X_M[\mu]| \}
\end{equation}

The amplitude is estimated by taking the magnitude at the maximum $\hat{A} = | X_M[\hat{\mu}_0] |$.

First a function is defined which estimates the frequency for a given number of zeros appended to the signal before calculating the DFT. Without loss of generality is is assumed that $A=1$.

```python
N = 128  # length of the signal
Om0 = 5.33*(2*np.pi/N)  # frequency of exponential signal

# generate harmonic signal
k = np.arange(N)
x = np.exp(1j*Om0*np.arange(N))

def estimate_frequency_amplitude(x, P):
    # perform zero-padding and DFT
    xM = np.concatenate((x, np.zeros(P)))
    XM = np.fft.fft(xM)

    # estimate frequency/amplitude of harmonic signal
    mu_max = np.argmax(abs(XM))
    amplitude = 1/N * abs(XM[mu_max])

    # print results
    Om = np.fft.fftfreq(N+P, 1/(2*np.pi))
    print('Normalized frequency of signal: {0:1.4f} (real) / {1:1.4f} (estimated) / {2:1.4f} (absolute error)'.format(Om0, Om[mu_max], abs(Om0 - Om[mu_max])))
    print('Amplitude of signal: {0:1.4f} (real) / {1:1.4f} (estimated) / {2:2.2f} dB (magnitude error)'.format(1, amplitude, 20*np.log10(abs(1/amplitude))))
```

First the estimation is performed without zero-padding

```python
estimate_frequency_amplitude(x, 0)
```

    Normalized frequency of signal: 0.2616 (real) / 0.2454 (estimated) / 0.0162 (absolute error)
    Amplitude of signal: 1.0000 (real) / 0.8303 (estimated) / 1.62 dB (magnitude error)

Then the signal is zero-padded to a total length of eight times its original length

```python
estimate_frequency_amplitude(x, 7*N)
```

    Normalized frequency of signal: 0.2616 (real) / 0.2638 (estimated) / 0.0022 (absolute error)
    Amplitude of signal: 1.0000 (real) / 0.9967 (estimated) / 0.03 dB (magnitude error)

**Exercise**

* What is the maximum error that can occur when estimating the frequency from the maximum of the (zero-padded) magnitude spectrum?

Solution: The maximum absolute error occurs if the maximum in the DTFT of the signal is in between two adjacent bins $\mu$ of the DFT. Since the DTFT is sampled at $\Omega = \frac{2 \pi}{M}$ to derive the DFT, the maximum absolute error is given by $\frac{\pi}{M}$ where $M$ denotes the length of the zero-padded signal/DFT.


# Maximum Entropy

Information entropy is a function of probability distributions measure the quantity of information contained in a random variable (typically in bits).  Consider a binary random variable that takes on two values, $H$ and $L$.  The probability it takes the value $H$ is $p$ and the probability it takes value $L$ is $1-p$.  Then the average information content of this random variable is measured as,

\begin{align}
    H(p) &= -\left( p \log(p) + (1-p)\log(1-p) \right)
\end{align}

Choose the value of $p$ that maximizes the entropy function (i.e., maximizes the uncertainty, or information content of the binary random variable.)

```python
from sympy import *
from sympy.plotting import plot
init_printing()
```

```python
# Declare our symbols and setup the
# entropy function.
p = Symbol('p', real=True, positive=True)
H = -1*(p * log(p) + (1 - p) * log(1-p))

Eq(Symbol('H(p)'), H)
```

```python
# Take the derivative with respect to
# the probability of H: p.
DH = H.diff(p)
Eq(Symbol('\\frac{\partial H(p)}{\partial p}'), DH)
```

```python
# Set the derivative equal to zero
# and solve for p to find the value that
# satisfies the first order condition for
# a maximum.
p_star = solve(DH, p)[0]
Eq(Symbol('p^*'), p_star)
```

```python
# Find the second derivative so we can
# test the second order condition for
# a maximum.
D2H = H.diff(p).diff(p)
Eq(Symbol('\\frac{\partial^2 H(p)}{\partial p^2}'), D2H)
```

```python
# Evaluate the sign of the second derivative
# at the critical point we found, p*.
Eq(Symbol('\\frac{\partial^2 H(p)}{\partial p^2}|_{p^*}'), D2H.subs(p, p_star))
```

As we can see, the second derivative is negative and the critical point we found $p^* = 1/2$ is a maximum.  Thus, maximum entropy occurs at the uniform distribution $(p, 1-p) = (1/2, 1/2)$.

```python
plot(H, (p, 0.01, 0.99))
```


# Profit Maximizing Quantity (Linear Demand)

Consider a situation of a monopolist facing a linear demand curve

\begin{align}
    D(p) &= a - b p
\end{align}

where $a, b > 0$.  The firm will produce exactly enough units of their product to meet the demand $D(p)$ and it costs them $c > 0$ to produce each unit of product.  The total profits the monopolist expects from choosing price $p>0$ is

\begin{align}
    \pi(p) &= (a - bp)p - c(a - bp) \\
    &= (p - c)(a - bp)
\end{align}

To identify the profit maximizing price we need to identify a local maximum consisting of a critical point, an $x^*$ that satisfies a first order condition $\frac{d\pi }{dp} (x^*) = 0$ and a second order condition $\frac{d^2 \pi}{d x^2}(x^*) < 0$.

```python
from sympy import *
init_printing()
```

```python
a, b, c, P = symbols('a b c P',
                     real=True,
                     positive=True,
                     finite=True)
demand = a - b * P
revenue = P * demand
cost = c * demand
profit = factor(revenue - cost)

Eq(Symbol('\pi(P)'), profit)
```

```python
# To satisfy the first order condition
# for a maximum we take the derivative
# of the profit function w.r.t. p
DP = profit.diff(P)
Eq(Symbol('\\frac{d \pi}{d p}'), DP)
```

```python
# Set the derivative equal to zero
# and solve for p.
P_star = solve(DP, P)[0]
Eq(Symbol('P^{*}(a,b,c)'), P_star)
```

Now that we have the price that satisfies the first order condition, we need to evaluate the second order condition wich is the second derivative of profit with respect to price and test its sign at the $p^*$.

```python
D2P = DP.diff(P)
D2P, D2P.is_negative
```

    (-2*b, True)

From the above sign we see that the second derivative is negative at all prices, so it is clearly going to be negative at any critical point we find.