<jupyter_start><jupyter_text>II. Modos de Vibración  1. Librerías<jupyter_code>import numpy as np
np.set_printoptions(formatter = {'float': lambda x: '{0:0.5f}'.format(x)})

import matplotlib.pyplot as plt

from tabulate import tabulate<jupyter_output><empty_output><jupyter_text>2. Grados de Libertad<jupyter_code>while True:
    try:
        gdl = int(input('* Ingrese el número de grados de libertad: '))
        break
    except ValueError:
        print('! Ingrese un número de GDL válido.\n')

print(f'* El modelo es de {gdl} GDL.')<jupyter_output>* El modelo es de 2 GDL.<jupyter_text>3. Matriz de Rigidez  $$\textbf{K} =  \begin{pmatrix}  K_1 + K_2 & -K_2 & 0 & \cdots & 0 & 0  \\  -K_2 & K_2 + K_3 & - K_3 & \cdots & 0  & 0 \\  0 & - K_3 &  K_3 + K_4 & \cdots & 0  & 0 \\  \vdots  & \vdots  & \vdots  & \ddots & \vdots  & \vdots   \\  0 & 0 &  0 & \cdots & K_{n-1} + K_{n} & -K_{n}\\  0 & 0 &  0 & \cdots & -K_n & -K_{n} \end{pmatrix} $$  3.1 Rigideces de Entrepiso<jupyter_code>k = np.empty(gdl)

for i in range(gdl):
    while True:
        try:
            k[i] = float(input(f'* Rigidez K{i + 1} (kg/cm): '))
            print(f'\n> Rigidez K{i + 1} = {k[i]} kg/cm')
            break
        except ValueError:
            print(f'\n! Ingrese un valor de K{i + 1} válido.')<jupyter_output>> Rigidez K1 = 155555.56 kg/cm

> Rigidez K2 = 87179.49 kg/cm<jupyter_text>3.2 Formulación de la Matriz de Rigidez<jupyter_code>K = np.zeros((gdl, gdl))

for i in range(gdl):
    ## Cálculo de rigideces

    # Rigidez actual
    k1 = k[i]

    # Rigidez posterior
    try:
        k2 = k[i + 1]
    except IndexError:
        k2 = 0

    ## Llenado de la matriz

    # Posición actual
    K[i, i] = k1 + k2

    # Posición derecha
    if i + 1 < gdl:
        K[i, i + 1] = -k2

    # Posición izquierda
    if i - 1 >= 0:
        K[i, i - 1] = -k1<jupyter_output><empty_output><jupyter_text>3.3 Representación de la Matriz de Rigidez<jupyter_code>K_r = tabulate(K, tablefmt = 'fancy_grid')

print('• Matriz K =\n')
print(K_r)<jupyter_output>• Matriz K =

╒══════════╤══════════╕
│ 242735   │ -87179.5 │
├──────────┼──────────┤
│ -87179.5 │  87179.5 │
╘══════════╧══════════╛<jupyter_text>4. Matriz de Masas  $$\textbf{M} =\begin{pmatrix}m_1 &   0   &   \cdots  &   0   \\0   &   m_2 &   \cdots  &   0   \\\vdots  &   \vdots  &   \ddots  &   \vdots \\0   &   0   &   \cdots  &   m_n   \end{pmatrix}$$  4.1 Masas Concentradas<jupyter_code>m = np.empty(gdl)

for i in range(gdl):
    while True:
        try:
            m[i] = float(input(f'* Masa M{i + 1} (kg-s2/cm): '))
            print(f'\n> Masa M{i + 1} = {m[i]} kg-s2/cm')
            break
        except ValueError:
            print(f'\n! Ingrese un valor de M{i + 1} válido.')<jupyter_output>> Masa M1 = 154.74 kg-s2/cm

> Masa M2 = 150.25 kg-s2/cm<jupyter_text>4.2 Formulación de la Matriz de Masas<jupyter_code>M =  np.zeros((gdl, gdl))

for i in range(gdl):
    M[i, i] = m[i]<jupyter_output><empty_output><jupyter_text>4.3 Representación de la Matriz de Masas<jupyter_code>M_r = tabulate(M, tablefmt = 'fancy_grid')

print('- Matriz M =\n')
print(M_r)<jupyter_output>- Matriz M =

