Assigning a routine name to a different routine in Fortran - pointers

I have a solver that iterates for a good amount of time (several hours) and I'm trying to remove several if statements from the main loop in order to save time.
What I'm essentially trying to do here is to create a routine, updateGhosts, which points to an assigned routine. This routine belongs to a derived data type which contains several other properties and routines. I want to use a routine, setGhosts, to set updateGhost to be either ghostOne or ghostTwo, which will be routines that properly update some conditions.
I can't seem to figure out a method that leads the code to compile, though I've tried several different things to no avail.
I have attempted to reduce the code sample down as far as possible for simplicity, but in reality types GridPoint and BlockType have many more parameters to deal with, so simple refactoring is not an option.
Here's the reduced code:
module BlockModule
implicit none
type GridPoint
real(kind=8) :: x, y, T
end type GridPoint
type BlockType
integer :: BC
type (GridPoint) :: Points(0:102,0:102)
contains
procedure :: setGhosts, updateGhosts
procedure :: ghostOne, ghostTwo
end type BlockType
contains
subroutine setGhosts(this)
class(BlockType), intent(inout) :: this
if (this%BC == -1) then
! We want to assign updateGhosts to ghostOne.
this%updateGhosts => this%ghostOne
else
! We want to assign updateGhosts to ghostTwo.
this%updateGhosts => this%ghostTwo
end if
end subroutine
! Routine that will be either ghostOne or ghostTwo.
subroutine updateGhosts(this)
class(BlockType), intent(inout) :: this
end subroutine
! Routine will do something.
subroutine ghostOne(this)
class(BlockType), intent(inout) :: this
end subroutine
! Routine will do something completely different, with same inputs.
subroutine ghostTwo(this)
class(BlockType), intent(inout) :: this
end subroutine
end module
How can I assign a routine name to point to a different routine in Fortran90/95/03? (The oldest version possible is ideal, but not necessary.) Sorry if similar questions have been asked before, I tried a search but I'm not quite sure what I need to look for.
Thanks for reading!

(Question was answered in a comment. See Question with no answers, but issue solved in the comments (or extended in chat) )
#SuperCow wrote:
Does this help? Procedure Pointer, Derived Type
The OP wrote:
Yes! This was the trick.

Related

Passing Fortran POINTER to SUBROUTINES as MODULE PROCEDURE

