簡體   English   中英

派生類型的Fortran 90/95指針

[英]Fortran 90/95 Pointers in Derived Type

我有一個派生類型,它有一個指向第二個派生類型的數組的指針

TYPE vertex
   REAL :: x, y, z
END TYPE

TYPE path
   TYPE(vertex), DIMENSION(:), POINTER :: vertices => NULL()
END TYPE

目的是使頂點數組可調整大小,以便可以將任意數量的頂點添加到數組中。 我已經創建了將頂點附加到該指針的代碼。

SUBROUTINE path_append_vertex(this, x, y, z)
IMPLICIT NONE

!-------------------------------------------------------------------------------
!  Variable declarations.
!-------------------------------------------------------------------------------
TYPE(path), INTENT(inout) :: this
REAL, INTENT(in)   :: x, y, z

!-------------------------------------------------------------------------------
!  Local Variable declarations.
!-------------------------------------------------------------------------------
INTEGER :: status
TYPE(vertex), DIMENSION(:), ALLOCATABLE :: vertices

!-------------------------------------------------------------------------------
!  Start of executable code
!-------------------------------------------------------------------------------
IF (ASSOCIATED(this%vertices)) THEN
! Create a temporary array the same size as current number of vertices. Copy the
! contents of the old array to the new array then delete the old array.
   ALLOCATE(vertices(SIZE(this%vertices)), STAT = status)
   CALL check_status(status)
   vertices = this%vertices
   DEALLOCATE(this%vertices)

! Create a new array with one extra element. Copy the contents of the temporary
! array to the new one the delete the temporary array.
   ALLOCATE(this%vertices(SIZE(vertices) + 1), STAT = status)
   CALL check_status(status)
   this%vertices(1:SIZE(vertices)) = vertices
   DEALLOCATE(vertices)

   this%vertices(SIZE(this%vertices))%x = x
   this%vertices(SIZE(this%vertices))%y = y
   this%vertices(SIZE(this%vertices))%z = z
ELSE
   ALLOCATE(this%vertices(1), STAT = status)
   CALL check_status(status)

   this%vertices(1)%x = x
   this%vertices(1)%y = y
   this%vertices(1)%z = z
ENDIF

END SUBROUTINE

我創建一些路徑對象。

TYPE ipch_desc
   ...
   TYPE(path) :: chordPath
END TYPE

SUBROUTINE ipch_desc_construct(this, ...)
...
TYPE (ipch_desc), INTENT(inout)          :: this
...
!  Must NULL out the vertices array or else it will point to the last
!  integration_path created in memory. Not sure why these are defaulting
!  to NULL
this%chordPath%vertices => NULL()

CALL path_append_vertex(this%chordPath, xcart_i(1), xcart_i(2), xcart_i(3))
CALL path_append_vertex(this%chordPath, xcart_f(1), xcart_f(2), xcart_f(3))

!  Check the value of the path vertices.
write(*,*) this%chordPath%vertices

END SUBROUTINE

一切都很好,我為每個頂點獲取正確的值。 例如,對於創建的三個路徑對象,我得到

 -0.33808113528699218        1.0467574437103653       0.10713720000000000      -0.16057879084545851       0.49717960298733294       0.10713720000000000     
 -0.33322243268266594        1.0483142707971911       1.42240000000000010E-003 -0.14945358419461796       0.47017940500485894       1.42240000000000010E-003
 -0.33656460666251325        1.0472460386853264      -0.10629900000000000      -0.15821659220752302       0.49230280357365630      -0.10629900000000000

在代碼后面使用這些路徑對象時,

SUBROUTINE ipch_mc_model_compute(a_ipch, ...)
...
TYPE (ipch_desc), INTENT (inout)     :: a_ipch
...
!  Check the value of the path vertices again.
write(*,*) a_ipch%chordPath%vertices
...
END SUBROUTINE