╒════════╤════════╕
│ 154.74 │   0    │
├────────┼────────┤
│   0    │ 150.25 │
╘════════╧════════╛<jupyter_text>5. Frecuencias y Períodos- Para el cálculo de las _frecuencias modales_ se parte de la expresión:  $$\textbf{K} \cdot \textbf{X} = \omega ^2 \ \textbf{M} \cdot \textbf{X}  \\[3pt]$$- Multiplicando por la _inversa de la Matriz de Masas_ $\textbf{M}^{-1}$ a ambos miembros se tiene:  $$\textbf{M}^{-1} \cdot \textbf{K}  \cdot \textbf{X} = \omega ^2 \ \textbf{X} \\[3pt]$$- Lo cual equivale al _Problema de Valores Característicos_ (PVC) de la matriz $\textbf{A}$.  $$\textbf{A} \cdot \textbf{X} = \lambda \cdot \textbf{X}$$  5.1 Obtención de la Matriz A<jupyter_code>M_ = np.linalg.inv(M)

A = np.matmul(M_, K)<jupyter_output><empty_output><jupyter_text>5.2 Representación de la Matriz A<jupyter_code>A_r = tabulate(A, tablefmt = 'fancy_grid')

print('- Matriz A:\n')
print(A_r)<jupyter_output>- Matriz A:

╒═════════╤══════════╕
│ 1568.66 │ -563.393 │
├─────────┼──────────┤
│ -580.23 │  580.23  │
╘═════════╧══════════╛<jupyter_text>5.3 Autovalores de A<jupyter_code>A_lambda = np.linalg.eig(A)[0][::-1]

print('- Autovalores:')

for i in range(gdl):
    print(f'\n\t* λ{i + 1} = {A_lambda[i]:.2f}')<jupyter_output>- Autovalores:

	* λ1 = 318.70

	* λ2 = 1830.19<jupyter_text>5.4 Cálculo de Frecuencias<jupyter_code># Frecuencias circulares
w = np.sqrt(A_lambda)

print('- Frecuencias circulares (rad/s)')

for i in range(gdl):
    print(f'\n\t* w{i + 1} = {w[i]:.4f}')

# Frecuencias
f = w / (2 * np.pi)

print('\n- Frecuencias naturales (Hz)')

for i in range(gdl):
    print(f'\n\t* f{i + 1} = {f[i]:.4f}')<jupyter_output>- Frecuencias circulares (rad/s)

	* w1 = 17.8523

	* w2 = 42.7807

- Frecuencias naturales (Hz)

	* f1 = 2.8413

	* f2 = 6.8088<jupyter_text>5.5 Cálculo de Períodos<jupyter_code>T = 1 / f

print('- Períodos (s)')

for i in range(gdl):
    print(f'\n\t* T{i + 1} = {T[i]:.3f}')<jupyter_output>- Períodos (s)

	* T1 = 0.352

	* T2 = 0.147<jupyter_text>6. Modos de Vibración* A partir de la solución de la _matriz de vectores propios_ $\textbf{X}$ de la matriz $\textbf{A}$ se tiene:$$\textbf{X}=\left[ \begin{Bmatrix} \\X_n  \\\\\end{Bmatrix}\cdots\begin{Bmatrix} \\X_2 \\\\\end{Bmatrix}\begin{Bmatrix} \\X_1  \\\\\end{Bmatrix} \right]$$* Donde cada vector $X_{i}$ se conoce como modo de vibración. Este, es un vector unitario _tomado de forma vertical_ dentro de la matriz.* Existen diversos métodos para normalizar los modos de vibración. El más conveniente, para una posterior aplicación del _Método Dinámico Modal Espectral_, es aquel respecto a la _Matriz de Masas_ $\textbf{M}$.$$\phi_i = \frac{X_i}{\sqrt{\displaystyle  X_i^T \cdot \textbf{M} \cdot X_i}}$$  6.1 Matriz de Vectores Propios<jupyter_code>X = np.linalg.eig(A)[1]

X_r = tabulate(X, tablefmt = 'fancy_grid')

print('- Matriz X:\n')
print(X_r)<jupyter_output>- Matriz X:

╒═══════════╤══════════╕
│  0.907039 │ 0.410917 │
├───────────┼──────────┤
│ -0.421046 │ 0.911673 │
╘═══════════╧══════════╛<jupyter_text>6.2 Vectores de Modos de Vibración<jupyter_code># Traspuesta de la matriz de autovectores de A
Xt = X.T

