Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations waross on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Array Declaration

Status
Not open for further replies.

ahad29

Mechanical
Feb 24, 2005
46
0
0
US
Hi, I am new to Fortran and using Compaq visual fortran. I tried looking up on google but couldn't resolve ths problem.

I need to declare a matrix but the dimensions of this will not be knwon till the program gets to the executable part of the code. From the executable part i get a value for say j and my matrix needs to be F(1,j). These lines in the executable part of the code
==============================
REAL, dimension(1,j):: FN
FN(1,:)=0
==============================
create the following error: "Error: A specification statement cannot appear in the executable section."

Is there a way to define a matrix in the beginning with the help of variables whose value is established in the executable part of the program. Please help.Thanks

ahad
 
Replies continue below

Recommended for you

Thanks HTH, I am going through the information. The reason i need this functionality is that I have a matrix
D=(1,1,1,0,0,0,1,1,0,0,1,0) which I have stated in my program as

REAL, DIMENSION(1,12):: D
D = RESHAPE((/1,1,1,0,0,0,1,1,0,0,1,0/),(/1,12/))

I want a matrix F such that it tells me the locations of the "1" in D

F=(1,2,3,7,8,11)

I tried a simple DO LOOP in my code
===========================
do i=1,12
if (D(1,i)==1) then
j=j+1
F(1,j)=i
end if
end do
=========================

but since my matrix F is not pre-defined it gives me an error: "Error: A specification statement cannot appear in the executable section."

In order to define the matrix F in the beginning part of the code I will have to know the number of "1" in D. The DO LOOP above does it but the number od "1"s will not be known till this part of the code is executed. That is the reason I wanted to know if there is way to define a matrix in the beginning of the code but let its dimensions vary in the later part of the code. I hope this explains my madness. May be there is an easier way to do this but since I am only a week old at Fortran I don't know how to do it. Thanks

Ahad
 
Ahad, the HTH is shorthand for Hope This Helps. It has been forever since I wrote any Fortran, but do you need an array to hold the results of the location of the "1"?

I am unfamiliar with the Function RESHAPE since I learned Fortran in 1968 and it did not exist then, but I did Google up this reference:

Maybe there is another function to do what you want.

HTH, George

_____________________________________
I have been called "A storehouse of worthless information" many times.
 
Thanks George,
The answer to your question "...but do you need an array to hold the results of the location of the "1"?
is Yes. That is exactly what I need.

ahad
 
The problem is that there is no 'realloc' function in fortran. You could try something clumsy like this
Code:
program main
   integer, dimension(1,12):: d
   integer, dimension(:), allocatable, target:: fbuf1, fbuf2
   integer, dimension(:), pointer:: f
   integer::fcount, fmax, oldmax
   D = RESHAPE((/1,1,1,0,0,0,1,1,0,0,1,0/),(/1,12/))

   fmax = 2
   fcount = 0
   print *, 'allocating'
   allocate (fbuf1(fmax))
   f => fbuf1
   do i = 1, 12, 1
      if (D(1,i) .eq. 1) then
         fcount = fcount + 1
         if (fcount .gt. fmax) then
            ! copy
            oldmax = fmax
            allocate (fbuf2(oldmax))
            do j = 1, oldmax, 1
               fbuf2(j) = fbuf1(j)
            enddo
            ! reallocate
            fmax = fmax + 2
            print *, 'reallocating'
            deallocate (fbuf1)
            allocate (fbuf1(fmax))
            ! restore
            do j = 1, oldmax, 1
               fbuf1(j) = fbuf2(j)
            enddo
            deallocate (fbuf2)
            f => fbuf1
         endif
         f(fcount) = i
         print '(12I3)', (f(j), j = 1, fcount, 1)
      endif
   enddo
   
   stop
end program main
You could make the code more efficient by buffer switching so the copy is only done once. Someone has also written a realloc function: have a look at
There is some talk about reallocate in the 2003 std but I don't have access to a 2003 compiler so I can't suggest anything about it.
 
You guys are getting way too complicated I think, for this relatively simple task. There are 2 quick ways you can handle this situation.

1) Declare your F() array up front to be the same size as your D() array. F() is always big enough now. You just need one other variable to keep track of the maximum "needed" size of F(). If D() is not a huge array, this is probably the simplest, fastest executing, most efficient way to do things.

2) Declare F() as an allocatable array up front. Use the COUNT function to quickly count the number of "1" entries in D(). Allocate F() to be F(1,j) where j is the value returned by the COUNT function. Now, use a simple loop to assign values to all the elements in F(). Once again, unless D() is really huge, this will be a quick, painless procedure. This method is only marginally more complex than the first method above.

You can always use pointers as XWB did in his example ( I didn't review it closely ), but... pointers are more error prone, harder to understand, and... if F() needs to be very big at all, pointers will slow your code down considerably. I tend to only recommend pointer usage where there is no other viable method ( my opinion only of course ).

Dan :)
dan@dtware.com
 
Perhaps this will help ...
You can dimension an array using integer variables.
these variables can be passed into your function or subroutine along with the value you want to assign
As a very basic example:-

SUBROUTINE DOTHIS(NARG,MARG,VALUE)

DIMENSION MYARRAY(NARG,MARG)

DO I=1,MARG
DO J=1,NARG
MYARRAY(I,J)=VALUE
END DO
END DO

END

To add complexity, the VALUE could alternatively be assigned by CALL functions or subroutines within the DO statements ... or maybe this is far too simple and I have not grasped your question!

 
in order to use a matrix whose dimensions are not known beforehand u can use an allocatable matrix, eg:

program
.
real, allocatable :: a:),:)
.
.
.
.
allocate ( a(3,6) )
.
end

this creates a matrix and u get to give the dimensions u want later on. it could be like this:

program
integer, allocatable :: a:),:)
.
.
write(*,*) 'input n and m matrix dimensions'
read(*,*) n, m
.
allocate ( a(n,m) )
.
.
end

this would allow you to have a matrix and input the dimensions you want every time you run the program.
 
Status
Not open for further replies.
Back
Top