在 Fortran 中多次循环后访问派生数据类型

Posted

技术标签:

【中文标题】在 Fortran 中多次循环后访问派生数据类型【英文标题】:Accessing derived data types after several loops in Fortran 【发布时间】:2018-07-08 14:21:15 【问题描述】:

我有以下代码:

program testdatatype

integer(8), parameter :: Stot= 2 
integer(8), dimension(Stot) :: Nf
integer(8) :: f, s, Qind
integer(8), dimension(:, :), allocatable :: NqG
real(16), dimension(:, :, :), allocatable :: d3xnormfac

type NqGtype
    integer(8), dimension(:, :), allocatable :: NqGvalT
end type NqGtype
type(NqGtype), dimension(Stot) :: NqGT

type d3xnormfactype
    real(16), dimension(:, :, :), allocatable :: d3xnormfacvalT
end type d3xnormfactype
type(d3xnormfactype), dimension(Stot) :: d3xnormfacT

! ----------------------------------------------------

! LOOP 1.1:

do s= 1, Stot, 1

    Nf(s)= 2d0

    write(*, *) 'NfLoop1.1= ', Nf(s)

end do

! LOOP 1.2:

do s= 1, Stot, 1

    write(*, *) 'NfLoop1.2= ', Nf(s)

end do

! ----------------------------------------------------

! LOOP 2.1:

do s= 1, Stot, 1

    allocate(NqG(Nf(s), Stot))

    do f= 1, Nf(s), 1

        NqG(f, s)= 5d0
        NqGT(s)%NqGvalT= NqG

        write(*, *) 'NqGLoop2.1= ', NqG(f, s)
        write(*, *) 'NqGTLoop2.1= ', NqGT(s)%NqGvalT(f, s)

    end do

    deallocate(NqG)

end do

! LOOP 2.2:

do s= 1, Stot, 1    
    do f= 1, Nf(s), 1

        write(*, *) 'NqGTLoop2.2= ', NqGT(s)%NqGvalT(f, s)

    end do
end do

! ----------------------------------------------------

! LOOP 3.1:

do s= 1, Stot, 1                    
    do f= 1, Nf(s), 1   

        allocate(d3xnormfac(Nf(s), Stot, NqGT(s)%NqGvalT(f, s)))

        do Qind= 1, NqGT(s)%NqGvalT(f, s)

            d3xnormfac(f, s, Qind)= 153d12
            d3xnormfacT(s)%d3xnormfacvalT= d3xnormfac

            write(*, *) 'd3xnormfacLoop3.1= ', d3xnormfac(f, s, Qind)
            write(*, *) 'd3xnormfacTLoop3.1= ', d3xnormfacT(s)%d3xnormfacvalT(f, s, Qind)

        end do  

        deallocate(d3xnormfac)

    end do
end do

! LOOP 3.2:

do s= 1, Stot, 1                    
    do f= 1, Nf(s), 1                       
        do Qind= 1, NqGT(s)%NqGvalT(f, s)

            write(*, *) 'd3xnormfacTLoop3.2= ', d3xnormfacT(s)%d3xnormfacvalT(f, s, Qind)

        end do
    end do
end do

! ----------------------------------------------------

end program testdatatype

我在 mpif90 编译器上编译这个 .f90 文件。正如您在运行此代码时所看到的,很明显循环 1.1 中的 write 语句给出的结果与循环 1.2 中的相同,也就是说,Nf(:) 的值对于循环 1.1 之外的所有 s 值都是正确的。 Loop 2.1 和 Loop 2.2 也是如此(这次创建了派生数据类型)。循环 1 的输出如下:

 NfLoop1.1=                     2
 NfLoop1.1=                     2
 NfLoop1.2=                     2
 NfLoop1.2=                     2

对于创建它的循环(循环 2.1)之外的任何 f 和 s 值(在循环 2.2 中),我可以调用数据类型 NqGT(s)%NqGT(f, s) 的任何正确值。到目前为止没有问题。当我使用 Loop 2 运行 Loop 1 变量时,会给出以下输出:

 NfLoop1.1=                     2
 NfLoop1.1=                     2
 NfLoop1.2=                     2
 NfLoop1.2=                     2
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGTLoop2.2=                     5
 NqGTLoop2.2=                     5
 NqGTLoop2.2=                     5
 NqGTLoop2.2=                     5

