将数组从Fortran子程序传输到主程序

时间:2017-08-12 21:53:16

标签: fortran subroutine

我有一个打开并读取文件的子程序。最终结果是一个数组,它以重新组织的方式包含输入文件中的数据。我想调用主程序中的子程序来使用上述数组。

子例程具有作为在其文件中声明的单独程序运行所需的所有变量。我是新用的Fortran,所以我不确定如何正确使用子程序。我是否需要将任何形式变量分配给子程序的第一行,还是应该有一组空的括号?

子程序位于一个文件(subroutine.f03)中,该文件与主程序的文件(main.f03)分开。

主程序代码:

PROGRAM main
IMPLICIT NONE

CALL readBasis
WRITE(*,*) basis(1,1)

END PROGRAM

子程序代码:

SUBROUTINE readBasis()
IMPLICIT NONE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! io_open = IOSTATUS FOR OPENING THE BASIS FILE                                                                        !!
!! io_red = IOSTATUS FOR READING THE BASIS FILE                                                                         !!
!! atom_num = NUMBER ASSIGNED TO A PARTICULAR ATOM IN THE BASIS FILE                                                    !!
!! end_of_line = 0, DEFAULT BASIS SET INPUT FORMAT                                                                      !!
!! end_of_line_1 = 0.00 DEFAULT BASIS SET INPUT FORMAT                                                                  !!
!! atom_end = **** INDICATES THE END OF THE BASIS SET INFO FOR A GIVEN ATOM                                             !!
!! primitives = NUMBER OF PRIMITIVES IN A CONTRACTION                                                                   !!
!! basis_type = ANGULAR MOMENTUM ASSOCIATED WITH A CONTRACTION                                                          !!
!! expo = GAUSSIAN PRIMITIVE EXPONENT                                                                                   !!
!! coeff = CONTRACTION COEFFICIENT FOR AN S, P, D PRIMITIVE RESPECTIVELY IN A S, P, D SHELL                             !!
!! s_coeff & p_coeff = CONTRACTION COEFFICIENTS FOR S AND P PRIMITIVES IN AN SP SHELL                                   !!
!! basis = ARRAY CONTAINING ALL OF THE BASIS SET INFORMATION. THE FORMAT IS GIVEN BELLOW:                               !!
!!         BASIS NUMBER | PRIMITIVE TYPE | EXPONENT | S COEFF | P COEFF  | D COEFF | X COORDS | Y COORDS | Z COORDS      !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGER :: i, io_open, io_read, atom_num, end_of_line, primitives, gauss_i, gauss_f
INTEGER :: total_basis_functions, total_primitives, primitive_counter, primitive_num 
INTEGER :: func_start, func_end, func_counter
CHARACTER (LEN=4) :: basis_type, atom_end
REAL :: scaling, end_of_line_1
REAL :: expo, coeff, s_coeff, p_coeff
REAL, ALLOCATABLE :: basis(:,:)

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! atom_loop WILL LET YOU READ THE BASIS FUNCTIONS FOR EVERY ATOM  !!
!! contraction_loop WILL LET YOU READ EACH BASIS FUNCTION PER ATOM !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
OPEN(UNIT=10, FILE="BASIS", STATUS="OLD", ACTION="READ", IOSTAT=io_open)

READ(10,*) total_basis_functions
READ(10,*) total_primitives

ALLOCATE(basis(total_primitives,6))


READ(10,*,IOSTAT=io_read) atom_num, end_of_line
READ(10,*) basis_type, primitives, scaling, end_of_line_1, func_start, func_end

atom_end = basis_type
primitive_num = 1
atom_loop: DO WHILE (io_read .EQ. 0) 
 contraction_loop: DO WHILE (atom_end .NE. "****")
  orbital_type_loop: IF (basis_type == "S   ") THEN 
   DO func_counter = func_start, func_end
    DO primitive_counter = 1, primitives
     READ(10,*) expo, coeff
     basis(primitive_num,1) = REAL(func_counter)
     basis(primitive_num,2) = REAL(0)
     basis(primitive_num,3) = expo
     basis(primitive_num,4) = coeff
     basis(primitive_num,5) = REAL(0)
     basis(primitive_num,6) = REAL(0)
     primitive_num = primitive_num + 1
    END DO
    IF (func_counter .LT. func_end) THEN
     DO primitive_counter = 1, primitives
      BACKSPACE(10)
     END DO
    ELSE
     CONTINUE                                                                                           
    END IF
   END DO                                                                                               
  ELSE IF (basis_type .EQ. "P   ") THEN     
   DO func_counter = func_start, func_end
    DO primitive_counter = 1, primitives
     READ(10,*) expo, coeff
     basis(primitive_num,1) = REAL(func_counter)
     basis(primitive_num,2) = REAL(1)
     basis(primitive_num,3) = expo     
     basis(primitive_num,4) = REAL(0)
     basis(primitive_num,5) = coeff
     basis(primitive_num,6) = REAL(0)
     primitive_num = primitive_num + 1
    END DO
    IF (func_counter .LT. func_end) THEN
     DO primitive_counter = 1, primitives
      BACKSPACE(10)
     END DO
    ELSE
     CONTINUE                                                                         
    END IF
  END DO                                                                             
  ELSE IF (basis_type == "D   ") THEN 
   DO func_counter = func_start, func_end
    DO primitive_counter = 1, primitives
     READ(10,*) expo, coeff
     basis(primitive_num, 1) = REAL(func_counter)
     basis(primitive_num,2) = REAL(2)
     basis(primitive_num,3) = expo
     basis(primitive_num,4) = REAL(0)
     basis(primitive_num,5) = REAL(0)
     basis(primitive_num,6) = coeff
     primitive_num = primitive_num + 1
    END DO
    IF (func_counter .LT. func_end) THEN
     DO primitive_counter = 1, primitives
      BACKSPACE(10)
     END DO
    ELSE
     CONTINUE                                                                         
    END IF
   END DO                                                                             
  ELSE IF (basis_type .EQ. "SP  ") THEN
   DO func_counter = func_start, func_end
    DO primitive_counter = 1, primitives
     READ(10,*) expo, s_coeff, p_coeff
     basis(primitive_num,1) = REAL(func_counter)
     basis(primitive_num,2) = REAL(10)
     basis(primitive_num,3) = expo
     basis(primitive_num,4) = s_coeff
     basis(primitive_num,5) = p_coeff
     basis(primitive_num,6) = REAL(0)
     primitive_num = primitive_num + 1
    END DO
    IF (func_counter .LT. func_end) THEN
     DO primitive_counter = 1, primitives
      BACKSPACE(10)
     END DO
    ELSE 
     CONTINUE
    END IF
   END DO
  END IF orbital_type_loop
  READ(10,*) atom_end
  IF (atom_end .EQ. "****") THEN
   READ(10,*,IOSTAT=io_read) atom_num, end_of_line
   IF (io_read < 0) THEN
    EXIT atom_loop
   ELSE IF (io_read > 0) THEN
    WRITE(*,*) "FILE COULD NOT BE READ."
    EXIT atom_loop
   ELSE
    READ(10,*) basis_type, primitives, scaling, end_of_line_1, func_start, func_end
    atom_end = basis_type
    EXIT contraction_loop
   END IF
  ELSE
   BACKSPACE(10)
   READ(10,*) basis_type, primitives, scaling, end_of_line_1, func_start, func_end
  END IF
 END DO contraction_loop
END DO atom_loop
CLOSE(10)                                                                                                                                                       

RETURN

END SUBROUTINE

1 个答案:

答案 0 :(得分:0)

子程序在开始时在括号中标识了“虚拟变量”。这些可以是混合数据类型的输入或输出参数,即整数,整数数组,实数等的混合。在任何过程语句之前,每个虚拟变量必须具有在子例程的变量声明部分中分配的数据类型。 IMO的好习惯是使用意图修饰符来确保输入和输出变量之间的清晰度。在子例程中本地存在且未明确输入或输出的变量不需要在parens中,但确实需要声明,除非它们具有隐式数据类型。这是一个例子:

subroutine MEGA_SUBROUTINE(X,Y,Z,OUTPUT_ARRAY)
   implicit none
   real, intent(in):: X,Y,Z
   real:: local_var
   real, intent(out):: OUTPUT_ARRAY
! begin procedural section
! do stuff with your variables here, assign a value to output array
end subroutine MEGA_SUBROUTINE