INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Getting the name of an array from a string

Getting the name of an array from a string

(OP)
Hello everybody,

I have a question related to fortran 90. I have a subroutine named for instance f1 that needs an array 'a' (defined as double precision) and gives some output. That is ----> f1(a,output).

Now, imagine that I would like to call the subroutine f1, but giving the name of the array 'a' from a string. For example, imagine that I have three arrays named 'array1', 'array2' and 'array_test' and at a given stage of the program I create a string named 'array1' and I try that the subroutine gets it as the double percision array (array1). I think there should be some way to do it, but as I am sure that someone, a part from me, should have thought on this question, I would appreciate if you could give me a posible solution.

Thank you very much in advance

RE: Getting the name of an array from a string

But why cannot you use simple subroutine arguments like

CODE

subroutine do_with_array(my_array)
  ...
end subroutine do_with_array 
and than call it with your arrays

CODE

if (my_string .eq. 'array1') then 
  call do_with_array(array1)
else if (my_string .eq. 'array2') then
  call do_with_array(array2)
... 

RE: Getting the name of an array from a string

Or, the same thing, but...if the subroutine is contained inside a module where the arrays have been declared and, thus, are readily available inside the subroutine, you can pass the string and put the above if-then-else clause inside the subroutine (not identical, but very similar one).

RE: Getting the name of an array from a string

(OP)
Thanks guys. 'Mikrom', what you propose is what I did from the beginning. The problem is that I want to avoid using 'if' statements, as the whole program consumes lot of memory. This is why I want to create the string. For instance, if my arrays are called array1, array2, array3, and array4, and, for example, in a do loop, I am at i=3 (at this stage I would like to use array3), I could create first a string called 'array', concatenate it with i=3 to obtain the string 'array3' and then pass it to the subroutine. I would like to know if it is possible. This is my particular question. Of course, that I have other solutions like those you have proposed with the if statements, but I would like to avoi using them.

Many thanks in advance

RE: Getting the name of an array from a string

Quote (usermg)


The problem is that I want to avoid using 'if' statements, as the whole program consumes lot of memory.
IMO if it will not be more memory consuming when you add some IF-logic.

Quote (usermg)


... I want to create the string ...
For instance, if my arrays are called array1, array2, array3, and array4, and, for example, in a do loop, I am at i=3 (at this stage I would like to use array3), I could create first a string called 'array', concatenate it with i=3 to obtain the string 'array3' and then pass it to the subroutine.
Of course you can create the string and pass it to the procedure but you will still need the IF logic in the procedure, for example you can declare a subroutine which argument ist the string:

CODE

subroutine process_arrays(my_string)
character(*), intent(in) :: my_string
if (my_string .eq. 'array1') then 
  call do_with_array(array1)
else if (my_string .eq. 'array2') then
  call do_with_array(array2)
...
end subroutine process_arrays 

and then in your main program create the string and then call the subroutine like this

CODE

! TODO create string ARR_NAME which contains 
! the array name (array name + stage number)
..
! call the procedure
call process_arrays(ARR_NAME) 

RE: Getting the name of an array from a string

(OP)
Well, when I said memory consuming I just referred to time consuming (sorry). When 'if statements' are present, there is an evaluation to choose the condition and it makes the caluclations to go slower, this is why I wanted to avoid if statements in this case. However, I have found a way, playing with 'goto' to go faster.

Thanks you very much for your fast answers. I like to enter this forum to share things with programmers

RE: Getting the name of an array from a string

Goto?...come on...this is highly discourage.

By the way, if you think that an "if" evaluation is time consuming, you should check how long the string concatenation operation takes.

Another thing I would suggest doing is simply to create a short array of pointers and have them point to the beginning of each of the arrays:

arrptr(1) => array1(1)
arrptr(2) => array2(1)
arrptr(3) => array3(1)
arrptr(4) => array4(1)

then, getting back to your loop, you don't need an 'if' statement and you can simply use the loop variable:

do i = 1,4
do_with_array( arrptr(i) )
end do

RE: Getting the name of an array from a string

Quote (usermg)


I like to enter this forum to share things with programmers
You are welcome.

RE: Getting the name of an array from a string

(OP)
Thanks salgerman for your suggestion. In fact, in my case, I have arrays defined such as 'array1(:,:)', 'array2(:,:)', 'array3(:,:)'.... which I allocate during the program. I have tried to create a short array of pointers pointing to the first element of each of these matrices, but it seems to fail (I have tried different ways to write the assignation =>). I do not know if, in this case, it is still possible to do what you suggested to me (I like the whole idea, so I wanted to ask to you if I could be doing something wrong during the way).

Thanks

RE: Getting the name of an array from a string

This works in gfortran, but I'm not sure if it's what you want

CODE

module arrays
  implicit none
  ! type pointer on matrix
  type pmatrix
      real, dimension(:,:), pointer :: ptr
  end type pmatrix
  ! array of pointers on matrix
  type(pmatrix), dimension(:), pointer::  pointers 

contains
  subroutine print_matrix(mat)
    real, dimension(:,:) :: mat
    integer :: n, i, j
    n = size(mat, 1)
    do i=1, n
      write(*,*) mat(i,:)
    end do
    write(*,*)
  end subroutine print_matrix
end module arrays

program array_pointers
  use arrays
  implicit none
  real, dimension(:,:), allocatable, target :: matrix
  integer, parameter :: N = 4
  integer :: i

  allocate(pointers(N))

  do i=1, N
    ! allocate array
    allocate(matrix(i,i))

    ! set the values
    matrix = i
    
    ! set pointer to the array
    pointers(i)%ptr => matrix

    ! print resulting array
    write(*,*) 'array of dimension', i
    call print_matrix(pointers(i)%ptr)

    ! deallocate array
    deallocate(matrix)
  end do
end program array_pointers 

Output:

CODE

$ gfortran array_pointers.f95 -o array_pointers

$ array_pointers
 array of dimension           1
   1.00000000

 array of dimension           2
   2.00000000       2.00000000
   2.00000000       2.00000000

 array of dimension           3
   3.00000000       3.00000000       3.00000000
   3.00000000       3.00000000       3.00000000
   3.00000000       3.00000000       3.00000000

 array of dimension           4
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000 

RE: Getting the name of an array from a string

I don't think that what is shown in the previous post is what is being requested, after all, those matrices do not even co-exist.

In any case, I'll be honest...I think I spoke too soon, as I am yet to use pointers in Fortran. I was just thinking back to my C days where you could get a pointer point to a spot in memory and pass that address around.

A little googling and, apparently, that is not the case in Fortran; in Fortran, for some reason, the pointer needs to be the same rank as the target.

So, I tried to do something similar to what mikrom shows and while I was able to have the matrices co-exist and display them one a time with separate calls to the subroutine, I started to get an error as soon as I tried to display them with the same, single subroutine call within a DO-loop...things got fixed as soon as I added an interface to the subroutine...go figure.

Here is the approach:
  • Declare (target) 2D matrices to process
  • Define a derived type containing a single 2D-matrix pointer
  • Declare 1D-array variable of the derived type
  • Define an interface to the processing subroutine
Here is the source code:

CODE

program p123
  integer i
  real, target, dimension(3,3) :: arr1, arr2, arr3
  
  type d2
    real, pointer, dimension(:,:) :: ptr
  end type
  type(d2), dimension(3) :: parr

  interface display
    subroutine arrdisp(a)
      real, dimension(:,:) :: a
    end subroutine arrdisp
  end interface
  
  data arr1/ 1, 2, 3, 4, 5, 6, 7, 8, 9/
  data arr2/11,12,13,14,15,16,17,18,19/
  data arr3/21,22,23,24,25,26,27,28,29/
    
  parr(1)%ptr => arr1
  parr(2)%ptr => arr2
  parr(3)%ptr => arr3
  
  do i = 1,3
    call display( parr(i)%ptr )
  end do
  
end program p123

subroutine arrdisp(a)
    real, dimension(:,:) :: a
    write(*,'(3f5.1)') ((a(i,j),j=1,3),i=1,3)
    write(*,*)
end subroutine arrdisp 
Results:

CODE

1.0  4.0  7.0
  2.0  5.0  8.0
  3.0  6.0  9.0

 11.0 14.0 17.0
 12.0 15.0 18.0
 13.0 16.0 19.0

 21.0 24.0 27.0
 22.0 25.0 28.0
 23.0 26.0 29.0 

Needless to say, my data blocks initialize the matrices column-wise as Fortran internal storage scheme is column-major.





RE: Getting the name of an array from a string

Quote (salgerman)


I don't think that what is shown in the previous post is what is being requested, after all, those matrices do not even co-exist.
There is no problem with coexisting matrices, it's similar I need only a little bit modify the code:

CODE

module arrays
  implicit none
  ! type pointer on matrix
  type pmatrix
      real, dimension(:,:), pointer :: ptr
  end type pmatrix
  ! array of pointers on matrix
  type(pmatrix), dimension(:), pointer::  pointers 

contains
  subroutine print_matrix(mat)
    real, dimension(:,:) :: mat
    integer :: n, i, j
    n = size(mat, 1)
    do i=1, n
      write(*,*) mat(i,:)
    end do
    write(*,*)
  end subroutine print_matrix
end module arrays