My first question is, "Can POINTER be passed to subroutines next to INTENT?"
Although passing Fortran POINTER with INTENT(IN) or INTENT(INOUT) seems to be a common practice, the documentation of Intel for Fortran POINTER says(https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference/a-to-z-reference/o-to-p/pointer-fortran.html)
The pointer cannot be declared with the INTENT or PARAMETER attributes
which confuses me a lot.
My second question is related to following code.
I tried overloading write_matrix with write_matrix_2d - which is for 2d arrays - and write_matrix_2d_ptr - which is for 2d Fortran POINTERs.
It turned out the code fails to compile with
Ambiguous generic interface WRITE_MATRIX: previously declared specific procedure WRITE_MATRIX_2D is not distinguishable from this declaration. [WRITE_MATRIX_2D_PTR]
If I comment (1) then it complies, and runs fine ( but I suppose this is bad practice since POINTER arguments going into subroutien write_matrix_2d which expects array input.)
Is there any way to overload Fortran subroutines just by their arguments' datatype just like C/C++?
module mod_write
implicit none
interface write_matrix
module procedure write_matrix_2d
(1) !module procedure write_matrix_2d_ptr
end interface
contains
subroutine write_matrix_2d(a)
implicit none
real, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in ARRAY printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
subroutine write_matrix_2d_ptr(a)
implicit none
real, pointer, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in POINTER printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
end module
program test
use mod_write
implicit none
real, dimension(9) :: b = (/21, 22, 23, 24, 25, 26, 27, 28, 29/)
real, dimension(3,3) :: c
real, dimension(3,3), target :: ct(3,3)
real, dimension(:,:), pointer :: cptr(:,:)
c = reshape( b, (/3, 3/) )
write(*,*)
write(*,*) 'c'
call write_matrix(c)
(2) !call write_matrix_2d(c)
ct = c
cptr => ct(2:3,2:3)
write(*,*)
write(*,*) 'ct'
call write_matrix(ct)
(2,3)!call write_matrix_2d_ptr(ct)
write(*,*) 'cptr'
call write_matrix(cptr)
(2) !call write_matrix_2d_ptr(cptr)
end program
My third question is again related to the attached code. Overloading is not that big a deal since I can just use write_matrix_2d and write_matrix_2d_ptr separately as (2)s in the code. But, as you can see at (3), call write_matrix_2d_ptr(ct) runs fine with the target input ct while write_matrix_2d_ptr expects pointer input. Is this okay, or should I make another write_matrix_2d_target?
Thank you.
The compiler documentation is wrong (or badly out of date). A dummy argument that is a pointer can also have the intent attribute. The attribute applies to the pointer association status of the argument, not the target.
Procedures in a generic interface can be overloaded if their dummy arguments are distinguishable. Dummy arguments are distinguishable if they have different type, kind or rank. Whether something is a pointer or not is not part of its type. (To be complete, arguments are also distinguishable if one is a pointer without intent(in) and the other is allocatable.) The requirements for distinguishable dummy arguments for different procedures in a generic interface mean that the rules around which specific procedure a particular generic reference resolves to are very simple.
Your example of overloading would be ambiguous - it is fine to pass a(n associated) pointer actual argument to a non-pointer dummy - the actual argument designates the target of the pointer. It is also permitted to pass a non-pointer actual with the target attribute to an intent(in) pointer dummy.
Whether something is a pointer or not is completely orthogonal to whether it is an array or not.
Pointers in Fortran are primarily used to reference different things (targets) during program execution.
Dummy arguments only need to be a pointer if you need to do something inside the procedure that relates to the association status of the pointer - perhaps you want to test the association status, or associate the pointer with something else.
(1) The intent restriction is some copy and paste error or it is in some strange context I do not understand. There was such a resteiction in Fortran 90.
(2) "but I suppose this is bad practice since POINTER arguments going into subroutien write_matrix_2d which expects array input."
There is nothing bad about passing a Fortran pointer variable as an ordinary variable. The default argument passing mechanism is that the target of thee pointer is passed using the normal non-ointer mechanism. One only uses pinter dummy arguments if one has specific reasons to do so. Most often tbat means than one works with the association status inside the subroutine. There are some other uses but you need a specific reason to declare your argument as pointer, otherwise it just complicates things.
(3) target can be passed to pointer, intent(in) in Fortran 2008.

Calling .Fortran from R with helper functions

I have a two-part question that might brush on preferred habits, and whether I'm unnecessarily complicating a problem. I've been using .C and learned .Call to do the heavy lifting from R. I wanted to do a comparison with .Fortran, and so I've been learning it as I go. Therefore, my issue may be due to my limited Fortran knowledge.
There are several functions implemented in R that I'd like to translate to Fortran that are related to each other. Rather than hash out the details of the problem I've created a minimum synonymous example that's impractical but a good illustration.
I have two functions and two related subroutines to find the magnitude and squared-magnitude, which make the entirety of the file:
! Actual functions
real function sumofsquaresfun (x,y)
implicit none
real :: x,y
sumofsquaresfun=x*x+y*y
end function sumofsquaresfun
real function magnitudefun(x,y)
implicit none
real :: x,y,tmp
tmp=sumofsquaresfun(x,y)
magnitudefun=sqrt(tmp)
end function magnitudefun
! Wrappers for R accessibility since R requires subroutines
subroutine sumofsquares(x,y,answer)
implicit none
real :: x,y
real answer
answer=sumofsquaresfun(x,y)
end subroutine sumofsquares
subroutine magnitude(x,y,answer)
implicit none
real :: x,y
real answer
answer=magnitudefun(x,y)
end subroutine magnitude
Suppose that both subroutines are useful when I'm in R, so keeping the two separate is important.
When I try t compile using
R CMD SHLIB fortrancode.f95
I have several errors the same two types of errors:
Error: Return type mismatch of function 'sumofsquaresfun' at (1) (UNKNOWN/REAL(4))
Error: Function 'sumofsquaresfun' at (1) has no IMPLICIT type
etc.
My questions in order of importance:
Even if feasible, is this the preferred approach to such a problem? Should I be using modules instead? I've seen this discussion (using a Fortran module in R?) and the related one by the same OP but don't know if involving modules is necessary/optimal.
If what I am trying to do is the correct way, what causes these embarrassing errors?
I like to use functions because that's what they're meant for, but am I being too much of a purist by creating the subroutine wrappers? Is it better style to just do away with them so I only have the two subroutines?
Many thanks!
This is more of a Fortran question than an R question.
You haven't declared the functions in your subroutines.
Do it like this and it should compile.
! Actual functions
real function sumofsquaresfun (x,y)
implicit none
real :: x,y
sumofsquaresfun=x*x+y*y
end function sumofsquaresfun
real function magnitudefun(x,y)
implicit none
real :: x,y,tmp
real sumofsquaresfun
tmp=sumofsquaresfun(x,y)
magnitudefun=sqrt(tmp)
end function magnitudefun
! Wrappers for R accessibility since R requires subroutines
subroutine sumofsquares(x,y,answer)
implicit none
real :: x,y
real answer
real sumofsquaresfun
answer=sumofsquaresfun(x,y)
end subroutine sumofsquares
subroutine magnitude(x,y,answer)
implicit none
real :: x,y
real answer
real magnitudefun
answer=magnitudefun(x,y)
end subroutine magnitude
Warning: You are using real but don't forget that R uses double precision. real is single precision. You should use something like real*8 or the Fortran95 equivalent of that.

