In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import eigh
We have a shear type frame, with constant floor masses and constant storey stiffnesses. We have to specify just the number of stories
In [2]:
ns = 10
We form the structural matrices
In [3]:
ones = np.ones(ns)
M = np.diag(ones)
K = np.diag(ones*2)
K[-1,-1] = 1
K = K - np.diag(ones[1:], -1) - np.diag(ones[1:], +1)
evals, evecs = eigh(K, M)
evals[:3]
Out[3]:
In [4]:
def eigenplot(ns, evecs, ne=None, norm=False, fig_ax=None, title=None):
if fig_ax is None:
fig, ax = plt.subplots(figsize=(4,6))
else:
fig, ax = fig_ax
if ne is None: ne=ns
x = np.arange(ns+1)
y = evecs/(np.abs(evecs).max(axis=0) if norm else 1)/np.sign(evecs[-1])
y = np.vstack((np.zeros(y.shape[1]), y))
for i, evec in enumerate((y.T)[:ne], 1):
ax.plot(evec, x, label='$\\psi_{%d}$'%i)
ax.legend()
ax.grid(b=1, axis='y')
ax.yaxis.set_major_locator(plt.MultipleLocator(1))
if title : ax.set_title(title)
if not fig_ax : fig.tight_layout()
eigenplot(ns, evecs, ne=3, norm=1)
In [5]:
D0 = np.linalg.inv(K)@M
S = np.diag(ones)
sevals, sevecs = [], []
for i in range(3):
D = D0@S
x = ones
w2old = 0
while True:
xh = D@x
temp = xh@M
w2 = (temp@x)/(temp@xh)
x = xh*w2
if abs(w2-w2old)/w2 < 1E-8 : break
w2old = w2
sevals.append(w2)
sevecs.append(x)
modal_m = x.T@M@x
S = S - np.outer(x,x)@M/modal_m
print(evals[:3])
print(sevals)
sevecs = np.array(sevecs).T
In [6]:
fig, axes = plt.subplots(1,2,figsize=(8,8))
eigenplot(ns, sevecs, norm=1, fig_ax=(fig, axes[0]), title='Matrix Iteration')
eigenplot(ns, evecs, ne=3, norm=1, fig_ax=(fig, axes[1]), title='"Exact" Eigenvectors')
In [7]:
np.random.seed(20190402)
phi = D0@(np.random.random((ns,8))-0.5)
k, m = phi.T@K@phi, phi.T@M@phi
zevals, zevecs = eigh(k, m)
psi = phi@zevecs
print(zevals)
print(evals[:8])
fig, axes = plt.subplots(1,2,figsize=(8,8))
eigenplot(ns, psi, ne=5,norm=1, fig_ax=(fig, axes[0]), title='Rayleigh-Ritz')
eigenplot(ns, evecs, ne=5, norm=1, fig_ax=(fig, axes[1]), title='"Exact" Eigenvectors')
In [8]:
np.random.seed(20190402)
psi = np.random.random((ns, 4))
for i in range(2):
phi = D0@psi
k, m = phi.T@K@phi, phi.T@M@phi
zevals, zevecs = eigh(k, m)
psi = phi@zevecs
print('Ex', evals[:4])
print('SI', zevals[:4])
fig, axes = plt.subplots(1,2,figsize=(8,8))
eigenplot(ns, psi, ne=4, norm=1, fig_ax=(fig, axes[0]), title='2 Subspace Iterations, M=4')
eigenplot(ns, evecs, ne=4, norm=1, fig_ax=(fig, axes[1]), title='"Exact" Eigenvectors')
In [9]:
np.random.seed(20190402)
psi = np.random.random((ns, 8))
for i in range(2):
phi = D0@psi
k, m = phi.T@K@phi, phi.T@M@phi
zevals, zevecs = eigh(k, m)
psi = phi@zevecs
print('Ex', evals[:4])
print('SI', zevals[:4])
fig, axes = plt.subplots(1,2,figsize=(8,8))
eigenplot(ns, psi, ne=4, norm=1, fig_ax=(fig, axes[0]), title='2 Subspace Iterations, M=8')
eigenplot(ns, evecs, ne=4, norm=1, fig_ax=(fig, axes[1]), title='"Exact" Eigenvectors')
In [10]:
ns = 1000
ones = np.ones(ns)
M = np.diag(ones)
K = np.diag(ones*2)
K[-1,-1] = 1
K = K - np.diag(ones[1:], -1) - np.diag(ones[1:], +1)
K = K*500
evals, evecs = eigh(K, M)
evals[:3]
D0 = np.linalg.inv(K)@M
In [11]:
np.random.seed(20190402)
psi = np.random.random((ns, 4))
for i in range(3):
phi = D0@psi
k, m = phi.T@K@phi, phi.T@M@phi
zevals, zevecs = eigh(k, m)
psi = phi@zevecs
print('Ex', evals[:4])
print('SI', zevals[:4])
#fig, axes = plt.subplots(1,2,figsize=(8,8))
#eigenplot(ns, psi, ne=4, norm=1, fig_ax=(fig, axes[0]), title='2 Subspace Iterations, M=4')
#eigenplot(ns, evecs, ne=4, norm=1, fig_ax=(fig, axes[1]), title='"Exact" Eigenvectors')
In [12]:
np.random.seed(20190402)
psi = np.random.random((ns, 6))
for i in range(3):
phi = D0@psi
k, m = phi.T@K@phi, phi.T@M@phi
zevals, zevecs = eigh(k, m)
psi = phi@zevecs
print('Ex', evals[:4])
print('SI', zevals[:4])