此外,当将循环 1 变量运行到循环 2 派生数据类型中时,这些数据类型又与循环 3 一起使用,给出以下输出:

 NfLoop1.1=                     2
 NfLoop1.1=                     2
 NfLoop1.2=                     2
 NfLoop1.2=                     2
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGLoop2.1=                     5
 NqGTLoop2.1=                     5
 NqGTLoop2.2=                     5
 NqGTLoop2.2=                     5
 NqGTLoop2.2=                     5
 NqGTLoop2.2=                     5
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.1=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=   -1.83360386755485123703987599430319601E-2466
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    0.00000000000000000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000      
 d3xnormfacTLoop3.2=    153000000000000.000000000000000000000

但是,当我尝试对循环 3.1 执行相同操作时,我无法再获得派生数据类型 d3xnormfacT(s)%d3xnormfacvalT(f, s, Qind) 的所有正确值,也就是说,循环 3.2 中打印的数据类型不等于这些值在循环 3.1 中打印相同的数据类型(某些值是正确的,但其他值不是)。我怎样才能解决这个问题?我一定遗漏了一些东西(指针和/或派生数据类型的分配?)

【问题讨论】:

请贴出你运行代码得到的输出,以及你使用的编译命令。 对我来说,NqGT(1)%NqGvalT 没有分配,所以即使是循环 2.1 也会出现代码错误 代码需要 Fortran 2003 编译器。它似乎对我有用。您使用的是哪个编译器以及哪些编译器选项? 欢迎您,请务必使用tour 并阅读How to Ask。尝试始终提供基本信息,例如您正在使用的编译器、其版本、使用的编译器标志以及包含所有错误消息的输出。 我已经编辑了文本以包含输出。在命令行我有 之后我将可执行文件称为 任何想法为什么这些数字在从三个循环的派生数据类型中分配后不能转换?跨度> 【参考方案1】:

在循环 3.1 中,您只设置了 d3xnormfac 的特定索引,然后将整个 d3xnormfac 数组分配给 d3xnormfacT(s)%d3xnormfacvalT。因为d3xnormfac 被解除分配,然后多次分配,所以不能保证之前分配的值仍然被设置。

由于您的特定循环顺序,d3xnormfac(:,1,:) 中的值未初始化。根据编译器是否将d3xnormfac 重新分配到同一位置以及内存是否已清理,这些值最终可能是正确的。对于我的英特尔(使用-assume realloc-lhs 允许自动分配),大多数值都是正确的。如您所见,对于我的 gfortran,大多数值都不正确。行为可能也取决于真实的类型,这也解释了您的观察。

了解这一点的一个好方法是在分配后初始化每个值。修改代码以在循环 3.1 中添加:

        allocate(d3xnormfac(Nf(s), Stot, NqGT(s)%NqGvalT(f, s)))
        d3xnormfac = -1234     ! -- Added this line

        do Qind= 1, NqGT(s)%NqGvalT(f, s)

产生以下结果:

mach5% ifort -assume realloc_lhs -check all -warn all -traceback -g main.f90 && ./a.out 
 NfIN=                      2
 NfIN=                      2
 NfOUT=                      2
 NfOUT=                      2
 NqGIN=                     15
 NqGTIN=                     15
 NqGIN=                     15
 NqGTIN=                     15
 NqGIN=                     15
 NqGTIN=                     15
 NqGIN=                     15
 NqGTIN=                     15
 NqGTOUT=                     15
 NqGTOUT=                     15
 NqGTOUT=                     15
 NqGTOUT=                     15
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacIN=    153000000000000.000000000000000000      
 d3xnormfacTIN=    153000000000000.000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=   -1234.00000000000000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000      
 d3xnormfacTOUT=    153000000000000.000000000000000000

您可以看到仍然设置为 -1234 的部分。

澄清后

我现在看到这个问题来自对可分配数组如何属于派生类型的误解。 d3xnormfacT(s)%d3xnormfacvalT 是它自己的可分配数组。它是等级 3 并且(直到分配)是未分配的。它(通常)使用常规分配语句分配,例如:

allocate(d3xnormfacT(s)%d3xnormfacvalT((Nf(s), Stot, NqGT(s)%NqGvalT(f, s)))

没有这样做。您正在通过(无意中)使用 fortran 的高级功能绕过传统分配:自动左侧 (lhs) 分配。当一个数组被分配一个与其形状匹配的值时,该数组被分配或重新分配以匹配。更多信息在这里:Automatic array allocation upon assignment in Fortran

您的陈述:

        d3xnormfacT(s)%d3xnormfacvalT= d3xnormfac

实际上是同时做两件事。首先,d3xnormfacT(s)%d3xnormfacvalT分配以匹配d3xnormfac 的大小,因为d3xnormfacT(s)%d3xnormfacvalT 匹配d3xnormfac 的形状(3 维)。其次,新分配的d3xnormfacT(s)%d3xnormfacvalT分配d3xnormfac 相同的值。 (没有人指向其他任何东西。)

您应该更改代码以不使用此自动 lhs 分配。 2003 标准允许这种自动 lhs 分配,但某些编译器(英特尔直到 2017 年)故意默认不支持它。我个人认为这是危险且不直观的,所以我通常会避免它。对于不了解它的开发人员来说,此功能可能是一个“陷阱”。防止这种情况发生的 gfortran(我猜你正在使用,你只指定 mpif90 这只是一个包装器)标志是 -fno-realloc-lhs

更改代码后,您将更好地理解我的其余答案,这就是您看到问题的真正原因。

编辑:正如@eriktous 指出的那样,循环 2 中存在同样的问题,但循环顺序意味着没有未初始化的值被放入输出中。我真的不明白为什么s 索引both 派生数据类型和数组的最外层维度。也许是因为这只是一个玩具箱。如果您要扩展此代码,请务必解决这两个问题。

【讨论】:

顺便说一句,循环 2.1 中也存在同样的问题。 好点。但是,它不会显示为输出中的任何初始化值,因为NqGvalT 只是一个二维数组。 @eriktous 编辑了这个效果 分配 NqGT(s)%NqGvalT 和 d3xnormfacT(s)%d3xnormfacvalT 的 lhs 分配到底是什么意思?我正在使用以下语句在循环中分配数组: allocate(d3xnormfac(Nf(s), Stot, NqGT(s)%NqGvalT(f, s))) 我应该如何编写这部分或数据类型的声明提前? 对...这正是我问原始问题的原因,但您当时没有回答。 d3xnormfacT(s)% d3xnormfacvalTd3xnormfac完全不同的东西。它们在内存中占据不同的空间,不会一起分配。我将更新答案,以便为初学者提供更好的概述。【参考方案2】:

在分配后添加行d3xnormfac= 1234 @Ross 暗示似乎可以确保初始化。当 Loop 2 更改为以下内容时:

! LOOP 2.1:

do s= 1, Stot, 1
    allocate(NqGT(1)%NqGvalT(Nf(s), Stot))
    allocate(NqG(Nf(s), Stot))

    do f= 1, Nf(s), 1
        NqG(f, s)= 5d0
        write(*, *) 'NqGLoop2.1= ', NqG(f, s)

        NqGT(1)%NqGvalT= NqG(:, :)      
        write(*, *) 'NqGTLoop2.1= ', NqGT(1)%NqGvalT(f, s)

    end do

    deallocate(NqG)
    deallocate(NqGT(1)%NqGvalT)
end do

! LOOP 2.2:

write(*, *) 'NqGTLoop2.2= ', NqGT(1)%NqGvalT(:, :)

直接分配派生数据类型数组时,解除分配数组时会出现以下错误:

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x103880e46
#1  0x10388060c
#2  0x7fff59ff8f59
#3  0x1039095d5
#4  0x10390975e
#5  0x10390d0dd
#6  0x10367fbef
#7  0x10367fc9e
Segmentation fault: 11 

因此,lhs 自动分配派生数据类型是最初没有给出此错误的原因。当只分配d3xnormfac 并让d3xnormfacT(s)%d3xnormfacvalT 自动分配时,可以在3 次循环之后访问正确的数组值而不会出错,因为派生数据类型数组不会在内部循环中释放。只要派生的数据类型数组具有恒定的维度,我怀疑以后应该不是问题。至于数组值的完整初始化,@Ross 的解决方案似乎有效。如果谨慎使用,这种情况下 lhs 自动分配可以工作。

【讨论】:

以上是关于在 Fortran 中多次循环后访问派生数据类型的主要内容,如果未能解决你的问题,请参考以下文章

派生数据类型中的 Fortran、参数和静态表

在 fortran 中命名派生类型的良好做法

确定内存中的 Fortran 派生类型大小

GDB 可以用于在 Fortran 90 中打印派生类型的可分配数组的值吗? [复制]

Fortran 派生类型

在 Fortran 90 中使用二维数组与派生类型数组