2013-02-09 69 views
0

我有一個派生類型的指針的第二派生類型的Fortran 90/95指針在派生類型

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總是錯誤的價值觀結束。什麼可能導致這個?

回答

0

我想出了問題所在。 ipch_desc對象被構造爲一個temp,然後被分配給一個數組中的元素。

ipch_desc_arr(icount_chords) = ipch_desc_temp 

我要麼需要刪除該臨時或在加載默認的賦值操作符來解決它。

+0

如果你寫你自己的答案,你也應該接受它。 – 2013-02-11 11:18:14

1

您的代碼似乎正確。你可以簡化一下。爲什麼派生類型PATH包含單個變量?您可以直接調整VERTEX類型的數組的大小,而不使用這種附加類型。另外,我沒有理由使用指針;可分配的就足夠了。 Fortran 2003提供了MOVE_ALLOC,它也提供了簡化(如果這在您使用的編譯器中可用)(請參閱Insert a value changing shape in allocated vector 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