robaatz
robaatz

Reputation: 784

How to give an array with multiple dimensions from R to Fortran subroutine?

I want to use a fortran program in R, but I get errors when running the R program. The fortran code has REAL variables with 2 dimensions. A test code for fortran looks like: test_inside_program.f90:

program testprogram

implicit none
interface
    SUBROUTINE testm(testvar, thelength)
        IMPLICIT NONE
        REAL, INTENT(IN), DIMENSION(:) :: testvar
        INTEGER, INTENT(IN) :: thelength
    END SUBROUTINE testm
end interface

REAL, DIMENSION(:),ALLOCATABLE :: testvar
INTEGER :: i
allocate(testvar(3))
DO i = 1,2
  testvar(i) = i
ENDDO
call testm(testvar, 3)
write(*,*) 'program finished'
end program testprogram




SUBROUTINE testm(testvar,thelength)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: thelength
    REAL, INTENT(IN), DIMENSION(:) :: testvar

    write(*,*) 'program cont. X'
    write(*,*)' THe testvar 1st variable is', testvar

END SUBROUTINE testm

I want to call the subroutine testm from R. Of course I would like to maintain the dimensions. Therefore I generated following test code in R: test.r

dyn.load("test_inside_program.so")
is.loaded("testm")

dd <- c(5,2,3)
.Fortran("testm",as.single(dd),as.integer(3))

I would appreciate your help! I generate the .so with

R CMD SHLIB test_inside_program.f90

Upvotes: 1

Views: 990

Answers (2)

user1220978
user1220978

Reputation:

You can't declare an assumed shape array here, since R won't know how to pass such an array (it's not just a pointer to data, it must come together with dimensions).

This will work:

subroutine testm(testvar,thelength)
   implicit none
   integer, intent(in) :: thelength
   real, intent(in), dimension(thelength) :: testvar

   write(*,*) 'program cont. x'
   write(*,*) 'length=', thelength
   write(*,*) 'testvar=', testvar
end subroutine testm

Also, depending on your needs, you may consider declaring double precision arrays in your program and passing them "as is" from R (it's the default numeric type). For integers, you may also write 3L directly in R, thus, for single and double, it goes like this:

.Fortran("testm", as.single(dd), 3L)
.Fortran("testm", dd, 3L)

Upvotes: 1

robaatz
robaatz

Reputation: 784

Okay, problem solved! subroutines in fortran:

SUBROUTINE testm(testvar, thelength)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: thelength
    REAL, INTENT(IN), DIMENSION(thelength) :: testvar
END SUBROUTINE testm

in R

dd <- c(5.5,2,3.3)
#length(dd)
print("call fortran routine")
.Fortran("testm",as.single(dd),as.integer(3))

I dont know why it did not work before :o

Upvotes: 0

Related Questions