- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello all,
We have a problem with existing code that no longer compiles with a "new" version of the oneAPI Fortran. On our cluster, the upgrades are slow so what I mean by "old" is : ifort version 2021.3.0, and "newer" is ifort version 2021.9.0. But I guess that the latest versions show the same behaviour since they are now compliant with the Fortran standards.
Here is a simplified sample of our code :
module measurements_management
! Measurements types
!-------------------
type :: generic_measurement
end type generic_measurement
type, extends(generic_measurement) :: measurement_as_reals
real :: real_measurement
end type measurement_as_reals
type, extends(generic_measurement) :: measurement_as_integers
integer :: int_measurement
end type measurement_as_integers
! Generic management of measurement arrays
! ----------------------------------------
type measurements_buffer
integer :: nb_used = 0
class(generic_measurement), allocatable, dimension(:) :: tab_measurements
contains
procedure :: init => buffer_init
procedure :: realloc => buffer_realloc
end type measurements_buffer
contains
! create a buffer containing an array with a selected measurement type
! the measurement array has an initial dimension of 50 elements
subroutine buffer_init(this, measurement)
class(measurements_buffer), intent(inout) :: this
class(generic_measurement) :: measurement
allocate(this%tab_measurements(50), mold=measurement)
end subroutine buffer_init
! for an existing buffer created for a specific measurement type,
! reallocate the measurements array, adding 100 empty elements and
! copying the existing elements
subroutine buffer_realloc(this)
class(measurements_buffer), intent(inout) :: this
!.. Local variables ..
integer :: current_size
class(generic_measurement), allocatable, dimension(:) :: tab_tmp
current_size = size(this%tab_measurements)
write(*,*) 'current size=', current_size
allocate(tab_tmp(current_size+100), source=this%tab_measurements(1))
write(*,*) 'tab_tmp size after alloc = ',size(tab_tmp)
tab_tmp(1:current_size) = this%tab_measurements(1:current_size)
write(*,*) 'tab_tmp size after copy = ',size(tab_tmp)
call move_alloc(tab_tmp, this%tab_measurements)
end subroutine buffer_realloc
end module measurements_management
! example with a buffer of integer measurements
program polymorphic_realloc
use measurements_management
implicit none
type(measurements_buffer) :: buffer_of_integer_measurements
type(measurement_as_integers) :: measurement_int
call buffer_of_integer_measurements%init(measurement_int)
call buffer_of_integer_measurements%realloc()
end program polymorphic_realloc
We have a generic buffer that on initialization is set to contain an array of a specific measurement type. In this oversimplified sample, there are two measurement types (integer and real). In our software, there are 26 different types.
The problem occurs at line 55. It used to compile and works very well with the old compiler :
current size= 50
tab_tmp size after alloc = 150
tab_size after copy = 150
With the new compiler, we get the well-known :
error #8304: In an intrinsic assignment statement, variable shall not be a non-allocatable polymorphic.
Just to check, I have changed line 55 to :
tab_tmp = this%tab_measurements
OK, it compiles fine with both compilers but I get :
current size= 50
tab_tmp size after alloc = 150
tab_tmp size after copy = 50
So the reallocation is lost.
Is it possible to adapt the code and keep the generic handling of the buffer reallocation ?
Or do we have to change realloc() to an abstract subroutine and implement a dedicated subroutine for our 26 measurement types ?
Thanks in advance,
Franck
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This seems to do what you want and isn't any less efficient than what you had.
current_size = size(this%tab_measurements)
write(*,*) 'current size=', current_size
!allocate(tab_tmp(current_size+100), source=this%tab_measurements(1))
!write(*,*) 'tab_tmp size after alloc = ',size(tab_tmp)
!tab_tmp(1:current_size) = this%tab_measurements(1:current_size)
tab_tmp = reshape(this%tab_measurements,[current_size+100],this%tab_measurements)
write(*,*) 'tab_tmp size after copy = ',size(tab_tmp)
call move_alloc(tab_tmp, this%tab_measurements)
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This seems to do what you want and isn't any less efficient than what you had.
current_size = size(this%tab_measurements)
write(*,*) 'current size=', current_size
!allocate(tab_tmp(current_size+100), source=this%tab_measurements(1))
!write(*,*) 'tab_tmp size after alloc = ',size(tab_tmp)
!tab_tmp(1:current_size) = this%tab_measurements(1:current_size)
tab_tmp = reshape(this%tab_measurements,[current_size+100],this%tab_measurements)
write(*,*) 'tab_tmp size after copy = ',size(tab_tmp)
call move_alloc(tab_tmp, this%tab_measurements)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve ! That does the trick. You once more deserve your black belt.
Phew, I am really relieved.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page