只有前N-1個值保持正確。 對於上面創建的相同值,我得到,

 -0.33808113528699218        1.0467574437103653       0.10713720000000000      -0.16057879084545851       0.49717960298733294       0.10713720000000000     
 -0.33322243268266594        1.0483142707971911       1.42240000000000010E-003 -0.14945358419461796       0.47017940500485894       1.42240000000000010E-003
  0.15094203233057696       6.94277920927416864E-310 -0.10629900000000000       1.63041663127611360E-322  3.01884064661153912E-003  6.94277920927179713E-310

不管我創建的path對象有多少,第N個總是以錯誤的值結尾。 是什么原因造成的?

您的代碼似乎正確。 您可以簡化一下。 為什么派生類型PATH包含單個變量? 您可以直接調整VERTEX類型的數組的大小,而無需使用此附加類型。 另外,我認為沒有理由使用指針。 可以分配就足夠了。 Fortran 2003提供了MOVE_ALLOC,該方法也將提供簡化(如果正在使用的編譯器中提供此功能)(請參閱在分配的向量fortran中插入改變形狀的值 )。

module vertex_stuff

TYPE vertex
   REAL :: x, y, z
END TYPE

contains

SUBROUTINE path_append_vertex(this, x, y, z)
IMPLICIT NONE

!-------------------------------------------------------------------------------
!  Variable declarations.
!-------------------------------------------------------------------------------
TYPE(vertex), dimension (:), allocatable, INTENT(inout) :: this
REAL, INTENT(in)   :: x, y, z

!-------------------------------------------------------------------------------
!  Local Variable declarations.
!-------------------------------------------------------------------------------

TYPE(vertex), DIMENSION(:), ALLOCATABLE :: tmp_vertices

!-------------------------------------------------------------------------------
!  Start of executable code
!-------------------------------------------------------------------------------
IF (allocated(this)) THEN
! Create a temporary array the same size as current number of vertices. Copy the
! contents of the old array to the new array then delete the old array.
   ALLOCATE(tmp_vertices(SIZE(this)))
   tmp_vertices = this
   DEALLOCATE(this)

! Create a new array with one extra element. Copy the contents of the temporary
! array to the new one the delete the temporary array.
   ALLOCATE(this(SIZE(tmp_vertices) + 1))
   this(1:SIZE(tmp_vertices)) = tmp_vertices
   DEALLOCATE(tmp_vertices)

   this(SIZE(this))%x = x
   this(SIZE(this))%y = y
   this(SIZE(this))%z = z
ELSE
   ALLOCATE(this(1))

   this(1)%x = x
   this(1)%y = y
   this(1)%z = z
ENDIF

END SUBROUTINE


SUBROUTINE output_vertices (this)
IMPLICIT NONE

TYPE(vertex), dimension (:), INTENT(in) :: this
integer :: i

write (*, '(// "Current vertices:" )' )

do i=1, size(this)
   write (*, '( 3F5.2 )' ) this (i) % x, this (i) % y, this (i) % z
end do

end SUBROUTINE output_vertices

end module vertex_stuff


program vertices

use vertex_stuff

implicit none

TYPE (vertex), dimension (:), allocatable :: this

call path_append_vertex(this, 1.0, 1.1, 1.2)
call output_vertices (this)

call path_append_vertex(this, 2.0, 2.1, 2.2)
call output_vertices (this)

call path_append_vertex(this, 3.0, 3.1, 3.2)
call output_vertices (this)

call path_append_vertex(this, 4.0, 4.1, 4.2)
call output_vertices (this)

call path_append_vertex(this, 5.0, 5.1, 5.2)
call output_vertices (this)

end program vertices

我弄清楚問題出在哪里。 ipch_desc對象構造為臨時對象,然后將其分配給數組中的元素。

ipch_desc_arr(icount_chords) = ipch_desc_temp

我將需要刪除此臨時文件,或者需要重載默認的賦值運算符來修復它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM