Fortran90 中如何处理用户自定义的数据结构?
How to handle user-defined data structure in Fortran90?
在我的程序中,我定义了一个名为 Lyapunov_orbit
的数据类型,它包含 8 个字段,然后我用它从外部 .txt 文件中读取数据(见下文,为了方便,我只报告了几行,因为文件大约有 4000 行)。我需要通过使用这样的结构来执行一些操作(例如查找数组的最小值和最大值)但是为了处理它我必须声明一个名为 vec_J_cst
的“辅助”变量因为如果我尝试直接使用我的数据strucutre,我收到一些错误(结构名称无效或丢失)。
这是 .txt 文件:
-0.990036333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.337762568000000E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090089101800E+01
-0.990037333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.344404791697701E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090088741935E+01
-0.990038333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.351079970065519E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090088372775E+01
-0.990039333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.357762241991673E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090087996039E+01
-0.990040333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.364443669596976E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090087612278E+01
-0.990041333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.371123821002079E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090087221528E+01
-0.990042333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.377014880488160E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090086883260E+01
-0.990043333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.384445283931247E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090086421774E+01
-0.990044333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.390403586590581E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090086066251E+01
-0.990045333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.397792952615728E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090085591825E+01
-0.990046333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.403738458530992E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090085225121E+01
-0.990047333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.411139963724134E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090084733683E+01
-0.990048333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.417123805736171E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090084351603E+01
-0.990049333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.424484757953771E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090083847487E+01
-0.990050333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.430437019162321E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090083455851E+01
-0.990051333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.437812214383817E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090082934584E+01
-0.990052333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.443804068227964E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090082527265E+01
-0.990053333227001E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.451146181152564E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090081992963E+01
-0.990054333227001E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.457168852630379E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090081570545E+01
-0.990055333227001E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.463719562991478E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090081093777E+01
这是模块:
module Array
use DataType
contains
!***********************************************************************
subroutine linspace(from, to, array)
!***********************************************************************
! Generates evenly spaced numbers from `from` to `to` (inclusive).
!
! Inputs:
! -------
!
! from, to : the lower and upper boundaries of the numbers to generate
!
! Outputs:
! -------
!
! array : Array of evenly spaced numbers
!***********************************************************************
implicit none
!Arguments
real(pr), intent(in) :: from, to
real(pr), intent(out) :: array(:)
real(pr) :: range
integer :: n, i
n = size(array)
range = to - from
if (n == 0) return
if (n == 1) then
array(1) = from
return
end if
do i=1, n
array(i) = from + range * (i - 1) / (n - 1)
end do
end subroutine
end module Array
!***************************************************************************
! Program name: Cheops ver 0
! Author: Elena Fantino, ETSEIAT - UPC
! Date: August 2015
!***************************************************************************
module DataType
implicit none
INTEGER, PARAMETER :: pr = SELECTED_REAL_KIND (p = 15)
!"Lyapunov_orbit" data type declaration
type Lyapunov_orbit
real(pr) :: a
real(pr) :: b
real(pr) :: c
real(pr) :: d
real(pr) :: e
real(pr) :: f
real(pr) :: g
real(pr) :: J_cst
end type Lyapunov_orbit
end module DataType
这是我的主程序:
program Main_Planar_Lyapunov_orbits
use DataType
use Array
implicit none
! Declarations
character*100 :: input_path,input_filename, output_path, output_filename,line
character*30, dimension(1) :: str_output !questo mi servira per le intestazioni nel file di output
integer :: i,j, iu_in,iu_out,n_lines, iflag, pos_err_min
type(Lyapunov_orbit), dimension (:), allocatable :: Ly_data_SE_L1
real(pr), dimension(:), allocatable :: vec_J_cst, err
real(pr), dimension(1) :: first_J_cst_vec, last_J_cst_vec, Delta_J, step, accepted_value
real(pr), dimension(50) :: array_Ly_orb
! Definition of constants, paths names and file names
iu_in = 10
iu_out = 11
input_path = 'D:\OneDrive\MSc_Thesis\Projects\Planar_Lyapunov_orbits\InputFiles\'
input_filename = 'Planar_Lyapunov_SE_L1_Buono.txt'
output_path = 'D:\OneDrive\MSc_Thesis\Projects\Planar_Lyapunov_orbits\OutputFiles\'
output_filename = 'Planar_Lyapunov_SE_L1_evenly_spaced.txt'
! Reading of Lyapunov orbits data from input file
open(unit = iu_in, file = trim(input_path) // trim(input_filename), status='old', &
access = 'sequential',form = 'formatted', action='read')
! Count lines
n_lines = 0
do
read(iu_in,*,iostat = iflag)
if (iflag/=0) exit
n_lines = n_lines + 1
enddo
rewind(iu_in)
! Variables allocation
allocate(Ly_data_SE_L1(n_lines))
! Data reading
do i = 1, n_lines
read(iu_in,*) Ly_data_SE_L1(i)
enddo
close(unit = iu_in, status='keep')
! Creation of Jacobi constant evenly spaced 1-D array of 50 elements,
! the first one and the last are the corresponding ones of input data
! Extraction of the first and last element by using auxiliary variable
!allocate(vec_J_cst(n_lines))
!do i = 1,n_lines
! vec_J_cst(i) = Ly_data_SE_L1(i)%J_cst
! first_J_cst_vec = vec_J_cst (lbound(vec_J_cst)) ! max
! last_J_cst_vec = vec_J_cst (ubound(vec_J_cst)) ! min
!enddo
!! ATTEMPT TO AVOID another variable usage (IT DOES NOT WORK!)
first_J_cst_vec = Ly_data_SE_L1(:)%J_cst (lbound(Ly_data_SE_L1(:)%J_cst)) ! max
last_J_cst_vec = Ly_data_SE_L1(:)%J_cst (ubound(Ly_data_SE_L1(:)%J_cst)) ! min
! Evenly spaced array: the 1st element is the greater value of jacobi constant:
! the size of the array has to be specified in the declarations
call linspace(from = first_J_cst_vec(1), to = last_J_cst_vec(1), array = array_Ly_orb)
allocate(err(n_lines))
! Filter the original input file and write data on new file of 50 Lyapunov orbits based on input data
open(unit = iu_out, file = trim(output_path) // trim(output_filename), status = 'unknown', action ='write')
! Compare the original Jacobi constants array(Ly_data_SE_L1%J_cst) with the created evenly spaced array(array_Ly_orb)
! Header line
write(iu_out,'(2a15)') 'unknown','Jacobi constant'
! Nested cycles
do i = 1,50
do j = 1, n_lines
! Compute the error between the i-th element of evenly spaced array and the current element of original jacobi constants array
err(j) = abs( vec_J_cst(j) - array_Ly_orb(i) )
enddo
! Find the location of the absolute minimum of the Err array
pos_err_min = minloc(err, dim =1)
write(iu_out,'(2e25.15)') Ly_data_SE_L1(pos_err_min)%a, vec_J_cst(pos_err_min)
enddo
close(unit = iu_out,status='keep')
!Idea di algoritmo per la parte di confronto e scrittura
! Abbiamo due array, il primo è quello originale con circa 4000 element e il secondo è quello creato con 50 elementi. Per prima cosa faccio un
! ciclo sul secondo array (indice i), poi ciclo sul primo array e calcolo l'errore fra il valore corrente j e quello fissato i, tale errore
! sarà un vettore di circa 4000 elem. Uso la funzione predefinita minloc per localizzre la posizione del minimo assoluo del vettore di errore,
! e quindi accetto questo valore che poi deve essere scritto nel file. A questo punto si passa
! al successivo valore dell'indice i e si ripete la procedura. Alla fine devo avere un file di 50 elementi.
end program Main_Planar_Lyapunov_orbits
有没有办法避免使用我上面描述的“辅助”变量 (vec_J_cst
)?
错误:
error #6410: This name has not been declared as an array or a function. [J_CST]
error #6158: The structure-name is invalid or is missing. [LY_DATA_SE_L1]
error #6158: The structure-name is invalid or is missing. [LY_DATA_SE_L1]
线路问题
first_J_cst_vec = Ly_data_SE_L1(:)%J_cst (lbound(Ly_data_SE_L1(:)%J_cst))
last_J_cst_vec = Ly_data_SE_L1(:)%J_cst (ubound(Ly_data_SE_L1(:)%J_cst))
是J_cst
是标量成员变量,所以不能索引
我假设您的逻辑是 Ly_data_SE_L1(:)%J_cst
是一个数组,因此 Ly_data_SE_L1(:)%J_cst(i)
将访问该数组的第 i
个元素,但这是错误的语法。相反,您需要 Ly_data_SE_L1(i)%J_cst
,即访问第 i
个元素的 J_cst
,而不是 J_cst
数组的第 i
个元素。
因此,这些行应为
first_J_cst_vec = Ly_data_SE_L1(lbound(Ly_data_SE_L1(:)%J_cst))%J_cst
last_J_cst_vec = Ly_data_SE_L1(ubound(Ly_data_SE_L1(:)%J_cst))%J_cst
请注意 Ly_data_SE_L1(:)%J_cst
与 Ly_data_SE_L1
具有相同的 lbound
和 ubound
,因此您可以将其简化为
first_J_cst_vec = Ly_data_SE_L1(lbound(Ly_data_SE_L1))%J_cst
last_J_cst_vec = Ly_data_SE_L1(ubound(Ly_data_SE_L1))%J_cst
在我的程序中,我定义了一个名为 Lyapunov_orbit
的数据类型,它包含 8 个字段,然后我用它从外部 .txt 文件中读取数据(见下文,为了方便,我只报告了几行,因为文件大约有 4000 行)。我需要通过使用这样的结构来执行一些操作(例如查找数组的最小值和最大值)但是为了处理它我必须声明一个名为 vec_J_cst
的“辅助”变量因为如果我尝试直接使用我的数据strucutre,我收到一些错误(结构名称无效或丢失)。
这是 .txt 文件:
-0.990036333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.337762568000000E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090089101800E+01
-0.990037333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.344404791697701E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090088741935E+01
-0.990038333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.351079970065519E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090088372775E+01
-0.990039333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.357762241991673E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090087996039E+01
-0.990040333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.364443669596976E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090087612278E+01
-0.990041333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.371123821002079E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090087221528E+01
-0.990042333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.377014880488160E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090086883260E+01
-0.990043333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.384445283931247E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090086421774E+01
-0.990044333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.390403586590581E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090086066251E+01
-0.990045333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.397792952615728E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090085591825E+01
-0.990046333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.403738458530992E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090085225121E+01
-0.990047333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.411139963724134E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090084733683E+01
-0.990048333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.417123805736171E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090084351603E+01
-0.990049333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.424484757953771E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090083847487E+01
-0.990050333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.430437019162321E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090083455851E+01
-0.990051333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.437812214383817E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090082934584E+01
-0.990052333227000E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.443804068227964E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090082527265E+01
-0.990053333227001E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.451146181152564E-03 0.000000000000000E+00 0.301148079918400E+01 0.300090081992963E+01
-0.990054333227001E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.457168852630379E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090081570545E+01
-0.990055333227001E+00 0.000000000000000E+00 0.000000000000000E+00 0.000000000000000E+00 0.463719562991478E-03 0.000000000000000E+00 0.302089167668145E+01 0.300090081093777E+01
这是模块:
module Array
use DataType
contains
!***********************************************************************
subroutine linspace(from, to, array)
!***********************************************************************
! Generates evenly spaced numbers from `from` to `to` (inclusive).
!
! Inputs:
! -------
!
! from, to : the lower and upper boundaries of the numbers to generate
!
! Outputs:
! -------
!
! array : Array of evenly spaced numbers
!***********************************************************************
implicit none
!Arguments
real(pr), intent(in) :: from, to
real(pr), intent(out) :: array(:)
real(pr) :: range
integer :: n, i
n = size(array)
range = to - from
if (n == 0) return
if (n == 1) then
array(1) = from
return
end if
do i=1, n
array(i) = from + range * (i - 1) / (n - 1)
end do
end subroutine
end module Array
!***************************************************************************
! Program name: Cheops ver 0
! Author: Elena Fantino, ETSEIAT - UPC
! Date: August 2015
!***************************************************************************
module DataType
implicit none
INTEGER, PARAMETER :: pr = SELECTED_REAL_KIND (p = 15)
!"Lyapunov_orbit" data type declaration
type Lyapunov_orbit
real(pr) :: a
real(pr) :: b
real(pr) :: c
real(pr) :: d
real(pr) :: e
real(pr) :: f
real(pr) :: g
real(pr) :: J_cst
end type Lyapunov_orbit
end module DataType
这是我的主程序:
program Main_Planar_Lyapunov_orbits
use DataType
use Array
implicit none
! Declarations
character*100 :: input_path,input_filename, output_path, output_filename,line
character*30, dimension(1) :: str_output !questo mi servira per le intestazioni nel file di output
integer :: i,j, iu_in,iu_out,n_lines, iflag, pos_err_min
type(Lyapunov_orbit), dimension (:), allocatable :: Ly_data_SE_L1
real(pr), dimension(:), allocatable :: vec_J_cst, err
real(pr), dimension(1) :: first_J_cst_vec, last_J_cst_vec, Delta_J, step, accepted_value
real(pr), dimension(50) :: array_Ly_orb
! Definition of constants, paths names and file names
iu_in = 10
iu_out = 11
input_path = 'D:\OneDrive\MSc_Thesis\Projects\Planar_Lyapunov_orbits\InputFiles\'
input_filename = 'Planar_Lyapunov_SE_L1_Buono.txt'
output_path = 'D:\OneDrive\MSc_Thesis\Projects\Planar_Lyapunov_orbits\OutputFiles\'
output_filename = 'Planar_Lyapunov_SE_L1_evenly_spaced.txt'
! Reading of Lyapunov orbits data from input file
open(unit = iu_in, file = trim(input_path) // trim(input_filename), status='old', &
access = 'sequential',form = 'formatted', action='read')
! Count lines
n_lines = 0
do
read(iu_in,*,iostat = iflag)
if (iflag/=0) exit
n_lines = n_lines + 1
enddo
rewind(iu_in)
! Variables allocation
allocate(Ly_data_SE_L1(n_lines))
! Data reading
do i = 1, n_lines
read(iu_in,*) Ly_data_SE_L1(i)
enddo
close(unit = iu_in, status='keep')
! Creation of Jacobi constant evenly spaced 1-D array of 50 elements,
! the first one and the last are the corresponding ones of input data
! Extraction of the first and last element by using auxiliary variable
!allocate(vec_J_cst(n_lines))
!do i = 1,n_lines
! vec_J_cst(i) = Ly_data_SE_L1(i)%J_cst
! first_J_cst_vec = vec_J_cst (lbound(vec_J_cst)) ! max
! last_J_cst_vec = vec_J_cst (ubound(vec_J_cst)) ! min
!enddo
!! ATTEMPT TO AVOID another variable usage (IT DOES NOT WORK!)
first_J_cst_vec = Ly_data_SE_L1(:)%J_cst (lbound(Ly_data_SE_L1(:)%J_cst)) ! max
last_J_cst_vec = Ly_data_SE_L1(:)%J_cst (ubound(Ly_data_SE_L1(:)%J_cst)) ! min
! Evenly spaced array: the 1st element is the greater value of jacobi constant:
! the size of the array has to be specified in the declarations
call linspace(from = first_J_cst_vec(1), to = last_J_cst_vec(1), array = array_Ly_orb)
allocate(err(n_lines))
! Filter the original input file and write data on new file of 50 Lyapunov orbits based on input data
open(unit = iu_out, file = trim(output_path) // trim(output_filename), status = 'unknown', action ='write')
! Compare the original Jacobi constants array(Ly_data_SE_L1%J_cst) with the created evenly spaced array(array_Ly_orb)
! Header line
write(iu_out,'(2a15)') 'unknown','Jacobi constant'
! Nested cycles
do i = 1,50
do j = 1, n_lines
! Compute the error between the i-th element of evenly spaced array and the current element of original jacobi constants array
err(j) = abs( vec_J_cst(j) - array_Ly_orb(i) )
enddo
! Find the location of the absolute minimum of the Err array
pos_err_min = minloc(err, dim =1)
write(iu_out,'(2e25.15)') Ly_data_SE_L1(pos_err_min)%a, vec_J_cst(pos_err_min)
enddo
close(unit = iu_out,status='keep')
!Idea di algoritmo per la parte di confronto e scrittura
! Abbiamo due array, il primo è quello originale con circa 4000 element e il secondo è quello creato con 50 elementi. Per prima cosa faccio un
! ciclo sul secondo array (indice i), poi ciclo sul primo array e calcolo l'errore fra il valore corrente j e quello fissato i, tale errore
! sarà un vettore di circa 4000 elem. Uso la funzione predefinita minloc per localizzre la posizione del minimo assoluo del vettore di errore,
! e quindi accetto questo valore che poi deve essere scritto nel file. A questo punto si passa
! al successivo valore dell'indice i e si ripete la procedura. Alla fine devo avere un file di 50 elementi.
end program Main_Planar_Lyapunov_orbits
有没有办法避免使用我上面描述的“辅助”变量 (vec_J_cst
)?
错误:
error #6410: This name has not been declared as an array or a function. [J_CST]
error #6158: The structure-name is invalid or is missing. [LY_DATA_SE_L1]
error #6158: The structure-name is invalid or is missing. [LY_DATA_SE_L1]
线路问题
first_J_cst_vec = Ly_data_SE_L1(:)%J_cst (lbound(Ly_data_SE_L1(:)%J_cst))
last_J_cst_vec = Ly_data_SE_L1(:)%J_cst (ubound(Ly_data_SE_L1(:)%J_cst))
是J_cst
是标量成员变量,所以不能索引
我假设您的逻辑是 Ly_data_SE_L1(:)%J_cst
是一个数组,因此 Ly_data_SE_L1(:)%J_cst(i)
将访问该数组的第 i
个元素,但这是错误的语法。相反,您需要 Ly_data_SE_L1(i)%J_cst
,即访问第 i
个元素的 J_cst
,而不是 J_cst
数组的第 i
个元素。
因此,这些行应为
first_J_cst_vec = Ly_data_SE_L1(lbound(Ly_data_SE_L1(:)%J_cst))%J_cst
last_J_cst_vec = Ly_data_SE_L1(ubound(Ly_data_SE_L1(:)%J_cst))%J_cst
请注意 Ly_data_SE_L1(:)%J_cst
与 Ly_data_SE_L1
具有相同的 lbound
和 ubound
,因此您可以将其简化为
first_J_cst_vec = Ly_data_SE_L1(lbound(Ly_data_SE_L1))%J_cst
last_J_cst_vec = Ly_data_SE_L1(ubound(Ly_data_SE_L1))%J_cst