Baixe o app para aproveitar ainda mais
Prévia do material em texto
61 2.8 – O método de Runge-Kutta multidimensional 0 5 10 15 20 25 1 2 3 4 5 Γ (x ) x Γ(x)— intgama1.py Γ(x)— Gnuplot Figura 2.12: Cálculo de Γ(x) com o método de Runge-Kutta: saída de intgam1 com- parada com a função Γ(x) do programa de plotagem (Gnuplot) 2.11 Resolva, usando o método de Euler de ordem 2, e compare com a solução analítica: d y d x + y = x2 exp(−x), y(0) = 1. 2.12 Na equação d y d x + y x = sen � 2πx L � , y(0) = 0, estude a sensibilidade do h, necessário para produzir ε= 0,001, ao valor L. 2.13 Utilizando um método implícito semi-analítico, resolva d y d x + y x = ex x , y(x) = 0. 2.14 Resolva, utilizando Runge-Kutta: d y d x + y = sen(x), y(0) = 1. 2.8 –O método de Runge-Kutta multidimensional Vamos, na sequência, generalizar o método de Runge-Kutta para que ele seja capaz de resolver sistemas de equações diferenciais ordinárias do tipo d y d x = f (x , y). Note que y e f são vetores, enquanto que x permanece sendo um escalar. Matemática Aplicada 62 Listagem 2.24: Listas em Python 1 #!/usr/bin/python 2 # -*- coding: iso-8859-1 -*- 3 # ---------------------------------------------------------- 4 # tentalista: tenta manipular uma lista como se ela fosse 5 # um vetor matemático. 6 # ---------------------------------------------------------- 7 from __future__ import print_function 8 uu = [1,2] # lista com dois elementos 9 vv = [3,4] # outra lista com dois elementos 10 ww = uu + vv # soma para ver no que dá 11 kk = 3*uu # multiplica pelo escalar 3 para ver no 12 # que dá 13 print('ww = ', ww) ; 14 print('kk = ',kk) ; A base para a solução de sistemas de equações diferenciais ordinárias com o mé- todo de Runge-Kutta é muito simples: basta reconhecer que as equações também “funcionam” vetorialmente! De fato, podemos escrever k1 = f (xn, yn), k2 = h f (xn+ h 2 , yn+ 1 2 k1), k3 = h f (xn+ h 2 , yn+ 1 2 k2), k4 = h f (xn+ h, yn+ k3), yn+1 = yn+ 1 6 k1+ 1 3 k2+ 1 3 k3+ 1 6 k4. As questões fundamentais que nós teremos aqui do ponto de vista de implemen- tação computacional do método de Runge-Kutta multidimensional são como: • Representar um vetor computacionalmente. • Multiplicar um vetor por um escalar. • Somar dois vetores. A primeira idéia que vem à cabeça é representar um vetor em Python por uma lista; assim, por exemplo, o vetor (1,−1) seria representado pela lista [1,-1]. É preciso lidar com o fato de que em geral nós escrevemos para as componentes de um vetor em matemática: u = (u1, u2, u3) (os subscritos começam em 1), enquanto que os elementos de uma lista u em Python são u[0], u[1], e u[2]. Vamos tentar então utilizar listas, no programa tentalista.py, mostrado na lis- tagem 2.24. O resultado de rodar tentalista.py é ww = [1, 2, 3, 4] kk = [1, 2, 1, 2, 1, 2] 63 2.8 – O método de Runge-Kutta multidimensional Listagem 2.25: tentaarray.py: arrays com Numpy 1 #!/usr/bin/python 2 # -*- coding: iso-8859-1 -*- 3 # ---------------------------------------------------------- 4 # tentaarray: usa arrays, em vez de listas 5 # ---------------------------------------------------------- 6 from __future__ import print_function 7 from numpy import array 8 uu = array([1,2]) # lista com dois elementos 9 vv = array([3,4]) # outra lista com dois elementos 10 ww = uu + vv # soma para ver no que dá 11 kk = 3*uu # multiplica pelo escalar 3 para ver no 12 # que dá 13 print('ww = ', ww) ; 14 print('kk = ',kk) ; Que não é o que esperávamos! O operador + aplicado a listas não soma com- ponente a componente, mas sim concatena as duas listas; e o produto por 3 não multiplica componente a componente, mas sim repete a lista 3 vezes. Felizmente, existe uma maneira de se obter o comportamento esperado — mas não com listas. Um módulo extra-Python (que tem que ser instalado separadamente), denominado numpy, faz a mágica. A principal contribuição de numpy é que ele provê um novo tipo chamado array, que se comporta como um vetor. Vamos vê-lo em ação no próximo programa, tentaarray.py mostrado na listagem 2.25, cujo resultado é ww = [4 6] kk = [3 6] Como podemos ver, agora as coisas “funcionam”. Para usar numpy, é claro, você tem que baixar o pacote, e ler o manual: procure em http://numpy.scipy.org. Vamos agora resolver um caso para o qual possuímos solução analítica. Dado o sistema du1 d x = u2, du2 d x = u1, a sua solução é u1(x) = k1e −x + k2e x , u2(x) =−k1e−x + k2ex . O programa que resolve este sistema é o rungek4v.py mostrado na listagem 2.26; o mais interessante, e um dos pontos fortes de Python, é que a rotina rk4 segue inalterada: observe que ela é capaz de receber como entrada um array (y), assim como uma função que agora devolve array’s (ff), e que ela própria agora devolve um array. Com um h= 0.1, os erros relativos médios de u1 e u2 são extremamente pequenos: ε = 0.000004 em ambos os casos. Graficamente, temos a resultado mostrado na figura 2.13. Note que cosh x ≈ sinh x para x ¦ 2,5. http://numpy.scipy.org Matemática Aplicada 64 Listagem 2.26: rungek4v.py: o método de Runge-Kutta multidimensional 1 #!/usr/bin/python 2 # -*- coding: iso-8859-1 -*- 3 # ---------------------------------------------------------- 4 # rungek4v: resolve as equações diferenciais 5 # 6 # du1/dx = u2, 7 # du2/dx = u1, 8 # 9 # usando o método de Runge-Kutta de ordem 4 10 # ---------------------------------------------------------- 11 from __future__ import print_function 12 from numpy import array 13 h = 0.1 # passo em x 14 x = [0.0] # x inicial 15 y = [array([1.0,0.0])] # y inicial 16 n = int(10/h) # número de passos 17 from math import sinh, cosh 18 def ff(x,y): 19 return array([y[1],y[0]]) 20 def rk4(x,y,h,ff): 21 ''' 22 rk4 implementa um passo do método de Runge-Kutta de ordem 4 23 ''' 24 k1 = h*ff(x,y) 25 k2 = h*ff(x+h/2,y+k1/2) 26 k3 = h*ff(x+h/2,y+k2/2) 27 k4 = h*ff(x+h,y+k3) 28 yn = y + k1/6.0 + k2/3.0 + k3/3.0 + k4/6.0 29 return yn 30 for i in range(0,n): # loop da solução numérica 31 xn = (i+1)*h 32 yn = rk4(x[i],y[i],h,ff) 33 x.append(xn) 34 y.append(yn) 35 erro0 = 0.0 # calcula o erro relativo médio 36 erro1 = 0.0 37 for i in range(1,n+1): 38 yana0 = cosh(x[i]) 39 yana1 = sinh(x[i]) 40 erro0 += abs( (y[i][0] - yana0)/yana0 ) 41 erro1 += abs( (y[i][1] - yana1)/yana1 ) 42 erro0 /= n 43 erro1 /= n 44 print ( 'erro relativo médio = ', '%10.6f %10.6f' % (erro0,erro1) ) 45 fou = open('rungek4v.out','wt') 46 for i in range(0,n+1): # imprime o arquivo de saída 47 fou.write( '%12.6f %12.6f %12.6f\n' % (x[i],y[i][0],y[i][1]) ) 48 fou.close() 65 2.8 – O método de Runge-Kutta multidimensional 0.0 5.0 10.0 15.0 20.0 25.0 30.0 0 0.5 1 1.5 2 2.5 3 3.5 4 u (x ) x delta x = 0.5 u1(x) (num) u1(x) (ana) u2(x) (num) u2(x) (ana) Figura 2.13: Solução numérica pelo Método de Runge-Kutta de um sistema de 2 equações diferenciais ordinárias h(x , t) x z Figura 2.14: Drenagem de um maciço poroso semi-infinito inicialmente totalmente saturado.
Compartilhar