Resolving procedure confusion when using OOP - oop

I am writing a vector type in Fortran and am getting very confused.
Suppose I have the following derived type
Type (Vector)
Real :: x, y
Contains
Procedure :: vector_smul
End Type
Function vector_smul &
( &
va, vb &
) &
Result (c)
Real :: c
Class (Vector), Intent (In) :: va, vb
c = (va%x + vb%x) + (va%y * vb%y)
End Function vector_smul
However when I use
Type (Vectors)
Real :: x, y
Contains
Procedure :: smul => vector_smul
End Type
I get an error when I use
Program Test
Use Vector
Implicit None
Real :: c
Type (Vector) :: va, vb
c = smul (va, vb)
End Program

You are just defining a type-bound procedure xyz%smul that points to vector_smul! The original module procedure vector_smul is not effected!
To stay in the terminology of the Fortran Standard (2008, ch. 4.5.5), smul is the binding name for the procedure name vector_smul. You still can access the procedure itself.
You can "rename" the function when using it in the main program:
Program Test
Use Vector, only: Vector, smul => vector_smul
Implicit None
Real :: c
Type (Vector) :: va, vb
c = smul (va, vb)
End Program
[Although it is not possible to have the same name for the type different and the module, i.e. not name them both Vector...]
Take a look at the corresponding topic at the Fortran Wiki...

Related

OOP and Fortran90

Hello I am trying to learn Object Oriented Programming using Fortran (all my codes are written in Fortran 90), I partially know C++ but I want to carry on using Fortran.
In Fortran you make classes employing modules. I am facing compiling errors when writing the integer, parameter :: dp = selected_real_kind(15,307) statement. Here goes my academic code. Its a short code that uses Abstract classes
module class_Rectangle
implicit none
integer, parameter :: dp = selected_real_kind(15,307)
type Rectangle
real(dp) :: a,b
end type Rectangle
contains
subroutine area_rectangle(area,info)
implicit none
real(dp), intent(out) :: area
type(Rectangle), intent(in) :: info
area = info%a * info%b
end subroutine area_rectangle
end module class_Rectangle
program Main
use class_Rectangle
use class_Circle
implicit none
integer, parameter :: dp = selected_real_kind(15,307)
interface compute_area
module procedure area_rectangle, area_circle
end interface compute_area
type(Rectangle) :: geoA
type(Circle) :: geoB
real(dp) :: area
geoA = Rectangle(2.0d0,4.0d0)
call area_rectangle(area,geoA)
write(*,*) 'Rectangle area:', area
geoB = Circle(1.0d0)
call area_circle(area,geoB)
write(*,*) 'Circle area:',area
end program Main
The message that the compiler returns me is the following:
integer, parameter :: dp = selected_real_kind(15,307)
1
Error: Name 'dp' at (1) is an ambiguous reference to 'dp' from module 'class_rectangle'
Main.f90:81.13:
real(dp) :: area
1
Error: Name 'dp' at (1) is an ambiguous reference to 'dp' from module 'class_rectangle'
Main.f90:84.30:
Any hint or advice is welcome.
Always try to use USE statement with ONLY. If you do so, you will not encounter the ambiguity error you get. In addition, you will know exactly what is being used in your code from each module, just by a quick look at the top lines of your code. Therefore, your main program header could look like this:
program Main
use class_Rectangle, only: Rectangle, area_rectangle
use class_Circle, only: Circle, area_circle
implicit none
integer, parameter :: dp = selected_real_kind(15,307)
interface compute_area
module procedure area_rectangle, area_circle
end interface
type(Rectangle) :: geoA
type(Circle) :: geoB
real(dp) :: area
geoA = Rectangle(2.0d0,4.0d0)
call area_rectangle(area,geoA)
write(*,*) 'Rectangle area:', area
geoB = Circle(1.0d0)
call area_circle(area,geoB)
write(*,*) 'Circle area:',area
end program Main
For a good tutorial on OOP programming in Fortran with some good examples, see the book "Modern Fortran Explained" by Metcalf et al.
Depending on your compiler, you should get pretty helpful messages
module a
end module a
program b
implicit none
use a
end program b
And compile:
$ gfortran mod_test.F90
mod_test.F90:6:9:
implicit none
2
use a
1
Error: USE statement at (1) cannot follow IMPLICIT NONE statement at (2)
Just omit: integer, parameter :: dp = selected_real_kind(15,307)
in the main program! By USEing class_Rectangle the main program it
shares this variable with the module (except you declare it private,
which is not what you want here I guess).

Calling type-bound procedure for an array of derrived types in Fortran

