Function 如何在Fortran的不同文件中使用变量?

Function 如何在Fortran的不同文件中使用变量?,function,fortran,main,Function,Fortran,Main,我有一个Fortran项目的问题,我想也许你能帮我 我使用代码块作为IDE,在那里你可以创建项目,所以我创建了一个项目,其中有两个文件:一个主程序和一个功能,我不知道还能用什么,我可以使用一些不同于功能的东西 所以我有一个函数,它从一个.txt文件中读取值,并将它们保存为实数,一切正常。我想做的是,从文件main调用这个函数,并将我用函数收集的数据保存在main中,以便main保持干净 我该怎么做?如果你愿意,我可以发布整个脚本,但我不认为它会增加那么多 编辑:如您所问,此处未剪切: progr

我有一个Fortran项目的问题,我想也许你能帮我

我使用代码块作为IDE,在那里你可以创建项目,所以我创建了一个项目,其中有两个文件:一个主程序和一个功能,我不知道还能用什么,我可以使用一些不同于功能的东西

所以我有一个函数,它从一个.txt文件中读取值,并将它们保存为实数,一切正常。我想做的是,从文件main调用这个函数,并将我用函数收集的数据保存在main中,以便main保持干净

我该怎么做?如果你愿意,我可以发布整个脚本,但我不认为它会增加那么多

编辑:如您所问,此处未剪切:

program main

    ! Variables
    real :: d1, r1, r2, a, teta, freq, Dt, mu, g0, r_t, height, r, omega, H, lx, ly, lz, m_c0, &
        Jx, Jy, Jz, gmax, I_s, K, Jx0, Jy0, Jz0, Vmin, tsp_0, Fmax, Isp, c1, n, F, DV, tfin, cont, Tmax
    real :: data_input

    ! Call the funcion
    data_input=data_module(d1, r1, r2, a, teta, freq, Dt, mu, g0, r_t, height, r, omega, H, lx, ly, lz, m_c0, &
          Jx, Jy, Jz, gmax, I_s, K, Jx0, Jy0, Jz0, Vmin, tsp_0, Fmax, Isp, c1, n, F, DV, tfin, cont, Tmax)

    ! Error 
    if (data_input/=1) then
        print*, 'ERROR: data_module did not work'
    end if

   !Just to show it
    print*,'After'
    print*, d1, r1, r2, a, teta, freq, Dt, mu, g0, r_t, height, r, omega, H, lx, ly, lz, m_c0, &
        Jx, Jy, Jz, gmax, I_s, K, Jx0, Jy0, Jz0, Vmin, tsp_0, Fmax, Isp, c1, n, F, DV, tfin, cont, Tmax
end program main

real function data_module ()

  ! Variables
  implicit none
  integer :: flag_read=0, w_int, d_int
  real:: coefficient, d1, r1, r2, a, teta, freq, Dt, mu, g0, r_t, height, r, omega, H, lx, ly, lz, m_c0, &
          Jx, Jy, Jz, gmax, I_s, K, Jx0, Jy0, Jz0, Vmin, tsp_0, Fmax, Isp, c1, n, F, DV, tfin, cont, Tmax
  character (LEN=35) :: starting_string, name*15, coefficient_string*20, w_string, d_string, number_format
  character :: w*2, d

  ! Open file
  open (11, file = 'Data.txt', status = 'old', access = 'sequential', form = 'formatted')

  ! Read a new line for every iteration
  sentence_reader: do while (flag_read==0)
    read (11, fmt='(A)', iostat = flag_read) starting_string

    ! Error
    if (flag_read>0)then
        print*, 'ERROR: could not read data'
        stop
    end if

    ! Skip useless lines
    if (starting_string(1:1)=='%' .OR. starting_string(1:1)==' ') then
        cycle
    end if

    ! Exit when you're done
    if (flag_read<0)then
        exit sentence_reader
    end if

    ! Just stuff to prepare it
    name=trim(starting_string(1:index(starting_string, '=')-1))
    coefficient_string=trim(adjustl(starting_string(index(starting_string, '=')+1:index(starting_string,';')-1)))
    if (scan(coefficient_string,'E')/=0) then
        w_string=coefficient_string
        w_int=len_trim(w_string)
        write(w, '(BN,I2)') w_int
        d_string=coefficient_string(index(coefficient_string, '.')+1:index(coefficient_string, 'E')-1)
        d_int=len_trim(d_string)
        write(d, '(BN,I1)') d_int

        !All togheter
        number_format='(BN,F' // trim(w) // '.' // d // ')'
    else
        w_string=coefficient_string
        w_int=len_trim(w_string)
        write(w, '(BN,I1)') w_int
        d_string=coefficient_string(index(coefficient_string, '.')+1:len_trim(coefficient_string))
        d_int=len_trim(d_string)
        write(d, '(BN,I1)') d_int
        number_format='(BN,F' // trim(w) // '.' // d // ')'

    end if

    ! Read the number
    read(coefficient_string,number_format) coefficient


    ! Save where it's needed (is there an easier way to do it?)
    select case (name)
        case ('d1')
            d1=coefficient
        case ('r1')
            r1=coefficient
        case ('r2')
            r2=coefficient
        case ('a')
            exit
        case ('teta')
            exit
        case ('freq')
            freq=coefficient
        case ('Dt')
            exit
        case ('mu')
            mu=coefficient
        case ('g0')
            g0=coefficient
        case ('r_t')
            r_t=coefficient
        case ('height')
            height=coefficient
        case ('lx')
            lx=coefficient
        case ('ly')
            ly=coefficient
        case ('lz')
            lz=coefficient
        case ('m_c0')
            m_c0=coefficient
        case ('Jx')
            Jx=coefficient
        case ('Jy')
            Jy=coefficient
        case ('Jz')
            Jz=coefficient
        case ('gmax')
            gmax=coefficient
        case ('I_s')
            I_s=coefficient
        case ('K')
            K=coefficient
        case ('Vmin')
            Vmin=coefficient
        case ('tsp_0')
            tsp_0=coefficient
        case ('Fmax')
            Fmax=coefficient
        case ('Isp')
            Isp=coefficient
        case ('n')
            n=coefficient
        case ('tfin')
            tfin=coefficient
        case ('cont')
            cont=coefficient
        case ('Tmax')
            Tmax=coefficient
        case default
            print*, 'Variable ', name, ' is not recognized'
    end select


  end do sentence_reader


  ! Other stuff I need
  teta=atan((r1 - r2)/d1)
  a=sqrt(d1**2 + (r1 - r2)**2)
  Dt=1/freq
  r=r_t + height
  omega=(mu/(r**3))**0.5
  H=(r*mu)**0.5
  Jx0=Jx - I_s
  Jy0=Jy - I_s
  Jz0=Jz - I_s
  c1=Isp*g0
  F=n*Fmax
  DV=(F/m_c0)*tsp_0

  ! Shows that the function is correctly executed
  data_module=1
  print*,'Before'
  print*, d1, r1, r2, a, teta, freq, Dt, mu, g0, r_t, height, r, omega, H, lx, ly, lz, m_c0, &
        Jx, Jy, Jz, gmax, I_s, K, Jx0, Jy0, Jz0, Vmin, tsp_0, Fmax, Isp, c1, n, F, DV, tfin, cont, Tmax

