Passing multi-dimensional array in fortran subroutines - multidimensional-array

I am trying to understand a Fortran code written by someone else. The code is doing what it is supposed to do so I am assuming that it works fine. A subroutine called "fft" is being called from another subroutine called "convol". Inside "convol", an array is declared like this:
real, dimension fri(n+1,n,nh,2,0:1)
call fft(fri)
Inside "fft", the declaration is like this:
subroutine wrft3b(fri)
real, dimension fri(2,n+1,n,nh,0:1)
I don't understand why the array lengths are not consistent and still the code is working. Any clues what might be happening here?

The important thing is that the length is the same. If the interface is not explicit, this will not throw an error for the contiguous explicit-shape array. Only the elements of the array will have different indexes (determined by the column-major order), that in the calling program.

Related

Reshaping 1d array to 2D pointer array Fortran

I have a pointer uvw(:,:) which is two-dimensional, and I got a 1d buffer array x(:).
Now I need to point uvw(1,:)=>x(1:ncell) and uvw(2,:)=>x(ncell+1:ncell*2) etc.
I made a very simple example. I know that array of pointers does not work, but does anybody have an idea how this can be worked around?
PS: For a pragmatic reason I do not want to wrap my uvw with a declared type. ( i am changing some bit of code, and need uvw as 2D pointer. Currently is an array, and my idea is to avoid changing the way uvw is being used as it being used thousands of times)
program test
real, allocatable,target :: x(:)
real, pointer :: ptr(:,:)
allocate(x(100) )
x = 1.
ptr(1,:) => x(1:10)
end program
The error message says:
`error #8524: The syntax of this data pointer assignment is incorrect:
either 'bound spec' or 'bound remapping' is expected in this context.
[1]
ptr(1,:) => x(1:10)
----^`
You are trying to perform pointer bounds remapping, but you have the incorrect syntax and approach.
Pointer bounds remapping is a way to have the shape of the pointer different from that of the target. In particular, the rank of the pointer and target may differ. However, in such an assignment it is necessary to explicitly specify the lower and upper bounds of the remapping; it isn't sufficient to use : by itself.
Also, you'll need to assign the whole pointer in one go. That is, you can't have "the first ten elements point to this slice, the next ten to this slice" and so on in multiple statements.
The assignment statement would be
ptr(1:10,1:10) => x
Note, that this also means that you can't actually have what you want. You are asking for the elements ptr(1,1:10) to correspond to x(1:10) and ptr(2,2:10) to correspond to x(11:20). That isn't possible: the array elements must match in order: ptr(1:10,1) being the first ten elements of ptr must instead be associated with the first ten elements x(1:10). The corrected pointer assignment above has this.
If you prefer avoiding a pointer, then the UNION/MAP is an option depending on compiler. It was added to gfortran a while ago... then you can think of the array as a rank=2 but also use the vector (Rank=1) for SIMD operations.
All this assumes that one wants to avoid pointers...

In (Free) Pascal, can a function return a value that can be modified without dereference?

In Pascal, I understand that one could create a function returning a pointer which can be dereferenced and then assign a value to that, such as in the following (obnoxiously useless) example:
type ptr = ^integer;
var d: integer;
function f(x: integer): ptr;
begin
f := #x;
end;
begin
f(d)^ := 4;
end.
And now d is 4.
(The actual usage is to access part of a quite complicated array of records data structure. I know that a class would be better than an array of nested records, but it isn't my code (it's TeX: The Program) and was written before Pascal implementations supported object-orientation. The code was written using essentially a language built on top of Pascal that added macros which expand before the compiler sees them. Thus you could define some macro m that takes an argument x and expands into thearray[x + 1].f1.f2 instead of writing that every time; the usage would be m(x) := somevalue. I want to replicate this functionality with a function instead of a macro.)
However, is it possible to achieve this functionality without the ^ operator? Can a function f be written such that f(x) := y (no caret) assigns the value y to x? I know that this is stupid and the answer is probably no, but I just (a) don't really like the look of it and (b) am trying to mimic exactly the form of the macro I mentioned above.
References are not first class objects in Pascal, unlike languages such as C++ or D. So the simple answer is that you cannot directly achieve what you want.
Using a pointer as you illustrated is one way to achieve the same effect although in real code you'd need to return the address of an object whose lifetime extends beyond that of the function. In your code that is not the case because the argument x is only valid until the function returns.
You could use an enhanced record with operator overloading to encapsulate the pointer, and so encapsulate the pointer dereferencing code. That may be a good option, but it very much depends on your overall problem, of which we do not have sight.

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.

Nullifying Pointers in Fortran

I am adding a module to a Fortran code, and ran across the following issue. I have a derived data type Info that contains several other variables, among them a 4D pointer array (it is a hydro code, so it is 3 spatial components and 1 variable component). To make my subroutine easier to read, I just make a pointer q and point to Info%q, as follows:
real,pointer::q(:,:,:,:)
q=>Info%q
...
some work on q
The question I am running into is: should I use deallocate(q) before nullify(q)? Or, since q is pointing to an array that is necessary elsewhere in the code, should I just use nullify?
Thanks for your help.
Only nullify! Otherwise the original pointer would be undefined and the array would no longer exist!

Pointers to subroutines in FORTRAN [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Function pointer arrays in Fortran
How to alias a function name in Fortran
In FORTRAN, how I can create and use a pointer, which points to a subroutine?
Furthermore, is it possible to have a hole array of pointers pointing in various subroutines?
I know that these things can be easily implemented in C, but what about FORTRAN?
EDIT
I have tried to use the command:
PROCEDURE (), POINTER :: pMYSUB => NULL()
I made pMYSUB pointer to point at the subroutine:
pMYSUB => MYSUB
I have also put MYSUB subroutine into INTERFACE:
INTERFACE
SUBROUTINE MYSUB
END SUBROUTINE
END INTERFACE
MYSUB subroutine has no arguments. The problem is that when I use:
call pMYSUB
I get the linking error: unresolved external symbol _pMYSUB.
What I am doing wrong?
The command:
POINTER(pMYSUB, MYSUB)
is another way of making the point pMYSUB to point at the subroutine MYSUB?
Function pointers in Fortran are called "procedure pointers", part of the Fortran 2003 standard. Many modern compilers support them nowadays. There's also a very limited form of function pointer going back to at least F77, where you can have a procedure argument which is a procedure; you cannot have normal function pointer variables before F2003 though. If you have problems even after googling up something based on the above, post some code of yours that you're writing and I'm sure someone will help you out.
Wrt. an array of pointers, that is for some reason not allowed. The common work-around is to create a derived type with a pointer component, then make an array of these derived types.
The problem was that my subroutine's name was DO_CALC, and for some reason the statement:
PROCEDURE (DO_CALC), POINTER :: pDO_CALC => NULL()
didn't like to the compiler. I changed my subroutine's name and now works OK!
#Janneb, nice idea to use an array of derived types instead of an array of function pointers which is isn't allowed in Fortran.

Resources