curso8.mw

Capítulo 8  Equações Diferenciais Parciais (EDPs) 

Introdução 

 

O principal comando para resolver EDPs é pdsolve , cuja sintaxe é 

 

    pdsolve(EDP) 

    pdsolve(EDP, f, HINT=..., INTEGRATE, build) 

 

onde 

 

     EDP é uma equação diferencial parcial 

     f é o nome da função indeterminada (opcional) 

    HINT=... é um parâmetro de sugestões dado pelo usuário (opcional) 

    INTEGRATE provoca a integração automática das ODE's encontradas pelo método de separação de variáveis da EDP (optional)  

    build tenta construir uma expressão explícita para a função indeterminada seja qual for a generalidade da solução encontrada (opcional) 

 

Os parâmetros opcionais podem ser usados em qualquer ordem. Se o comando pdsolve não tiver sucesso, a opção HINT permite ao usuário sugerir uma estratégia para a resolução da EDP.  

Solução Geral e Solução Quase-geral 

 

Pdsolve tenta em primeiro lugar achar uma solução geral da EDP. Por exemplo, considere a seguinte EDP. 

> restart

> EDP := `+`(`*`(exp(y), `*`(diff(F(x, y, z), x))), `*`(2, `*`(sin(`+`(`*`(2, `*`(x)))), `*`(diff(F(x, y, z), y))))) = 0; 1
`+`(`*`(exp(y), `*`(diff(F(x, y, z), x))), `*`(2, `*`(sin(`+`(`*`(2, `*`(x)))), `*`(diff(F(x, y, z), y))))) = 0 (1.2.1)
 

Pdsolve encontra a solução geral em termos da função arbitrária _F1. 

> sol := pdsolve(EDP)
F(x, y, z) = _F1(`+`(`*`(`/`(1, 4), `*`(exp(y))), `*`(`/`(1, 4), `*`(cos(`+`(`*`(2, `*`(x))))))), z) (1.2.2)
 

Por exemplo, a função arbitrária _F1 pode ser da seguinte forma: 

> _F1 := proc (a, b) options operator, arrow; `+`(`*`(`^`(a, 2)), `*`(`^`(b, 3))) end proc
proc (a, b) options operator, arrow; `+`(`*`(`^`(a, 2)), `*`(`^`(b, 3))) end proc (1.2.3)
 

Neste case a solução fica com a seguinte cara: 

> sol
F(x, y, z) = `+`(`*`(`^`(`+`(`*`(`/`(1, 4), `*`(exp(y))), `*`(`/`(1, 4), `*`(cos(`+`(`*`(2, `*`(x))))))), 2)), `*`(`^`(z, 3))) (1.2.4)
 

Vamos testar se esta solução está correta: 

> eval(subs(sol, EDP))
0 = 0 (1.2.5)
 

Podemos fazer o mesmo teste através do comando pdetest . 

> pdetest(sol, EDP)
0 (1.2.6)
 

A solução de uma EDP de ordem n dependendo de k variáveis é geral quando é dada em termos de n funções arbitrárias e `+`(k, `-`(1)) variáveis. No exemplo acima, a ordem da EDP é 1 (derivada de ordem mais alta) e o número de variáveis é 3 (x, y, z). Podemos ver que a solução é dada em termos de 1 função arbitrária (_F1) que depende de 2 variáveis. 

 

Se pdsolve não consegue achar a solução geral, a solução é dada usando a estrutura  

 

