Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29348 Discussions

Passing allocatable arrays as arguments

Adrian_F_1
Beginner
726 Views

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?


0 Kudos
4 Replies
Adrian_F_1
Beginner
726 Views
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?
0 Kudos
Steven_L_Intel1
Employee
726 Views
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.
0 Kudos
Adrian_F_1
Beginner
726 Views

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?

0 Kudos
Anonymous66
Valued Contributor I
726 Views
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
0 Kudos
Reply