Fortran calls: advantage of passing by pointer vs passing by reference

It is my understanding that in Fortran arrays are passed by reference. So is there an advantage to passing a pointer to a large array (into a subroutine) as opposed to passing the array itself.
Could you also clarify this in the context of recursive functions. I have seen implementations where pointers are used "for efficiency", but if everything is passed by reference, then what's the benefit of pointers.
Here's an example. I have an array X (in reality lets say it's a very large array).
INTEGER :: X(:)
I can define a subrouitne that takes this array as follows:
SUBROUTINE FOO(X)
INTEGER, INTENT(IN) :: X(:)
INTEGER :: I
DO I = 1, 4
WRITE(*,*) X(I)
ENDDO
END SUBROUTINE FOO
When I call the subroutine above then the array X is not copied as fortran passes a reference to it. Now lets say I have a modified version of the subroutine:
SUBROUTINE FOO2(X)
INTEGER, POINTER, INTENT(IN) :: X(:)
INTEGER :: I
DO I = 1, 4
WRITE(*,*) X(I)
ENDDO
END SUBROUTINE FOO2
I can call FOO2 from a program as follows:
PROGRAM TEST
IMPLICIT NONE
INTEGER, TARGET :: X(5)
INTEGER, POINTER :: Y(:)
X = (/1,2,3,4,5/)
Y => X
CALL FOO2(Y)
END PROGRAM TEST
Then here's my question: is there a performance difference between the two versions of foo? Is there any useful scenario where the declaration of FOO2 might be preferable to FOO?
In this simple case there shouldn't be any real difference. Note the program is illegal, you don't have the explicit interface to FOO or FOO2, but I will assume you just ommited it for simplicity and they are in a module or internal.
Both arrays can be non-contiguous in principle, so no difference here. If that slows down the code, the contiguous attribute might help. Or assumed size or explicite size arrays too.
Your subroutine is too simple, so there is no danger of aliasing too. This is the common source of decreasing performance with pointers. There could be potential aliasing with some other argument or another variable you access by host or use association provided it has the target attribute.
The purpose of pointer arguments is actually to either allow disassociated (null()) arguments, or to allow changing of the association status in the subroutines. Your example doesn't use neither and therefore the pointer attribute is superfluous.
There is on last small difference. It is not specified in the standard what is actually passed to the subroutine at the machine code level for the pointer variables. If it is just an address (likely for scalars) it is the same as non-pointer, just the aliasing rules and the allowed usage are different. Otherwise some descriptor is passed, but any overhead should be negligible, the assumed shape arrays use a descriptor too.

Fortran Pointer arithmetic