end function data_module
顺便说一句,我知道模块,但是有了open和其他东西,我无法让它们工作。我很乐意


我想做的是将我在data_模块中收集的数据d1、r1、ecc传递到main并保存在main中,但这样做不会保存它们,如果您运行它,当您在一切正常之前打印它们,当您在得到所有零之后打印它们。

好的,我注意到一些事情

您的函数是real类型的,但您只将其设置为1,即整数,当您将其放在注释中时,将显示该函数已正确执行。 让一个过程返回一个值来显示它是否正确执行并不少见,但它通常是一个错误代码,零意味着没有错误发生,一切正常。 此外,您可能希望将函数声明为整数而不是实数,因为整数更适合这种情况。比较起来更可靠

至于您的实际问题:如果您想将多个值传递回调用例程,那么您需要声明intentout伪变量。请参见此示例:

integer function test_output(outdata)
    integer, intent(out) :: outdata(10)
    integer :: i
    outdata = (/(i, i=1, 10)/)
    ! All worked well
    test_output = 0
    return
end function test_output
模块是一条路要走。下面是一个非常有限的示例,说明如何将上述功能合并到模块中,并在程序中使用该模块:

module mod_test
    implicit none
    ! Here you can place variables that should be available
    ! to any procedure using this module
contains
    ! Here you can place all the procedures (functions and
    ! subroutines)
    integer function test_output(outdata)
        integer, intent(out) :: outdata(10)
        integer :: i
        outdata = (/(i, i=1, 10)/)
        ! All worked well
        test_output = 0
        return
    end function test_output
end module mod_test

program test
    ! The 'USE' statement is the only thing that needs to be 
    ! *ahead* of the 'implicit none'
    use mod_test
    implicit none
    integer :: mydata(10) ! The variable that will contain the data
                          ! from the function
    integer :: status     ! The variable that will contain the error
                          ! code.
    status = test_output(mydata)

    if (status == 0) then
         print*, mydata
    end if

end program test
如果模块位于不同的源文件中,则需要以这种方式编译它们,假设您使用gfortran:


显示您的代码。我不太清楚你在描述什么。你的函数返回什么?它是函数还是子程序?您知道模块吗?您应该需要在函数def中指定变量作为参数:实函数数据_模块d1、r1、r2,。。。如果你真的使用了一个模块,这种错误会给你一个非常清晰的错误消息agentp,我敢肯定我试了5次,但都没有成功。现在我又试了一次,它神奇地起了作用。这很奇怪,但谢谢你。我知道我觉得自己有点傻,但希望它能帮助其他人上网。我找了一会儿,什么也没找到。就风格而言,这应该是一个子程序,而不是一个函数,因为你从来没有设置过函数返回值,我看不到data_module=。。在任何地方或尝试使用它。它实际上在那里,在底部。我用它来确保我读过它,但它可能毫无意义,所以我可能会使用一个子程序,谢谢,还有一个小的附加点-如果错误代码永远不会被设置为错误值,那么返回错误代码是没有意义的。是的,但由于他使用了错误代码或类似于他自己的示例中的代码,我想展示一下如何将其包括在内。另外:如果您合理地确定在不久的将来您将添加某种类型的错误检查,那么使用它会有所帮助,因为您以后不必更改太多代码。
$ gfortran -c -o mod_test.o mod_test.f90
$ gfortran -c -o test.o test.f90
$ gfortran -o test test.o mod_test.o