(solução em termos de _F1, _F2, ...) &where [{EDO's envolvendo _F1, _F2, ...}] 

 

Nesse caso, _F1, _F2, () .. () não são funções arbitrárias. Elas obedecem às EDO's descritas pelo segundo operando do operador &where. Por exemplo, a equação de difusão (ou de propagação de calor) em 1 dimensão é  

> EDP := `*`(`^`(a, 2), `*`(diff(f(x, t), x, x))) = diff(f(x, t), t); 1
`*`(`^`(a, 2), `*`(diff(diff(f(x, t), x), x))) = diff(f(x, t), t) (1.2.7)
 

A solução é dada da forma 

> sol1 := pdsolve(EDP)
PDESolStruc(f(x, t) = `*`(_F2(x), `*`(_F3(t))), [{diff(_F3(t), t) = `*`(`^`(a, 2), `*`(_c[1], `*`(_F3(t)))), diff(diff(_F2(x), x), x) = `*`(_c[1], `*`(_F2(x)))}]) (1.2.8)
 

onde _c1 é a constante de separação de variáveis. O argumento opcional build provoca a integração das EDO's dadas no segundo operando de &where. 

> sol2 := pdsolve(EDP, build)
f(x, t) = `+`(`*`(_C3, `*`(exp(`*`(`^`(a, 2), `*`(_c[1], `*`(t)))), `*`(_C1, `*`(exp(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))))))), `/`(`*`(_C3, `*`(exp(`*`(`^`(a, 2), `*`(_c[1], `*`(t)))), `*`(_C2))), `*`(... (1.2.9)
 

onde as constantes _C1, _C2, _C3 foram introduzidas na integração de uma ODE de segunda ordem e uma ODE de primeira orderm. A opção INTEGRATE produz um resultado mantendo o operador &where. 

> sol3 := pdsolve(EDP, INTEGRATE)
PDESolStruc(f(x, t) = `*`(_F2(x), `*`(_F3(t))), [{{_F2(x) = `+`(`*`(_C1, `*`(exp(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))))), `*`(_C2, `*`(exp(`+`(`-`(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))))))))}, {_F3(t) = `*... (1.2.10)
 

O comando pdetest funciona com qualquer dessas formas de solução. 

> seq(pdetest(sol || i, EDP), i = 1 .. 3)
0, 0, 0 (1.2.11)
 

 

Solução Numérica 

Se os métodos analíticos de resolução de equações diferenciais falharem, podemos usar métodos numéricos, cuja página de ajuda principal é pdsolve/numeric . Vejamos um exemplo: 

> restart

> EDP := diff(u(x, t), t) = `+`(`-`(diff(u(x, t), x)))
diff(u(x, t), t) = `+`(`-`(diff(u(x, t), x))) (1.3.1)
 

> CI := {u(0, t) = `+`(`-`(sin(`+`(`*`(2, `*`(Pi, `*`(t))))))), u(x, 0) = sin(`+`(`*`(2, `*`(Pi, `*`(x)))))}
{u(0, t) = `+`(`-`(sin(`+`(`*`(2, `*`(Pi, `*`(t))))))), u(x, 0) = sin(`+`(`*`(2, `*`(Pi, `*`(x)))))} (1.3.2)
 

> sol := pdsolve(EDP, CI, numeric, time = t, range = 0 .. 1)
_m140224078572544 (1.3.3)
 

A solução é um módulo ( module ). Para usar uma função f dentro do módulo de nome sol, devemos usar a notação sol:-f onde substitui o ponto na notação usual das linguagens orientadas a objetos. Por exemplo, para usar a função plot para fazer o gráfico no instante t = `/`(1, 10): 

> sol:-plot(t = `/`(1, 10), numpoints = 50)
Plot_2d
 

 

O Pacote PDEtools 

 

O pacote   PDEtools contém funções que complementam o comando   pdesolve na tarefa de encontrar soluções para EDP's. 

> with(PDEtools)
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
[CanonicalCoordinates, ChangeSymmetry, CharacteristicQ, CharacteristicQInvariants, ConservedCurrentTest, ConservedCurrents, ConsistencyTest, D_Dx, DeterminingPDE, Eta_k, Euler, FromJet, FunctionFieldS...
(1.4.1)
 

Comando build 

 

O comando build constrói uma solução explícita para as funções indeterminadas que obedecem as EDO's dentro do operador &where. O argumento do comando build deve ser uma solução fornecido pelo comando pdsolve. Por exemplo, considere a EDP de Laplace com um termo não homogêneo. 

> Laplace_EDP := `+`(diff(f(x, y), x, x), diff(f(x, y), y, y)) = f(x, y); 1
`+`(diff(diff(f(x, y), x), x), diff(diff(f(x, y), y), y)) = f(x, y) (1.4.1.1)
 

A solução é dada em termos de duas funções indeterminadas. 

> sol := pdsolve(Laplace_EDP)
PDESolStruc(f(x, y) = `*`(_F1(x), `*`(_F2(y))), [{diff(diff(_F1(x), x), x) = `*`(_c[1], `*`(_F1(x))), diff(diff(_F2(y), y), y) = `+`(`-`(`*`(_c[1], `*`(_F2(y)))), _F2(y))}]) (1.4.1.2)
 

Para construir uma solução explícita: 

> build(sol)
f(x, y) = `+`(`*`(_C1, `*`(exp(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))), `*`(_C3, `*`(sin(`*`(`^`(`+`(_c[1], `-`(1)), `/`(1, 2)), `*`(y))))))), `*`(_C1, `*`(exp(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))), `*`(_C4...
f(x, y) = `+`(`*`(_C1, `*`(exp(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))), `*`(_C3, `*`(sin(`*`(`^`(`+`(_c[1], `-`(1)), `/`(1, 2)), `*`(y))))))), `*`(_C1, `*`(exp(`*`(`^`(_c[1], `/`(1, 2)), `*`(x))), `*`(_C4...
(1.4.1.3)
 

 

Comando dchange 

 

O comando dchange serve para fazer mudança de variáveis em EDP (e em outras expressões algébricas). A título de exemplo vamos resolver a EDP 

> EDP := `+`(`*`(3, `*`(diff(f(x, y), x))), `*`(4, `*`(diff(f(x, y), y))), `-`(`*`(2, `*`(f(x, y))))) = 1; 1
`+`(`*`(3, `*`(diff(f(x, y), x))), `*`(4, `*`(diff(f(x, y), y))), `-`(`*`(2, `*`(f(x, y))))) = 1 (1.4.2.1)
 

sem usar o comando pdsolve. Vamos considerar a seguinte tranformação de variáveis 

> tr := {x = `+`(`*`(v, `*`(cos(alpha))), `-`(`*`(w, `*`(sin(alpha))))), y = `+`(`*`(v, `*`(sin(alpha))), `*`(w, `*`(cos(alpha))))}
{x = `+`(`*`(v, `*`(cos(alpha))), `-`(`*`(w, `*`(sin(alpha))))), y = `+`(`*`(v, `*`(sin(alpha))), `*`(w, `*`(cos(alpha))))} (1.4.2.2)
 

e a partir dela determinar o valor de alpha que transforma a EDP numa ODE. Uma vez que essa tranformação possui parâmetro alpha, vamos adicionar o terceiro argumento [v, w] no comando   dchange . 

> new_EDP := dchange(tr, EDP, [v, w])
`+`(`*`(3, `*`(diff(f(v, w, alpha), v), `*`(cos(alpha)))), `-`(`*`(3, `*`(diff(f(v, w, alpha), w), `*`(sin(alpha))))), `*`(4, `*`(diff(f(v, w, alpha), v), `*`(sin(alpha)))), `*`(4, `*`(diff(f(v, w, al...
`+`(`*`(3, `*`(diff(f(v, w, alpha), v), `*`(cos(alpha)))), `-`(`*`(3, `*`(diff(f(v, w, alpha), w), `*`(sin(alpha))))), `*`(4, `*`(diff(f(v, w, alpha), v), `*`(sin(alpha)))), `*`(4, `*`(diff(f(v, w, al...
(1.4.2.3)
 

Vamos fazer a seguinte substituição para eliminar o parâmetro alpha que infelizmente foi introduzido na função f. 

> new_EDP := subs(f(v, w, alpha) = f(v, w), new_EDP)
`+`(`*`(3, `*`(diff(f(v, w), v), `*`(cos(alpha)))), `-`(`*`(3, `*`(diff(f(v, w), w), `*`(sin(alpha))))), `*`(4, `*`(diff(f(v, w), v), `*`(sin(alpha)))), `*`(4, `*`(diff(f(v, w), w), `*`(cos(alpha)))),...
`+`(`*`(3, `*`(diff(f(v, w), v), `*`(cos(alpha)))), `-`(`*`(3, `*`(diff(f(v, w), w), `*`(sin(alpha))))), `*`(4, `*`(diff(f(v, w), v), `*`(sin(alpha)))), `*`(4, `*`(diff(f(v, w), w), `*`(cos(alpha)))),...
(1.4.2.4)
 

Vamos determinar alpha de forma que o coeficiente do termo diff(f(v, w), w) seja zero. 

> coeff_w := coeff(lhs(new_EDP), diff(f(v, w), w))

> alpha := solve(coeff_w = 0, alpha)
 

(1.4.2.5)
 

Vejamos o formato da EDP agora. 

> new_EDP
`+`(`*`(5, `*`(diff(f(v, w), v))), `-`(`*`(2, `*`(f(v, w))))) = 1 (1.4.2.6)
 

Ela pode ser resolvida como o comando dsolve . (em vez de pdsolve). 

> sol := dsolve(new_EDP, f(v, w))
f(v, w) = `+`(`-`(`/`(1, 2)), `*`(exp(`+`(`*`(`/`(2, 5), `*`(v)))), `*`(_F1(w)))) (1.4.2.7)
 

O último passo é recuperar as variáveis originais. 

> f(x, y) = subs(solve(tr, {v, w}), rhs(sol))
f(x, y) = `+`(`-`(`/`(1, 2)), `*`(exp(`+`(`*`(`/`(6, 25), `*`(x)), `*`(`/`(8, 25), `*`(y)))), `*`(_F1(`+`(`*`(`/`(3, 5), `*`(y)), `-`(`*`(`/`(4, 5), `*`(x)))))))) (1.4.2.8)
 

Podemos confirmar a solução. 

> pdetest(%, EDP)
0 (1.4.2.9)
 

 

Comando PDEplot 

 

O comando PDEplot faz o gráfico da solução de uma EDP de primeira ordem uma vez dadas as condições iniciais. A EDP não pode ter parâmetro livres. Como exemplo, considere a seguinte EDP. 

> Maple_logo_EDP := `+`(`*`(`+`(`*`(`^`(y, 2)), `*`(`^`(z(x, y), 2)), `*`(`^`(x, 2))), `*`(diff(z(x, y), x))), `-`(`*`(2, `*`(x, `*`(y, `*`(diff(z(x, y), y)))))), `-`(`*`(2, `*`(z(x, y), `*`(x))))) = 0
`+`(`*`(`+`(`*`(`^`(y, 2)), `*`(`^`(z(x, y), 2)), `*`(`^`(x, 2))), `*`(diff(z(x, y), x))), `-`(`*`(2, `*`(x, `*`(y, `*`(diff(z(x, y), y)))))), `-`(`*`(2, `*`(z(x, y), `*`(x))))) = 0 (1.4.3.1)
 

cuja solução fornece o gráfico usado como logo da versão 4 do Maple. 

> PDEplot(Maple_logo_EDP, z(x, y), [t, t, `+`(`*`(`/`(1, 10), `*`(sin(`*`(Pi, `*`(t, `*`(`/`(.1))))))))], t = 0 .. .1, numchar = 40, orientation = [-163, 56], basechar = true, numsteps = [20, 20], steps...
PDEplot(Maple_logo_EDP, z(x, y), [t, t, `+`(`*`(`/`(1, 10), `*`(sin(`*`(Pi, `*`(t, `*`(`/`(.1))))))))], t = 0 .. .1, numchar = 40, orientation = [-163, 56], basechar = true, numsteps = [20, 20], steps...
PDEplot(Maple_logo_EDP, z(x, y), [t, t, `+`(`*`(`/`(1, 10), `*`(sin(`*`(Pi, `*`(t, `*`(`/`(.1))))))))], t = 0 .. .1, numchar = 40, orientation = [-163, 56], basechar = true, numsteps = [20, 20], steps...
Plot_2d
 

 

Exemplo 1 - Transmissão de calor 

Ref. 1: Wikipedia - Equação de calor 

Ref. 2: A. O. de Morais, Transferência de calor no escoamento laminar não Newtoniano com difusividade térmica efetiva em tubos. Monografia, Universidade de São Paulo, 2012. 

 

A equação geral da transmissão de calor é 

 

onde  

T temperatura do fluido 

vec(v) vetor velocidade do fluido 

rho densidade do fluido 

c[p] calor específico do fluido 

k condutividade térmica do fluido 

diff(q[V], t)  geração volumétrica de calor 

 

Problema Considere uma barra de comprimento 85 cm e largura 15 cm inicialmente a 37 graus centígrados isolada do meio ambiente exceto pelas suas extremidades, que são mantidas a 0 graus centígrados. Suponha que `*`(rho, `*`(c[p])) = 1 e k = 1 para esta barra. Encontre a temperatura da barra. 

Solução: A equação que rege a evolução da temperatura em função da variável expacial x e do tempo t é 

`+`(`*`(rho, `*`(c[p], `*`(diff(T, t)))), `-`(`*`(k, `*`(diff(T, x, x))))) = 0 

pois v = 0 e diff(q[V], t) = 0. Vamos supor que a barra vai de x = 0 até x = 85. 

>

> restart; 1

> with(plots); -1

> cp, k, T0 := `/`(1, `*`(rho)), 1, 37; -1

> pde := `+`(`*`(rho, `*`(cp, `*`(diff(T(x, t), t)))), `-`(`*`(k, `*`(diff(T(x, t), x, x)))))
(1.5.1)
 

As condições de contorno e as condições iniciais são 

> CC := T(0, t) = 0, T(85, t) = 0

> CI := T(x, 0) = T0
 

(1.5.2)
 

A solução fornecida pelo pdsolve é  

> res := pdsolve({CC, CI, pde})
T(x, t) = Sum(`+`(`-`(`/`(`*`(74, `*`(`+`(`^`(-1, _Z1), `-`(1)), `*`(sin(`+`(`*`(`/`(1, 85), `*`(_Z1, `*`(Pi, `*`(x)))))), `*`(exp(`+`(`-`(`*`(`/`(1, 7225), `*`(`^`(Pi, 2), `*`(`^`(_Z1, 2), `*`(t)))))... (1.5.3)
 

Note que a solução é uma série de Fourier. Vamos fazer a seguinte aproximação. Vamos tomar um número finito (truncamento) de termos e substituir o índice mudo do somatório para a variável j (por uma questão de elegância): 

> sol := subs(infinity = 1000, _Z1 = j, rhs(res))
Sum(`+`(`-`(`/`(`*`(74, `*`(`+`(`^`(-1, j), `-`(1)), `*`(sin(`+`(`*`(`/`(1, 85), `*`(j, `*`(Pi, `*`(x)))))), `*`(exp(`+`(`-`(`*`(`/`(1, 7225), `*`(`^`(Pi, 2), `*`(`^`(j, 2), `*`(t))))))))))), `*`(Pi, ... (1.5.4)
 

Podemos ver que para t = 0, teremos uma aproximação da condição inicial: 

> plot(subs(t = 0, sol), x = 0 .. 85)
Plot_2d
 

Se aumentarmos o truncamento da série de Fourier, obteremos um aproximação melhor. As oscilações da função representando a condição inicial nas extremidades da barra são chamadas de fenômeno de Gibbs e refletem a dificuldade de aproximar funções discontínuas por séries de Fourier, que são somas de funções oscilatórias contínuas. 

 

Podemos agora animar a solução 

> plots:-animate(plot, [sol, x = 0 .. 85, T = 0 .. `+`(T0, 1)], t = .2 .. 3000)
Plot_2d
 

O gráfico de densidade é bem mais elegante (Temperatura T0 é vermelha e temperatura 0 graus centígrados é preta): 

> plots:-densityplot(eval(subs(t = 10, sol)), x = 0 .. 85, y = -15 .. 15, scaletorange = 0 .. T0, scaling = constrained, style = patchnogrid, axes = none, title =
plots:-densityplot(eval(subs(t = 10, sol)), x = 0 .. 85, y = -15 .. 15, scaletorange = 0 .. T0, scaling = constrained, style = patchnogrid, axes = none, title =
Plot_2d
 

Para fazer a animação usando o gráfico de densidade, é importante usar a opção scaletorange :  

> plots:-animate(plots:-densityplot, [sol, x = 0 .. 85, y = -15 .. 15, scaletorange = 0 .. T0, scaling = constrained, style = patchnogrid, axes = none, title =
plots:-animate(plots:-densityplot, [sol, x = 0 .. 85, y = -15 .. 15, scaletorange = 0 .. T0, scaling = constrained, style = patchnogrid, axes = none, title =
Plot_2d
 

 

Exemplo 2 - Propagação de ondas em cordas 

Ref.: Wikipedia - Equação da onda   

 

Vamos considerar uma corda horizontal infinita uniformemente distentida por uma tração T. Vamos supor que as oscilações da corda são sempre na direção vertical. Sob certas restrições, como por exemplo pequenas amplitudes, a equação de onda que descreve o deslocamento vertical u (dependente das variável espacial x e do tempo t) na ausência de forças externas é  dada  por:   

 

onde `*`(`^`(c, 2)) = `/`(`*`(T), `*`(mu)) e mu é a densidade de massa.  

 

Resolução da equação de onda 

Vamos atribuir a equação diferencial deste problema à variável eq_de_onda: 

>

> restart

> with(plots); -1

> eq_de_onda := `*`(`^`(c, 2), `*`(diff(u(x, t), x, x))) = diff(u(x, t), t, t)
`*`(`^`(c, 2), `*`(diff(diff(u(x, t), x), x))) = diff(diff(u(x, t), t), t) (1.6.1.1)
 

A solução geral pode ser encontrada pelo comando pdsolve : 

> sol := pdsolve(eq_de_onda)
u(x, t) = `+`(_F1(`+`(`*`(c, `*`(t)), x)), _F2(`+`(`*`(c, `*`(t)), `-`(x)))) (1.6.1.2)
 

onde _F1 e _F2 são funções genéricas. Um pulso senoidal se movendo para a direita e gerado da seguinte maneira:  

> c := 1
1 (1.6.1.3)
 

> sol2 := eval(subs(_F1 = 0, _F2 = (proc (z) options operator, arrow; piecewise(`and`(`<=`(0, `+`(`-`(z))), `<=`(`+`(`-`(z)), Pi)), `+`(`-`(sin(z))), 0) end proc), sol))
u(x, t) = piecewise(`and`(`<=`(0, `+`(`-`(t), x)), `<=`(`+`(`-`(t), x), Pi)), `+`(`-`(sin(`+`(t, `-`(x))))), 0) (1.6.1.4)
 

> plots:-animate(rhs(sol2), x = 0 .. `+`(10, Pi), t = 0 .. 10, scaling = constrained)
Plot_2d
 

Note que a animação dura 10 unidades de tempo (por exemplo: segundos) e o pulso foi do ponto x = 0 até x = 10 em unidades de distância (por exemplo: centímetros). Portanto, a velocidade de onda é 1 m/s. Como exercício, mude o valor de c e verifique que a velocidade do pulso muda (o intervalo para x também deve ser mudado). 

 

A superposição de dois pulsos senoidais se movendo em direção oposta e gerado da seguinte maneira: 

> sol3 := eval(subs(_F1 = (proc (z) options operator, arrow; piecewise(`and`(`<=`(`+`(`*`(3, `*`(Pi))), z), `<=`(z, `+`(`*`(4, `*`(Pi))))), sin(z), 0) end proc), _F2 = (proc (z) options operator, arrow;...
sol3 := eval(subs(_F1 = (proc (z) options operator, arrow; piecewise(`and`(`<=`(`+`(`*`(3, `*`(Pi))), z), `<=`(z, `+`(`*`(4, `*`(Pi))))), sin(z), 0) end proc), _F2 = (proc (z) options operator, arrow;...
u(x, t) = `+`(piecewise(`and`(`<=`(`+`(`*`(3, `*`(Pi))), `+`(t, x)), `<=`(`+`(t, x), `+`(`*`(4, `*`(Pi))))), sin(`+`(t, x)), 0), piecewise(`and`(`<=`(0, `+`(`-`(t), x)), `<=`(`+`(`-`(t), x), Pi)), `+`...
u(x, t) = `+`(piecewise(`and`(`<=`(`+`(`*`(3, `*`(Pi))), `+`(t, x)), `<=`(`+`(t, x), `+`(`*`(4, `*`(Pi))))), sin(`+`(t, x)), 0), piecewise(`and`(`<=`(0, `+`(`-`(t), x)), `<=`(`+`(`-`(t), x), Pi)), `+`...
(1.6.1.5)
 

> plots:-animate(rhs(sol3), x = 0 .. `+`(10, Pi), t = 0 .. 10, scaling = constrained)
Plot_2d
 

Se a corda estiver presa nas extremidades (em x = 0 e x = a), a equação diferencial parcial pode ser resolvida pelo método de separação de variáveis e a solução geral pode ser expressa por uma série de Fourier. A corda de comprimento a presa nas extremidades é caracterizada pelas seguintes condições de contorno: u(0, t) = 0 e para t gerérico.Vamos resolver a equação de onda usando o método de separação de variáveis. Vamos supor que u é uma função separável nas variáveis x, t, isto é, u = `*`(X(x), `*`(T(t))):  

>

> c := 'c'; -1

> eq1 := expand(value(`/`(`*`(subs(u(x, t) = `*`(X(x), `*`(T(t))), eq_de_onda)), `*`(X(x), `*`(T(t))))))
(1.6.1.6)
 

Cada termo da expressão acima deve ser constante, pois cada um é função de uma variável independente. Vamos selecionar o termo dependente de x, e igualar a uma constante : 

> eqx := lhs(eq1) = lambda1
`/`(`*`(`^`(c, 2), `*`(diff(diff(X(x), x), x))), `*`(X(x))) = lambda1 (1.6.1.7)
 

A equação diferencial acima pode ter soluções oscilatórias, lineares ou exponenciais dependendo se a constante for negativa, zero ou positiva, respectivamente (exercício: resolva a EDO acima para . Para que as condições de contorno sejam satisfeitas, isto é, `and`(X(0) = X(a), X(a) = 0), temos que impor que a constante lambda1 seja negativa:  

> lambda1 := `+`(`-`(`*`(`^`(constante, 2)))); 1
`+`(`-`(`*`(`^`(constante, 2)))) (1.6.1.8)
 

> X := 'X'; -1

> sol_X := dsolve({eqx, X(0) = 0})
(1.6.1.9)
 

Para a condição de contorno X(0) = 0 ser satisfeita, vamos impor a condição de contorno X(a) = 0.   

> constante := solve(subs(x = a, rhs(sol_X)) = 0, constante, allsolutions)
`/`(`*`(Pi, `*`(_Z1, `*`(c))), `*`(a)) (1.6.1.10)
 

> getassumptions(%)
{Pi::Pi, _Z1::integer} (1.6.1.11)
 

Note que _Z1 tem que ser um número inteiro. 

> constante := subs(_Z1 = n, constante)
`/`(`*`(Pi, `*`(n, `*`(c))), `*`(a)) (1.6.1.12)
 

onde n é um inteiro positivo (no lugar de _Z1).  

 

Vamos eliminar a constante arbitrária por enquanto: 

> X := unapply(subs(_C1 = 1, rhs(sol_X)), x)
proc (x) options operator, arrow; sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))) end proc (1.6.1.13)
 

A equação diferencial para a função dependente da variável t é obtida da seguinte forma: 

> eqt := subs(eqx, eq1)
`+`(`-`(`/`(`*`(`^`(c, 2), `*`(`^`(Pi, 2), `*`(`^`(n, 2)))), `*`(`^`(a, 2))))) = `/`(`*`(diff(diff(T(t), t), t)), `*`(T(t))) (1.6.1.14)
 

cuja solução geral é: 

> T := 'T'; -1

> sol_T := dsolve(eqt)
(1.6.1.15)
 

Vamos colocar esta solução numa forma mais conveniente: 

> T := unapply(subs({_C1 = B(n), _C2 = A(n)}, rhs(sol_T)), t)
proc (t) options operator, arrow; `+`(`*`(B(n), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(c, `*`(t)))), `*`(a))))), `*`(A(n), `*`(cos(`/`(`*`(Pi, `*`(n, `*`(c, `*`(t)))), `*`(a)))))) end proc (1.6.1.16)
 

onde A e B são constantes que podem depender dos autovalores m e n. Vamos definir a frequência do modo normal <n>: 

> omega := proc (n) options operator, arrow; `/`(`*`(n, `*`(Pi, `*`(c))), `*`(a)) end proc
proc (n) options operator, arrow; `/`(`*`(n, `*`(Pi, `*`(c))), `*`(a)) end proc (1.6.1.17)
 

e definir os modos normais como uma função de m e n. Existem duas possibilidades que são: 

> normalmode := unapply(eval(subs(A = 1, B = 0, `*`(X(x), `*`(T(t))))), n)
proc (n) options operator, arrow; `*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))), `*`(cos(`/`(`*`(Pi, `*`(n, `*`(c, `*`(t)))), `*`(a))))) end proc (1.6.1.18)
 

