Departamento de Física Aplicada e Termodinâmica
Física Computacional A
DFAT/
FiscompFA
Equações Diferenciais Ordinárias
Professor: Anibal Leonardo Pereira
última atualização: junho 2011
Estagiários:
2004/1 a 2005/2
Luciana Conceição Iecker Lima
2010/1
Magali dos Santos Leodato
2009/1 a 2010/2
Filipe da Fonseca Cordovil
Monitores:
2001/1
Diego Chagas Garcia
2002/2
Erick Azevedo Meirelles
2003/1 a 2003/2
Luciana Maria dos Santos Azevedo
2003/1 a 2003/2
Tatiana Gonçalves Martins
2003/1 a 2005/2
Renato Nascente Júnior
2004/1 a 2005/2
Públio Martins Romano M. Carreiro
2006/1 a 2007/2
Luiz Fernando Rosalba Telles Souza
2006/1 a 2007/2
Paulo Henrique Pfitzner
2008/1 a 2008/2
Filipe da Fonseca Cordovil
2008/1 a 2009/2
Magali dos Santos Leodato
2011/1 a
Filipe da Fonseca Cordovil
1. Introdução
O método de Euler é o método numérico mais simples que pode ser usado para resolver uma equação
diferencial ordinária de primeira ordem (
Equação Diferencial Ordinária– EDO).
Uma equação diferencial ordinária é uma equação que envolve só uma variável independente. Por exemplo, a
equação diferencial que descreve o movimento de um pêndulo simples de massa m e comprimento l é
d
2
dt
2
g
l
sen
=
0
ou
d
2
dt
2=−
g
l
sen
que é uma equação diferencial ordinária de primeira ordem pois a única variável independente é o tempo.
As equações
dy
dx
=
x
8
d
2y
dx
2
3
dy
dx
2y
=
0
d
3y
dx
3
2
⋅
d
2y
dx
2
2
dy
dx
=
cos
x
x
⋅
dy
dx
y
=
3
d
2y
dx
2
2
dy
dx
3
enquanto as equações
∂
z
∂
x
−
z
−
x
∂
z
∂
y
=
0
∂
2z
∂
x
2
∂
2z
∂
y
2=
x
2
y
não são, pois possuem duas variáveis independentes x e y.
As equações diferenciais podem ser classificadas quanto ao tipo, a ordem e a linearidade:
•
Tipo
podem ser ordinárias ou parciais. Ordinárias quando as funções forem somente funções de uma
variável, por exemplo:
y
=
f
x
. Parciais quando as funções forem funções de mais de uma
variável independente:
z
=
f
x , y
•
Ordem
pode ser de 1
a, 2
a, 3
a, …, enésima ordem, dependendo da derivada de maior ordem presente na
equação. A equação
d
2
dt
2=−
g
l
sen
é uma equação diferencial ordinária de segunda ordem
•
Linearidade
Será linear quando as incógnitas e suas derivadas aparecem de forma linear na equação e não
linear caso contrário. A equação
x
⋅
dy
dx
y
=
3
é uma equação diferencial ordinária de primeira
ordem linear
Equações diferenciais ordinárias de primeira ordem são equações que podem ser escritas assim:
F
t , y , y '
=
0
ou
dy
dt
=
f
t , y
ou então
F
x , y , y '
=
0
ou
dy
dx
=
f
x , y
2. Método de Euler
Vários problemas encontrados na física envolvem equações diferenciais ordinárias de primeira ordem, por
exemplo:
movimento de projétil
movimento harmônico
são exemplos clássicos.
O método de Euler (
método de Euler padrão; método de Euler progressivo; Forward Euler method) para uma
equação
diferencial ordinária de primeira ordem
pode ser apresentado assim:
Considere a equação diferencial
dy
dx
=
f
x , y
onde x e y são as variáveis independentes e dependentes e
f
x , y
é a função derivada.
A função derivada pode ser determinada usando-se as diferenças finitas, então:
dy
dx
=
lim
x0
y
x
=
lim
x0
y
i1−
y
ix
i1−
x
i
=
lim
h0
y
i1−
y
ih
dy
dx
≃
y
i1−
y
ih
onde se fez
x
=
h
=
x
i1−
x
i(
geralmente h é chamado de passo e feito constante)
f
x , y
=
y
i1−
y
ih
o que nos leva a
y
i1=
y
i
h f
x
i, y
i
.
Esta forma de chegar ao novo valor de y, o valor
y
i1, conhecido o valor anterior,
y
i, é chamada de
método de Euler (
Euler padrão ou Euler progressivo).
No problema do valor inicial (Problema do Valor Inicial – PVI)
{
dy
dx
=
f
x , y
y
x
0=
y
0
valores iniciais: x0, y0os pares de valores (x, y) são encontrados utilizando-se recursivamente a equação
y
i1=
y
i
h f
x
i, y
i
.
Esta Folha contém
03 Atividades
00 atividades exemplos
03 atividade exemplo com ajustes e/ou acréscimos
00 atividades para serem feitas
00 atividades para serem ajustadas e/ou acrescidas
Seu professor de laboratório (e/ou teoria) poderá alterar esta relação !
Código da folha de atividades
Acesse a Home Page da disciplina, entre no link Datas-e-Atividades, para obter o código da folha de atividades. Toda atividade tem que ter o "xx" substituído pelo código indicado. Exemplos: código 02 ► fxxa3.f03
→
f02a3.f03Atividade 01
Entregar em meio magnético:
1. programa: euler1_prog fxxa1.f03
2. módulos: fc_constantes.f03 m_rotinas.f03 m1func.f03
3. scripts: euler1.plt
4. arquivos: euler1-h05.dados euler1-h02.dados euler1-h005.dados euler.gif
Exemplo/Acréscimo/Ajuste:
Exemplifica o uso do método de Euler progressivo para a solução de equação diferencial ordinária com valor inicial especificado
Observação:
As soluções, exata e as numéricas são colocadas num mesmo gráfico para evidenciar o erro nos valores da solução, conforme h vai aumentando
Fazer:
do valor inicial:
dy
dx
=
cos
4x
x
2
y
x
0=
y
0
=
2
no intervalo [0,1] com h=0.5, h=0.2 e h=0.05. Construa ográfico (arquivo euler.gif) contendo a solução exata
y
=
2
1
3
x
3
1
4
sin
4x
e as três soluções encontradas pelométodo de Euler progressivo.
a1.2) A velocidade de queda de um corpo é descrita pela equação
dv
dt
=−
g
onde v é a velocidade e a aceleração da gravidade vale g=9.8067 m/s2. Calcule v como função da velocidade para um corpo com (a) saindo do repouso e (b) com velocidade inicial diferente de zero, no intervalo de t=o até t=10s. Construa o gráfico com a solução numérica e a solução analítica.a1.3) um corpo move-se segundo a equação
dx
dt
=
v
x . Se a velocidade é constante e igual a 40 m/s uma tabela com asposições x como função do tempo. Entregue o gráfico correspondente.
a1.4) A equação
dI
dt
=
aI
−
bI
2
descreve o crescimento populacional, sendo I o número de indivíduos. O termo aI
corresponde ao número de nascimentos e -bI2 o número de mortes. Solucione o problema (a) com b=0 e (b) com a=10 e b=3
Não deixe de substituir os
xxpelo código adequado.
Escreva o programa
euler1_proge salve-o no arquivo
fxxa1.f03Escreva os módulos e os scripts
Gere os arquivos de dados e os gráficos solicitados
Não deixe de atualizar o cabeçalho de forma adequada.
________________________________________________________________________________________
►
arquivo: fxxa1.f03◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
program euler1_prog !
!---! Propósito: Constrói tabela de valores (x,y) solução da equação
! diferencial ordinária de 1a ordem com valor inicial y0 ! utilizando o método de Euler (Euler progressivo)
!---! Arquivo:fxxa1.f03
! Autor: Anibal L. Pereira 14/02/2009 !Revisões:
!---use fc_constantes
use fc_rotinas use fc_m1func implicit none
integer::i, & !contador
npassos ! número de passos inteiros real::x0,y0, & ! valor inicial
a,b, & ! intervalo - ponto inicial e ponto final h, & ! incremento h
delta ! incremento mais próximo de h
real,allocatable,dimension(:)::xt,yt !pontos da tabela
!---! Entrada pontos da tabela
!---print*, "====================================" print*, "Entre com o valor inicial x(0) e y(0)" print*, "====================================" read*, x0,y0
print*, "====================================" print*, "Entre com o incremento h "
print*, "====================================" read*, h
!---número de passos inteiros no intervalo a-b call incremento(a,b,h,npassos,delta)
print*,"npassos,delta",npassos,delta
!---cria vetores x e y da tabela allocate(xt(npassos+1),yt(npassos+1)) xt=0.0
yt=0.0
!---! cálculo da tabela solução da EDO
!---!---função derivada: fun6=f(x)=cos(4*x)+x*x
call euler_tab(fun6,x0,y0,a,b,delta,xt,yt)
!---! preserva resultado num arquivo
!---open(unit=10, file="euler-h05.dados", status="replace",action="readwrite") !open(unit=20, file="euler-h02.dados", status="replace",action="readwrite") !open(unit=30, file="euler-h005.dados", status="replace",action="readwrite")
do i=1,size(xt)
write(unit=10,fmt=*) xt(i),yt(i) end do
close(unit=10)
program euler1_prog
_______________________________________________________________________________________
►
arquivo: fc_constantes.f03◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄
►
Utilize os módulos existentes:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
_______________________________________________________________________________________
►
arquivo: fc_rotinas.f03◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄►◄
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
module fc_rotinas
!--- !Propósito:
! Guarda funções e sub-rotinas
!--- !USO:
! Coloque no seu programa fonte as declarações ! use fc_constantes
! use fc_rotinas !
!COMPILAÇÃO:
! (1) deste módulo fiscomp_rotinas
! f03 -c fc_constantes.o fc_rotinas !
! (2) para usar o módulo com o programa <prog.f03>
! f03 -o <prog> fc_constantes.o fc_rotinas.o <prog.f03>
!--- ! Arquivo: fc_rotinas.f03
! Autor: Anibal L. Pereira 23/01/2009 !Revisões: Anibal L. Pereira 11/02/2009
!Revisões: Anibal L. Pereira 16/04/2010 !
!--- use fc_constantes
implicit none
!--- ! Interfaçes (funções e sub-rotinas sobrecarregadas)
interface copia_matriz
module procedure copia_matriz_i, copia_matriz_r, copia_matriz_d end interface
interface swap
module procedure swap_i, swap_r, swap_rv, swap_c, swap_cv end interface
interface incremento
module procedure incr_r, incr1_rv, incr2_rv end interface
interface entra_linha_matriz
module procedure entra_linha_matriz_t, entra_linha_matriz_a end interface
!--- ! Funções
!--- public:: derivada
!--- ! Sub-rotinas
!---
public:: gauss, & !gauss elimination AX=B !ok entra_linha_matriz, & !entra linha de uma matriz !ok !rotina sobrecarregada
!1)entra_linha_matriz_t(mat)
! entra linha da matriz pelo teclado !2)entra_linha_matriz_a(mat,arq)
! entra linha da matriz via arquivo
inversa_matriz, & !inversa matriz - método eliminação Gauss !ok copia_matriz, & !copia matriz em outra matriz !ok !rotina sobrecarregada
!1)copia_matriz(src,dest,n_cop,n_ncop) ! copia matriz de valores inteiros !2)copia_matriz(src,dest,n_cop,n_ncop) ! copia matriz de valores reais, sp !3)copia_matriz(src,dest,n_cop,n_ncop) ! copia matriz de valores reais, dp
swap, & !troca valores !ok !rotina sobrecarregada
!1)swap(a,b)
! troca valores inteiros !2)swap(a,b)
! troca valores reais, sp !3)swap(a,b)
! troca valores de vetor reais, sp !4)swap(a,b)
! troca valores complexos, sp !5)swap(a,b)
! troca valores de vetor complexo, sp
incremento, & !calcula incremento e gera vetor de pontos !ok !rotina sobrecarregada
!1)incremento(a,b,incr,ninterv,incrp)
! retorna número de intervalos inteiro para a-b e incremento !(ou incremento próximo)
!2)incremento(a,b,vet)
! Retorna um vetor com 100 pontos no intervalo a-b !3)incremento(a,b,incrp,vet)
! Retorna um vetor com os N pontos gerados pelo incremento em a-b
interp_lagrange, & !interpolação polinomial de Lagrange !ok interp_newton, & !interpolação polinomial diferenças divididas !ok interp_polinomial, & !interpolação polinomial diferenças divididas
! similar ao (Numerical Recipes) !ok dif_finita_asc, & !constrói tabela de diferenças finitas ascendente !ok dif_divididas_asc, & !constrói tabela de diferenças divididas ascendente
! 3-pontos !ok der2, & !derivada segunda da função usando diferença central ! 3-pontos !ok fit_poli, & !ajuste mínimos quadrados !ok euler1_tab, & !tabela com solução EDO 1a ordem
! PVI - Euler progressivo !ok euler2_tab, & !tabela com solução EDO 2a ordem
! PVI - Euler progressivo !ok euler_mod_tab !tabela com solução EDO 1a ordem
! PVI - Euler modificado !ok
contains
!!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !!@@@@@@@@@@@@@@@@@@@@ SUB-ROTINAS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!@@@@@@@@@
!--- subroutine copia_matriz_i(src,dest,n_cop,n_ncop)
!--- !Propósito:
! Copia matriz do tipo inteiro de qualquer tamanho ! Adaptação de sub-rotina do numerical recipes
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! copia_matriz_i(src,dest,n_cop,n_ncop) !
! src
! (in) matriz inteira ! matriz original ! dest
! (out) matriz inteira ! matriz copiada ! n_cop
! (out) inteiro
! número de elementos copiados ! n_ncop
! (out) inteiro
! número de elementos não copiados
!--- integer,intent(in) ,dimension(:)::src ! fonte
integer,intent(out),dimension(:)::dest ! copia
integer,intent(out)::n_cop, & ! número de dados copiados n_ncop ! número de dados não copiados
n_cop = min(size(src),size(dest)) ! menor valor entre os tamanhos n_ncop = size(src)- n_cop ! diferença entre os valores dest(1:n_cop) = src(1:n_cop) ! copia a matriz
end subroutine copia_matriz_i
!@@@@@@@@@
!--- subroutine copia_matriz_r(src,dest,n_cop,n_ncop)
!--- !Propósito:
! Copia matriz do tipo real de precisão simples de qualquer tamanho ! Adaptação de sub-rotina do numerical recipes
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! copia_matriz_r(src,dest,n_cop,n_ncop) !
! src
! (in) matriz real ! matriz original ! dest
! (out) matriz real ! matriz copiada ! n_cop
! (out) inteiro
! número de elementos copiados ! n_ncop
! (out) inteiro
! número de elementos não copiados
!--- real,intent(in) ,dimension(:)::src ! fonte
real,intent(out),dimension(:)::dest ! copia
integer,intent(out)::n_cop, & ! número de dados copiados n_ncop ! número de dados não copiados
n_cop = min(size(src),size(dest)) ! menor valor entre os tamanhos n_ncop = size(src)- n_cop ! diferença entre os valores dest(1:n_cop) = src(1:n_cop) ! copia a matriz
end subroutine copia_matriz_r
!@@@@@@@@@
!--- subroutine copia_matriz_d(src,dest,n_cop,n_ncop)
!--- !Propósito:
! Copia matriz do tipo real de precisão dupla de qualquer tamanho ! Adaptação de sub-rotina do numerical recipes
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! copia_matriz_d(src,dest,n_cop,n_ncop) !
! src
! (in) matriz real,dp ! matriz original ! dest
! (out) matriz real,dp ! matriz copiada ! n_cop
! (out) inteiro,I4B
! número de elementos copiados ! n_ncop
! (out) inteiro
! número de elementos não copiados
!--- real(kind=dp),intent(in) ,dimension(:)::src ! fonte
real(kind=dp),intent(out),dimension(:)::dest ! copia
integer,intent(out)::n_cop, & ! número de dados copiados n_ncop ! número de dados não copiados
n_cop = min(size(src),size(dest)) ! menor valor entre os tamanhos n_ncop = size(src)- n_cop ! diferença entre os valores dest(1:n_cop) = src(1:n_cop) ! copia a matriz
end subroutine copia_matriz_d
!--- subroutine swap_i(a,b)
!--- !Propósito:
! Troca posição de dois inteiros
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! swap_i(a, b) !
! a
! (inout) inteiro ! primeiro valor ! b
! (inout) inteiro ! segundo valor
!--- integer,intent(inout):: a, &! primeiro valor
b ! segundo valor integer:: temp ! valor temporário
temp = a a = b b = temp
end subroutine swap_i
!@@@@@@@@@
!--- subroutine swap_r(a,b)
!--- !Propósito:
! Troca posição de dois reais, precisão simples ! Adaptação de sub-rotina do numerical recipes
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! swap_r(a, b) !
! a
! (inout) real ! primeiro valor ! b
! (inout) real ! segundo valor
!--- real,intent(inout):: a, &! primeiro valor
b ! segundo valor real:: temp ! valor temporário
temp = a a = b b = temp
end subroutine swap_r
!@@@@@@@@@
!--- subroutine swap_rv(a,b)
! Troca conteúdo de dois vetores reais, precisão simples, tamanho qualquer ! Adaptação de sub-rotina do numerical recipes
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! swap_rv(a, b) !
! a
! (inout) vetor real ! vetor primeiro valor ! b
! (inout) vetor real ! vetor segundo valor
!--- real,intent(inout),dimension(:):: a, &! vetor primeiro valor
b ! vetor segundo valor real,dimension(size(a))::temp ! vetor temporário
temp = a a = b b = temp
end subroutine swap_rv
!@@@@@@@@@
!--- subroutine swap_c(a,b)
!--- !Propósito:
! Troca posição de dois números complexos, precisão simples ! Adaptação de sub-rotina do numerical recipes
!--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! swap_c(a, b) !
! a
! (inout) complex ! primeiro valor ! b
! (inout) complex ! segundo valor
!--- complex,intent(inout):: a, &! primeiro valor
b ! segundo valor complex:: temp ! valor temporário
temp = a a = b b = temp
end subroutine swap_c
!@@@@@@@@@
!--- subroutine swap_cv(a,b)
!--- !Propósito:
! Troca conteúdo de dois vetores complexos, precisão simples, tamanho qualquer ! Adaptação de sub-rotina do numerical recipes
!Autor: Anibal L. Pereira 26/01/2009 !Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! swap_cv(a, b) !
! a
! (inout) vetor complex ! vetor primeiro valor ! b
! (inout) vetor complexo ! vetor segundo valor
!--- complex,intent(inout),dimension(:):: a, &! vetor primeiro valor
b ! vetor segundo valor complex,dimension(size(a))::temp ! vetor temporário
temp = a a = b b = temp
end subroutine swap_cv
!@@@@@@@@@
!--- subroutine gauss(n,a)
!--- !Propósito:
! Solução numérica de sistema de equações lineares pelo método da eliminação ! de Gauss
!
! Atenção: pelo menos um dos coeficientes não homogêneos tem que ser diferente ! de zero. Caso contrário não há garantia de funcionamento correto !--- !Autor: Anibal L. Pereira 23/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! gauss(n, a ) !
! n
! (in) inteiro
! número de equações lineares ! a
! (in/out) matriz real,dp, shape(:,:)
! na entrada: matriz aumentada original Nx(N+1)
! na saída : matriz aumentada contendo soluções na coluna N+1
!--- real(kind=dp),dimension(:,:),intent(inout)::a
integer,intent(in)::n ! número de equações lineares integer:: i, & !
j, & ! contador
jc, & ! contador, anda pela coluna jr, &
k, & kc, & nv, &
pv !número da coluna com maior valor absoluto do coeficiente integer::i9
real(kind=dp):: det=1.0, & ! determinante eps, & ! epsilon da máquina eps2, & ! dobro de epsilon r, & !
tm, & ! valor temporário para troca va
!--- !---
! Determina épsilon da máquina !--- eps=epsilon(det)
eps2 = eps*2
!--- ! gera a matriz triagonal
!---
do i=1,n-1 ! anda nas colunas, 1,2,...,N-1 (até penúltima) pv=i ! identifica o pivot
!---
do j=i+1,n !na coluna i anda da linha 2 até última para achar o maior valor absoluto
if(abs(a(pv,i)) < abs(a(j,i))) pv=j !pv = número da linha que contém maior valor absoluto end do
!---
if(pv /= i) then ! coloca linha com maior valor nesta posição do jc=1,n+1 ! anda pelas colunas
tm=a(i,jc) ! guarda temporariamente valor da linha i a(i,jc)=a(pv,jc) ! escreve valor da linha pv na linha i a(pv,jc)=tm ! escreve valor da linha i na linhas pv end do
det=-det ! valor do determinante end if
!---
if(a(i,i) == 0) then ! matriz singular - primeiro pivot igual a zero --> para o processo print*,"a(",i,i,") = 0 Matriz singular! "
stop end if
!---
do jr=i+1,n !eliminação dos coeficientes abaixo do pivot da linha i if(a(jr,i) /= 0) then
r = a(jr,i)/a(i,i)
do kc=i,n+1 ! anda na linha coluna a coluna ate a última temp=a(jr,kc)
a(jr,kc)=a(jr,kc)-r*a(i,kc)
! se o valor for menor que 2*epsilon ele é zerado if(abs(a(jr,kc))<eps2*temp) a(jr,kc)=0.0 end do
end if end do end do
!--- ! calcula o determinante
!--- do i=1,n
det = det*a(i,i) end do
if(det == 0) then
print*,"Determinante = 0 Matriz é singular" stop
else
! solução das equações a(n,n+1)=a(n,n+1)/a(n,n) do nv= (n-1),1,-1
va = a(nv,n+1) do k=(nv+1),n
va = va - a(nv,k)*a(k,n+1) end do
a(nv,n+1)=va/a(nv,nv) end do
return end if
end subroutine gauss
!@@@@@@@@@
!--- subroutine entra_linha_matriz_t(mat)
!--- !Propósito:
!--- !Autor: Anibal L. Pereira 23/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! entra_linha_matriz_t(mat) !
! mat
! (out) real, shape(:,:)
! matriz com dados obtidos via teclado
!--- real,dimension(:,:),intent(out)::mat
integer::i,n,m
n = size(mat,dim=1) ! número de linhas m = size(mat,dim=2) ! número de colunas
do i=1,n
read*, mat(i,1:m) end do
end subroutine entra_linha_matriz_t
!@@@@@@@@@
!--- subroutine entra_linha_matriz_a(mat,arq)
!--- !Propósito:
! Entra valores da linha de uma matriz via arquivo
!--- !Autor: Anibal L. Pereira 23/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! entra_linha_matriz_a(mat,arq) !
! mat
! (out) real, shape(:,:)
! matriz com dados obtidos do arquivo ! arq
! (in) caractere
! nome do arquivo de dados
!--- real,dimension(:,:),intent(out)::mat
character(len=*),intent(in)::arq integer::i,n,m
n = size(mat,dim=1) ! número de linhas m = size(mat,dim=2) ! número de colunas
open(unit=20, file=arq, status="old", action="read")
do i=1,n
read(unit=20,fmt=*) mat(i,1:m) end do
close(unit=20)
end subroutine entra_linha_matriz_a
!@@@@@@@@@
!--- subroutine inversa_matriz(n,mat,inv)
!--- !Propósito:
!--- !Autor: Anibal L. Pereira 24/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! inversa_matriz(n,mat,inv) !
! n
! (in) inteiro
! número de linhas da matriz quadrada NxN ! mat
! (in) matriz quadrada real, shape(:,:) ! matriz a ser invertida
! inv
! (out) matriz quadrada real,shape(:,:) ! matriz inversa
!--- real,dimension(:,:),intent(in) ::mat ! matriz
real,dimension(:,:),intent(out)::inv ! matriz inversa integer,intent(in)::n ! número de linhas na matriz original real,allocatable,dimension(:,:)::mat_aum ! matriz aumentada N x M integer::m ! número de colunas na matriz aumentada => m=2*n
integer:: cci,ccj! contadores
integer:: i, & ! contador, anda pelas colunas de 1 até n-1 j, & ! contador, anda pelas linhas de i+1 até n jc, & ! contador, anda pelas colunas de 1 até m jr, & ! contador, anda pelas linhas de i+1 até n k, &
kc, & ! contador, anda pelas colunas de 1 até m ma, & ! contador, indo de n+1 até m --> n elementos nv, &
pv ! número da linha que tem o maior valor absoluto real:: det=1.0, & ! inicialização do determinante
eps, & ! epsilon da máquina eps2, & ! dobro de epsilon r, & !
temp, & ! valor temporário para troca tm, & ! valor temporário para troca va
!--- m = 2*n
allocate(mat_aum(n,m)) mat_aum = 0
!--- ! copia a matriz e agrega matriz unitária na matriz aumentada !--- do cci=1,n
mat_aum(cci,1:n) = mat(cci,1:n) end do
do cci=1,n do ccj=n+1,m
if ((cci+n) == ccj)then mat_aum(cci,ccj) = 1.0 end if
end do end do
!--- ! Determina épsilon da máquina !--- eps=epsilon(det)
eps2 = eps*2
!---
do i=1,n-1 ! i=número da coluna -- (forward elimination) (n-1)passos pv=i ! pv=número da linha com maior valor absoluto
do j=i+1,n ! j=número da linha, sempre começando 1 unidade a mais que a coluna if(abs(mat_aum(pv,i)) < abs(mat_aum(j,i))) pv=j
end do
! se esta linha não contém o maior valor troca as linhas de posição pivota a linha do jc=1,m !jc=coluna
tm = mat_aum(i,jc)
mat_aum(i,jc)= mat_aum(pv,jc) mat_aum(pv,jc)= tm
end do
det = - det ! cada mudança de linha muda o sinal de det end if
do jr=i+1,n ! anda pela linhas debaixo do pivot ! zera os valores abaixo do pivot
if(mat_aum(jr,i) /= 0) then r = mat_aum(jr,i)/mat_aum(i,i)
do kc=i,m ! anda pelas colunas ! escreve novos valores na linha
temp= mat_aum(jr,kc)
mat_aum(jr,kc)= mat_aum(jr,kc)-r*mat_aum(i,kc) ! se o valor for menor que 2*epsilon ele é zerado
if(abs(mat_aum(jr,kc))< eps2*temp) mat_aum(jr,kc)=0.0 end do
end if end do end do
!--- ! calcula o terminante da matriz NxN pivotada !--- do i=1,n
det = det*mat_aum(i,i) end do
if(mat_aum(n,n) /= 0) then !backward elimination
do ma=n+1, m !coloca a matriz I à esquerda da matriz aumentada mat_aum(n,ma)= mat_aum(n,ma)/mat_aum(n,n)
do nv=n-1,1,-1
va = mat_aum(nv,ma) do k=nv+1,n
va = va - mat_aum(nv,k)* mat_aum(k,ma) end do
mat_aum(nv,ma)=va/mat_aum(nv,nv) end do
end do end if
!--- ! copia inversa para matriz inv !--- do i=1,n
inv(i,:)=mat_aum(i,n+1:m) end do
deallocate(mat_aum)
end subroutine inversa_matriz
!@@@@@@@@@
!--- subroutine interp_lagrange(np,xt,yt,x,yans)
!--- !Propósito:
! Interpola e extrapola usando a fórmula de Lagrange (polinômio de Lagrange) !--- !Autor: Anibal L. Pereira 26/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! lagrange_interp(n,xt,yt,x,yans) !
! np
! (in) inteiro
! número de pontos da tabela ! xt
! (in) vetor real
! yt
! (in) vetor real
! vetor com pontos y da tabela ! x
! (in) real
! ponto x para o qual a interpolação será calculada ! yans
! (out) real
! ponto y interpolado
!--- integer,intent(in)::np ! número de pontos da tabela
real,dimension(0:np-1),intent(in)::xt ! ponto x da tabela real,dimension(0:np-1),intent(in)::yt ! ponto y da tabela real,intent(in)::x ! ponto x para interpolação real,intent(out)::yans ! ponto y interpolado !---
integer:: i, j ! contadores real::z ! produto dos fatores !--- yans=0.0
do i=0,np-1 z=1.0 do j=0,np-1
if(i /= j) z=z*(x-xt(j))/(xt(i)-xt(j)) end do
yans=yans+z*yt(i) end do
end subroutine interp_lagrange
!@@@@@@@@@
!--- subroutine incr_r(a,b,incr,ninterv,incrp)
!--- !Propósito:
! Retorna o próprio incremento ou o incremento mais próximo do incremento solicitado ! que gera um números inteiro de intervalos iniciando em a e terminando em b.
! Também retorna o número de incrementos
!--- !Autor: Anibal L. Pereira 27/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! incr_r(a,b,incr,ninterv,incrp) !
! a
! (in) real ! ponto inicial ! b
! (in) real ! ponto final ! incr
! (in) real
! increvento sugerido ! ninterv
! (out) inteiro
! número de intervalos ! incrp
! (out) real
! incremento igual ou próximo do desejado para gerar um números de intervalos ! inteiro em a-b
!--- real,intent(in):: a, &! ponto inicial
b, &! ponto final do intervalo incr ! incremento desejado
integer,intent(out)::ninterv ! números de intervalos em a-b real,intent(out):: incrp ! incremento mais próximo !---
integer::iN_pontos
!--- ! cálculo do incremento e número de intervalos !--- N_pontos=(b-a)/incr
iN_pontos=int(N_pontos) ninterv=iN_pontos
if(N_pontos /= iN_pontos) then !Incremento mais próximo incrp=(b-a)/iN_pontos else
!Mesmo incremento incrp=incr
end if
end subroutine incr_r
!@@@@@@@@@
!--- subroutine incr1_rv(a,b,vet)
!--- !Propósito:
! Retorna um vetor com 100 pontos no intervalo a-b
!--- !Autor: Anibal L. Pereira 27/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! incr1_rv(a,b,vet) !
! a
! (in) real ! ponto inicial ! b
! (in) real ! ponto final ! vet
! (out) vetor real, shape(:)
! vetor com 100 pontos no intervalo a,b
!--- real,intent(in):: a, & ! ponto inicial
b ! ponto final do intervalo
real,intent(out),dimension(100):: vet ! vetor de pontos no intervalo a-b !---
real(sp)::delta integer:: i
delta=(b-a)/100
vet=[ a,((a+i*delta),i=2,100) ] end subroutine incr1_rv
!@@@@@@@@@
!--- subroutine incr2_rv(a,b,incrp,vet)
!--- !Propósito:
! Retorna um vetor com os N pontos gerados com o incremento especificado ! iniciando em a e terminando em b
! !
!ATENÇÃO: porque o tamanho do vetor tem que ser conhecido pelo programa que chama ! esta sub-rotina, esta sub-rotina só possa ser camada depois do vetor ! ter sido alocado com o tamanho certo, então:
!
! primeiro: call incremento(a,b,incr,ninterv,incrp) !
!--- !Autor: Anibal L. Pereira 27/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! incr2_rv(a,b,incrp,vet) !
! a
! (in) real ! ponto inicial ! b
! (in) real ! ponto final ! incrp
! (in) real
! tamanho dos intervalos em a-b ! vet
! (out) vetor real
! vetor com N posições gerado com incrp no intervalo a-b
!--- real,intent(in):: a, &! ponto inicial
b, &! ponto final do intervalo incrp ! incremento
real,intent(out),dimension(:)::vet ! vetor com pontos de a até b !---
integer:: i,n
n=size(vet)
vet=[ a,((a+i*incrp),i=1,n-1) ] end subroutine incr2_rv
!@@@@@@@@@
!--- subroutine interp_newton(xt,yt,x,y)
!--- !Propósito:
! Interpolação progressiva de Newton - intervalos iguais, aceita tabela de ! dados com tamanho N (qualquer, maior que 2)
!--- !Autor: Anibal L. Pereira 24/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! interp_newton(xt,yt,x,y) !
! xt
! (in) vetor real ! X - pontos da tabela ! yt
! (in) vetor real ! Y - pontos da tabela ! x
! (in) real ! ponto desejado ! y
! (out) real
! ponto interpolado
!--- real,intent(in),dimension(:)::xt,yt ! tabela original
real,intent(in) :: x ! ponto
real,intent(out):: y ! ponto interpolado !---
real,allocatable,dimension(:)::xti,yti ! tabela para interpolação real,allocatable,dimension(:,:)::dd ! diferenças finitas real,dimension(1)::po !posição da menor diferença
real,dimension(0:9)::pr ! produtos real::s, & ! variável local fator ! fatorial integer:: i,i1,j , &! contador
ipo, &! posição do ponto mais próximo de x tam, &! tamanho do vetor
k ! posição de x0 para criar a tabela de interpolação !---
!--- cria os vetores com tamanho certo tam=size(xt)
if(tam < 2) stop "tabela necessita de pelo menos 2 pontos" if(tam >= 10) then
allocate(xti(0:9),yti(0:9),hi(tam),dd(0:9,0:9)) xti=0.0
yti=0.0
hi=0.0 dd=0.0
else
!---tamanho maior que 2 e menor que 10
allocate(xti(tam),yti(tam),hi(tam),dd(tam,tam)) xti=0.0
yti=0.0
hi=0.0 dd=0.0
end if
!--- cria vetor com diferenças hi=abs(x-xt)
!--- ! tabela original com 10 ou mais pontos
!--- !
!---localiza a posição mais próxima do ponto x po=minloc(hi)
ipo=po(1)
if (x == xt(ipo)) then
y=yt(ipo) ! ponto-base não necessita interpolação return
end if
!--- gera tabela de interpolação com 10 pontos, iniciando em x0 if(ipo-4 >= 0) then
!--- tem 4 elementos anteriores if(size(xt)-ipo >=5) then
!--- tem 5 elementos posteriores k=ipo-4
!---cria tabela de interpolação do i=0,9
xti(i)=xt(k+i) yti(i)=yt(k+i) end do
else
!--- não tem 5 elementos depois k=ipo-(9-(size(xt)-ipo))
do i=0,9
xti(i)=xt(k+i) yti(i)=yt(k+i) end do
end if else
!--- não tem 4 elementos anteriores k=1
!---cria tabela de interpolação do i=0,9
xti(i)=xt(k+i) yti(i)=yt(k+i) end do
end if
!--- !
!---cálculos das diferenças finitas dd(0:9,0)=yti
do i=1,9 ! completando a tabela de diferença finita iniciando k=9-i
do j=0,k
dd(j,i)=dd(j+1,i-1)-dd(j,i-1) end do
end do
!--- variável local
s=(x-xti(0))/(xti(1)-xti(0)) !--- gera os produtos
pr(0)=1.0 pr(1)=s pr(9)=0.0 do j=2,8
pr(j)=pr(j-1)*(s-(j-1)) end do
!--- ponto interpolado y=dd(0,0)
fator=1.0 do i=1,9
fator=fator*i
y=y+(pr(i)/fator)*dd(0,i) end do
end subroutine interp_newton
!@@@@@@@@@
!--- subroutine interp_polinomial(xt,yt,x,y)
!--- !Propósito:
! Interpolação polinomial - intervalos não necessitam ser iguais, tamanho da ! tabela é N (com N qualquer)
!
! Adaptação da sub-rotina polint do numerical recipes
!--- !Autor: Anibal L. Pereira 24/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! interp_polinomial(xt,yt,x,y) !
! xt
! (in) vetor real
! X - pontos da tabela - máximo de 10 ! yt
! (in) vetor real
! Y - pontos da tabela - máximo de 10 ! x
! (in) real ! ponto desejado ! y
! (out) real
! ponto interpolado
!--- real,intent(in),dimension(:):: xt,yt ! pontos x,y da tabela
real,intent(in):: x ! ponto para interpolação real,intent(out):: y ! valor interpolado !---
integer:: i, & ! contador do loop tn, & ! tamanho dos vetores
ipvmp ! posição na tabela do menor valor de x-xt
integer,dimension(1):: pvmp ! posição do menor valor de x-xt real,dimension(size(xt)):: copy1, & ! vetor
den, & ! vetor
d1, & ! vetor com diferença obtida por xt-x vdax ! vetor diferença absoluta para x real::dy ! flutuação no valor y
!--- tn=size(xt) ! tamanho do vetor xt
if(tn /= size(yt)) stop "<== Programa terminou porque vetores tem tamanhos diferentes" copy1=yt ! copia o vetor yt nos vetores copy1 e
copy2=yt ! copy2
d1=xt-x ! subtrai x de todos os pontos x da tabela
vdax=abs(x-xt) ! vetor com diferenças absolutas entre x e os pontos xt pvmp=minloc(vdax)
ipvmp=pvmp(1) ! índice do valor tabelado mais perto de x y=yt(ipvmp) ! valor inicial da interpolação
ipvmp=ipvmp-1 !
do i=1,tn-1 ! den(1:tn-i)=d1(1:tn-i)- d1(1+i:tn)
if (any(den(1:tn-i) == 0.0)) stop "<== Calculo falhou" den(1:tn-i)=(copy1(2:tn-i+1)-copy2(1:tn-i))/den(1:tn-i) copy2(1:tn-i)=d1(1+i:tn)*den(1:tn-i) copy1(1:tn-i)=d1(1:tn-i)*den(1:tn-i)
if (2*ipvmp < tn-i) then dy=copy1(ipvmp+1)
else
dy=copy2(ipvmp) ipvmp=ipvmp-1 end if
y=y+dy end do
end subroutine interp_polinomial
!@@@@@@@@@
!--- subroutine dif_finita_asc(xt,yt,dif)
!--- !Propósito:
! Constrói a tabela de diferenças finitas ascendente - incrementos equidistantes !--- !Autor: Anibal L. Pereira 30/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! dif_finita_asc(xt,yt,dif) !
! xt
! (in) vetor real, shape(:) ! valores X da tabela ! yt
! (in) vetor real, shape(:) ! valores Y da tabela ! dif
! (out) matriz, shape(:,:)
! contém x e as diferenças finitas: y,Dy,D^2y,...
!--- real,dimension(:),intent(in)::xt, yt
real,dimension(:,:),intent(out)::dif !---
integer:: i,j,k, & ! contadores n_pontos ! número de pontos !--- ! copia xt e yt para a matriz dif
n_pontos=size(xt)
if(n_pontos > 10) stop "Maximo 10 pontos" do i=1,n_pontos
end do
!print*,"--- matriz dif ---"
!print"(8f12.5)",((dif(i,j),j=1,n_pontos+1),i=1,n_pontos) !stop
do k=3,n_pontos+1 ! anda pelas colunas j=n_pontos - (k-2)
do i=1,j
dif(i,k)=dif(i+1,k-1)-dif(i,k-1) end do
end do
end subroutine dif_finita_asc
!@@@@@@@@@
!--- subroutine dif_divididas_asc(xt,yt,dif)
!--- !Propósito:
! Constrói a tabela de diferenças divididas ascendente - incrementos podem ser ! desiguais
!--- !Autor: Anibal L. Pereira 30/01/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: nenhum ![ funções]: nenhuma ![sub-rotinas]: nenhuma
!--- !Argumentos:
! dif_divididas_asc(xt,yt,dif) !
! xt
! (in) vetor real, shape(:) ! valores X da tabela ! yt
! (in) vetor real, shape(:) ! valores Y da tabela ! dif
! (out) matriz, shape(:,:)
! contém x e as diferenças divididas
!--- real,dimension(:),intent(in)::xt, yt
real,dimension(:,:),intent(out)::dif !---
integer:: i,j,k, & ! contadores n_pontos ! número de pontos !--- ! copia xt e yt para a matriz dif
n_pontos=size(xt)
if(n_pontos > 10) stop "Maximo 10 pontos" do i=1,n_pontos
dif(i,1)=xt(i) dif(i,2)=yt(i) end do
do k=3,n_pontos+1 ! anda pelas colunas j=n_pontos - (k-2) ! anda dentro da coluna do i=1,j
! diferença dividida
dif(i,k)=(dif(i+1,k-1)-dif(i,k-1))/(dif(i+(k-2),1)-dif(i,1)) end do
end do
end subroutine dif_divididas_asc
!@@@@@@@@@
!--- subroutine bissecao(func,a,b,tol,zero,ifail)
!--- !Propósito:
! Calcula a integral da função usando o método da bisseção
!--- !Autor: Anibal L. Pereira 30/01/2009
!Revisões:
!DEPENDÊNCIA:
![ módulos]: <<<<<< especificado pelo usuário >>>>>> ![ funções]: <<<<<< especificada pelo usuário >>>>>> ![sub-rotinas]: nenhuma
!--- !Argumentos:
! bissecao(func,a,b,tol,zero,ifail) !
! func
! (in) função, real, dp
! funçãoespecidicada pelo usuário ! a
! (in) real, dp
! valores inicial da integral definida ! b
! (in) real, dp
! valores final da integral definida ! zero
! (out) real, dp
! valores da integral definida ! ifail
! (out) inteiro
! valores indicando o status
!--- real(kind=dp),external::func
real(kind=dp),intent(in)::a,b,tol real(kind=dp),intent(out)::zero
integer,intent(out)::ifail ! indicador de erro !---
real(kind=dp)::a1,b1 ! copia local dos limites iniciais integer:: i, & ! contador
num_int ! número de iterações real(kind=dp)::meio_intr ! meio do intervalo !--- ! status e causas de erro
ifail=0
if(func(a)*func(b)>0) then
! 0 raiz pode ser encontrada
ifail=1 ! 1 raiz não está dentro do intervalo a-b return
endif
if(tol < 0) then
ifail=2 ! 2 tolerância inválida tolerância<0 return
endif
if(a > b) then
ifail=3 ! 3 intervalo inválido a>b return
endif a1=a b1=b
num_int=ceiling(log(tol/(b1-a1))/log(0.5_dp)) do i=1,num_int
meio_intr=(a1+b1)/2
if(func(a1)*func(meio_intr)<0)then b1=meio_intr
else
a1=meio_intr end if
end do
zero=(a1+b1)/2
end subroutine bissecao
!@@@@@@@@@
!--- subroutine newton_raphson(func,x,tol,zero)
!--- !Propósito:
! Calcula zero da função pelo método de Newton-Raphson
!--- !Autor: Anibal L. Pereira 04/02/2009
!Revisões:
!DEPENDÊNCIA:
![ módulos]: <<<<<< especificado pelo usuário >>>>>> ![ funções]: <<<<<< especificada pelo usuário >>>>>> ![sub-rotinas]: nenhuma
!--- !Argumentos:
! newtom_raphson(func,x,tol,zero) !
! func
! (in) função real,dp
! função especificada pelo usuário ! x
! (in) real,dp
! valores x da abcissa ! tol
! (in) real,dp
! valor da tolerância - erro ! zero
! (out) real,dp ! zero da função
!--- real(kind=dp),external::func
real(kind=dp),intent(in)::x, tol real(kind=dp),intent(out)::zero
!--- real(kind=dp)::erro, & !erro
xb, & !valor prévio de x y_deriv, & !derivada no ponto x xt !raiz
integer:: n ! número de iterações !--- erro=1.0D10
xt=x xb=xt n=0
do while (erro > tol) n=n+1
y_deriv=derivada(func,xt) xt=xt-func(xt)/y_deriv erro=abs(xt-xb)
xb=xt end do zero=xt
end subroutine newton_raphson
!@@@@@@@@@
!--- subroutine integ_trapezio(func,a,b,n,it)
!--- !Propósito:
! Calcula a integral da função entre os pontos a e b utilizando n intervalos ! pelo método do trapézio
!--- !Autor: Anibal L. Pereira 04/02/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: <<<<<< especificado pelo usuário >>>>>> ![ funções]: <<<<<< especificada pelo usuário >>>>>> ![sub-rotinas]: nenhuma
!--- !Argumentos:
! integ_trapezio(func,a,b,n,it) !
! func
! (in) função real,dp
! função especificada pelo usuário ! a
! (in) real,dp
! valores inicial da integral definida ! b
! (in) real,dp
! n
! (in) inteiro
! número de intervalos ! it
! (out) real,dp
! valor da integral definida
!--- real(kind=dp),external::func
real(kind=dp),intent(in)::a, b integer,intent(in)::n
real(kind=dp),intent(out)::it
!--- real(kind=dp)::dx, & !incremento
s1, & !parte da soma s2, & !parte da soma p !ponto
integer:: i ! contador
!--- dx=(b-a)/n
s1=func(a)+func(b) p=a
s2=0.0_dp do i=1,n-1 p=p+dx
s2=s2+func(p) end do
it=(dx/2.0_dp)*(s1+2_dp*(s2)) end subroutine integ_trapezio
!@@@@@@@@@
!--- subroutine simpson_1_3(func,a,b,n,simp)
!--- !Propósito:
! Calcula a integral da função entre os pontos a e b utilizando n1 intervalos ! pelo método de simpson 1/3
!--- !Autor: Anibal L. Pereira 04/02/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: <<<<<< especificado pelo usuário >>>>>> ![ funções]: <<<<<< especificada pelo usuário >>>>>> ![sub-rotinas]: nenhuma
!--- !Argumentos:
! simpson_1_3(func,a,b,n,it) !
! func
! (in) função real,dp
! função especificada pelo usuário ! a
! (in) real,dp
! valores inicial da integral definida ! b
! (in) real,dp
! valor final da integral definida ! n
! (in) inteiro
! número de intervalos ! simp
! (out) real,dp
! valor da integral definida
!--- real(kind=dp),external::func
real(kind=dp),intent(in)::a, b ! ponto inicial e final
integer,intent(in)::n ! número sugerindo de intervalos real(kind=dp),intent(out)::simp ! valor da integral
!--- real(kind=dp)::h, & !tamanho do incremento x !ponto
!---
!--- ! garante que o número de intervalos é sempre par, o que garante ! numeros impares de pontos
! (n=par)===> n1=n (n=impar) ===> n1=n+1
!--- n1=max(n,2)
n1=n1+modulo(n1,2)
h=(b-a)/n1 x=a
simp=func(x) ! simp=f(a)
do i=1,n1-1
x=a+i*h ! anda por cada um dos pontos de x(2) até x(n-1) simp = simp + (3 -(-1)**i)*func(x) ! soma 4*f(x_impares) e 2*f(x_pares)
end do
x=b
simp = simp + func(x) ! soma último ponto f(b) simp = h*(simp/3)
end subroutine simpson_1_3
!@@@@@@@@@
!--- subroutine der1(func,x,tol,der)
!--- !Propósito:
! Calcula a derivada primeira da função fornecida no ponto x usando a ! aproximação da diferença central para 3-pontos
!--- !Autor: Anibal L. Pereira 07/02/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: <<<<<< especificado pelo usuário >>>>>> ![ funções]: <<<<<< especificada pelo usuário >>>>>> ![sub-rotinas]: nenhuma
!--- !Argumentos:
! der1(func,x,tol,der) !
! func
! (in) função real,dp
! função especificada pelo usuário ! x
! (in) real,dp
! valores do ponto no qual será calculada a derivada primeira ! tol
! (in) real,dp ! tolerância ! der
! (out) real,dp
! valor da derivada no ponto x
!--- real(kind=dp),external::func
real(kind=dp),intent(in)::x,tol real(kind=dp),intent(out)::der !---
real(kind=dp)::h ! incremento real(kind=dp),dimension(0:100)::d, & ! derivadas
e ! diferença entre as derivadas integer::i ! contador
!--- h=1.0
d(0) =0.5*(func(x+h)-func(x-h))/h do i=1,2
h=h/2
d(i)= 0.5*(func(x+h)-func(x-h))/h e(i)= abs(d(i))-abs(d(i-1)) end do
do while ( e(i) > tol .and. (i < 100) ) h=h/2
d(i+2) = 0.5*(func(x+h)-func(x-h))/h e(i+2) = abs(d(i+2) - d(i+1))
i=i+1 end do der=d(i+1)
end subroutine der1
!@@@@@@@@@
!--- subroutine der2(func,x,tol,der)
!--- !Propósito:
! Calcula a derivada segunda da função fornecida no ponto x usando a ! aproximação da diferença central para 3-pontos
!--- !Autor: Anibal L. Pereira 10/02/2009
!Revisões:
!--- !DEPENDÊNCIA:
![ módulos]: <<<<<< especificado pelo usuário >>>>>> ![ funções]: <<<<<< especificada pelo usuário >>>>>> ![sub-rotinas]: nenhuma
!--- !Argumentos:
! der2(func,x,tol,der) !
! func
! (in) função real,dp
! função especificada pelo usuário ! x
! (in) real,dp
! valores do ponto no qual será calculada a derivada primeira ! tol
! (in) real,dp ! tolerância ! der
! (out) real,dp
! valor da derivada no ponto x
!--- real(kind=dp),external::func
real(kind=dp),intent(in)::x,tol real(kind=dp),intent(out)::der !---
real(kind=dp)::h ! incremento real(kind=dp),dimension(0:100)::d2, & ! derivadas
e ! diferença entre as derivadas integer::i ! contador
!--- h=1.0
d2(0) = (func(x+h)-2*func(x)+func(x-h))/(h*h) do i=1,2
h=h/2
d2(i)= (func(x+h)-2*func(x)+func(x-h))/(h*h) e(i)= abs(d2(i))-abs(d2(i-1))
end do i=1
do while ( e(i) > tol .and. (i < 100) ) h=h/2
d2(i+2) = (func(x+h)-2*func(x)+func(x-h))/(h*h) e(i+2) = abs(d2(i+2) - d2(i+1))
i=i+1 end do der=d2(i+1)
end subroutine der2
!@@@@@@@@@
!--- subroutine fit_poli(n,xt,yt,coef)
!--- !Propósito: