Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

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

dynamical array problem

Status
Not open for further replies.

kostis1981

Programmer
Mar 17, 2007
6
GR
I have an array R defined as follows:
real, dimension:),:), pointer, save :: R
so i guess R is assigned with the ALLOCATABLE attribute

Starting the code R becomes (100,100)

In a point I want a subroutine(Ro) that takes R(100,100) and extends dimensions giving a R(102,102)
In the subroutine i want to define the values of the additional elements while i want the untouched elements to remain the same.

In the output of the subroutine i want an array R(102,102) ready for use by the following commands (i do not want to change the name R)
How do I do that???

Please provide help on the following structure:
Code:
program main
implicit none
real, dimension(:,:), pointer, save :: R
.........
call subroutine(R)
print'(...)',R(101,101)
.........
end program

subroutine(Ro)
                !how should i define Ro here???                   
                !(without conficting with R definition)
Ro(101,101)=Ro(100,100)
.........
end subroutine


THANX!!!!!








 
1) You can't have a subroutine with no name. I just assume that is a typo and you really knew that anyway.

2) save is not really required in the main program. It is useful in subroutines/functions for remembering what value a variable had when it previously exited the routine but this problem doesn't exist in the main program.

3) Do you know the dimensions of the array? With multi dimensional arrays, all except the first should really be specified so that the system knows how big your array is. I have never gotten ubound and lbound to work with dummy arrays. Something like
Code:
subroutine dump(points, xmax, ymax)
   integer, intent(in):: xmax, ymax
   integer, dimension(xmax,ymax), intent(inout):: points
   integer:: xx, yy
   do yy = 1, ymax
      print '(10I4)', (points(xx,yy), xx = 1, xmax)
   enddo
   return
end subroutine
Note that you can't flag an argument as allocatable on most f95 compilers but you can get around it using modules.
 
kostis

why do you declare R to be a pointer ? This would be a variable to point to the memory adress of some other variable. But from your question I guess you want to store values.

What I would do is the following:

Code:
module pointdata
   real,allocatable,dimension(:,:)::r
   integer::nx,ny  ! number elements in rows and columns
end module pointdata

program main
   use pointdata
   implicit none
   integer status
   logical addpoints, ll
   nx = 100
   ny = 100
   allocate(r(nx,ny),stat=status) !your original data
   if(status.ne.0)then
      print*,'allocate r went wrong'
      stop
   endif
   ll = addpoints(105,105)
   if(.not.ll)then
!      do what you need to do in case this went wrong, errormessage, abort or what
   endif

   ....
!  your further statements
   ...
end program

logical function addpoints(newnx,newny)
   use pointdata
   implicit none
   integer status,newnx,newny,jx,jy
   logical addpoints ! (don't know if needed right now)
   real,allocattable,dimension(:,:)::buffer

   addpoints=.false.
   if(newnx.lt.nx.or.newny.lt.ny)then
       print*,'attempt to reduce size of matrix'
       return
   endif
   allocate(buffer(nx,ny),stat=status)
   if(status.ne.0)then
       print*,' allocate of buffer went wrong'
       return
   endif

   buffer = r  ! save the content of r into buffer
   deallocate (r,stat=status)  ! 'delete' the old r
   if(status.ne.0)then
       print*,'deallocate r went wrong'
       return
   endif

   allocate (r(newnx,newny),stat=status) ! allocate r with new number of elements
   if(status.ne.0)then
       print*,'re-allocate of R went wrong'
       return
   endif

   do jx,1,nx
       do jy,1,ny
           r(jx,jy)=buffer(jx,jy) ! save buffer to new r
       enddo
   enddo
   nx=newnx    ! save new numbers of elements
   ny=newny
!
!  now fill up your additional elements
!
   addpoints=.true.  ! all went fine
   return
end function

 
I still cant do it...
gummibaer thanx for ur code:
Why do u use a logical function instead of a subroutine??

I wrote a more nderstandable code so u can see what i want to do

Now i get a segmentation error in the subroutine (im sure that the indices are correct)
I think that redefining L in subroutine "change" it thinks its a new variable that needs allocation and it neglects the first allocation in init..

How can i overcome this???


Code:
module variables
implicit none
real(),dimension(:,:), pointer, save :: R
integer() :: ix,iz
end module variables
...............................................
program MAIN
implicit none
integer() :: t
call init                 ! reads the first R(100,100)
                          ! from an external file
                          ! R is first allocated (100,100)          
do t=1,500
call sweep
call keep                      ! saves values for each step    
enddo
end program MAIN
...............................................
subroutine sweep
use variables
implicit none
call change(R,104,104)
print'()', R                   ! here i need the bigger R(104,104)
end subroutine sweep
...............................................
subroutine change(L,newx,newy)
use variables
implicit none
real(),dimension(:,:),allocatable :: buffer
real(),dimension(:,:),allocatable :: L

allocate(buffer(100,100))
buffer(1:100)=L(1:100)           ! HERE IS MY PROBLEM !!!!! 

deallocate(L)
allocate(L(newx,newz))

do ix=1,100
 do iz=1,100
L(ix,iz)=buffer(ix,iz)        
 enddo
enddo

L(0,5)=buffer(1,5)           

end subroutine change

Thanx all of you
 
I prefer logical functions to subroutines because I can easily handle errors this way. If the function went okay, the return value is set to .true., otherwise to .false.. You could still write your code as subroutine - just a matter of personal taste.


Some comments of mine:

You are bound to get an error: you have declared R in module variables and use this module in subroutine change. So there R(100,100) is defined in change. But you have the dummy argument L which is changed in dimension to newx,newy. And you pass R from main to your subroutine to get its dimension changed. So in the end you still have R set in your module to (100,100) but return (104,104) values to it. I do not know what the result might be - but nothing predictable for sure.

If you pass R to your subroutine by way of module variables there is no need to pass it as a dummy argument as well. In fact this is a source for errors. Just can manipulate R directly. This would be the way to do the job, if it is allways R that you want to resize, never another array.

If you have a multitude of arrays that you want to resize - I do not know (yet) how to set about.

buffer(1:100)=L(1:100)

Seems to be just a syntax error. If L and buffer have the same shape (i.e. numbers of columns and rows) then you can just write

buffer = L

(i1:i2) I only know from strings to mean character i1 to character i2 (but xwb may know more about this).

You sure should keep track of the size of your array, that is, save the number of elements in module variables.

Your subroutine change allways sets out from a matrix sized 100 by 100 elements by allocating the buffer that size. Is this allways the case ? No need to change size a second time from 104 by 104 to still more elements ?

Do you really want a printout of 104 times 104 elements exceeding 10,000 figures ?? 500 times over ?

Now if you just omit the error messages that I included then your code is pretty similar to what I proposed.

Norbert
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top