Finding roots of a function in Fortran

Asked

Viewed 354 times

6

I created a code that uses 3 methods to determine the roots of a function, the direct method of kicking x, Newton-Raphson and secant values. In the direct method, I set x values close to the roots, and I used while to add increments of 0.1 to these values until the moment the function changed signal, proximity situation of f(x) = 0. Only as a result, my program gets inifitamente inside those of while and does not run the rest. Here is my code

  program raizes
     implicit none
     integer n, i           !escolha dos chutes iniciais para cada raiz
     real*8, parameter :: r1=-3.d0/10.d0,r2=1.d0/10.d0,r3=4.d0/10.d0
     real*8 r1d, r2d, r3d, xd !novos valore de x a serem testados no
                               !método direto
     real*8 r1_nr, r2_nr, r3_nr, nr1, nr2, nr3 !variáveis do método 
                                               !Newton-Raphson
     real*8 r1_si,r2_si,r3_si,r1_s,r2_s,r3_s,sec1,sec2,sec3 !variáveis do
                                        !método das secantes
     read(*,*)n
     open(10,file="tab3_out.dat")
     xd = 0.d0
     do i = 0, n-1
     !Método Iteração direta
        xd =xd + 1.d0/10.d0 !incremento do chute inicial do método direto
        do while (f(r1d).ge.0.d0) !situação em que a função quase muda 
                                  !de sinal
           r1d = r1 - xd !como a raíz está em -0.5, o r1 deve ser 
                         !diminuído
        end do
        do while (f(r2d).ge.0.d0)
           r2d = r2 + xd !como a raíz está em 0.33,o r2 deve ser   
                       !aumentado        
        end do
        do while (f(r3d).le.0.d0)!situação em que a função está quase 
                                 !mudando de sinal
           r3d = r3 + xd !como a raíz está em 0.66, o r3 deve ser 
                         !aumentado
        end do
     !Método Newton-Raphson (N-R)
        r1_nr = r1 !----------valores iniciais de x
        r2_nr = r2
        r3_nr = r3
        nr1 = r1_nr - f(r1_nr)/df(r1_nr) !equação de N-R
        nr2 = r2_nr - f(r2_nr)/df(r2_nr) !equação de N-R
         nr3 = r3_nr +f(r3_nr)/df(r3_nr) !equação de N-R
        r1_nr = nr1 !alterando os valores iniciais de x para a 
        r2_nr = nr2 !próxima iteração
        r3_nr = nr3
     !Método Secante
        r1_si = -2.d0/10.d0 !valores xi-1 na equação do método da secante
        r2_si =  0.d0
        r3_si =  3.d0/10.d0
        r1_s = r1           !valores xi na equação
        r2_s = r2
        r3_s = r3
        sec1 = r1_s - f(r1_s)*(r1_s - r1_si)/(f(r1_s)-f(r1_si)) !fórmula
                                                    !método das secantes
        sec2 = r2_s - f(r2_s)*(r2_s - r2_si)/(f(r2_s)-f(r2_si))
        sec3 = r3_s - f(r3_s)*(r3_s - r3_si)/(f(r3_s)-f(r3_si))
        r1_si = r1_s  !alterando os valores de xi-1 e xi para a próxima 
                       !iteração
        r2_si = r2_s
        r3_si = r3_s
        r1_s = sec1
        r2_s = sec2
        r3_s = sec3
        write(10,*) i,r1d,r2d,r3d,nr1,nr2,nr3,sec1,sec2,sec3
     end do
     close(10)

     contains !----------definições da função e de sua derivada
        real*8 function f(x)
     real*8 x
          f = 18.d0*(x**3.d0)-9.d0*(x**2.d0)-5.d0*x+2.d0
     end function f

     real*8 function df(x)
     real*8 x
          df = 54.d0*(x**2.d0)-18.d0*x-5.d0
     end function df
  end program raizes

I would like a suggestion to solve that while problem.

  • The values of the variables r1d, r2d andr3d do not change within the responses loopings (while). Probably, or the values of the variables r1, r2 and r3 or the value of xd shall be updated within loopings for them to finish.

  • I’ll try to get them updated, thanks for the tip.

2 answers

1

I couldn’t solve the problem with do while, so I only used if and Else. This is the part of the direct method.

  program direto
     implicit none
     integer n, i
     real*8, parameter :: r1=-3.d0/10.d0,r2=1.d0/10.d0,r3=4.d0/10.d0
     real*8 r1d,r2d,r3d, xd, raiz_1,raiz_3,raiz_2
     read(*,*)n
     !método iteração direta
     xd = 0.d0
     do i = 0, n-1
        xd =xd + 1.d0/5.d0
        if(f(r1d).ge.0.d0)then
           r1d = r1 - xd
        else
           raiz_1 = r1d
        end if
        if (f(r2d).ge.0.d0) then
           r2d = r2 + xd
        else
           raiz_2 = r2d
        end if
        if (f(r3d).ge.0.d0) then
           r3d = r3 + xd
        else
           raiz_3 = r3d
        end if
        write(*,*)i, raiz_1, raiz_2, raiz_3
     end do

     contains
        real*8 function f(x)
        real*8 x
            f = 18.d0*(x**3.d0)-9.d0*(x**2.d0)-5.d0*x+2.d0
     end function f
  end program direto

1

I think you need to initialize the values of r1d, r2d and r3d before using them on the first call of f(r1d). If you do not do this, the initial values of these variables will be assigned by the system, that is, you have no predictor control. Thus, your function may behave unexpectedly.
If you initialize them with 0.0, or with the values of r1, r2 and r3, I believe it solves the problem in the first version of the code (without the if/Else).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.