That's my first question post ever ... don't be cruel, please.
My problem is the following. I'd like to assign a fortran pointer as an expression. I think that's not possible by simple fortran techniques. But since new fortran versions seem to provide ways to handle things used in C and C++ (like c_ptr and c_f_pointer ... ), maybe someone knows a way to solve my problem. (I have not really in idea about C, but I read that pointer arithmetic is possible in C)
To make things more clear, here is the code which came to my mind immediately but isn't working:
program pointer
real(8),target :: a
real(8),pointer :: b
b=>a*2.0d0 ! b=>a is of course working
do i=1,10
a=dble(i)*2.0d0
write(*,*)b
end do
end program
I know that there are ways around this issue, but in the actual program, all of which came to my mind, would lead to much longer computation time and/or quite wiered code.
Thanks, a lot, in advance!
Best, Peter
From Michael Metcalf,
Pointers are variables with the POINTER attribute; they are not a distinct data type (and so no 'pointer arithmetic' is possible).
They are conceptually a descriptor listing the attributes of the objects (targets) that the pointer may point to, and the address, if any, of a target. They have no associated storage until it is allocated or otherwise associated (by pointer assignment, see below):
So your idea of b=>a*2 doesn't work because b is being assigned to a and not given the value of a.
Expression, in general (there two and a half very significant exceptions), are not valid pointer targets. Evaluation of an expression (in general) yields a value, not an object.
(The exceptions relate to the case where the overall expression results in a reference to a function with a data pointer result - in that case the expression can be used on the right hand side of a pointer assignment statement, or as the actual argument in a procedure reference that correspond to a pointer dummy argument or [perhaps - and F2008 only] in any context where a variable might be required, such as the left hand side of an ordinary assignment statement. But your expressions do not result in such a function reference and I don't think the use cases are relevant to what you wnt to do. )
I think you want the value of b to change as the "underlying" value of a changes, as per the form of the initial expression. Beyond the valid pointer target issue, this requires behaviour contrary to one of the basic principles of the language (most languages really) - evaluation of an expression uses the value of its primaries at the time the expression is evaluation - subsequent changes in those primaries do not result in a change in the historically evaluated value.
Instead, consider writing a function that calculates b based on a.
program pointer
IMPLICIT NONE
real(8) :: a
do i=1,10
a=dble(i)*2.0d0
write(*,*) b(a)
end do
contains
function b(x)
real(kind(a)), intent(in) :: x
real(kind(a)) :: b
b = 2.0d0 * x
end function b
end program
Update: I'm getting closer to what I wanted to have (for those who are interested):
module test
real,target :: a
real, pointer :: c
abstract interface
function func()
real :: func
end function func
end interface
procedure (func), pointer :: f => null ()
contains
function f1()
real,target :: f1
c=>a
f1 = 2.0*c
return
end function f1
end module
program test_func_ptrs
use test
implicit none
integer::i
f=>f1
do i=1,10
a=real(i)*2.0
write(*,*)f()
end do
end program test_func_ptrs
I would be completely satisfied if I could find a way to avoid the dummy arguments (at least in when I'm calling f).
Additional information: The point is that I want to define different functions f1 and deside before starting the loop, what f is going to be inside of the loop (depending on whatever input).
Pointer arithmetic, in the sense of calculating address offsets from a pointer, is not allowed in Fortran. Pointer arithmetic can easily cause memory errors and the authors of Fortran considered it unnecessary. (One could do it via the back door of interoperability with C.)
Pointers in Fortran are useful for passing procedures as arguments, setting up data structures such as linked lists (e.g., How can I implement a linked list in fortran 2003-2008), etc.

Set array's rank at runtime

I have written a program which reads a file containing multidimensional data (most commonly 3D, but 2D could occur as well). To heighten simplicity I would like to store the data in an array of the same rank (or something pretending to be one), i.e. using a three-dimensional array for 3D data, etc.; the trouble is that the program only learns about the dimensionality on reading the data file.
Currently I store all data in an array of rank one and calculate each element's index in that array from the element's coordinates (this was also suggested here). However, I have also read about pointer rank remapping, which seems very elegant and just what I have been looking for, as it would allow me to scrap my procedures for array index determination (which are probably far less efficient than what goes on behind the scenes). Now, however, it looks like I'm facing the same problem as with directly declaring a multidimensional array - how to do the declaration? Again, it requires information about the rank.
How could I use pointer rank remapping or some other, more suitable technique for setting an array's rank at runtime - in case this can be done at all. Or am I best off sticking to the rank one-array that I am currently using?
I once asked something similar, i.e. how to treat a two-dimensional array as one dimension, see here: changing array dimensions in fortran.
The answers were about the RESHAPE instrinsic of pointers, however there seems to be no way to use the same array name unless you use subroutine wrappers, but then you need callbacks to have the eventual subroutine with only one name, so the problems get larger.
program test
real, allocatable :: data(:)
allocate(data(n_data))
! read stuff, set is_2d and sizes
if (is_2d) then
call my_sub2(data, nX, nY)
else
call my_sub3(data, nX, nY, nZ)
end if
end program test
subroutine my_sub2(data, nX, nY)
real :: data(nx,nY)
! ...
end subroutine my_sub2
subroutine my_sub3(data, nX, nY, nZ)
real :: data(nx,nY,nZ)
! ...
end subroutine my_sub3
EDIT: as an alternative, set the third rank to 1:
program test
real, allocatable, target:: data(:)
real, pointer:: my_array(:,:,:)
logical is_2d
n_data = 100
allocate(data(n_data))
! read stuff, determine is_2d and n
if (is_2d) then
i=n
j=n
k=1
else
i=n
j=n
k=n
end if
my_array(1:i,1:j,1:k) => data
write(*,*) my_array
end program test
Then you handle the 2D case as a special 3D case with third dimension 1.
EDIT2: also, beware when passing non-contiguous arrays to subroutines with explicit-shape arrays: http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/lin/compiler_f/optaps/fortran/optaps_prg_arrs_f.htm
If I understand correctly, you read in data in and 1-D array and want to assign it to 2D or 3D arrays, which you know only after reading the file. Why not declare both 2D and 3D arrays as allocatable arrays, and allocate only one of them base on your data shape? You could use the intrinsic function RESHAPE to do this conveniently.
REAL,DIMENSION(:,:), ALLOCATABLE :: arr2d
REAL,DIMENSION(:,:,:),ALLOCATABLE :: arr3d
...
! Read data into 1-D array, arr1d;
...
IF(L2d)THEN
ALLOCATE(arr2d(im,jm))
arr2d=RESHAPE(arr1d,(/im,jm/))
ELSEIF(L3d)THEN
ALLOCATE(arr3d(im,jm,km))
arr3d=RESHAPE(arr1d,(/im,jm,km/))
ENDIF
You could use the EQUIVALENCE statement like this:
Program ranks
integer a_1d(12)
integer a_2d(2, 6)
integer a_3d(2, 2, 3)
equivalence (a_1d, a_2d, a_3d)
! fill array 1d
a_1d = (/1,2,3,4,5,6,7,8,9,10,11,12/)
print *, a_1d
print *, a_2d(1,1:6)
print *, a_2d(2,1:6)
print *, a_3d(1,1,1:3)
print *, a_3d(2,1,1:3)
print *, a_3d(1,2,1:3)
print *, a_3d(2,2,1:3)
end program ranks
You can write a subroutine for different ranks of array and create an interface
Here in example I have shown that how to populate an array of different array using interface statement `
program main
use data
implicit none
real,dimension(:,:,:),allocatable::data
integer::nx,ny,nz
nx = 5
ny = 10
nz = 7
call populate(nx,ny,nz,data)
print *,data
end program main `
data module is here
module data
private
public::populate
interface populate
module procedure populate_1d
module procedure populate_2d
module procedure populate_3d
end interface
contains
subroutine populate_1d(x,data)
implicit none
integer,intent(in)::x
real,dimension(:),allocatable,intent(out):: data
allocate(data(x))
data=rand()
end subroutine populate_1d
subroutine populate_2d(x,y,data)
implicit none
integer,intent(in)::x,y
real,dimension(:,:),allocatable,intent(out):: data
allocate(data(x,y))
data=rand()
end subroutine populate_2d
subroutine populate_3d(x,y,z,data)
implicit none
integer,intent(in)::x,y,z
real,dimension(:,:,:),allocatable,intent(out):: data
allocate(data(x,y,z))
data=rand()
end subroutine populate_3d
end module data
There is an interface to populate 1d, 2d and 3d arrays. you can call populate interface instead of calling individual subroutines. It will automatically pick the relevant one.

Resources