如何初始化派生类型变量?
PS。我是一位老 F77 程序员,对使用 C# 的 OOP 有相当的了解,但对 Fortran 中的“派生类型”不熟悉。一名硕士生写了一大段代码就离开了。当使用 Intel 11(我不能再使用)编译时它可以工作,但使用 Intel 19(我可以在更大的项目中使用)时会抛出错误。我正在努力让它复活。 这是我在尝试理解学生代码时遇到的问题的 MWE。使用 Intel 11 不是一个选择。
program DerivedType
! investigate lines of code from large code "fabrics" that I do not understand
use strength_mod_test
! define and initialize array X
double precision, dimension(6) :: X = (/1,2,3,4,5,6/) ! just data, not PARAMETER. Values can be modified in the code.
! type (object) definition
type One
double precision :: small(6) ! the data in this type
! pointer :: Ff(:,:) ! Pointer is not permitted as a statement within a derived-type-def.
end type One
type TxT
double precision :: small(3,3) ! so that any var of type "type" has the correct size %small, depending of the "type"
end type Txt
! Why the constructor is not inside the type definition.
! Because "pointer" is not permitted inside a type def.
! You have to write the constructor outside the type def.
! Variables must be defined before any executable code.
! Define variables of type "type" using a constructor.
! Cannot be defined inside the type if "pointer" is used.
! "Type" constructor outside the type def. Note the ()
type(One), pointer :: Ff(:,:), Fw(:,:), sigmaf123(:,:), sigmaw123(:,:)
type(TxT), pointer :: Df(:,:), Dw(:,:), Omega_f(:,:), Omega_w(:,:)
! local variables
integer i,j
! Initialize type variables
! Df is of type TxT, and in type TxT, small is (3,3)
! Df%small = 0 ! A component cannot be an array if the encompassing structure is an array.[SMALL]
! so I do this
do i=1,3
do j=1,3
Df(i,j)%small = 0.d0 ! why access violation?!
enddo
end do
! TYPE (TxT) :: Df_new = TxT (Df = 0) does not work either
! I can't execute next statement until I initialize Df(i,j)%small and signf123(i,j)%small
Ff(i,j)%small = F_function (X, Df(i,j)%small, sigmaf123(i,j)%small)
end program
下面是模块strength_mod_test:
module strength_mod_test
contains
function F_function (R, D, sig)
double precision, dimension(6) :: F_function ! rank=1
double precision, dimension(6), intent(in) :: R, sig ! rank=1
double precision, dimension(3,3), intent(in) :: D ! rank=2
F_function = 0.d0
if (D(1,1) == 0.d0 .AND. sig(1) > 0.d0) then
F_function(1) = sig(1)/R(1)
end if
if (D(2,2) == 0.d0 .AND. sig(2) > 0.d0) then
F_function(2) = sig(2)/R(2)
end if
if (D(3,3) == 0.d0 .AND. sig(3) > 0.d0) then
F_function(3) = sig(3)/R(3)
end if
if (D(2,2) == 0.d0 .OR. D(3,3) == 0.d0) then
F_function(4) = abs(sig(4))/R(4)
end if
if (D(3,3) == 0.d0) then
F_function(5) = abs(sig(5))/R(5)
end if
if (D(2,2) == 0.d0) then
F_function(6) = abs(sig(6))/R(6)
end if
end function F_function
end module
感谢评论,很明显我忘记了分配指针,也忘记了正确初始化类型变量。下面的代码部分解决了所有这些问题。
! local variables
integer i,j
double precision, dimension(3,3) :: D_in=0.d0 ! used to initialize variables of type TxT, bec. the're 3x3
! define and initialize array X
double precision, dimension(6) :: X = (/1,2,3,4,5,6/) ! just data, not PARAMETER. Values can be modified in the code.
integer sv ! to check if allocation/deallocation was successful
! Allocate and initialize type variables
allocate(Ff(nf, nw),STAT=sv); if (sv /= 0) then; pause "sv/=0"; endif
allocate(Df(nf, nw),STAT=sv); if (sv /= 0) then; pause "sv/=0"; endif
allocate(sigmaf123(nf, nw),STAT=sv); if (sv /= 0) then; pause "sv/=0"; endif
! Df%small = 0 ! A component cannot be an array if the encompassing structure is an array.[SMALL]
! Solution: Df is of type TxT, & in type TxT, small is (3,3)
! Thus, each i,j element in Df must be initialized with a 3x3 matrix.
do i=1,3 ! nf
do j=1,3 ! nw
Df(i,j)%small = D_in ! 3x3 matrix of 3x3 matrices.
enddo
end do
do i=1,3 ! nf
do j=1,3 ! nw
Ff(i,j)%small = F_function (X, Df(i,j)%small, sigmaf123(i,j)%small)
enddo
enddo