Copying subsets of polymorphic arrays into target polymorphic arrays - oop

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.

With complete F2008 support, this is simply an assignment statement.
Within the constraints of that compiler, you may need to consider nested SELECT TYPE constructs, that eliminate the polymorphic nature of the left and right hand sides of the assignment.
module my_types
implicit none
type, abstract :: model
end type
type, extends(model) :: linearDivisionModel
character :: comp
end type linearDivisionModel
end module my_types
program p
use my_types
implicit none
class(model),allocatable :: model1(:), model2(:)
integer, allocatable :: indicies(:)
! define model1.
block
type(linearDivisionModel), allocatable :: tmp(:)
allocate(tmp(10))
tmp%comp = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
call move_alloc(tmp, model1)
end block
indicies = [1, 2, 4, 6]
! allocate model2.
allocate(model2(size(indicies)), mold=model1)
! define model2
select type (model1)
type is (linearDivisionModel)
select type (model2)
type is (linearDivisionModel)
model2 = model1(indicies)
end select
end select
! display results.
select type (model2)
type is (linearDivisionModel)
print *, model2%comp
end select
end program p
The above appears to work with current gfortran trunk.

Related

Does fortran permit inline operations on the return value of a function?

I am trying to design a data structure composed of objects which contain, as instance variables, objects of another type.
I'd like to be able to do something like this:
CALL type1_object%get_nested_type2_object()%some_type2_method()
Notice I am trying to immediately use the getter, get_nested_type2_object() and then act on its return value to call a method in the returned type2 object.
As it stands, gfortran v4.8.2 does not accept this syntax and thinks get_nested_type2_object() is an array reference, not a function call. Is there any syntax that I can use to clarify this or does the standard not allow this?
To give a more concrete example, here is some code illustrating this:
furniture_class.F95:
MODULE furniture_class
IMPLICIT NONE
TYPE furniture_object
INTEGER :: length
INTEGER :: width
INTEGER :: height
CONTAINS
PROCEDURE :: get_length
END TYPE furniture_object
CONTAINS
FUNCTION get_length(self)
IMPLICIT NONE
CLASS(furniture_object) :: self
INTEGER :: get_length
get_length = self%length
END FUNCTION
END MODULE furniture_class
Now a room object may contain one or more furniture objects.
room_class.F95:
MODULE room_class
USE furniture_class
IMPLICIT NONE
TYPE :: room_object
CLASS(furniture_object), POINTER :: furniture
CONTAINS
PROCEDURE :: get_furniture
END TYPE room_object
CONTAINS
FUNCTION get_furniture(self)
USE furniture_class
IMPLICIT NONE
CLASS(room_object) :: self
CLASS(furniture_object), POINTER :: get_furniture
get_furniture => self%furniture
END FUNCTION get_furniture
END MODULE room_class
Finally, here is a program where I attempt to access the furniture object inside the room (but the compiler won't let me):
room_test.F95
PROGRAM room_test
USE room_class
USE furniture_class
IMPLICIT NONE
CLASS(room_object), POINTER :: room_pointer
CLASS(furniture_object), POINTER :: furniture_pointer
ALLOCATE(room_pointer)
ALLOCATE(furniture_pointer)
room_pointer%furniture => furniture_pointer
furniture_pointer%length = 10
! WRITE(*,*) 'The length of furniture in the room is', room_pointer%furniture%get_length() - This works.
WRITE(*,*) 'The length of furniture in the room is', room_pointer%get_furniture()%get_length() ! This line fails to compile
END PROGRAM room_test
I can of course directly access the furniture object if I don't use a getter to return the nested object, but this ruins the encapsulation and can become problematic in production code that is much more complex than what I show here.
Is what I am trying to do not supported by the Fortran standard or do I just need a more compliant compiler?
What you want to do is not supported by the syntax of the standard language.
(Variations on the general syntax (not necessarily this specific case) that might apply for "dereferencing" a function result could be ambiguous - consider things like substrings, whole array references, array sections, etc.)
Typically you [pointer] assign the result of the first function call to a [pointer] variable of the appropriate type, and then apply the binding for the second function to that variable.
Alternatively, if you want to apply an operation to a primary in an expression (such as a function reference) to give another value, then you could use an operator.
Some, perhaps rather subjective, comments:
Your room object doesn't really contain a furniture object - it holds a reference to a furniture object. Perhaps you use that reference in a manner that implies the parent object "containing" it, but that's not what the component definition naturally suggests.
(Use of a pointer component suggests that you want the room to point at (i.e. reference) some furniture. In terms of the language, the object referenced by a pointer component is not usually considered part of the value of the parent object of the component - consider how intrinsic assignment works, restrictions around modifying INTENT(IN) arguments, etc.
A non-pointer component suggests to me that the furniture is part of the room. In a Fortran language sense an object that is a non-pointer component it is always part of the value of the parent object of the component.
To highlight - pointer components in different rooms could potentially point at the same piece of furniture; a non-pointer furniture object is only ever directly part of one room.)
You need to be very careful using functions with pointer results. In the general case, is it:
p = some_ptr_function(args)
(and perhaps I accidentally leak memory) or
p => some_ptr_function(args)
Only one little character difference, both valid syntax, quite different semantics. If the second case is what is intended, then why not just pass the pointer back via a subroutine argument? An inconsequential difference in typing and it is much safer.
A general reminder applicable to some of the above - in the context of an expression, evaluation of a function reference yields a value. Values are not variables and hence you are not permitted to vary [modify] them.

Procedure copy in each instance of data type

When we create multiple instances from a data type (class) that has a pass procedure pointer, is the actual procedure (subroutines/functions) copied in each instance? Or is just the pointer copied?
For example consider the following code that compiles and runs correctly.
module mod2
implicit none
private
type class_type
integer :: a, b, c
contains
procedure :: add => add_it
end type class_type
public :: class_type
contains
subroutine add_it(this)
implicit none
class(class_type), intent(inout) :: this
this%c = this%a + this%b
end subroutine add_it
end module mod2
program tester
use mod2
implicit none
type(class_type), dimension(10) :: objs
objs(:) = class_type(1, 2, 0)
end program tester
Is subroutine add_it duplicated in each of the 10 objects created from data type class_type? Or is the instruction-set of subroutine add_it stored somewhere and the pointers to it, i.e. "procedure :: add => add_it" copied in each object?
Typically neither. Note this is very much implementation specific - what I describe below is typical but different processors may do things differently.
Note there are no procedure pointers in your example. The type class_type has a binding. If the class_type had a procedure pointer, things are different.
Typical implementation for bindings is that the compiler creates a table of machine level pointers, with one entry for each specific binding, with the pointer pointing at the code for the procedure. A table (sometimes known as a "vtable", from the similar technique used for virtual member functions in C++ and similar languages) is created for each type in the program.
For polymorphic objects (things declared with CLASS), the compiler then creates a descriptor that has a machine level pointer to the relevant table for the dynamic (runtime) type of the object. This pointer effectively indicates the dynamic type of the object and may be used in constructs such as SELECT TYPE and invocations of things like SAME_TYPE_AS. If you have a polymorphic array the compiler will initially typically only create one descriptor for the entire array, as individual elements in the array must all have the same dynamic type.
When you call a binding on a polymorphic object, the compiler follows the pointer to the vtable, then looks up the relevant pointer to the procedure binding.
No such descriptor or pointer dereferencing is required for non-polymorphic objects (things declared with TYPE) as the dynamic and declared type are always the same, the compiler knows what the declared type is and the compiler knows, at compile time, which procedure will be called.
If you have a procedure call where a non-polymorphic actual argument is associated with a polymorphic dummy argument, then the compiler will typically create the necessary descriptor as part of making the procedure call. Similarly for passing a polymorphic array element to a procedure taking a polymorphic scalar.
The main program of your code contains no polymorphic entities, and you call no procedures, so there may not be any machine pointers back to the vtable.
Procedure pointer components (components declared PROCEDURE(xxx), POINTER :: yyy before the CONTAINS of the type declaration) can be different for every object (including being different for every element in an array). In that case typical implementation is to store a machine level pointer to the code for the relevant procedure (or a null pointer if the procedure pointer component has not been associated).

How to specify procedures to be executed depending on data type of polymorphic variables

Conside the following sample code:
module mod
implicit none
type :: typeBase1
integer :: A1
end type
type :: typeBase2
integer :: A3
end type
type :: typeBase3
integer :: A3
end type
type, extends(typeBase1) :: typeDerived1
! Void
end type
type, extends(typeBase2) :: typeDerived2
! Void
end type
type, extends(typeBase3) :: typeDerived3
! Void
end type
type, extends(typeBase1) :: typeDerived11
! Void
end type
type, extends(typeBase2) :: typeDerived21
! Void
end type
type, extends(typeBase3) :: typeDerived31
! Void
end type
type :: complexType
class(typeBase1), pointer :: ptrBase1 ! typeBase1, 2 and 3 are extensible
class(typeBase2), pointer :: ptrBase2
class(typeBase3), pointer :: ptrBase3
end type
interface calcul
subroutine calculA(obj1, obj2, obj3)
import
type(typeDerived1) :: obj1 ! typeDerived 1, 2 et 3 are derived type of typeBase1, 2 and 3
type(typeDerived2) :: obj2
type(typeDerived3) :: obj3
end subroutine
subroutine calculB(obj1, obj2, obj3)
import
type(typeDerived11) :: obj1 ! typeDerived 11, 21 et 31 are derived type of typeBase1, 2 and 3
type(typeDerived21) :: obj2
type(typeDerived31) :: obj3
end subroutine
end interface calcul
contains
subroutine calculComplexType(complex)
type(ComplexType), intent(inout) :: complex
call calcul(complex % ptrBase1, complex % ptrBase2, complex % ptrBase3)
end subroutine
end module mod
What I am trying to do is that the subroutine calculComplexType calls a different version of the subroutine calcul, basing on the dynamic type of ptrBase1, ptrBase2 and ptrBase3.
The code does not work, because the compiler looks for a subroutine with the following interface:
subroutine calcul(obj1, obj2, obj3)
class(typeBase1) :: obj1
class(typeBase1) :: obj2
class(typeBase1) :: obj3
end subroutine
whatever the dynamic type of ptrBase1, ptrBase2 and ptrBase3 is.
My question is: is there a way in Fortran to write the interface calcul in order to automatically select a procedure basing on the dynamic type of the arguments?
I would like to avoid to use a long sequence of "select class".
Any suggestion to rewrite the code is welcome!
If you request dispatch based on all three arguments, it cannot be done. Some languages offer so called multimethods for this.
In Fortran you can use normal single dispatch methods (type-bound procedures), but in that case it can choose the subroutine only according to one argument.
Otherwise you have to use select the select type construct and make a case for every possible combination, be it inside one single procedure, or to select between more versions of it.
For two arguments, you can also consider the double dispatch pattern.
This is simply not possible in Fortran; the best you can do with polymorphism is to use an overridden type-bound procedure, selecting a function based on the dynamic type of one particular entity.
However, depending on the nature of what calcul does, it may make more sense to define just one version of calcul that takes polymorphic arguments (i.e. class(typeBase1), class(typeBase2), class(typeBase3)), and deal with the dynamic type inside calcul itself. The benefits are twofold:
calcul may be able to test the type of each argument independently from the others. If that is the case, you will still have to write three select type constructs, but they won't be nested or duplicated.
It's likely that you can use single dispatch (with type-bound procedures) to remove the need for a select type construct completely.
It's difficult for me to think of a situation where the code in this question is really the best design you could use.
If calcul is really doing something completely "different" for each dynamic type, in a way that's relevant to the code that calls it, then the calling code should not be using polymorphic pointers (e.g. perhaps there should be a different complexType for each different calcul).
But if every version of calcul is doing essentially "the same" operation (as far as higher-level code knows/cares about), regardless of dynamic type, then there should only be one version and it should accept arguments that are of the base class.

How to use an inherited component's integer value as array length in an extension

That's what I want to do:
type dataframe
integer::a,d
integer,dimension(:),allocatable::n
end type dataframe
type,extends(dataframe):: datafilled
double precision,dimension(sum(n),d)::x
end type datafilled
So the dataframe should be able to store the size information for its child datafilled. gfortran wants to know the type of n for compilation, but in my opinion it's already inherited. (Proof: If I define n in datafilled again, gfortran complains about the duplication.) How can I get it working?
Note: I declare n to be allocatable according to this question and because gfortran obviously doesn't yet support the len attribute of Fortran2003.
EDIT: OK, I admit I can do it with the allocatable attribute and allocate at each initialisation step later on.
There are constraints on what can be in a component array specification, that for non-allocatable/non-pointer components allow the specification to be evaluated at compile time (at the point that a type declaration for an object of the type being defined is encountered). Specifically, the value of a bound in the specification must not depend on the value of a variable - see C446 in F2008 for the details.
The component n in some object of type dataframe is a variable; calculating sum(n) requires its value; you are violating the constraint.
Length type parameters, even if your compiler supported them, can only be scalar.
As you've concluded - using an allocatable component, and allocating things correctly in some sort of construction procedure is the way to go.

Determining variable type in Fortran

In Fortran, is there a way to determine the type of a variable?
A possible use case where the type of a variable would be needed is the following. We pass a variable's type as an argument to a function, to be able to call type-specific code with that function, thus eliminating the need to have separate similar functions for each data type.
Well you might be able to do what you want if you mess about with the KIND intrinsic and POINTERs, but if you are only concerned with the signature of functions and subroutines, leave it to Fortran. If you define
function calc8(arg1)
real(8), intent(in) :: arg1
...
and
function calc4(arg1)
real(4), intent(in) :: arg1
...
in a module, and declare an interface like this
interface calc
module procedure calc8
module procedure calc4
end interface
(Warning, I haven't checked the syntax in detail, that's your responsibility.)
then Fortran will match the call to the right version of the function. Sure, you have to write both versions of the function, but that's really the Fortran 95 way of doing it. This can be quite tedious, I tend to write a generic version and run a sed script to specialise it. It's a bit of a kludge but it works.
If the code of the function is identical apart from the kind of the arguments I sometimes write the function for real(8) (or whatever) and write a version for real(4) which calls the real(8) version wrapped in type conversions.
In Fortran 2003 there are improved ways of defining polymorphic and generic functions, but I haven't really got my head around them yet.
Yes, there are two ways.
The first way does requires you to write separate functions or subroutines for each variable type, but you don't have to call different functions. This may or may not be close enough to what you want. You write the separate routines, then to write an interface to create a generic function or subroutine wrapping these specific subroutines. You don't have to pass the variable type, or do anything special in your call -- it is all done via the declaration and automatically by the compiler from the variable itself, as long as the variables are different enough that the compiler can distinguish them (there are rules about what is required). This is similar to how intrinsic functions work -- you can call sin with a real argument, a double precision real argument or a complex argument and the compiler calls the correct actual function and returns the matching result. High Performance Mark sketched a solution along these lines. For another question, I posted a working example, where the distinguishing feature of the variables was array rank: how to write wrapper for 'allocate'. An advantage of this method is that it is widely support by Fortran compilers.
In Fortran 2003/2008 there are extensive object oriented features. Quoting "Fortran 95/2003 explained" by Metcalf, Reid and Cohen, "To execute alternative code depending on the dynamic type of a polymorphic entity and to gain access to the dynamic parts, the select type construct is provided." The select type statement is a bit similar to a select case statement. This is support by fewer compilers. Again, you don't have to pass the type, since the compiler can figure it you from the variable itself. But it has to be a polymorphic type... Both Intel ifort and gfortran list select type and polymorphic datatypes as supported -- the later with some experimental aspects in gfortran (http://gcc.gnu.org/wiki/Fortran2003). These are recent additions to these compilers.
Here is a piece of code that determines what the type of something is. The action is trivial but you should be able to extend it to your use case.
module element_to_datatype
use iso_fortran_env
use mpi_f08
implicit none
contains
function get_element_datatype(element) result(datatype)
class(*), intent(in) :: element
type(MPI_Datatype) :: datatype
select type(element)
! REAL types
type is ( real(kind=REAL32) )
datatype = MPI_REAL4
type is ( real(kind=REAL64) )
datatype = MPI_REAL8
! COMPLEX types
type is ( complex(kind=REAL32) )
datatype = MPI_COMPLEX8
type is ( complex(kind=REAL64) )
datatype = MPI_COMPLEX16
! INTEGER types
type is ( integer(kind=INT8) )
datatype = MPI_INTEGER1
type is ( integer(kind=INT16) )
datatype = MPI_INTEGER2
type is ( integer(kind=INT32) )
datatype = MPI_INTEGER4
type is ( integer(kind=INT64) )
datatype = MPI_INTEGER8
! OTHER types
type is ( logical )
datatype = MPI_LOGICAL
end select
end function
end module element_to_datatype
A previous answer shows how to do this with interfaces, so I won't repeat that.