x = np.empty((gdl, gdl))

print('- Vectores x:')

for i in range(gdl):
    x[i] = Xt[gdl - i - 1].flatten()
    print(f'\n\t* Vector x{i + 1} = {x[i]}')<jupyter_output>- Vectores x:

	* Vector x1 = [0.41092 0.91167]

	* Vector x2 = [0.90704 -0.42105]<jupyter_text>6.3 Normalización Respecto a la Matriz de Masas<jupyter_code>phi = np.copy(x)

for i in range(gdl):
    # Normalización en una línea, por <NAME>
    phi[i] = x[i] / np.sqrt(x[i] @ M @ x[i].reshape(-1, 1))

print('\n- Vectores Normalizados Φ:')

for i in range(gdl):
    print(f'\n\t* Vector Φ{i + 1} = {phi[i]}')
phi[0]<jupyter_output><empty_output><jupyter_text>7. Interpretación de Resultados<jupyter_code>plt.rcParams['figure.figsize'] = 4.5 * len(phi), 8
plt.rcParams['font.family'] = 'Georgia'
plt.rcParams['font.style'] = 'italic'
plt.style.use('grayscale')
# Creación de subplots
fig, axs = plt.subplots(1, gdl)

# Título global
fig.suptitle('Modos de Vibración', fontsize = '26')

for i, x in enumerate(phi):
    y = []

    for j in range(len(phi[i])):
        y.append(6 * (j + 1) / len(phi[i]))

    axs[i].set_title(f'i = {i + 1}', fontsize = '14')
    
    axs[i].yaxis.set_visible(False)
    axs[i].xaxis.set_visible(False)

    axs[i].plot(0, 0, marker = '_', markersize = 30)

    # Posición inicial
    axs[i].plot(np.zeros(len(phi[i])), y, marker = 'o', markersize = 23, linestyle = '', color = '#d8dcd6', zorder = 0)
    axs[i].plot(np.zeros(len(phi[i]) + 1), np.append(0, y), linestyle = '--', color = '#d8dcd6')

    
    # Posición final
    axs[i].plot(x, y, marker = 'o', markersize = 23, linestyle = '', color = '#c14a09', zorder = 1)
    axs[i].plot(np.append(0, x), np.append(0, y), linestyle = '-', color = '#c14a09', alpha = 0.75)

    # Vectores desplazamiento
    axs[i].quiver(np.zeros(len(phi[i])), y, x, np.zeros(len(phi[i])), scale = 1, zorder = 2, color = '#d8dcd6', units = 'x', alpha = 0.75)

    # Frecuencias circulares
    axs[i].text(0, -0.5, f'w{i + 1} = {w[i]:.2f} rad/s', fontsize = 11, ha = 'center', color = '#363737')

    axs[i].set_xlim([-1.5 * abs(phi).max(), 1.5 * abs(phi).max()])
    axs[i].set_ylim([-1, 7])

plt.show()<jupyter_output><empty_output><jupyter_text>8. Dependencias<jupyter_code>%load_ext watermark

# Compilador y librerías
%watermark -v
%watermark -iv

# Sistema operativo
%watermark -m

# Fecha de subida
%watermark -u -n -t -z<jupyter_output>Python implementation: CPython
Python version       : 3.9.5
IPython version      : 7.24.1

sys       : 3.9.5 (default, May 18 2021, 14:42:02) [MSC v.1916 64 bit (AMD64)]
numpy     : 1.20.2
matplotlib: 3.3.4

Compiler    : MSC v.1916 64 bit (AMD64)
OS          : Windows
Release     : 10
Machine     : AMD64
Processor   : Intel64 Family 6 Model 165 Stepping 3, GenuineIntel
CPU cores   : 12
Architecture: 64bit

Last updated: Mon Jun 21 2021 12:17:33SA Pacific Standard Time
{'fraction_non_alphanumeric': 0.195416164053076, 'fraction_numerical': 0.04956683846913039, 'mean_word_length': 3.269662921348315, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '440448', 'license': 'MIT', 'n_tokens_mistral': 4387, 'n_tokens_neox': 4002, 'n_words': 948, 'path': 'ing-sismorresistente/02-modos-de-vibracion/02-modos-de-vibracion.ipynb', 'repo_name': 'ffrancoa/my-notebooks', 'size': '9126'}