Passing allocatable arrays as arguments

Passing allocatable arrays as arguments

I am using a set of C++ sparsematrix routines to represent sparse matrices in Fortran.  I also have a toggle to switch between the Fortran arrays (ie. full) and the sparse functions.  Trouble is that references exist to these sparse matrices all over the code and I have to put this code in everywhere I use this functionality:

           if(iway == 0) then   ! the old "full array" way
             ALLOCATE ( GTJACB(NNIN+3,NNIN+3,LQTEAR) )
             GTJACB = 0.D0
           else                        ! the new sparse array function
             iGTJACB = matrixCreate(NNIN+3,NNIN+3,LQTEAR)
           endif

These can be 1 or 2 dimensional arrays too, eg:

            if(iway == 0) then
              ALLOCATE ( CREVAL(NNMOL1) )
              CREVAL = 0.0D0
            else
              iCREVAL = matrixCreate(NNMOL1,1,1)
            endif

I want to replace all these blocks with one call such as:

             iGTJACB = f_matrixCreate(GTJACB,NNIN+3,NNIN+3,LQTEAR)

             iCREVAL = f_matrixCreate(CREVAL,NNMOL1)

In the latter case CREVAL is a 1 dimensional array.

The code of f_matrixCreate should look something like:

      INTEGER FUNCTION f_matrixCreate(iway, fArr, nSizeA, nSizeB, nSizeC)
      IMPLICIT NONE
      include 'sparsematrix.inc'

      INTEGER :: iway
      REAL*8, allocatable :: fArr(:,:,:)
      INTEGER :: nSizeA
      INTEGER :: nSizeB
      INTEGER :: nSizeC

      if(iway == 0) then
        ALLOCATE ( fArr(nSizeA, nSizeB, nSizeC) )
        fArr = 0.D0
      else
        f_matrixCreate = matrixCreate(nSizeA, nSizeB, nSizeC)
      endif

      RETURN
      END

However this fails with an access violation on the ALLOACTE statement.  I guess the syntax is not correct.  Any idea how the code should look?  Also what about the 1 and 2 dimensional cases?  Do I need separate functions for 1, 2 and 3 dimensional cases?

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

I fixed the access violation error, I guess I'm missing an explicit declaration. I wrapped the function in a module and it works fine. However I'm still having problems with generalizing to 1 and 2 arrays. This will not complie:

MODULE SPARSEINT

CONTAINS

INTEGER FUNCTION f_matrixCreate(iway, fArr, nSizeA, nSizeB, nSizeC)
IMPLICIT NONE
! include 'sparsematrix.inc'

INTEGER :: iway
REAL*8, allocatable :: fArr(:,:,:)
INTEGER :: nSizeA
INTEGER, optional :: nSizeB
INTEGER, optional :: nSizeC

if(iway == 0) then
if(present(nSizeB) .and. present(nSizeC)) then
ALLOCATE ( fArr(nSizeA, nSizeB, nSizeC) )
elseif(present(nSizeB)) then
ALLOCATE ( fArr(nSizeA, nSizeB) )
else
ALLOCATE ( fArr(nSizeA) )
endif
fArr = 0.D0
else
! f_matrixCreate = matrixCreate(nSizeA, nSizeB, nSizeC)
endif

RETURN
END FUNCTION f_matrixCreate

END MODULE SPARSEINT

program spp
use sparseint
implicit none

integer :: iway
integer :: iGTJACB
integer :: iGT1D
REAL*8, allocatable :: GTJACB(:,:,:)
REAL*8, allocatable :: GT1D(:)

read(5,*) iway

iGTJACB = f_matrixCreate(iway, GTJACB, 2, 3, 4)
write(6,*) size(GTJACB,1), size(GTJACB,2), size(GTJACB,3)

iGT1D = f_matrixCreate(iway, GT1D, 15)
write(6,*) size(GT1D,1)

end

Help with generalizing to 1,2,3 D arrays?

Steve Lionel (Intel)'s picture

You can't do it this way. The Fortran way to do this is to have separate procedures which accept the array as rank 1, 2 and 3, and then declare a generic interface with the three module procedures. The compiler will automatically select the correct one depending on which rank argument is passed.

Steve

Quote:

sblionel wrote:

You can't do it this way. The Fortran way to do this is to have separate procedures which accept the array as rank 1, 2 and 3, and then declare a generic interface with the three module procedures. The compiler will automatically select the correct one depending on which rank argument is passed.

Sounds like a good solution. Do you have an example of this?

Below is a simple example of generic interfaces:
module mod
 
implicit none
 
interface foo
  
module procedure foo_int, foo_array
 
end interface
contains
function foo_int(x)

  integer :: x

  foo_int = x

 end function foo_int
function foo_array(x)

  integer :: x(:)

  foo_array = x(1)

 end function foo_array

end module mod

Login to leave a comment.