Prev: NEQNF/DNEQNF
Next: SLATEC
From: pieterprovoost on
Hi,

I'm trying to use pointers and allocatable arrays for the first time,
but I just can't get it right. The program first calls a subroutine
which generates a matrix of which the size is given as a dummy
argument. The matrix itself is declared as allocatable. The allocation
itself happens in the subroutine I just mentioned. Then the program
calls another subroutine named run_model. I'm not sure if this is
correct but I think I can only pass a pointer to the matrix instead of
the matrix itself, because the dimensions of the matrix are only known
at run time. This subroutine calls another one which performs some
calculations with the matrix, and again, I try to pass the pointer. So,
I hope someone can tell me what's wrong with my understanding of
pointers and memory allocation...

This is the code:

program testmodel2
use model
implicit none
double precision, target, dimension(:,:), allocatable :: matrix
double precision, pointer, dimension(:,:) :: pmatrix
double precision, dimension(10) :: initial_profile
initial_profile = (/100.,0.,0.,0.,0.,0.,0.,0.,0.,0./)
call generate_matrix (matrix, 10)
write (*,*) matrix
pmatrix => matrix
call run_model (pmatrix, initial_profile, 50)
end program testmodel2

module model
contains
!***************************************
! subroutine run_model
!***************************************
subroutine run_model (pmatrix, initial_profile, iterations)
implicit none
integer :: iterations, iteration
double precision, dimension(10) :: profile
double precision, pointer, dimension(:,:) :: pmatrix
double precision, dimension(10) :: initial_profile
profile = initial_profile
open(unit=1,file='profiles.txt',status='replace')
write (1,'(10F8.3)') profile
do iteration = 1,iterations
call transition (pmatrix, profile)
write (1,'(10F8.3)') profile
end do
close(1)
end subroutine run_model
!***************************************
! subroutine transition
!***************************************
subroutine transition (pmatrix, profile)
implicit none
integer :: slices, slice, column
double precision, pointer, dimension(:,:) :: pmatrix
double precision, dimension(10) :: profile, old_profile
slices = size(profile)
old_profile = profile
do slice = 1,slices
profile(slice) = 0.
do column = 1,slices
profile(slice) = profile(slice) + pmatrix(slice,column) *
old_profile(column)
end do
end do
end subroutine transition
!***************************************
! subroutine generate_matrix
!***************************************
subroutine generate_matrix (matrix, size)
implicit none
integer :: size, n
double precision, dimension(:,:), allocatable :: matrix
allocate(matrix(size,size))
matrix(:,:) = 0.
do n = 1,size
matrix(n,n) = .9
end do
end subroutine generate_matrix
end module model

These are the errors I get:

forrtl: severe (161): Program Exception - array bounds exceeded
Image PC Routine Line Source
model.exe 0040128A MODEL_mp_TRANSITI 49 model.f90
model.exe 0040110E MODEL_mp_RUN_MODE 23 model.f90
model.exe 004018E7 TESTMODEL2 18
testmodel2.f90
model.exe 00441089 Unknown Unknown Unknown
model.exe 0042A489 Unknown Unknown Unknown
kernel32.dll 7C816FD7 Unknown Unknown Unknown
Press any key to continue

Many thanks in advance,
Piet

From: Richard E Maine on
pieterprovoost(a)gmail.com <pieterprovoost(a)gmail.com> wrote:

> I'm trying to use pointers and allocatable arrays for the first time,
> but I just can't get it right.

Actually, it looks more or less ok to me, at least at a quick glance.

> The program first calls a subroutine
> which generates a matrix of which the size is given as a dummy
> argument. The matrix itself is declared as allocatable. The allocation
> itself happens in the subroutine I just mentioned.

Be aware that allocatable dummy arguments are a feature of either f2003
or the f95 TR (which amounts to an officially standardized extension to
f95). They are also a feature that has been tricky for compiler vendors
to get correct. It would not surprise me at all to find that you have
just found a compiler bug in this regard. I don't see that you mentioned
the exact compiler and version; it might matter in this case.

> I'm not sure if this is
> correct but I think I can only pass a pointer to the matrix instead of
> the matrix itself, because the dimensions of the matrix are only known
> at run time.

No, that is not correct. That wasn't even correct in Fortran 77. The
pointer business is just unnecessary complication here. It looks like
what you have done with it is valid, but it just adds complication (and
extra places for bugs to happen) without adding anything useful. I'd
recommend getting rid of all the pointer stuff.

Note also that you don't need the allocatable attribute (and I'd
recommend not adding it) in any of the subroutines except for
generate_matrix. You only need the dummy to be allocatable when you are
doing something related to the allocation in the subroutine. You need it
in generate_matrix because of the allocate there. For the other
subroutines, you just use the array without changing its allocation in
any way. It is perfectly fine and normal to pass an allocatable (or
pointer, for that matter) array as an actual argument, while the dummy
is a non-allocatable, non-pointer, assumed shape array.

I just compiled and ran your code as is with the NAG compiler, with all
warnings tuned on. Other than the one line that wrapped in posting, and
a warning about allocatable dummies being an extension to f95, there
were no complaints. It ran "normally". I didn't check that the numbers
were actually correct, but they were at least "normal" numbers.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
From: pieterprovoost on
Thank you for your comments, Richard. Of course I should have mentioned
that I'm using Compaq Visual Fortran Professional Edition 6.6.0. I got
rid of the pointers and declared matrix like this for all the
subroutines except generate_matrix:

double precision, dimension(:,:) :: matrix

I'm not getting any errors, now, but the numbers in the matrix are a
bit strange:

0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000 1.009553927772605E-307
1.009626074980000E-307 1.623744768794673E-317 0.000000000000000E+000
1.009397748882363E-307 1.620989858753463E-317 6.150978952342684E-318
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
....

From: Michael Metcalf on

<pieterprovoost(a)gmail.com> wrote in message
news:1169836575.436238.98700(a)v33g2000cwv.googlegroups.com...
> Thank you for your comments, Richard. Of course I should have mentioned
> that I'm using Compaq Visual Fortran Professional Edition 6.6.0. I got
> rid of the pointers and declared matrix like this for all the
> subroutines except generate_matrix:
>
I ran your code without change using CVF version 6.6C, and it appears to
work perfectly. Perhaps you should apply the appropriate patch(es) to your
compiler.

Regards,

Mike Metcalf


From: pieterprovoost on
Thanks everyone. I couldn't find any updates for my version of CVF (I
did find the pages but not the files), but it works fine with G95...

Cheers,
Piet

 |  Next  |  Last
Pages: 1 2
Prev: NEQNF/DNEQNF
Next: SLATEC