Solução numérica para ondas estacionárias em membranas
Introdução
Nem sempre é necessário ou possível obter a solução exata de um determinado sistema, para esses problemas usamos modelagem e simulações para obter soluções numéricas.
A ideia com essa modelagem é mostrar que apesar do problema exato ser complexo, a solução numérica é simples e têm diversas aplicações.
Equação de onda:
Como é feita a discretização para a equação de onda
Para a forma matricial usaremos para a modelagem:
Bibliotecas usadas
import numpy as np
import scipy.linalg as la
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
Cria o índice global
O índice global será o que dará a forma da base do sistema. A escolha para ser desse jeito é por pura conveniência, já que o método reshape do numpy “desfaz” essa forma de indexar.
def ij2n(i,j,Nx):
return(i + j*Nx)
Construção das matrizes K e M
Na construção das matrizes K e M irei considerar rho e sigma constantes, mas poderia passar uma função com poucas modificações
def buildKM(Nx, Ny, rho, sigma, delta, mask):
NxNy = Nx*Ny
K = np.zeros( (NxNy,NxNy) )
M = np.zeros( (NxNy,NxNy) )
for i in range(1, Nx-1):
for j in range(1, Ny-1):
Ic = ij2n(i, j, Nx)
K[Ic,Ic] = -4
Ie = ij2n(i+1, j, Nx)
K[Ic,Ie] = 1
Iw = ij2n(i-1, j, Nx)
K[Ic,Iw] = 1
In = ij2n(i, j+1, Nx)
K[Ic,In] = 1
Is = ij2n(i, j-1, Nx)
K[Ic,Is] = 1
K *= -sigma/(delta**2)
for i in range(Nx):
for j in range(Ny):
Ic=ij2n(i, j, Nx)
if not mask[i, j]:
K[Ic,:]=0.
K[:,Ic]=0.
K[Ic,Ic]=1e9
M[Ic,Ic] = rho
return(K, M)
Montagem da máscara da membrana
A máscara é uma matriz com zeros e uns para facilitar na construção da forma da membrana, onde os uns são posições onde a membrana tem liberdade para mudar de posição e os zeros posições que serão travadas
def mask(Nx, Ny):
Mk = np.ones( (Nx,Ny), np.int )
# Define um raio que tem 40% do menor lado da malha
r = np.floor(0.4*min(Nx, Ny))
for i in range(Nx):
x = i - Nx//2
for j in range(Ny):
y = j - Ny//2
# Pode colocar a função que desejar no if
if x**2 + y**2 > r**2:
# Define com 0 os pontos da membrana que estão travados
Mk[i,j] = 0
# Trava as bordas
Mk[ 0, :] = 0
Mk[-1, :] = 0
Mk[ :, 0] = 0
Mk[ :,-1] = 0
return Mk
Como resolver o sistema e obter os Autovalores e Autovetores
Funcionamento da função de eig do scipy
a = matriz (n x n)
b = matriz (n x n)
D = autovalores (n)
V = autovetores (n x n)
[D, V] = scipy.linalg.eig(a, b)
a*V = D*b*V
def solve(K, M):
omega2, phi = la.eig(K, M)
# Ordena os resultados
idx = np.argsort(omega2)
omega2 = omega2[idx]
phi = phi[:,idx]
omega = np.sqrt(omega2)
return(phi.real, omega.real)
Atribuindo valores
Nx = int(input("Nx: "))
Ny = int(input("Ny: "))
sigma = float(input("sigma: "))
rho = float(input("rho: "))
Lx = 1.
delta = Lx/(Nx-1)
K, M = buildKM(Nx, Ny, rho, sigma, delta, mask(Nx, Ny))
phi, omega = solve(K, M)
Visualização dos dados
while True:
k = int(input("Digite o indice do modo: "))
ciclos = float(input("Digite o número de ciclos: "))
Z = phi[:, k].reshape(Nx, Ny)
dt = (ciclos*2*np.pi)/omega[k]
zlim = np.max(np.abs(Z))*1.02
x = range(Nx)
y = range(Ny)
X, Y = np.meshgrid(x, y)
fig = plt.figure(dpi=200)
ax = plt.axes(projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_xlim(0, Nx-1)
ax.set_ylim(0, Ny-1)
ax.set_zlim(-zlim, zlim)
plt.tight_layout()
plt.ion()
for i in np.linspace(0, dt, 20):
ax.clear()
ax.set_zlim(-zlim, zlim)
ax.plot_surface(X, Y, Z*np.sin(omega[k]*i), cmap="binary")
plt.show()
plt.pause(0.001)