[英]Fortran 90/95 Pointers in Derived Type
I have a derived type with a pointer to an array of a second derived type 我有一个派生类型,它有一个指向第二个派生类型的数组的指针
TYPE vertex
REAL :: x, y, z
END TYPE
TYPE path
TYPE(vertex), DIMENSION(:), POINTER :: vertices => NULL()
END TYPE
The intent is to make the vertices array resizable so that any number of vertex points can be added to the array. 目的是使顶点数组可调整大小,以便可以将任意数量的顶点添加到数组中。 I have created code to append a vertex to that pointer.
我已经创建了将顶点附加到该指针的代码。
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
I create a few path objects. 我创建一些路径对象。
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
Everything work all well and good and I get the correct values for each vertex. 一切都很好,我为每个顶点获取正确的值。 For instance for three path objects created I get
例如,对于创建的三个路径对象,我得到
-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
When using these path objects latter in the code, 在代码后面使用这些路径对象时,
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
only the first N-1 values remain correct. 只有前N-1个值保持正确。 For the same values created above I get,
对于上面创建的相同值,我得到,
-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
Regardless of the number of path
objects I create, the Nth always ends up with wrong values. 不管我创建的
path
对象有多少,第N个总是以错误的值结尾。 What could be causing this? 是什么原因造成的?
Your code seems correct. 您的代码似乎正确。 You could simplify it a bit.
您可以简化一下。 Why have a derived type PATH to contain a single variable?
为什么派生类型PATH包含单个变量? You could directly resize an array of type VERTEX without this additional type.
您可以直接调整VERTEX类型的数组的大小,而无需使用此附加类型。 Also, I see no reason to use a pointer;
另外,我认为没有理由使用指针。 allocatable would see to be sufficient.
可以分配就足够了。 Fortran 2003 provide MOVE_ALLOC, which would also provide a simplification (if this is available in the compiler that you are using) (see Insert a value changing shape in allocated vector fortran ).
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
I figured out where the problem was. 我弄清楚问题出在哪里。 The
ipch_desc
object was being constructed to a temp then assigned to an element in an array. 将
ipch_desc
对象构造为临时对象,然后将其分配给数组中的元素。
ipch_desc_arr(icount_chords) = ipch_desc_temp
I will either need to remove this temporary or over load the default assignment operators to fix it. 我将需要删除此临时文件,或者需要重载默认的赋值运算符来修复它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.