ortran

Lenguaje de programación orientado a aplicaciones científicas y numéricas de alto rendimiento

Variable compleja

Introducción

Las variables complejas son de primera clase en Fortran. Tan solo será necesario declarar la variable de ese tipo y podemos acceder a su parte real e imaginaria con z%re y con z%im pero también se puede asignar una valor complejo en un solo paso con z=cmplx(0,1)

program coseno
    complex w, z


    ! Entrada
    write (*, "(a)", advance="no") "Valor real de z: "
    read *, z%re
    write (*, "(a)", advance="no") "Valor imaginario de z: "
    read *, z%im

    ! También se puede usar la función intrínseca
    ! z = cmplx(a, b)

    ! Cálculos
    w = cos(z)

    ! Salida
    write (*,"(a)") "w=cos(z)"
    write (*,"(a,f4.2,sp,f5.2,a)") "z:", real(z), aimag(z), "i"
    write (*,"(a,f4.2,sp,f5.2,a)") "w:", real(w), aimag(w), "i"

end program coseno

Integrales complejas

Una integral compleja puede ser calculada mediante una serie sucesiva de sumas. Las iteraciones deben ser parametrizadas. En este ejemplo, el parámetro de iteración paso a paso es t. Cada iteración es la suma del producto formado por la función en el punto en función de f(gamma(t)) por la derivada del camino gamma'(t) por el diferencial dt.

Se presentan dos versiones. Una sin coarrays y otra mucho más rápida con coarrays.

Versión sin coarrays

program Integral_sin_coarray
! Calcular $\int_{\gamma=\{|z|=1\}} \frac{Ln z}{z} dz$
! SOLUCIÓN
! Para calular esta integral compleja debemos hallar el camino y la 
! derivada de este a lo largo del contorno
!
! Camino:                   gamma(t)=e^{it}
! Derivada del camino:      gamma'(t)=ie^{it} dt
! Función:                 f(gamma(t))=\frac{Ln e^{it}}{e^{it}}=\frac{it}{e^{it}}

    use iso_fortran_env
    implicit none
    real, parameter:: pi = 3.141592654
    real, parameter:: t_0=0, t_end=2*pi
    real(real64), parameter:: dt = 0.0000001
    real(real64):: t
    complex(real64):: suma
    complex:: i = cmplx(0,1)

    ! Inicializar variables
    t = t_0
    suma = 0

    ! Cabecera
    write (*, "(a25)") "------------------------"
    write (*,"(a8,a8,a9)") "Iter.", "Re", "Im"
    write (*, "(a25)") "------------------------"
    do while (t <= t_end)
        suma = suma + f(t) * fp(t) * dt
        write (*,"(f8.2,f8.2, sp, f8.2, a1)") t, suma%re, suma%im, "i"
        t = t + dt
    end do

    ! Mostrar resultados
    write (*, "(a25)") "------------------------"




contains

    complex(real64) function f(t) result (res)
        ! Función a integrar en función de t
        implicit none
        real(real64), intent(in):: t
        res = (i*t)/(exp(i*t))
    end function f


    complex(real64) function fp(t) result(res)
        ! Derivada del camino en función de t
        implicit none
        real(real64), intent(in):: t
        res = i * exp(i*t)
    end function fp

end program Integral_sin_coarray

Versión con coarrays

program Integral_coarray
! Calcular $\int_{\gamma=\{|z|=1\}} \frac{Ln z}{z} dz$
! SOLUCIÓN
! Para calular esta integral compleja debemos hallar el camino y la 
! derivada de este a lo largo del contorno
!
! Camino:                   gamma(t)=e^{it}
! Derivada del camino:      gamma'(t)=ie^{it} dt
! Función:                 f(gamma(t))=\frac{Ln e^{it}}{e^{it}}=\frac{it}{e^{it}}

    use iso_fortran_env
    implicit none

    real, parameter:: pi = 3.141592654
    real, parameter:: t_0=0, t_end=2*pi
    real(real64), parameter:: dt = 0.000001
    real(real64):: t[*]
    complex(real64):: suma[*]
    complex:: i = cmplx(0,1)

    ! Inicializar variables
    t = t_0 + dt * this_image()-1
    suma = 0

    ! Bucle principal
    do while (t <= t_end)
        suma = suma + f(t) * fp(t) * dt
        t = t + dt * num_images()
    end do

    ! Sumar los resultados y mostrarlos en pantalla
    call co_sum(suma)
    if (this_image() == 1) then
        write (*,"(f8.2,f8.2, sp, f8.2, a1)") t, suma%re, suma%im, "i"
    end if





contains

    complex(real64) function f(t) result (res)
        ! Función a integrar: f(gamma(t))
        implicit none
        real(real64), intent(in):: t
        res = (i*t)/(exp(i*t))
    end function f


    complex(real64) function fp(t) result(res)
        ! Derivada del camino: gammma'(t)
        implicit none
        real(real64), intent(in):: t
        res = i * exp(i*t)
    end function fp

end program Integral_coarray