I am trying to copy the target to a pointer in a derived type variable to another variable of the same type, but I have no idea how to do it
Say that I have a scattered list of points that I want to triangulate. I will have a
type :: triangulation
type(vertex), allocatable :: points(:)
type(triangle), allocatable :: triangles(:)
end type triangulation
To save memory, I am defining each triangle using pointers to the nodes:
type :: triangle
type(vertex), pointer :: A => null()
type(vertex), pointer :: B => null()
type(vertex), pointer :: C => null()
end type triangle
that will be in the same object. For example, to generate a new triangle in the triangulation, I will run:
type(triangle) function triangulation_new_triangle(this,iA,iB,iC) result(tri)
class(triangulation), intent(in), target :: this
integer, intent(in) :: iA, iB, iC ! Indices of the three nodes
tri%A => this%points(iA)
tri%B => this%points(iB)
tri%C => this%points(iC)
end function
Now, assume I have to reallocate the list of triangles. How do I copy it to a new list for the same triangulation, without losing their pointer references? I.e., I wanna do something like this:
subroutine triangulation_reallocate(this)
class(triangulation), intent(inout) :: this
! Local variables
integer, parameter :: TRIANGLE_CHUNK_SIZE = 1024
integer :: old_size
type(triangle), allocatable :: new_triangle_pool(:)
! Get old size
old_size = merge(size(this%triangles),0,allocated(this%triangles))
! Allocate new array of triangles
allocate(new_triangle_pool(old_size+TRIANGLE_CHUNK_SIZE))
! Copy data from old to new array
[..... missing code here .......]
! Move allocation back to the triangulation object
call move_alloc(from=new_triangle_pool,to=this%triangles)
end subroutine triangulation_reallocate
I am thinking of a way to copy the triangle associations. If I do something like:
do i=1,old_size
new_triangle_pool(i) = this%triangles(i)
end do
will that work? I am concerned that if I copy something like:
new_triangle_pool(i)%A => this%triangles(i)%A
then this is a pointer-to-a-pointer and not to the original vertex, and the association will be lost when the old this%triangles
variables is deallocated?
Your suggestion should work. However, a simpler suggestion:
new_triangle_pool = this%triangles
Since new_triangle_pool
is ALLOCATABLE
, the array should automatically be allocated to the size of the source of the assignment (this%triangles
), then be initialized via an element-wise copy from the source.
Pointer components of a derived type are copied as a shallow-copy by default. This means that no memory is duplicated, but rather the A
, B
, and C
pointers on each element of new_triangle_pool
will become associated with the same target as the A
, B
, and C
pointers on the corresponding element of this%triangles
. If the pointers on an element of this%triangles
become associated with a different target or nullified, the pointers on new_triangle_pool
will remain associated with the original target.
The only way you would run into an issue is if the pointers on this%triangles
were to be deallocated instead of nullified. At that point, the memory would no longer be allocated, and you would be left with dangling pointers on new_triangle_pool
. However, with some care you can avoid that problem.
If a deep copy is needed (i.e., allocate the pointers in new_triangle_pool
and then copy the values from this%triangles
into the new memory), then you must explicitly write code to do so. Otherwise, only a shallow copy will be done by default (which I believe is what you want).