Let's assume that I have a derived type Coordinates with its type-bound procedure swap:
module myTypes
implicit none
public :: Coordinates
type Coordinates
real :: x,y
contains
procedure :: swap ! Error here
end type
contains
subroutine swap(this)
class (Coordinates) :: this
this%x = this%x + this%y
this%y = -(this%y - this%x)
this%x = this%x - this%y
end subroutine
end module
Now, if I have an instance of Coordinates called point_A, and if I want to call the type-bound procedure swap for it, I would just write: call point_A%swap. But if I have an array of instances of Coordinates, like:
type(Coordinates), dimension(:), allocatable :: setOfPoints
then to call the swap for all the elements of setOfPoints, I would like to write:
call setOfPoints(:)%swap
In order to achieve that, I change the code of swap procedure to:
subroutine swap(these)
class (Coordinates), dimension(:) :: these
integer :: i
do i = 1, size(this)
this(i)%x = this(i)%x + this(i)%y
this(i)%y = -(this(i)%y - this(i)%x)
this(i)%x = this(i)%x - this(i)%y
end do
end subroutine
Unfortunately, gfortran doesn't like my idea. On the line that I marked in the first piece of code it says:
Error: Passed-object dummy argument of 'swap' must be scalar.
Question: how can I call the type-bound procedure for all the instances of the derived type at once? I don't want to put the call in the loop, but I want to do this as I wrote it before, like what we always do with arrays in Fortran.
I read about the ELEMENTAL keyword, but if I want to use it, I need the type-bound procedure to be 'pure', which is not my case.
I tried to place a DEFERRED keyword after the word procedure, but then compiler says:
Error: Interface must be specified for DEFERRED binding
I created an interface for swap, but I couldn't figure out where to place it. I tried many positions and compiler said that 'interface was unexpected there'.
Also, I read about SELECT TYPE, but I think it won't help in my case.
Your specific example is perfectly fine with ELEMENTAL
module myTypes
implicit none
public :: Coordinates
type Coordinates
real :: x,y
contains
procedure :: swap ! Error here
end type
contains
elemental subroutine swap(this)
class (Coordinates), intent(inout) :: this
this%x = this%x + this%y
this%y = -(this%y - this%x)
this%x = this%x - this%y
end subroutine
end module
use myTypes
type(Coordinates) :: arr(10)
arr = Coordinates(1.,2.)
call arr%swap
end
Your subroutine is pure. If it cannot be, consider using impure elemental.

Fortran : generic procedure of parent is called instead of child when allocating child from class of parent

I explain my question in the form of an example.
I have a type (location2d_t) which includes two members x, and y and a type-bound procedure (calcdist2d). The procedure, in addition of (this) with class of (location2d_t), accepts its own type (as second dummy argument) to calculate a distance.
Now, I go further and extend the type to (location3d_t) which has z as well.
To re-define the procedure, I cannot override the previous one so I create a new procedure (calcdist3d) with the second argument of type of (location3d_t) and make a generic procedure (calcdist) for them. In other words, second arguments have different types so generic idea is applicable.
In a more general scope, let's say main program here, for the sake of generality I declare my object as class of parent. When I allocate the object with type of child (location3d_t), a call to (calcdist) whose second dummy argument is (location3d_t) refers to parent generic and says
Error: Found no matching specific binding for the call to the GENERIC 'calcdist'
The code is
module point_mod
implicit none
type location2d_t
integer :: x,y
contains
procedure :: calcdist2d => calcdistance2d
procedure :: here => here_location2d
generic :: calcdist => calcdist2d
end type
type, extends(location2d_t) :: location3d_t
integer :: z
contains
procedure :: calcdist3d => calcdistance3d
procedure, public :: here => here_location3d
generic, public :: calcdist => calcdist3d
end type
contains
function calcdistance2d(this,location) result(output)
class(location2d_t) :: this
type(location2d_t) :: location
integer :: output
output = int(sqrt(real((location%x-this%x)**2+(location%y-this%y)**2)))
end function
function calcdistance3d(this,location) result(output)
class(location3d_t) :: this
type(location3d_t) :: location
integer :: output
output = int(sqrt(real((location%x-this%x)**2+ &
(location%y-this%y)**2+(location%z-this%z)**2)))
end function
subroutine here_location2d(this)
class (location2d_t) :: this
print*, "we are in locationd2d_t"
end subroutine
subroutine here_location3d(this)
class (location3d_t) :: this
print*, "we are in locationd3d_t"
end subroutine
end module
The module is compiled without any error. The below program is implemented to use the module:
program main
use point_mod
implicit none
class (location2d_t), allocatable :: loc
type (location3d_t) :: dum
allocate(location2d_t::loc)
call loc%here() ! calls location2d_t procedure
deallocate(loc)
allocate(location3d_t::loc)
call loc%here() !correctly calls procedure of location3d_t
print*,loc%calcdist(dum) ! gives error
select type (loc)
type is (location3d_t)
print*,loc%calcdist(dum) ! runs well
end select
end program
The procedure "Here" finds its dynamic type correctly. Why isn't generic procedure of child (calcdist) explicitly called ? Do I have to use "select type" block always even in this obvious case?
N.B.: I checked the code with GNU fortran 4.8 and 4.9, and ifort 14.
Yes, you have to use "select type". Outside the "type is" block, loc is polymorphic. Only inside type is (location3d_t), loc has a type and can be passed as dummy argument with defined type.
Generic procedures are always not overridden when the type is extended, so in location3d_t, calcdist is the generic binding for calcdist3d and calcdist2d and loc needs a specific type when calling calcdist to find the appropriate procedure.
When location2d_t is extended, to location3d_t, here binding is overriden and there is only one procedure associated to loc%here() so can be called outside the "type is" block
You can accomplish this behavior without generics with only a slight tweak to your calcdistanceXd functions. The reason you couldn't override the function in your extended type is that the argument type of location was mismatched. If you instead declare location in calcdistance2d to be class(location2d_t) then you can match this in calcdistance3d. You will have to add in a select type construct into calcdistance3d in order to access the members of location3d_t from the polymorphic variable location.
Example:
module point_mod
implicit none
type :: location2d_t
integer :: x, y
contains
procedure, public, pass(this) :: calcdist => calcdistance2d
procedure, public, pass(this) :: here => here_location2d
end type
type, extends(location2d_t) :: location3d_t
integer :: z
contains
procedure, public, pass(this) :: calcdist => calcdistance3d
procedure, public, pass(this) :: here => here_location3d
end type
contains
function calcdistance2d(this, location) result(output)
class(location2d_t) :: this
class(location2d_t) :: location
integer :: output
output = int(sqrt(real((location%x-this%x)**2+(location%y-this%y)**2)))
end function
function calcdistance3d(this,location) result(output)
class(location3d_t) :: this
class(location2d_t) :: location
integer :: output
select type (location)
type is (location3d_t)
output = int(sqrt(real((location%x-this%x)**2+ &
(location%y-this%y)**2+(location%z-this%z)**2)))
class default
output = -1
end select
end function
subroutine here_location2d(this)
class (location2d_t) :: this
print*, "we are in locationd2d_t"
end subroutine
subroutine here_location3d(this)
class (location3d_t) :: this
print*, "we are in locationd3d_t"
end subroutine
end module
With this version of point_mod, your example program works:
program main
use point_mod
implicit none
class (location2d_t), allocatable :: loc
type (location3d_t) :: dum
allocate(location2d_t::loc)
call loc%here() ! calls location2d_t procedure
deallocate(loc)
allocate(location3d_t::loc)
call loc%here() !correctly calls procedure of location3d_t
print*,loc%calcdist(dum)
end program
It is true this approach still requires a select type, but it is hidden in the module implementation rather than being required by users of the module.

Node Class with Value of Arbitrary Type, Fortran 2003

I have not found the host of information on generics in Fortran to be useful.
I would like to create a Node class that:
Contains a variable of arbitrary class, "ANYTHING :: value,"
the class of which can be specified either (a) at instantiation or (b) through an init subroutine.
Ideally, I would like to imitate the Java functionality of:
Node<Integer> n = new Node<Integer>();
Is this possible in Fortran 2003? Or will I have to create a Node-derived class for every possible class that 'value' might have?
The solution presented in the first post does not quite accomplish what I want. Consider:
program generics_test
implicit none
type node_int
integer :: x
end type node_int
type node
class(*), allocatable :: value
end type node
type(node) :: obj
allocate(node_int :: obj%value)
!This must be used:
select type (val => obj%value)
type is (node_int)
val%x = 1
class default
!throw en error
end select
end program generics_test
This illustrates the main issue: the need for select type to interact with an allocated unlimited polymorphic object. Take for example:
module node_class
type node
class(*), allocatable :: anything
contains
procedure, public :: init => init_sub
end type node
private :: init_sub
contains
subroutine init_sub(this, something)
class(node) :: this
somethingObj :: something ! <--- this assumes we know what soemthing is;
! generous, since my question doesn't assume that
allocate(this%anything, source=something)
end subroutine init_sub
end module node_class
It seems that, although you may take class(*), allocatable :: anything and allocate(anythingObj, source=somethingObj) somewhere inside of type node, node cannot ever treat anything as though it were a somethingObj unless anything appears in a select type... type is (somethingObj) block. Thus, to emulate the snippet of Java I've written above select type would have to have a case for every single object that will ever be encountered.
It is possible to have a component an unlimited polymorphic entity.
type node_int
end type node_int
type node
class(*), allocatable :: value
end type node
type(node) obj
allocate(node_int :: obj%value)
end
Here, the class(*) is your "ANYTHING" (even, thanks to #IanH correcting me, intrinsic types) and the allocate statement sets the type.
It is possible, if you want to get closer to Java-ness to override the structure constructor, so that
obj = node(mold)
works, where the dynamic type is taken from mold. [Fortran 2008 has the mold= specifier in allocate.] But I won't go into that unless requested.
Depending on exactly what you want to do you may find this approach is much more work than having distinct types.
Edit, following question update
When one then wants to use the value of an unlimited polymorphic entity as given above, one is tempted by something like
allocate (integer :: obj%value)
obj%value = 1
This won't work without the Fortran 2008 rules of automatic allocation. [In the question one has an x component of node_int, but I'll just pretend node_int is itself an integer.]
Instead, one can use sourced allocation:
allocate (obj%value, source=1)
or a select type construct
select type ( x => obj%value)
type is(integer)
x = 1
end select
[This is the heart of my suggestion that it's a lot of work.]
A more detailed example, including sourced allocation and constructor
module types
type Penguin
character(len=20) :: name
end type Penguin
type node
class(*), allocatable :: value
end type node
interface node
module procedure node_c
end interface node
contains
function node_c(value)
class(*), intent(in) :: value
type(node) node_c
allocate(node_c%value, source=value)
end function node_c
end module types
program test
use types
type(node) obj(3)
allocate(obj(1)%value, source = 1)
allocate(obj(2)%value, source = Penguin('Percy'))
obj(3) = node(Penguin('Harold'))
do i=1, 3
select type (val => obj(i)%value)
type is (integer)
print '("Value is an integer: ", I0)', val
class is (Penguin)
print '("Value is a penguin called ", A)', TRIM(val%name)
end select
end do
end
Output from the above, compiled with ifort 14.0.1
Value is an integer: 1
Value is a penguin called Percy
Value is a penguin called Harold

Fortran90 assigning pointers and derived types at runtime

I have a question regarding assigning Fortran90 derived types and pointers at runtime. I want to pass a derived variable type to a subroutine after the code reads an input file. So depending on the input I pass the appropriate data type. Let me explain:
I have two modules:
Module A_mod and Module B_mod. Each has it's own unique data type and subroutines. For example:
Module A_mod
type A
real :: x, y
end type
contains
subroutine FunA(me)
type (A), intent(in) :: me
<do stuff>
end subroutine
End module A_mod
Module B_mod is a mirror of the above with B replacing A (also the data type B has x and y defined as integers).
I also have a third module that has this interface:
interface fun
modular procedure funA, funB
end interface
Here is my problem. The user via an input file determines which module subroutine to use. How can I make a generic pointer that gets associated at runtime? Or something similar that doesn't require pointers.
For example:
type (?) :: pt
Call fun(pt)
where after the program reads the input file it picks the correct data type to be sent to the interfaced subroutine "fun". So the type is unknown until runtime.
If Fortran would let me declare a variable in my execution portion of code it would look like this for example
IF(input.EQ."A") THEN
type(A) :: pt
ELSE
type(B) :: pt
END IF
CALL fun(pt)
Any suggestion would be appreciated !!
Thank you
This is difficult to do cleanly in Fortran 90. It is straight forward in Fortran 2003.
Resolution of the procedure to call when the generic reference fun is encountered (in CALL fun(pt)) is done at compile time, based on the declared type of pt.
If you are limited to Fortran 90, then effectively you will need to maintain a flag of some sort that indicates at runtime which particular derived type you want to work with, have a named object for each of type A and type B, and everytime you want to reference fun have an IF construct that selects the correctly named argument.
(If the size of the objects is significant you can arrange for them to have common storage.)
Something like:
TYPE(A) :: pt_A
TYPE(B) :: pt_B
...
IF (input .EQ. 'A') THEN
CALL fun(pt_A)
ELSE
CALL fun(pt_B)
END IF
In F2003, you would define a common parent type, that had a specific binding named fun. pt would then be a polymorphic allocatable object, allocated based on input to either type A or type B as appropriate.
TYPE :: Parent
CONTAINS
PROCEDURE(parent_Fun), DEFERRED :: Fun
END TYPE Parent
ABSTRACT INTERFACE
SUBROUTINE parent_Fun(obj)
IMPORT :: Parent
IMPLICIT NONE
CLASS(Parent), INTENT(IN) :: obj
END SUBROUTINE parent_Fun
END INTERFACE
TYPE, EXTENDS(Parent) :: A
REAL :: x, y
CONTAINS
PROCEDURE :: A => A_Fun
END TYPE A
TYPE, EXTENDS(Parent) :: B
INTEGER :: x, y
CONTAINS
PROCEDURE :: B => B_Fun
END TYPE B
CLASS(Parent), ALLOCATABLE :: pt
...
IF (input .EQ. 'A') THEN
ALLOCATE(A:: pt)
ELSE
ALLOCATE(B:: pt)
END IF
...
CALL pt%Fun()