如何在Fortran中的其他文件中使用变量?

时间:2017-03-27 19:14:35

标签: function fortran main

我遇到了Fortran项目的问题,并想出也许你可以帮助我。

我使用代码块作为IDE,你可以在那里制作项目,所以我创建了一个包含两个文件的项目:一个主程序和一个功能(我不知道还有什么用,我可能会使用与功能不同的东西。)

所以我的函数从.txt读取值并将它们保存为实数,一切正常。我想要做的是,从文件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

PS。我知道模块,但有开放和所有其他东西,我无法让他们工作。愿意。

我想要做的是将我在data_module中收集的数据d1,r1,ecc传递给main并将它们保存在main中,但是这样做它不会保存它们(如果你运行它,当你打印它们之前&#34;之前&#34;一切都很好,当你打印它们时#34;在#34之后你就全部为零。

1 个答案:

答案 0 :(得分:1)

好的,我注意到了一些事情。

  1. 您的sed -i '/^title/s/;/*/g' file.txt 类型为function,但您只将它设置为1(整数),并将其放入注释中“显示该函数已正确执行”。 让一个过程返回一个值以显示它是否正确执行并不常见,但它通常是一个错误代码,零意味着没有错误发生,一切都很顺利。 此外,您可能希望将函数声明为real而不是integer,因为整数对于那种事情更好。 (比较可靠。)

  2. 关于您的实际问题:如果您想将多个值传递回调用例程,您可能需要声明real虚拟变量。见这个例子:

    intent(out)
  3. 模块是要走的路。这是一个非常有限的例子,说明如何将上述功能合并到一个模块中,并在程序中使用该模块:

    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