0

Relatively arbitrary example:

Consider a two-dimensional array r

integer :: nDim = 3, nPoints = 5
real, dimension(nDim,nPoints) :: r

which corresponds to a number of points with x, y and z coordinates.

Suppose I have a problem which requires this array to be reshaped to instead be one dimensional and looking like (x1, y1, z1, x2, y2, z2,..., z5) which I can obviously achieve like so

real, dimension(nDim*nPoints) :: r_reshaped ! Imagine this declaration is in the correct place
r_reshaped = reshape(r, (/ nDim*nPoints/) )

which I can then assign into a different array.

If my problem required constant switching between the arrays in these two shapes, with this method, despite the fact that nothing actually needs to change in memory due to the layout of the array, I am constantly assigning values to the two separate memory locations of r and r_reshaped which seems unnecessary.

The question is, is there a way to have two references to the same piece of memory wherein fortran can perceive each of the two references as an array of different shapes? That way, any calculations/updates/use/etc of the array in either shape would affect 1 piece of memory only.

I'm assuming this can be done using pointers, though I have not used pointers in fortran before. Also, I would appreciate that if the solution changes should the array be dynamically allocated, please flag that.

Please feel free to clarify anything. Cheers

Immot
  • 241
  • 2
  • 7
  • Does the Fortran “EQUIVALENCE” statement still work? – lastchance May 08 '23 at 05:12
  • Yes, `equivalence` has not been deleted. – Vladimir F Героям слава May 08 '23 at 06:25
  • There's a way to do it with Pointers that I can never remeber and I'm away from my books at the moment - but it's definitely described in Metcalf, Reid and Cohen – Ian Bush May 08 '23 at 07:07
  • Not sure why this has been closed: (Fortran) pointers were not much mentioned in the post that this has been marked as duplicate of. Both EQUIVALENCE and pointers work, although EQUIVALENCE has been declared obsolescent in the latest Fortran standard. As Ian Bush wrote, the pointers technique is in Metcalf, Reid and Cohen (which I highly recommend). – lastchance May 08 '23 at 07:24
  • Would that "pointers technique", @lastchance, be the one given by the accepted answer of the linked question? – francescalus May 08 '23 at 07:33
  • Ah yes @francescalus - you are right. I noted that the accepted answer started with a rather prominent RESHAPE, but failed to notice that it then went on to the "pointers" solution. So, mea culpa. – lastchance May 08 '23 at 07:38

1 Answers1

0

Pointers are a solution, but they work the other way: you have to declare the array as rank 1, and then point it as a rank 2:

integer :: nDim = 3, nPoints = 5
real, target :: r1(nDim*nPoints)
real, pointer :: r2(:,:)

r2(1:nDim,1:nPoints) => r1(:)

Then you can use indifferently r1 or r2

Also, remind that when passing an array to a subroutine, dimension mismatch are allowed as long as the dummy argument is not "assumed shape".

The following will work:

integer :: nDim = 3, nPoints = 5
real :: r2(nDim,nPoints)

call someroutine(nDim*nPoints,r2)

...

subroutine someroutine(n,r1)
integer, intent(in) :: n
real, intent(in) :: r1(n)   ! r1(*) would also do
                            ! but not r1(:)
...
PierU
  • 1,391
  • 3
  • 15