program array_pointers
  use arrays
  implicit none
  real, dimension(:,:), allocatable, target :: m1, m2, m3, m4
  integer, parameter :: N = 4
  integer :: i

  allocate(pointers(N))

  ! allocate arrays
  allocate(m1(1,1))
  allocate(m2(2,2))
  allocate(m3(3,3))
  allocate(m4(4,4))

  ! set the values
  m1 = 1
  m2 = 2
  m3 = 3
  m4 = 4
    
  ! set pointers to the arrays
  pointers(1)%ptr => m1
  pointers(2)%ptr => m2
  pointers(3)%ptr => m3
  pointers(4)%ptr => m4

  ! process arrays
  do i=1, N
    ! print resulting array
    write(*,*) 'array of dimension', i
    call print_matrix(pointers(i)%ptr)
  end do

  ! deallocate arrays
  deallocate(m1)
  deallocate(m2)
  deallocate(m3)
  deallocate(m4)
end program array_pointers 

Output:

CODE

$ gfortran array_pointers.f95 -o array_pointers

$ array_pointers
 array of dimension           1
   1.00000000

 array of dimension           2
   2.00000000       2.00000000
   2.00000000       2.00000000

 array of dimension           3
   3.00000000       3.00000000       3.00000000
   3.00000000       3.00000000       3.00000000
   3.00000000       3.00000000       3.00000000

 array of dimension           4
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000 

RE: Getting the name of an array from a string

Good.

While I am using Fortran 90 features with the pointer and the explicit interface, let's go ahead and truly do it the proper Fortran 90 style of using a module as mikrom does. The thing is that modules do a bit more than simply grouping stuff, as shown by the two programs above...mine without module needs an explicit interface, mikrom's with a module does not need an explicit interface...it is provided by the module, behind the scenes, as a free service.

RE: Getting the name of an array from a string

Yes sal, you are right.
Although I do not know detailed technical differences between using of modules and not using them, but I have learned that using them can save me a lot of troubles smile

RE: Getting the name of an array from a string

If somebody don't want to have module of any reason, then using CONTAINS in the program is other way to go - like this:

CODE

program array_pointers2
  implicit none
  ! type pointer on matrix
  type pmatrix
      real, dimension(:,:), pointer :: ptr
  end type pmatrix
  ! array of pointers on matrix
  type(pmatrix), dimension(:), pointer::  pointers 
  !
  real, dimension(:,:), allocatable, target :: m1, m2, m3, m4
  integer, parameter :: N = 4
  integer :: i

  allocate(pointers(N))

  ! allocate arrays
  allocate(m1(1,1))
  allocate(m2(2,2))
  allocate(m3(3,3))
  allocate(m4(4,4))

  ! set the values
  m1 = 1
  m2 = 2
  m3 = 3
  m4 = 4
    
  ! set pointers to the arrays
  pointers(1)%ptr => m1
  pointers(2)%ptr => m2
  pointers(3)%ptr => m3
  pointers(4)%ptr => m4

  ! process arrays
  do i=1, N
    ! print resulting array
    write(*,*) 'array of dimension', i
    call print_matrix(pointers(i)%ptr)
  end do

  ! deallocate arrays
  deallocate(m1)
  deallocate(m2)
  deallocate(m3)
  deallocate(m4)

contains
  subroutine print_matrix(mat)
    real, dimension(:,:) :: mat
    integer :: n, i, j
    n = size(mat, 1)
    do i=1, n
      write(*,*) mat(i,:)
    end do
    write(*,*)
  end subroutine print_matrix
end program array_pointers2 

CODE

$ gfortran array_pointers2.f95 -o array_pointers2

$ array_pointers2
 array of dimension           1
   1.00000000

 array of dimension           2
   2.00000000       2.00000000
   2.00000000       2.00000000

 array of dimension           3
   3.00000000       3.00000000       3.00000000
   3.00000000       3.00000000       3.00000000
   3.00000000       3.00000000       3.00000000

 array of dimension           4
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000
   4.00000000       4.00000000       4.00000000       4.00000000 

RE: Getting the name of an array from a string

(OP)
Hello everyone. Excuse me because I have been abroad for three days and was just able to look at the e-mail thorugh the mobile phone. I understand the idea of your codes, and they work. However, I will maybe end by using another time the if statements. My problem is that the arrays 'array1', array2', array3' and so on have different sizes (the dimension of the first one is (n,20) for instance, the dimension of the second is (n/4,22) as an example, and for the rest are also different). This is why I have to use the if statements, because in the case we are in a do loop at i=2 (for example), we have to consider the array2, and if we are at i=4 we use array4 with its size. These matrices are very big and I can not define a general matrix Agen(:,:,:) where the first index accounts for i, because of problems of internal memory (and I have to define each of the matrices with just its size).

Thanks

RE: Getting the name of an array from a string

Quote (usermg)


My problem is that the arrays 'array1', array2', array3' and so on have different sizes ...
concerning the array size - you can use function size as you see in the procedure print_matrix.

RE: Getting the name of an array from a string

yes.

As you can see, mikrom is already showing that the same kind of pointer can be use to point to matrices if different sizes...for as long as all your matrices are 2D, you should be o.k. If, one of your matrices a different number of dimensions, like 3, 4, or 5 or whatever, than, you can not use the same array of pointers.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close