0

i have allocated a lot of 2D arrays in my code, and I want each one array to read from a file named as array's name. The problem is that each array has different size, so I am looking for the most efficient way. The code is like this:

Module Test
USE ...
implicit NONE
private
public:: initializeTest, readFile

real(kind=8),dimension(:,:),allocatable,target:: ar1,ar2,ar3,ar4,ar5,...,ar10
real(kind=8),dimension(:,:),pointer:: pAr

CONTAINS
!
subroutine initializeTest
integer:: k1,k2,k3,k4,k5
integer:: ind1,ind2

allocate(ar1(k1,k1),ar2(k1,k2),ar3(k2,k4),ar4(k5,k5),...) !variable sizes

! here needs automatization - since its repeated
pAr => ar1
ind1 = size(pAr,1)
ind2 = size(pAr,2)   
call readFile(par,ind1,ind2)

pAr => ar2
ind1 = size(pAr,1)
ind2 = size(pAr,2)   
call readFile(par,ind1,ind2)

!....ar3, ... , ar9

pAr => ar10
ind1 = size(pAr,1)
ind2 = size(pAr,2)   
call readFile(par,ind1,ind2)

end subroutine initializeTest
!
!

subroutine readFile(ar,row,col)
real(kind=8),dimension(row,col)
integer:: i,j,row,col

! it should open the file with same name as 'ar'
open(unit=111,file='ar.dat')
do i = 1, row
 read(222,*) (ar(i,j),j=1,col) 
enddo
end subroutine importFile
!
!
end module Test

2 Answers2

1

If your arrays ar1, ar2, etc. had the same dimensions you could put them all in a 3-dimensional array. Since they have different dimensions, you can define a derived type, call it a "matrix", with an allocatable array component and then create an array of that derived type. Then you can read the i'th matrix from a file such as "input_1.txt" for i=1. The program below, which works with g95 and gfortran, shows how the derived type can be declared and used.

module foo
implicit none
type, public :: matrix
   real, allocatable :: xx(:,:)
end type matrix
end module foo

program xfoo
use foo, only: matrix
implicit none
integer, parameter :: nmat = 9
integer            :: i
character (len=20) :: fname
type(matrix) :: y(nmat)
do i=1,nmat
   allocate(y(i)%xx(i,i))
   write (fname,"('input_',i0)") i
   ! in actual code, read data into y(i)%xx from file fname
   y(i)%xx = 0.0
   print*,"read from file ",trim(fname)
end do
end program xfoo
Fortranner
  • 2,525
  • 2
  • 22
  • 25
  • thank you for your answer. I think it's better way to get rid of the pointers and use a derived type array as you commented. But the problem is that my arrays that I am using have different names. I don't want to make an array y(nmat), so y(1) = array1,etc. (array1,...,array10 was an example) but in the code they have distinct names that correspond to the data that allocate and I want to be readable so that people understand what data includes. – OverStacked Apr 29 '14 at 11:06
0

As far as I know, extracting the name of the variable from the variable at runtime isn't going to work.

If you need lots of automation for the arrays, consider using an array of a derived type, as one other answer suggests, in order to loop over them both for allocation and reading. Then you can enumerate the files, or store a label with the derived type.

Sticking to specific array names, an alternative is to just read/write the files with the required name as an argument to the routine:

Module Test
...
! here needs automatization - since its repeated 
call readFile(ar1,'ar1')
call readFile(ar2,'ar2')
!....ar3, ... , ar9
call readFile(ar10,'ar10')

end subroutine initializeTest

subroutine readFile(ar,label)
real(kind=8) :: ar(:,:)
character(len=*) :: label
integer:: i,j,nrow,ncol,fd
nrow=size(ar,1)
ncol=size(ar,2)    
open(newunit=fd,file=label)
do i = 1, row
  read(fd,*) (ar(i,j),j=1,col) 
enddo
end subroutine readFile

end module Test

Some unsollicited comments: I don't really get why (in this example) readFile is public, why the pointers are needed? Also, kind=8 shouldn't be used (Fortran 90 kind parameter).

Community
  • 1
  • 1
steabert
  • 6,540
  • 2
  • 26
  • 32
  • i tried your example and it works. Answers: Pointers was my perception of how to do that, not essential to be done using pointers. I didnt know that kind=8 can generate these problems. readFile is true not essential to be public. Two questions: open(newunit=fd) seems to work with f90, isnt a feature of f08 only? also is there a way to loop this call readFile(ar1,'ar1' to ar10,'ar10') but the names of the arrays are distinct so 'ar1' may be 'grav', 'ar2' may be 'radius', etc.. Can I make a list of the array variable names and loop through it? – OverStacked Apr 29 '14 at 11:09
  • `newunit` is Fortran 2008, but it's supported by e.g. gfortran (since 4.5, see http://gcc.gnu.org/wiki/Fortran2008Status). What do you mean with 'seems to work with f90'? Are you using e.g. `-std=f95` to compile? – steabert Apr 29 '14 at 11:14
  • no i dont use std=95 somewhere. I am having a makefile to compile with intel compiler, but i mean the module file is named as Module1.f90. – OverStacked Apr 29 '14 at 11:37
  • The `.f90` file extension doesn't mean Fortran 90, it's interpreted by both gfortran and ifort that it contains free-form source code, read this: https://software.intel.com/en-us/blogs/2013/01/11/doctor-fortran-in-source-form-just-wants-to-be-free – steabert Apr 29 '14 at 11:49
  • ok i see, helpful link. Do you have any idea of how to loop the call readFile(array1,'array1') from array1 to array20. – OverStacked Apr 29 '14 at 11:56