【问题标题】:Fortran 90/95 Pointers in Derived Type派生类型的 Fortran 90/95 指针
【发布时间】:2013-02-09 20:55:40
【问题描述】:

我有一个派生类型,它带有指向第二个派生类型数组的指针

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 个总是以错误的值结束。这可能是什么原因造成的?

【问题讨论】:

    标签: pointers fortran derived-types


    【解决方案1】:

    您的代码似乎正确。你可以稍微简化一下。为什么派生类型 PATH 包含单个变量?您可以直接调整类型为 VERTEX 的数组的大小,而无需此附加类型。另外,我认为没有理由使用指针。 allocatable 看起来就足够了。 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
    

    【讨论】:

      【解决方案2】:

      我发现问题出在哪里。 ipch_desc 对象被构造为一个临时对象,然后分配给数组中的一个元素。

      ipch_desc_arr(icount_chords) = ipch_desc_temp
      

      我要么需要删除这个临时的,要么重载默认的赋值运算符来修复它。

      【讨论】:

      • 如果你自己写答案,你也应该接受它。
      猜你喜欢
      • 2013-09-20
      • 1970-01-01
      • 1970-01-01
      • 2013-05-07
      • 2023-03-26
      • 1970-01-01
      • 2015-04-17
      • 2014-02-06
      • 1970-01-01
      相关资源
      最近更新 更多