I have two derived type polymorphic arrays (obj1 and obj2) in a subroutine. Based on the use of the subroutine, while the types of the two arrays may differ, both arrays are the same type; eg both type A or both type B. In the sample code below, I'm only showing one subtype of the abstract class (model), while in reality, I want this to work on multiple subtypes. Furthermore, in the production code, model1's elements have been modified before this copy.
program test
use env_kindtypes, only: si, dp
use abs_obj_model, only: model
use obj_linearDivisionModel, only: linearDivisionModel
implicit none
class(model),allocatable :: model1(:), model2(:)
allocate(linearDivisionModel::model1(10))
!want e.g. model2 = model1([1,4,6,2])
![...]
Given obj1, obj2 (type A) (given as model1, model2 of type linearDivisionMode in the example code) and a set of indices, I want to transfer the specified elements from obj1 to obj2, allocating obj2 in the process.
I have tried quite a few approaches to do so, but none seem to work.
First, I've tried direct assignment using a vector subscript; this fails, complaining that direct assignment of an allocatable polymorphic array is not yet supported.
indices = [ 1 , 2 ]
model2 = model1(indices)
result:
model2 = model1(indices)
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet supported
Second, I tried using sourced allocation. If I try this with array slice notation, it works (but my problem is not expressible solely with ranges like this). If I try to vector index the source array, it compiles, but upon runtime I get errors from running out of memory (this isn't realistic given the system).
allocate(model2,source=model1(indices))
runtime result:
Operating system error: Cannot allocate memory
Memory allocation failed
Error termination. Backtrace:
#0 0x434471 in __obj_lineardivisionmodel_MOD___copy_obj_lineardivisionmodel_Lineardivisionmode
at build/processed_src/obj_linear_model.f90:462
#1 0x436c75 in cg_charge_fit
at build/processed_src/test.f90:37
#2 0x403019 in main
at build/processed_src/test.f90:22
Works, but isn't sufficient for my purposes.
allocate(model2,source=model1(1:2))
Third, I've been able to allocate the polymorphic array in hopes of manually transferring subelements: However, when I try to do so, I get complaints of polymorphic objects and intrinsic assignment, which I come back to at later in this post.
indices = [ 1 , 2 ]
allocate(model2(size(indices)),source=model1(1))
do i=1,size(indices)
model2(i) = model1(indices(i))
enddo
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator.
I have tried using type select statements to remove the polymorphic context, but errors remain.
select type (POBJECT => model1)
TYPE IS (linearDivisionModel)
allocate(linearDivisionModel::model2(size(indices)))
do i=1,size(indices)
model2(i) = POBJECT(indices(i))
enddo
end select
results:
model2(i) = model1(indices(i))
1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator
As a work around, I hoped to use an intermediate pointer object, and to source allocation from that. Due to the f2008 standard (which is enforced here) I can't assign a pointer to a vector indexed array. Interestingly, if I create a pointer, vector index that pointer, the compiler segfaults, indicating that there make be something weird going on.
To address the compiler complaints about intrinsic assignment, I've considered writing assignment routines; however, this draws a new set of worries: the parent type both of these routines inherit from is abstract, and I cannot seem to specify a generic deferred assignment operator in that class, leading to a complex parent class which requires quite a few private methods to copy as it specifies no private variables. Furthermore, transformation between subclasses A and B is poorly defined. This still seems to be the only remaining way out, and seems complex.
How can I effectively transfer the specified polymorphic subrarrays?
I'm using gfortran version 6.1.1.