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:
Since
new_triangle_poolisALLOCATABLE, 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, andCpointers on each element ofnew_triangle_poolwill become associated with the same target as theA,B, andCpointers on the corresponding element ofthis%triangles. If the pointers on an element ofthis%trianglesbecome associated with a different target or nullified, the pointers onnew_triangle_poolwill remain associated with the original target.The only way you would run into an issue is if the pointers on
this%triangleswere to be deallocated instead of nullified. At that point, the memory would no longer be allocated, and you would be left with dangling pointers onnew_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_pooland then copy the values fromthis%trianglesinto 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).