> normalmode1 := unapply(eval(subs(A = 0, B = 1, `*`(X(x), `*`(T(t))))), n)
proc (n) options operator, arrow; `*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(c, `*`(t)))), `*`(a))))) end proc (1.6.1.19)
 

Uma vez que a equação diferencial do movimento da corda é linear e homogênea, a solução geral é uma superposição de todas as soluções linearmente independentes possíveis. Assim, tomaremos o somatório sobre todos os valores de m e n: 

> u := unapply(Sum(`*`(X(x), `*`(T(t))), n = 1 .. infinity), x, t); 1
proc (x, t) options operator, arrow; Sum(`*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))), `*`(`+`(`*`(B(n), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(c, `*`(t)))), `*`(a))))), `*`(A(n), `*`(cos(`/`(`*`(Pi, `*`(n, ... (1.6.1.20)
 

As constantes arbitrárias A(m, n) e B(m, n) são determinadas a partir das condições iniciais. Geralmente são elas a posição inicial u0(x) = u(x) e a velocidade inicial v0(x) = (D[2](u))(x, 0).  

  

Animação dos Modos Normais 

Os modos normais podem ser animados como a função animate. Vamos construir a função animate_mode, que anima o modo especificado pelos seus argumentos. Por exemplo, animate_mode(2) faz a animação do modo n=2.   

> with(plots); -1

Para fazer a animação de um determinado modo, temos que dar valores numéricos para os parâmetros a, b e c. Vamos supor que o comprimento é a=1, a largura é b=1 e a constante c=1 em um certo sistema de unidades: 

> animatemode := proc (n) options operator, arrow; plots:-animate(normalmode(n), x = 0 .. a, t = 0 .. `*`(.99, `*`(`+`(`/`(`*`(2, `*`(Pi)), `*`(omega(n)))))), frames = 16) end proc; -1

> a, c := 1, 1
1, 1 (1.6.2.1)
 

Vamos fazer a animação do modo n = 2:  

> animatemode(2)
Plot_2d
 

Vejamos a animação do modo n = 5: 

> animatemode(5)
Plot_2d
 

Os pontos que ficam imóveis são chamados pontos nodais. 

 

Animação com Condições Iniciais 

Encontramos anteriormente a função u(x, t) que descreve o movimento vertical da corda de comprimento a presa nas extremidades. Esta solução é uma série de Fourier. Uma vez que os modos normais com pequenos valores de n dominam sobre os que tem grandes valores, podemos truncar o somatório. O ponto de truncagem satisfatório depende das condições iniciais do problema. Vamos converter o somatório infinito num somatório finito com p termos e definir a função u_p(x, t, p) da seguinte forma: 

> A, B, n, a, c := 'A, B, n, a, c'
A, B, n, a, c (1.6.3.1)
 

> u_p := unapply(subs(infinity = 'p', u(x, t)), x, t, p)
proc (x, t, p) options operator, arrow; Sum(`*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))), `*`(`+`(`*`(B(n), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(c, `*`(t)))), `*`(a))))), `*`(A(n), `*`(cos(`/`(`*`(Pi, `*`(... (1.6.3.2)
 

As constantes A(m, n) e B(m, n), que aparecem na função u_p(x, y, t, p), podem ser obtidas a partir das condições iniciais posição inicial u0(x) = u(x, 0) e velocidade inicial v0(x) = (D[2](u))(x, 0) usando as seguintes fórmulas: A(m, n) = `+`(`/`(`*`(2, `*`(int(`*`(u0(x), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))))), x = 0 .. a))), `*`(a)))  e B(m, n) = `+`(`/`(`*`(2, `*`(int(`*`(v0(x), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))))), x = 0 .. a))), `*`(a, `*`(omega(n)))))  (veja referências sobre inversão de séries de Fourier, por exemplo, E. Butkov, Física Matemática, cap. 4). 

 

> A := proc (n) options operator, arrow; `+`(`/`(`*`(2, `*`(int(`*`(u0(x), `*`(sin(`/`(`*`(n, `*`(Pi, `*`(x))), `*`(a))))), x = 0 .. a))), `*`(a))) end proc
proc (n) options operator, arrow; `+`(`/`(`*`(2, `*`(int(`*`(u0(x), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))))), x = 0 .. a))), `*`(a))) end proc (1.6.3.3)
 

> B := proc (n) options operator, arrow; `+`(`/`(`*`(2, `*`(int(`*`(v0(x), `*`(sin(`/`(`*`(n, `*`(Pi, `*`(x))), `*`(a))))), x = 0 .. a))), `*`(a, `*`(omega(n))))) end proc
proc (n) options operator, arrow; `+`(`/`(`*`(2, `*`(int(`*`(v0(x), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(x))), `*`(a))))), x = 0 .. a))), `*`(a, `*`(omega(n))))) end proc (1.6.3.4)
 

Antes  de  fazer  a  animação com condições iniciais, vamos calcular as contantes A(m, n) e B(m, n) para m e n inteiros positivos genéricos. É mais eficiente calcular estas constantes para m e n genéricos e depois substituir valores numéricos, do que calcular diretamente para diversos valores numéricos de m e n. Vamos usar as seguintes condições iniciais: 

> u0 := proc (x) options operator, arrow; 1 end proc
proc (x) options operator, arrow; 1 end proc (1.6.3.5)
 

> v0 := proc (x) options operator, arrow; 0 end proc
proc (x) options operator, arrow; 0 end proc (1.6.3.6)
 

> a, c := 5, 1
5, 1 (1.6.3.7)
 

Para calcular A(n) e B(n) para n inteiro positivo genérico, vamos usar a função assume. Desta forma, o comando simplify das funções A(n) e B(n) poderá fazer as simplificações pertinentes: 

> assume(n::integer)

> A(n)
`+`(`/`(`*`(2, `*`(`+`(`-`(`^`(-1, n)), 1))), `*`(Pi, `*`(n)))) (1.6.3.8)
 

> B(n)
0 (1.6.3.9)
 

Vamos fazer o gráfico da posição inicial da corda desta vez descrita pela função u_p(x, y, t, p), pois a partir dela podemos achar um bom valor para a constante p, por comparação com o gráfico obtido diretamente de u0(x, y). Observe que para p = 10 a série de Fourier truncada aproxima razoavelmente bem a posição inicial da corda: 

> plot(value(u_p(x, 0, 30)), x = 0 .. a, scaling = constrained)
Plot_2d
 

Assim, o valor `>=`(p, 10) é satisfatório para esse tipo de condições iniciais. Note exite uma ondulação na parte superior do gráfico. Isto é consquência do truncamento da série de Fourier dupla. Esta ondulação só desparece a rigor, no limite quando proc (p) options operator, arrow; infinity end proc. Outro detalhe que podemos observar, é que a série truncada obedece às condicões de contorno, enquanto que a condição inicial não obedece (veja a expressão de u0(x)). Esta discrepância também só desaparece quando proc (p) options operator, arrow; infinity end proc. As oscilações da função representando a condição inicial nas extremidades da barra são chamadas de fenômeno de Gibbs e refletem a dificuldade de aproximar funções discontínuas por séries de Fourier, que são somas de funções oscilatórias contínuas. 

 

A função a seguir faz a animação do movimento da corda descrita pela função u_p(x, y, t, p). O primeiro argumento é o tempo de animação e o segundo é o número p que representa a truncagem do somatório duplo: 

> with(plots); -1

Para as condições iniciais descritas acima, a animação do movimento da corda com duas oscilações dominantes e p = 30 é: 

> animateinicond := proc (t_final, p, frames0) options operator, arrow; plots:-animate(value(u_p(x, t, p)), x = 0 .. a, t = 0 .. t_final, frames = frames0) end proc; -1
animateinicond := proc (t_final, p, frames0) options operator, arrow; plots:-animate(value(u_p(x, t, p)), x = 0 .. a, t = 0 .. t_final, frames = frames0) end proc; -1

> animateinicond(10, 300, 20)
animateinicond(10, 300, 20)
Plot_2d
 

 

Vamos fazer a animação no caso em que a corda está parada na posição horizontal, e sofre um impulso de cima para baixo em seu centro: 

> a, c := 2, 1
2, 1 (1.6.3.10)
 

> u0 := 0
0 (1.6.3.11)
 

> v0 := proc (x) options operator, arrow; `+`(`-`(Dirac(`+`(x, `-`(`*`(`/`(1, 2), `*`(a))))))) end proc
proc (x) options operator, arrow; `+`(`-`(Dirac(`+`(x, `-`(`*`(`/`(1, 2), `*`(a))))))) end proc (1.6.3.12)
 

Como antes, vamos calcular A(m, n) e B(m, n) com m e n inteiros positivos genéricos: 

> A(n)
0 (1.6.3.13)
 

> B(n)
`+`(`-`(`/`(`*`(2, `*`(sin(`+`(`*`(`/`(1, 2), `*`(Pi, `*`(n))))))), `*`(Pi, `*`(n))))) (1.6.3.14)
 

Vamos fazer a animação durante um tempo 5 e truncar o somatório em p = 30com 40 frames: 

> animateinicond(4, 30, 40)
Plot_2d
 

 

Exercícios 

 

1) Verifique que normalmode, normalmode1 e u(x, t) satisfazem a equação de onda. 

 

2)  a) Resolva a equação de onda para uma corda obedecendo às seguintes condições de contorno: Uma extremidade da corda está presa e a outra está livre. [Sug.: Quando a extremidade está livre, a derivada de u(x, t) deve se anular.] 

b) Obtenha os modos normais e a solução geral obedecendo às condições iniciais genéricas.  

c) Faça a animação dos modos normais. 

d) Faça a animação com diversas condições iniciais. 

 

 

Exemplo 3 - Oscilação de membranas usando séries de Fourier 

Ref.: R. Portugal, L. Golebiowski, D. Frenkel. Oscillation of membranes using computer algebra. American Journal of Physics 67 (6), 534-537, 1999. 

 

Vamos considerar uma membrana horizontal uniformemente distentida em todas as direções por uma tração T. A forma da membrana será especificada pelas condições de contorno. Qualquer que seja a forma, vamos analisar o caso em que toda a borda da membrana está fixa. As oscilações são sempre na direção vertical. Sob certas restrições, como por exemplo pequenas oscilações, a equação de onda que descreve o deslocamento vertical u (dependente das variáveis espaciais e do tempo) na ausência de forças externas é  dada  por:   

 

onde `*`(`^`(c, 2)) = `/`(`*`(T), `*`(mu)) e mu é a densidade de massa. Esta equação diferencial parcial pode ser resolvida pelo método de separação de variáveis e a solução geral pode ser expressa por uma série de Fourier generalizada. No caso da membrana retangular, a solução é uma série de Fourier tripla usual e no caso da membrana circular axialmente simétrica, a solução é uma série de Fourier-Bessel na parte espacial e Fourier usual na parte temporal. Vamos analisar o movimento oscilatório destes destes dois tipos de membranas. 

 

Membrana Retangular 

Resolução da equação de onda 

A membrana retangular de comprimento a e largura b presa nas bordas é caracterizada pelas seguintes condições de contorno: u(0, y, t) = 0 e u(a, y, t) = 0 para `<=`(y, b) e u(x, 0, t) = 0 e u(x, b, t) = 0 para `<=`(x, a). Vamos atribuir a equação diferencial deste problema à variável eq_de_onda: 

>

> restart

> eq_de_onda := `+`(diff(u(x, y, t), x, x), diff(u(x, y, t), y, y)) = `/`(`*`(diff(u(x, y, t), t, t)), `*`(`^`(c, 2)))
`+`(diff(diff(u(x, y, t), x), x), diff(diff(u(x, y, t), y), y)) = `/`(`*`(diff(diff(u(x, y, t), t), t)), `*`(`^`(c, 2))) (1.7.1.1.1)
 

> CI := u(0, y, t) = 0, u(a, y, t) = 0, u(x, 0, t) = 0, u(x, b, t) = 0
u(0, y, t) = 0, u(a, y, t) = 0, u(x, 0, t) = 0, u(x, b, t) = 0 (1.7.1.1.2)
 

Vamos resolver essa equação usando o método de separação de variáveis. Vamos supor que u é uma função separável nas variáveis x, y, t, isto é, u = `*`(X(x), `*`(Y(y), `*`(T(t)))):  

> eq1 := expand(value(`/`(`*`(subs(u(x, y, t) = `*`(X(x), `*`(Y(y), `*`(T(t)))), eq_de_onda)), `*`(X(x), `*`(Y(y), `*`(T(t)))))))
`+`(`/`(`*`(diff(diff(X(x), x), x)), `*`(X(x))), `/`(`*`(diff(diff(Y(y), y), y)), `*`(Y(y)))) = `/`(`*`(diff(diff(T(t), t), t)), `*`(T(t), `*`(`^`(c, 2)))) (1.7.1.1.3)
 

Cada termo da expressão acima deve ser constante, pois cada um é função de uma variável independente. Vamos selecionar o termo dependente de x, e igualar a uma constante : 

> eqx := select(has, lhs(eq1), x) = lambda1
`/`(`*`(diff(diff(X(x), x), x)), `*`(X(x))) = lambda1 (1.7.1.1.4)
 

A equação diferencial acima pode ter soluções oscilatórias, lineares ou exponenciais dependendo se a constante  for negativa, zero ou positiva, respectivamente. Para que as condições de contorno sejam satisfeitas, isto é, `and`(X(0) = X(a), X(a) = 0), temos que impor que a constante lambda1 seja negativa e que ela assuma valores discretos dados por:   

> lambda1 := `+`(`-`(`/`(`*`(`^`(m, 2), `*`(`^`(Pi, 2))), `*`(`^`(a, 2)))))
`+`(`-`(`/`(`*`(`^`(m, 2), `*`(`^`(Pi, 2))), `*`(`^`(a, 2))))) (1.7.1.1.5)
 

onde m é um inteiro positivo. A solução geral da equação da parte  é: 

> X := 'X'; -1

> sol_X := dsolve({eqx, X(0) = 0})
(1.7.1.1.6)
 

Vamos eliminar a constante arbitrária por enquanto: 

> X := unapply(subs(_C1 = 1, rhs(sol_X)), x)
proc (x) options operator, arrow; sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))) end proc (1.7.1.1.7)
 

Vamos repetir o mesmo procedimento para o termo dependente de y: 

> Y := 'Y'; -1

> eqy := expand(`*`(Y(y), select(has, lhs(eq1), y) = lambda2)); 1

> lambda2 := `+`(`-`(`/`(`*`(`^`(n, 2), `*`(`^`(Pi, 2))), `*`(`^`(b, 2))))); 1

> sol_Y := dsolve({eqy, Y(0) = 0}); -1
 

(1.7.1.1.8)
 

> Y := unapply(subs(_C1 = 1, rhs(sol_Y)), y)
proc (y) options operator, arrow; sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))) end proc (1.7.1.1.9)
 

A equação diferencial para a função dependente da variável t é obtida da seguinte forma: 

> eqt := subs(eqx, eqy, eq1)
`+`(`-`(`/`(`*`(`^`(m, 2), `*`(`^`(Pi, 2))), `*`(`^`(a, 2)))), `-`(`/`(`*`(`^`(n, 2), `*`(`^`(Pi, 2))), `*`(`^`(b, 2))))) = `/`(`*`(diff(diff(T(t), t), t)), `*`(T(t), `*`(`^`(c, 2)))) (1.7.1.1.10)
 

cuja solução geral é: 

> T := 'T'; -1

> sol_T := dsolve(eqt)
(1.7.1.1.11)
 

Vamos colocar esta solução numa forma mais conveniente: 

> T := unapply(subs({_C1 = B(m, n), _C2 = A(m, n)}, rhs(sol_T)), t)
proc (t) options operator, arrow; `+`(`*`(B(m, n), `*`(sin(`/`(`*`(Pi, `*`(c, `*`(`^`(`+`(`*`(`^`(a, 2), `*`(`^`(n, 2))), `*`(`^`(b, 2), `*`(`^`(m, 2)))), `/`(1, 2)), `*`(t)))), `*`(a, `*`(b)))))), `*... (1.7.1.1.12)
 

onde A e B são constantes que podem depender dos autovalores m e n. Vamos definir a frequência do modo normal <>: 

> omega := proc (m, n) options operator, arrow; `/`(`*`(sqrt(`+`(`*`(`^`(m, 2), `*`(`^`(b, 2))), `*`(`^`(n, 2), `*`(`^`(a, 2))))), `*`(Pi, `*`(c))), `*`(b, `*`(a))) end proc
proc (m, n) options operator, arrow; `/`(`*`(sqrt(`+`(`*`(`^`(m, 2), `*`(`^`(b, 2))), `*`(`^`(n, 2), `*`(`^`(a, 2))))), `*`(Pi, `*`(c))), `*`(a, `*`(b))) end proc (1.7.1.1.13)
 

e definir os modos normais como uma função de m e n. Existem duas possibilidades que são: 

> normalmode := unapply(eval(subs(A = 1, B = 0, `*`(X(x), `*`(Y(y), `*`(T(t)))))), m, n)
proc (m, n) options operator, arrow; `*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))), `*`(cos(`/`(`*`(Pi, `*`(c, `*`(`^`(`+`(`*`(`^`(m, 2), `*`(`^`(b, 2)))... (1.7.1.1.14)
 

> normalmode1 := unapply(eval(subs(A = 0, B = 1, `*`(X(x), `*`(Y(y), `*`(T(t)))))), m, n)
proc (m, n) options operator, arrow; `*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))), `*`(sin(`/`(`*`(Pi, `*`(c, `*`(`^`(`+`(`*`(`^`(m, 2), `*`(`^`(b, 2)))... (1.7.1.1.15)
 

Uma vez que a equação diferencial do movimento da membrana é linear e homogênea, a solução geral é uma superposição de todas as soluções linearmente independentes possíveis. Assim, tomaremos o somatório sobre todos os valores de m e n: 

> u := unapply(Sum(Sum(`*`(X(x), `*`(Y(y), `*`(T(t)))), m = 1 .. infinity), n = 1 .. infinity), x, y, t); 1
proc (x, y, t) options operator, arrow; Sum(Sum(`*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))), `*`(`+`(`*`(B(m, n), `*`(sin(`/`(`*`(Pi, `*`(c, `*`(`^`(`+...
proc (x, y, t) options operator, arrow; Sum(Sum(`*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))), `*`(`+`(`*`(B(m, n), `*`(sin(`/`(`*`(Pi, `*`(c, `*`(`^`(`+...
(1.7.1.1.16)
 

As constantes arbitrárias A(m, n) e B(m, n) são determinadas a partir das condições iniciais. Geralmente são elas a posição inicial u0(x, y) = u(x, y, 0) e a velocidade inicial v0(x, y) = (D[3](u))(x, y, 0).  

  

Animação dos Modos Normais 

Os modos normais podem ser animados como a função animate3d. Vamos construir a função animate_mode, que anima o modo especificado pelos seus argumentos. Por exemplo, animate_mode(1,2) faz a animação do modo m=1 e n=2.   

> with(plots); -1

Para fazer a animação de um determinado modo, temos que dar valores numéricos para os parâmetros a, b e c. Vamos supor que o comprimento é a=1, a largura é b=1 e a constante c=1 em um certo sistema de unidades: 

> animatemode := proc (m, n) options operator, arrow; plots:-animate3d(normalmode(m, n), x = 0 .. a, y = 0 .. b, t = 0 .. `*`(.99, `*`(`+`(`/`(`*`(2, `*`(Pi)), `*`(omega(m, n)))))), frames = 16) end pro...
animatemode := proc (m, n) options operator, arrow; plots:-animate3d(normalmode(m, n), x = 0 .. a, y = 0 .. b, t = 0 .. `*`(.99, `*`(`+`(`/`(`*`(2, `*`(Pi)), `*`(omega(m, n)))))), frames = 16) end pro...

> a := 1; 1b := 1; 1c := 1
 

 

1
1
1 (1.7.1.2.1)
 

Vamos fazer a animação do modo <1,2>  

> animatemode(1, 2)
Plot_2d
 

As linhas nodais são curvas cujos pontos se mantêm em repouso durante todo instante.  Por exemplo, vejamos a animação do modo <2,5>: 

> animatemode(5, 2)
Plot_2d
 

Podemos ver que há 4 retas nodais paralelas ao eixo y e 1 reta nodal paralela ao eixo x. Esta característica pode ser generalizada para qualquer modo de vibração. O modo <m,n> tem m-1 retas nodais paralelas ao eixo y e n-1 retas nodais paralelas ao eixo x. Em geral, as linhas nodais nem sempre são retas. Abaixo, mostraremos um exemplo de uma linha nodal fechada aproximadamente circular em uma membrana quadrada. Isso ocorre quando existe degenerescência. 

 

Análise da Degenerescência 

Num modo normal de vibração, todos os pontos da membrana vibram com a mesma frequência; cada modo normal tem um frequência característica omegam, n. Se a membrana for quadrada, dois modos normais diferentes podem oscilar com a mesma frequência. Por exemplo, para a membrana quadrada de largura de uma unidade, os modos <1,2> e <2,1> têm a mesma frequência: 

> a, b := 1, 1; -1

> omega(1, 2)

> omega(2, 1)
 

(1.7.1.3.1)
 

Neste caso, qualquer combinação linear destes modos de vibração também vai oscilar na mesma frequência. Este fenômeno é chamado de degenerescência. Isto ocorre sempre que um autovalor (a frequência) é degenerado, possuindo mais de um autovetor associado (o modo normal). A função a seguir faz a animação da combinação linear `+`(`*`(c1, `*`(normalmode(m, n))), `*`(c2, `*`(normalmode(n, m)))).  

Vamos considerar uma membrana quadrada: 

> animate_lc := proc (m, n, c1, c2) options operator, arrow; plots:-animate3d(`+`(`*`(c1, `*`(normalmode(m, n))), `*`(c2, `*`(normalmode(n, m)))), x = 0 .. a, y = 0 .. b, t = 0 .. `*`(.99, `*`(`+`(`/`(`...
animate_lc := proc (m, n, c1, c2) options operator, arrow; plots:-animate3d(`+`(`*`(c1, `*`(normalmode(m, n))), `*`(c2, `*`(normalmode(n, m)))), x = 0 .. a, y = 0 .. b, t = 0 .. `*`(.99, `*`(`+`(`/`(`...

> a, b, c := 1, 1, 1
1, 1, 1 (1.7.1.3.2)
 

Vamos fazer a animação da combinação linear `+`(normalmode(1, 3), normalmode(3, 1)), onde podemos verificar que a linha nodal é uma curva fechada: 

> animate_lc(1, 3, 1, 1)
Plot_2d
 

A combinação linear `+`(normalmode(1, 4), normalmode(4, 1)) tem como linha nodal uma curva fechada e uma reta (uma das diagonais da membrana): 

> animate_lc(1, 4, 1, 1)
Plot_2d
 

A linha nodal é descrita pela equação `+`(`*`(c1, `*`(mode(m, n))), `*`(c2, `*`(mode(m, n)))) = 0. Esta equação depende das variáveis x e y. O fator temporal é comum aos dois termos e portanto é cancelado. Através do comando implicitplot, podemos fazer o gráfico da curva y contra  x  mesmo  sem  resolver  explicitamente  a  equação.  A função nodal_line a seguir faz o desenho da linha nodal. Os argumentos desta função são iguais ao do função animate_lc.  

A linha nodal dos dois últimos exemplos que vimos acima são: 

> nodal_lines := proc (m, n, c1, c2) options operator, arrow; plots:-implicitplot(subs(t = 0, `+`(`*`(c1, `*`(normalmode(m, n))), `*`(c2, `*`(normalmode(n, m))))), x = 0 .. a, y = 0 .. b, 'scaling = con...
nodal_lines := proc (m, n, c1, c2) options operator, arrow; plots:-implicitplot(subs(t = 0, `+`(`*`(c1, `*`(normalmode(m, n))), `*`(c2, `*`(normalmode(n, m))))), x = 0 .. a, y = 0 .. b, 'scaling = con...

> nodal_lines(1, 3, 1, 1)
Plot_2d
 

e 

> nodal_lines(1, 4, 1, 1)
Plot_2d
 

 

Animação com Condições Iniciais 

Encontramos anteriormente a função u(x, y, t) que descreve o movimento vertical da membrana retangular de largura a e comprimento b presa nas bordas. Esta solução é uma série de Fourier dupla. Uma vez que os modos normais com pequenos valores de m e n dominam sobre os que tem grandes valores, podemos truncar o somatório duplo. O ponto de truncagem satisfatório depende das condições iniciais do problema. Vamos converter o somatório infinito num somatório finito com `*`(`^`(p, 2)) termos e definir a função u_p(x, y, t, p) da seguinte forma: 

>

>

>

>

>

>

>

>

>

> A, B, a, b, c, m, n, x, y, t, u0, v0 := 'A, B, a, b, c, m, n, x, y, t, u0, v0'
A, B, a, b, c, m, n, x, y, t, u0, v0 (1.7.1.4.1)
 

> u_p := unapply(subs(infinity = 'p', u(x, y, t)), x, y, t, p)
proc (x, y, t, p) options operator, arrow; Sum(Sum(`*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))), `*`(`+`(`*`(B(m, n), `*`(sin(`/`(`*`(Pi, `*`(c, `*`(`^`...
proc (x, y, t, p) options operator, arrow; Sum(Sum(`*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b))), `*`(`+`(`*`(B(m, n), `*`(sin(`/`(`*`(Pi, `*`(c, `*`(`^`...
(1.7.1.4.2)
 

As constantes A(m, n) e B(m, n), que aparecem na função u_p(x, y, t, p), podem ser obtidas a partir das condições iniciais posição inicial u0(x, y) = u(x, y, 0) e velocidade inicial v0(x, y) = (D[3](u))(x, y, 0) usando as seguintes fórmulas: A(m, n) = `+`(`/`(`*`(4, `*`(int(`*`(u0(x, y), `*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b)))))), [x = 0 .. a, y = 0 .. b]))), `*`(a, `*`(b))))  e B(m, n) = `+`(`/`(`*`(4, `*`(int(`*`(v0(x, y), `*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b)))))), [x = 0 .. a, y = 0 .. b]))), `*`(a, `*`(b, `*`(omega(m, ...  (veja referências sobre inversão de séries de Fourier). 

 

> A := proc (m, n) options operator, arrow; `+`(`/`(`*`(4, `*`(int(int(`*`(u0(x, y), `*`(sin(`/`(`*`(m, `*`(Pi, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(n, `*`(Pi, `*`(y))), `*`(b)))))), x = 0 .. a), y = 0 ....
proc (m, n) options operator, arrow; `+`(`/`(`*`(4, `*`(int(int(`*`(u0(x, y), `*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b)))))), x = 0 .. a), y = 0 .. b))... (1.7.1.4.3)
 

> B := proc (m, n) options operator, arrow; `+`(`/`(`*`(4, `*`(int(int(`*`(v0(x, y), `*`(sin(`/`(`*`(m, `*`(Pi, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(n, `*`(Pi, `*`(y))), `*`(b)))))), x = 0 .. a), y = 0 ....
proc (m, n) options operator, arrow; `+`(`/`(`*`(4, `*`(int(int(`*`(v0(x, y), `*`(sin(`/`(`*`(Pi, `*`(m, `*`(x))), `*`(a))), `*`(sin(`/`(`*`(Pi, `*`(n, `*`(y))), `*`(b)))))), x = 0 .. a), y = 0 .. b))... (1.7.1.4.4)
 

Antes  de  fazer  a  animação com condições iniciais, vamos calcular as contantes A(m, n) e B(m, n) para m e n inteiros positivos genéricos. É mais eficiente calcular estas constantes para m e n genéricos e depois substituir valores numéricos, do que calcular diretamente para diversos valores numéricos de m e n. Vamos usar as seguintes condições iniciais: 

> u0 := proc (x, y) options operator, arrow; 1 end proc
proc (x, y) options operator, arrow; 1 end proc (1.7.1.4.5)
 

> v0 := proc (x, y) options operator, arrow; 0 end proc
proc (x, y) options operator, arrow; 0 end proc (1.7.1.4.6)
 

> a, b, c := 5, 5, 1
5, 5, 1 (1.7.1.4.7)
 

O gráfico da posição inicial é: 

> plot3d(u0(x, y), x = 0 .. a, y = 0 .. b)
Plot_2d
 

Para calcular A(m, n) e B(m, n) para m e n inteiros positivos genéricos, vamos usar a função assume. Desta forma, o comando simplify das funções A(m, n) e B(m, n) poderá fazer as simplificações pertinentes: 

> assume(m::integer, n::integer)

> A(m, n)
`+`(`/`(`*`(4, `*`(`+`(`^`(-1, `+`(n, m)), `-`(`^`(-1, m)), `-`(`^`(-1, n)), 1))), `*`(`^`(Pi, 2), `*`(m, `*`(n))))) (1.7.1.4.8)
 

> B(m, n)
0 (1.7.1.4.9)
 

Vamos fazer o gráfico da posição inicial da membrana desta vez descrita pela função u_p(x, y, t, p), pois a partir dela podemos achar um bom valor para a constante p, por comparação com o gráfico obtido diretamente de u0(x, y). Observe que para p = 10 a série de Fourier truncada aproxima razoavelmente bem a posição inicial da membrana: 

> plot3d(value(u_p(x, y, 0, 10)), x = 0 .. a, y = 0 .. b, scaling = constrained)
Plot_2d
 

Assim, o valor `>=`(p, 10) é satisfatório para esse tipo de condições iniciais. Note exite uma ondulação na parte superior do gráfico. Isto é consquência do truncamento da série de Fourier dupla. Esta ondulação só desparece a rigor, no limite quando proc (p) options operator, arrow; infinity end proc. Outro detalhe que podemos observar, é que a série truncada obedece as condicões de contorno, enquanto que a condição inicial não obedece. Esta discrepância também só desaparece quando proc (p) options operator, arrow; infinity end proc. 

 

A função a seguir faz a animação do movimento da membrana descrita pela função u_p(x, y, t, p). O primeiro argumento é o tempo de animação e o segundo é o número p que representa a truncagem do somatório duplo: 

> with(plots); -1

Para as condições iniciais descritas acima, a animação do movimento da membrana com duas oscilações dominantes e p = 30 é: 

> animateinicond := proc (t_final, p, frames0) options operator, arrow; plots:-animate3d(value(u_p(x, y, t, p)), x = 0 .. a, y = 0 .. b, t = 0 .. t_final, frames = frames0) end proc; -1
animateinicond := proc (t_final, p, frames0) options operator, arrow; plots:-animate3d(value(u_p(x, y, t, p)), x = 0 .. a, y = 0 .. b, t = 0 .. t_final, frames = frames0) end proc; -1

> animateinicond(10, 30, 20)
animateinicond(10, 30, 20)
Plot_2d
 

 

Vamos fazer a animação no caso em que a membrana está parada na posição horizontal, e sofre um impulso de cima para baixo em seu centro: 

> a, b, c := 2, 2, 1
2, 2, 1 (1.7.1.4.10)
 

> u0 := 0
0 (1.7.1.4.11)
 

> v0 := proc (x, y) options operator, arrow; `+`(`-`(`*`(Dirac(`+`(x, `-`(`*`(`/`(1, 2), `*`(a))))), `*`(Dirac(`+`(y, `-`(`*`(`/`(1, 2), `*`(b))))))))) end proc
proc (x, y) options operator, arrow; `+`(`-`(`*`(Dirac(`+`(x, `-`(`*`(`/`(1, 2), `*`(a))))), `*`(Dirac(`+`(y, `-`(`*`(`/`(1, 2), `*`(b))))))))) end proc (1.7.1.4.12)
 

Como antes, vamos calcular A(m, n) e B(m, n) com m e n inteiros positivos genéricos: 

> A(m, n)
0 (1.7.1.4.13)
 

> B(m, n)
`+`(`-`(`/`(`*`(2, `*`(sin(`+`(`*`(`/`(1, 2), `*`(Pi, `*`(m))))), `*`(sin(`+`(`*`(`/`(1, 2), `*`(Pi, `*`(n)))))))), `*`(`^`(`+`(`*`(`^`(m, 2)), `*`(`^`(n, 2))), `/`(1, 2)), `*`(Pi))))) (1.7.1.4.14)
 

Vamos fazer a animação durante um tempo 5 e truncar o somatório em p = 30(900 termos) com 20 frames: 

> animateinicond(5, 30, 20)
Plot_2d
 

 

Exercícios 

 

1) Verifique que normalmode, normalmode1 e u(x, y, t) satisfazem a equação de onda. 

 

2) Use o comando pdsolve para encontrar a solução O comando dsolve não deve ser usado em nenhum momento.  

 

3)  a) Resolva a equação de onda para uma membrana obedecendo às seguintes condições de contorno: Duas extremidades opostas da membrana estão presas, e as outras duas estão livres. [Sug.: Quando a extremidade está livre, a derivada de u(x, y, t) deve se anular.] 

b) Obtenha os modos normais e a solução geral obedecendo às condições iniciais genéricas.  

c) Faça a animação dos modos normais. 

d) Faça uma análise da degenerescência. 

e) Faça a animação com diversas condições iniciais. 

Membrana Circular  

Resolução da Equação de Onda  

A membrana circular de raio a presa na borda é caracterizada pela seguinte condição de contorno em coordenadas cilíndricas: u(a, theta, t) = 0, para `and`(`<=`(0, theta), `<`(theta, `+`(`*`(2, `*`(Pi))))). Vamos atribuir a equação diferencial deste problema à variável wave_eq: 

>

> restart

> wave_eq := linalg[laplacian](u(r, theta, t), [r, theta, z], coords = cylindrical) = `/`(`*`(diff(u(r, theta, t), t, t)), `*`(`^`(c, 2)))
`/`(`*`(`+`(diff(u(r, theta, t), r), `*`(r, `*`(diff(diff(u(r, theta, t), r), r))), `/`(`*`(diff(diff(u(r, theta, t), theta), theta)), `*`(r)))), `*`(r)) = `/`(`*`(diff(diff(u(r, theta, t), t), t)), `... (1.7.2.1.1)
 

Vamos resolver essa equação usando o método de separação de variáveis. Substituindo u = `*`(R(r), `*`(Theta(theta), `*`(T(t)))) na variável wave_eq obtemos: 

> Eq1 := expand(value(`/`(`*`(subs(u(r, theta, t) = `*`(R(r), `*`(Theta(theta), `*`(T(t)))), wave_eq)), `*`(R(r), `*`(Theta(theta), `*`(T(t)))))))
`+`(`/`(`*`(diff(R(r), r)), `*`(R(r), `*`(r))), `/`(`*`(diff(diff(R(r), r), r)), `*`(R(r))), `/`(`*`(diff(diff(Theta(theta), theta), theta)), `*`(Theta(theta), `*`(`^`(r, 2))))) = `/`(`*`(diff(diff(T(... (1.7.2.1.2)
 

Vamos fazer agora a separação de variáveis:  

> Eqt := rhs(Eq1) = lambda
`/`(`*`(diff(diff(T(t), t), t)), `*`(T(t), `*`(`^`(c, 2)))) = lambda (1.7.2.1.3)
 

> Eqtheta := `*`(`^`(r, 2), `*`(select(has, lhs(Eq1), theta))) = lambda1
`/`(`*`(diff(diff(Theta(theta), theta), theta)), `*`(Theta(theta))) = lambda1 (1.7.2.1.4)
 

> Eqr := expand(simplify(Eq1, {Eqt, Eqtheta}))
`+`(`/`(`*`(diff(diff(R(r), r), r)), `*`(R(r))), `/`(`*`(lambda1), `*`(`^`(r, 2))), `/`(`*`(diff(R(r), r)), `*`(R(r), `*`(r)))) = lambda (1.7.2.1.5)
 

A condição de contorno u(a, theta, t) = 0 impõe que a constante lambda seja negativa pois quando ela é positiva ou nula, a equação Eqr não adimite soluções que se anulem para r = a. Além disso, a variável theta é periódica. Assim, vamos assumir que:  

> lambda := `+`(`-`(`*`(`^`(k(m, n), 2)))); 1; lambda1 := `+`(`-`(`*`(`^`(m, 2)))); 1

> lambda1 := `+`(`-`(`*`(`^`(m, 2))))
 

(1.7.2.1.6)
 

A solução geral para Eqr a menos de uma constante multiplicativa é: 

> R := proc (r) options operator, arrow; BesselJ(m, `*`(k(m, n), `*`(r))) end proc
proc (r) options operator, arrow; BesselJ(m, `*`(k(m, n), `*`(r))) end proc (1.7.2.1.7)
 

> simplify(Eqr)
`+`(`-`(`*`(`^`(k(m, n), 2)))) = `+`(`-`(`*`(`^`(k(m, n), 2)))) (1.7.2.1.8)
 

A solução geral para Theta(theta) é: 

> sol_theta := dsolve(Eqtheta)
Theta(theta) = `+`(`*`(_C1, `*`(sin(`*`(m, `*`(theta))))), `*`(_C2, `*`(cos(`*`(m, `*`(theta)))))) (1.7.2.1.9)
 

> Theta := unapply(subs({coeff(rhs(sol_theta), cos(`*`(m, `*`(theta)))) = C1, coeff(rhs(sol_theta), sin(`*`(m, `*`(theta)))) = C2}, rhs(sol_theta)), theta)
Theta := unapply(subs({coeff(rhs(sol_theta), cos(`*`(m, `*`(theta)))) = C1, coeff(rhs(sol_theta), sin(`*`(m, `*`(theta)))) = C2}, rhs(sol_theta)), theta)
proc (theta) options operator, arrow; `+`(`*`(C2, `*`(sin(`*`(m, `*`(theta))))), `*`(C1, `*`(cos(`*`(m, `*`(theta)))))) end proc (1.7.2.1.10)
 

A solução geral para T(t) é: 

> sol_T := dsolve(Eqt)
T(t) = `+`(`*`(_C1, `*`(sin(`*`(c, `*`(k(m, n), `*`(t)))))), `*`(_C2, `*`(cos(`*`(c, `*`(k(m, n), `*`(t))))))) (1.7.2.1.11)
 

> T := unapply(expand(subs(_C1 = I, _C2 = 1, convert(rhs(sol_T), exp))), t)
proc (t) options operator, arrow; exp(`*`(I, `*`(c, `*`(k(m, n), `*`(t))))) end proc (1.7.2.1.12)
 

Cálculo dos Modos Normais 

Vamos agora analisar os modos normais da membrana circular. Os modos com m = 0 não dependem da variável theta, isto é, eles são axialmente simétricos. Os modos com `<>`(m, 0) dependem da variável theta e em função disto veremos exemplos dos dois casos.  A frequência do modo normal é: 

> omega := proc (m, n) options operator, arrow; `*`(c, `*`(k(m, n))) end proc
proc (m, n) options operator, arrow; `*`(c, `*`(k(m, n))) end proc (1.7.2.2.1)
 

Para que as condições de contorno sejam satisfeitas, temos que impor que R(a) = 0 ou seja BesselJ(m, `*`(k(m, n), `*`(a))) = 0. Assim, `*`(k(m, n), `*`(a)) deve assumir valores que anulem a função de Bessel de ordem m: 

> k := proc (m, n) options operator, arrow; evalf(`/`(`*`(BesselJZeros(m, n)), `*`(a))) end proc
proc (m, n) options operator, arrow; evalf(`/`(`*`(BesselJZeros(m, n)), `*`(a))) end proc (1.7.2.2.2)
 

A função BesselJZeros calcula o n-ésimo zero da função de Bessel de ordem m. Vamos agora definir os modos normais em funçao de m e n. Se `<>`(m, 0) existe uma degenerescência de quarta ordem, isto é, podemos definir os seguintes modos normais: 

> normal_mode := unapply(`*`(R(r), `*`(evalc(Re(T(t))), `*`(subs(C1 = 1, C2 = 0, Theta(theta))))), m, n); 1; normal_mode1 := unapply(subs(C1 = 1, C2 = 0, `*`(R(r), `*`(evalc(Im(T(t))), `*`(Theta(theta))...

> normal_mode1 := unapply(subs(C1 = 1, C2 = 0, `*`(R(r), `*`(evalc(Im(T(t))), `*`(Theta(theta))))), m, n)

> normal_mode2 := unapply(subs(C1 = 0, C2 = 1, `*`(R(r), `*`(evalc(Re(T(t))), `*`(Theta(theta))))), m, n)

> normal_mode3 := unapply(subs(C1 = 0, C2 = 1, `*`(R(r), `*`(evalc(Im(T(t))), `*`(Theta(theta))))), m, n)
 

 

 

(1.7.2.2.3)
 

Os modos normais axialmente simétricos são os modos com m = 0. Neste caso, a degenerescência é dupla, já que os modos normal_mode2 e normal_mode3 acima são nulos. 

   

   A solução geral é a superposição de todos os modos normais. A variável m pode assumir qualquer valor inteiro de 0 a infinity e n de 1 a infinity. Porém, para as condicões iniciais que estamos tratando aqui, a série de Fourier converge rapidamente, de forma que podemos truncar o somatório. As variáveis p1 e p2 especificam o truncamento em m e n, respectivamente.  Vamos separar os termos com m = 0 pois estes coeficientes seguem uma regra diferente dos coeficientes com m diferente de zero: 

> u := unapply(`+`(`*`(2, `*`(Sum(`+`(factor(`+`(`*`(A1(0, n), `*`(normal_mode(0, n))), `*`(A2(0, n), `*`(normal_mode1(0, n))))), Sum(factor(`+`(`*`(A1(m, n), `*`(normal_mode(m, n))), `*`(A2(m, n), `*`(...
u := unapply(`+`(`*`(2, `*`(Sum(`+`(factor(`+`(`*`(A1(0, n), `*`(normal_mode(0, n))), `*`(A2(0, n), `*`(normal_mode1(0, n))))), Sum(factor(`+`(`*`(A1(m, n), `*`(normal_mode(m, n))), `*`(A2(m, n), `*`(...
u := unapply(`+`(`*`(2, `*`(Sum(`+`(factor(`+`(`*`(A1(0, n), `*`(normal_mode(0, n))), `*`(A2(0, n), `*`(normal_mode1(0, n))))), Sum(factor(`+`(`*`(A1(m, n), `*`(normal_mode(m, n))), `*`(A2(m, n), `*`(...
proc (r, theta, t, p1, p2) options operator, arrow; `+`(`*`(2, `*`(Sum(`+`(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n)...
proc (r, theta, t, p1, p2) options operator, arrow; `+`(`*`(2, `*`(Sum(`+`(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n)...
proc (r, theta, t, p1, p2) options operator, arrow; `+`(`*`(2, `*`(Sum(`+`(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n)...
proc (r, theta, t, p1, p2) options operator, arrow; `+`(`*`(2, `*`(Sum(`+`(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n)...
proc (r, theta, t, p1, p2) options operator, arrow; `+`(`*`(2, `*`(Sum(`+`(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n)...
(1.7.2.2.4)
 

Os coeficientes A1(m, n), A2(m, n), B1(m, n) e B2(m, n) são constantes que dependem dos parâmetros m e n. Quando as condições iniciais são axialmente simétricas, u(r, theta, t) não depende de theta. Neste caso, temos que tomar m = 0, o que é equivalente a tomar p1 = 0. A expressão de u(r, theta, t) se reduz a: 

> value(u(r, theta, t, 0, p2))
`+`(`*`(2, `*`(sum(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n), `*`(t))), `*`(a))))), `*`(A2(0, n), `*`(sin(`/`(`*`(c,...
`+`(`*`(2, `*`(sum(`*`(BesselJ(0, `/`(`*`(BesselJZeros(0, n), `*`(r)), `*`(a))), `*`(`+`(`*`(A1(0, n), `*`(cos(`/`(`*`(c, `*`(BesselJZeros(0, n), `*`(t))), `*`(a))))), `*`(A2(0, n), `*`(sin(`/`(`*`(c,...
(1.7.2.2.5)
 

 

Animação dos Modos Normais 

Vamos construir uma função para a membrana circular da mesma forma que foi construído para a membrana retangular: 

> with(plots); -1

Para fazer a animação de um determinado modo normal, temos que dar valores numéricos para os parâmetros a e c. Vamos supor que o raio é a = 1 e c = 1 em um certo sistema de unidades: 

> animate_mode := proc (m, n) options operator, arrow; animate3d([r, theta, normal_mode(m, n)], r = 0 .. a, theta = 0 .. `+`(`*`(2, `*`(Pi))), t = 0 .. `*`(.99, `*`(evalf(`+`(`/`(`*`(2, `*`(Pi)), `*`(om...
animate_mode := proc (m, n) options operator, arrow; animate3d([r, theta, normal_mode(m, n)], r = 0 .. a, theta = 0 .. `+`(`*`(2, `*`(Pi))), t = 0 .. `*`(.99, `*`(evalf(`+`(`/`(`*`(2, `*`(Pi)), `*`(om...

 

> a, c := 1, 1
1, 1 (1.7.2.3.1)
 

Primeiro, vamos analisar o movimento do modos normais axialmente siméticos (m = 0).  Vamos fazer a animação do modo <0,1>: 

> animate_mode(0, 1)
Plot_2d
 

O primeiro modo axialmente simétrico não possui linha nodal, como era de se esperar. O segundo modo deve ter uma linha nodal: 

> animate_mode(0, 2)
Plot_2d
 

A linha nodal é um círculo cujo raio pode ser calculado da seguinte maneira. Observe que um corte vertical passando pelo centro do gráfico acima tem a seguinte forma: 

> cut := eval(subs(t = 0, normal_mode(0, 2))); 1; plot(cut, r = `+`(`-`(a)) .. a); 1

> plot(cut, r = `+`(`-`(a)) .. a)
 

Plot_2d
 

A posição inicial do modo <0,2> é a figura formada pela rotação do gráfico acima em torno do eixo vertical. É fácil ver pelo gráfico que, de maneira geral, a primeira linha nodal do modo <0,n> tem o raio r = `/`(`*`(a, `*`(BesselJZeros(0, 1))), `*`(BesselJZeros(0, 2))).  No caso acima obtemos r = .4356. 

 

O primeiro modo normal não axialmente simétrico é o modo <1,1>: 

> animate_mode(1, 1)
Plot_2d
 

Neste caso, a linha nodal é uma reta passando pelo centro cujo ângulo é theta = `+`(`*`(`/`(1, 2), `*`(Pi))). Os modos normais com `<>`(m, 0) e `<`(1, n) são de difícil visualização sem recursos de animação. Vejamos o modo <1,2>: 

> animate_mode(1, 2)
Plot_2d
 

De maneira geral, o modo <m, n> tem m retas nodais passando pelo centro separadas entre si pelo ângulo theta = `/`(`*`(Pi), `*`(n)) e `+`(n, `-`(1)) círculos de raios r[p] = `/`(`*`(a, `*`(BesselJZeros(0, 1))), `*`(BesselJZeros(0, n))), onde p vai de 1 até `+`(n, `-`(1)).  As linhas nodais são mostradas pelo seguinte procedimento: 

Por exemplo, o modo <2,3> tem as seguintes linha nodais: 

> nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...
nodal_lines := proc (m::posint, n::nonnegint) local ci, sl, p; global a, r; for p to n do ci[p] := plots[polarplot](`/`(`*`(a, `*`(BesselJZeros(0, p))), `*`(BesselJZeros(0, n)))) end do; for p to m do...

> nodal_lines(2, 3)
Plot_2d
 

Observe que o círculo mais externo não deve ser contado como uma linha nodal, pois representa a borda da membrana.  

 

Animação com Condições Iniciais 

>

>

>

>

As constantes A1(m, n), A2(m, n), B1(m, n) e que aparecem na função u(r, theta, t, p1, p2) definida anteriormente, podem ser obtidas a partir das expressões teóricas derivadas a partir da inversão da série de Fourier: 

>

> A1 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `/`(`*`(BesselJZeros(m, n), `*`(r)), `*`(a))), `*`(int(`*`(u0(r, theta), `*`(cos(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*...
A1 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `/`(`*`(BesselJZeros(m, n), `*`(r)), `*`(a))), `*`(int(`*`(u0(r, theta), `*`(cos(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*...
A1 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `/`(`*`(BesselJZeros(m, n), `*`(r)), `*`(a))), `*`(int(`*`(u0(r, theta), `*`(cos(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*...

> A2 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `*`(k(m, n), `*`(r))), `*`(int(`*`(v0(r, theta), `*`(cos(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*`(2, `*`(Pi))))))), r = ...
A2 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `*`(k(m, n), `*`(r))), `*`(int(`*`(v0(r, theta), `*`(cos(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*`(2, `*`(Pi))))))), r = ...

> B1 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `/`(`*`(BesselJZeros(m, n), `*`(r)), `*`(a))), `*`(int(`*`(u0(r, theta), `*`(sin(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*...
B1 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `/`(`*`(BesselJZeros(m, n), `*`(r)), `*`(a))), `*`(int(`*`(u0(r, theta), `*`(sin(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*...

> B2 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `*`(k(m, n), `*`(r))), `*`(int(`*`(v0(r, theta), `*`(sin(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*`(2, `*`(Pi))))))), r = ...
B2 := proc (m, n) options operator, arrow; `/`(`*`(int(`*`(r, `*`(BesselJ(m, `*`(k(m, n), `*`(r))), `*`(int(`*`(v0(r, theta), `*`(sin(`*`(m, `*`(theta))))), theta = 0 .. `+`(`*`(2, `*`(Pi))))))), r = ...
 

 

 

(1.7.2.4.1)
 

A função a seguir faz a animação do movimento da membrana descrita pela função u(r, theta, t, p1, p2). O primeiro argumento do procedimento representa o tempo de oscilação, o seegundo argumento é o número p1 que representa a truncagem do somatório na variável m, o terceiro argumento é o número p2 que representa a truncagem do somatório na variável n e o quarto é o número de frames na animação. 

Vamos ver dois exemplos com condições iniciais axialmente simétricas. O primeiro com velocidade inicial nula e o segundo com delocamento inicial nulo. Vamos tomar as seguintes condições iniciais: 

> animate_ic := proc (nt, p1, p2, frames0) options operator, arrow; plots:-animate3d([r, theta, value(u(r, theta, t, p1, p2))], r = 0 .. a, theta = 0 .. `+`(`*`(2, `*`(Pi))), t = 0 .. nt, coords = cylin...
animate_ic := proc (nt, p1, p2, frames0) options operator, arrow; plots:-animate3d([r, theta, value(u(r, theta, t, p1, p2))], r = 0 .. a, theta = 0 .. `+`(`*`(2, `*`(Pi))), t = 0 .. nt, coords = cylin...

> u0 := proc (r, theta) options operator, arrow; 1 end proc

> v0 := proc (r, theta) options operator, arrow; 0 end proc
 

proc (r, theta) options operator, arrow; 1 end proc
proc (r, theta) options operator, arrow; 0 end proc (1.7.2.4.2)
 

Ou seja, a membrana está repouso na posição u = 1.  Tomaremos o raio da membrana igual a 5: 

> a, c := 5, 1
5, 1 (1.7.2.4.3)
 

Os coeficientes  A1(m, n), A2(m, n), B1(m, n) e B2(m, n)são:  

> assume(m, integer); 1; A1(0, n); 1; A1(m, n); 1; A2(0, n); 1; A2(m, n); 1; B1(m, n); 1; B2(m, n); 1

> A1(0, n)

> A1(m, n)

> A2(0, n)

> A2(m, n)

> B1(m, n)

> B2(m, n)
 

 

 

 

 

(1.7.2.4.4)
 

Vamos fazer a animação com duas oscilações dominantes e com . Uma vez que a condição inicial é axialmente simétrica, vamos tomar : 

> animate_ic(20, 0, 20, 10); 1
Plot_2d
 

Podemos ver pela animação que a onda reflete na borda da membrana e se superpõe no centro, produzindo um propagação típica de ondas, como deveria ser. A reflexão na borda inverte o deslocamento da onda, já que a extremidade é fixa. 

 

Vamos fazer a animação do movimento da membrana no caso em que ela está na posição horizontal e sofre um impulso de cima para baixo na região central. As condições iniciais são: 

> u0 := proc (r, theta) options operator, arrow; 0 end proc

> v0 := proc (r, theta) options operator, arrow; `+`(`-`(piecewise(`<`(r, `+`(`*`(`/`(1, 20), `*`(a)))), 1, 0))) end proc
 

proc (r, theta) options operator, arrow; 0 end proc
proc (r, theta) options operator, arrow; `+`(`-`(piecewise(`<`(r, `+`(`*`(`/`(1, 20), `*`(a)))), 1, 0))) end proc (1.7.2.4.5)
 

A animação é obtida da através do comando: 

> animate_ic(20, 0, 20, 12)
Plot_2d