This question already has answers here:
How to initialize two-dimensional arrays in Fortran
(3 answers)
Closed 7 years ago.
This is my code:
program test
integer, dimension(3,3) :: a =(/1,2,3,4,5,6,7,8,9/)
do i=1,3
write(*,*) (a(i,j),j=1,3)
enddo
end program
I get the following error:
Incompatible ranks 2 and 1 in assignment at (1)
Is the initialization method wrong?
Currently you are trying to assign a 1D array (of length 9) to a 2D (3x3) array. You need to reshape the array before the assignment:
program test
integer, dimension(3,3) :: a = reshape( (/1,2,3,4,5,6,7,8,9/), (/ 3,3/))
do i=1,3
write(*,*) (a(i,j),j=1,3)
enddo
end program
Related
This question already has answers here:
Read a file with an unknown number rows in Fortran
(1 answer)
Using do loop in a Fortran 90 program to read different number of lines for n frames?
(2 answers)
Closed 1 year ago.
I am trying to read a CSV file with the following structure:
12,30,2010,23,00,01,125550,1,10643,125550,125575,4665142,0,0
12,30,2010,23,00,44,125550,1,10644,125525,125550,4665188,0,0
12,30,2010,23,01,55,125575,1,10645,125550,125575,4665287,0,0
12,30,2010,23,02,20,125550,1,10646,125550,125575,4665299,0,0
The data is presented in the standard input.
I have been suggested to look at these SO posts:
Using do loop in a Fortran 90 program to read different number of lines for n frames?
Read a file with an unknown number rows in Fortran
Both uses files, not the standard input.
I have modified my code and added the iostat check:
program file_parser
implicit none
! -------------------
! TYPE DEFINITION
! -------------------
type :: type1_record
integer :: month
integer :: day
integer :: year
integer :: hour
integer :: minute
integer :: second
integer :: field1
integer :: field2
integer :: field3
integer :: field4
integer :: field5
integer :: field6
integer :: field7
integer :: field8
end type
! -------------------
! VARIABLE DEFINITION
! -------------------
integer :: i, io_result
type(type1_record), dimension(10000) :: input_data
i = 0
do
read(*,*,iostat=io_result) input_data(i)
if (io_result /= 0) exit
i = i + 1
end do
do i = 1, 3
write(*,*) input_data(i)
end do
end program
However, when I run the program I still get Segmentation fault (core dumped):
$cat test_data.txt | ./a.out
Segmentation fault (core dumped)
Note: test_data.txt contains the data presented at the beginning.
What I am doing wrong with respect of the SO posts that have been previously suggested?
I am using flang and trying to stick to Fortran 95 standard.
This question already has answers here:
Strange Function Call behavior
(1 answer)
Ignoring the intrinsic gamma function with gfortran [duplicate]
(2 answers)
Closed 1 year ago.
The code I'm trying to compile is named gepol93 which was finished in 1994 with FORTRAN 77.
It's a program designed to compute some chemical properties of a molecule.
I tried to compile the file using the command gfortran GEPOL93.FOR but an error was raised:
EPOL93.FOR:598.72:
IF(LPR)CALL STAT(NCOR)
1
Error: Missing actual argument 'values' in call to 'stat' at (1)
I'm not familar with FORTRAN, and I guess that the code is too old to be compatible with the compiler on my computer.
What I'm certain about is that the code is definitely correct because it has never been modified by other people since 1994 (you can check this with ls -l) and many scholars are using it to conduct research nowadays.
But the question is how to compile the code into a .out file? Can anybody help me?
In the first subroutine PCOUNT, STAT is called.
SUBROUTINE PCOUNT(NATOM,NCOR,KSURF,LPR)
C -------------------------------------------------------------------
C This prints general counters
C -------------------------------------------------------------------
IMPLICIT NONE
LOGICAL FIRST
LOGICAL LPR
INTEGER*2 IUSE
INTEGER*4 I,IUC
INTEGER*4 J
INTEGER*4 MC,MI
INTEGER*4 NATOM,NCOR,NEWS
REAL*4 RE
REAL*4 XE
REAL*4 YE
REAL*4 ZE
CHARACTER*5 KSURF
PARAMETER (MC=100000,MI=6)
COMMON/CSFE/XE(MC),YE(MC),ZE(MC),RE(MC),IUSE(MC)
DIMENSION IUC(MI)
IF(LPR)WRITE(6,'(/A)')' ===> Start Subroutine Pcount '
NEWS=NCOR-NATOM
IF(KSURF.EQ.'ESURF')THEN
WRITE(6,'(3(A,I7/))')
& ' Number of INITIAL coordinates ',NATOM,
& ' Number of NEW coordinates ',NEWS,
& ' Number of TOTAL coordinates ',NCOR
ELSE
WRITE(6,'(A,I7/)')
& ' Number of TOTAL coordinates ',NCOR
END IF
IF(LPR)THEN
DO J=1,MI
IUC(J)=0
END DO
DO I=1,NATOM
J=IUSE(I)
IUC(J)=IUC(J)+1
END DO
FIRST=.TRUE.
DO J=1,MI
IF(IUC(J).NE.0)THEN
IF(FIRST)THEN
FIRST=.FALSE.
WRITE(6,'(A)')
& ' MORE INFORMATION ABOUT INITIAL SET OF COORDINATES'
END IF
WRITE(6,'(A,I2,A,I7)')
& ' Number of coordinates with IUSE ',J,'=',IUC(J)
END IF
END DO
IF(KSURF.EQ.'ESURF')THEN
DO J=1,MI
IUC(J)=0
END DO
DO I=NATOM+1,NCOR
J=IUSE(I)
IUC(J)=IUC(J)+1
END DO
FIRST=.TRUE.
DO J=1,MI
IF(IUC(J).NE.0)THEN
IF(FIRST)THEN
FIRST=.FALSE.
WRITE(6,'(A)')
& ' MORE INFORMATION ABOUT NEW SET OF COORDINATES'
END IF
WRITE(6,'(A,I2,A,I7)')
& ' Number of coordinates with IUSE ',J,'=',IUC(J)
END IF
END DO
END IF
IF(LPR)CALL STAT(NCOR)
END IF
RETURN
END
SUBROUTINE STAT(NCOR)
C -------------------------------------------------------------
C This prepares some statistics about the set of spheres
C -------------------------------------------------------------
IMPLICIT NONE
INTEGER*2 IUSE
INTEGER*4 CT6,CT4
INTEGER*4 I
INTEGER*4 J
INTEGER*4 MAXI,MC
INTEGER*4 NCOR,NINT
INTEGER*4 TMIN,TMAX
REAL*4 C
REAL*4 R1,R2,RE
REAL*4 VINT
REAL*4 XE
REAL*4 YE
REAL*4 ZE
PARAMETER (MC=100000,MAXI=100)
COMMON/CSFE/XE(MC),YE(MC),ZE(MC),RE(MC),IUSE(MC)
DIMENSION CT4(MAXI),CT6(MAXI)
WRITE(6,'(/A)')' ==> Start subroutine STAT'
VINT=0.1
TMIN=9000
TMAX=0
DO J=1,MAXI
CT4(J)=0
CT6(J)=0
END DO
DO I=1,NCOR
C=RE(I)/VINT
J=INT(C)+1
IF(IUSE(I).EQ.6)THEN
IF(J.LT.MAXI)THEN
CT6(J)=CT6(J)+1
TMAX=MAX(TMAX,J)
TMIN=MIN(TMIN,J)
END IF
ELSE IF(IUSE(I).EQ.4)THEN
IF(J.LT.MAXI)THEN
CT4(J)=CT4(J)+1
TMAX=MAX(TMAX,J)
TMIN=MIN(TMIN,J)
END IF
END IF
END DO
WRITE(6,'(A)')' RADII .GE. and .LT. TYPE 4 TYPE 6'
DO J=TMIN,TMAX
R1=(J-1)*VINT
R2=J*VINT
WRITE(6,'(2F10.5,2I10)')R1,R2,CT4(J),CT6(J)
END DO
RETURN
END
C
This question already has answers here:
Passing character strings of different lengths to functions in Fortran
(2 answers)
Closed 2 years ago.
I have a bunch of files, which contain numbers in rows. I need to write a function, that
reads from file for the first time to find amount of elements in file;
allocates an array and reads numbers from file into array;
returns an array
My function gets a string - name of the file - as an input.
So, the function that I wrote is:
function arrays_proc(name) result(arr)
character(len=128), intent(in) :: name
integer :: i, tmp, ios
character(len=30) :: line
double precision, dimension(:), allocatable :: arr
open(unit=09, file=name, status='old', iostat=ios)
if ( ios /= 0) stop "error opening file"
tmp = 0
do
read(09, '(A)', iostat=ios) line
if (ios /= 0) exit
tmp = tmp + 1
end do
allocate(arr(tmp))
rewind(09)
do i=1, tmp
read(09, '(A)') arr(i)
end do
close(09)
return
end function arrays_proc
Then, in the main program I write
...
real(8), dimension(:), allocatable :: points, potent
points = arrays_proc(trim('carbon_mesh.txt'))
potent = arrays_proc(trim('carbon_pot.txt'))
...
When I run my program, I get instant "error opening file".
I assume the problem is with names of files or how I put them in my function.
Anyway, I hope someone can help me
When compiling your code with a minimal program, GFortran prints the following warnings:
a.f90:4:25:
4 | points = arrays_proc(trim('carbon_mesh.txt'))
| 1
Warning: Character length of actual argument shorter than of dummy argument ‘name’ (15/128) at (1)
a.f90:5:25:
5 | potent = arrays_proc(trim('carbon_pot.txt'))
| 1
Warning: Character length of actual argument shorter than of dummy argument ‘name’ (14/128) at (1)
Trying to print the value of name inside arrays_proc shows that it is filled with garbage. So, guided by the warnings, you can try to change the length of the name parameter to *, which allows a string of any length to be used as input.
With that change, the function manages to open the files.
See also: Passing character strings of different lengths to functions in Fortran
I'm writing a subroutine that transform a regular vector into the one with only non-zero elements. Say, vector a=(0,0,1,2,3)' (n by 1). Then the non-zero vector is c=(1,2,3), and the row index is recorded as ic=(0,0,0,1,2,3) where ic(1)=0, ic(i+1)-ic(i) is the number of non-zero elements in i-th row. The vector index jc=(1,1,1) with size 3 as there are 3 non-zero entries. See the sparse matrix wiki for FYI: https://en.wikipedia.org/wiki/Sparse_matrix.
Despite its simplicity, I'm having troubles in running the following code named sparsem.f90
!This subroutine coverts a regular sparse matrix a into a CSR form
MODULE SPARSEM
CONTAINS
SUBROUTINE vsparse(a,c,jc,ic,counta,ierr,myid)
IMPLICIT NONE
REAL(8), INTENT(IN):: a(:)
INTEGER, INTENT(IN):: counta,myid
REAL(8), INTENT(OUT):: c(counta)
INTEGER, INTENT(OUT):: jc(counta),ic(size(a)+1)
INTEGER:: ierr,countaa,i
character(len=90):: filename
ierr=0
jc=0
c=0.0d0
ic=0
PRINT *, 'SIZE OF A IN VSPARSE', size(a),count(a>0.0d0),counta
IF (COUNT(a>0.0d0) /= counta) THEN
ierr=1
PRINT *, 'ERROR: number count of non-zero a(i,j) is not', counta
ELSE
countaa=0
ic(1)=0
DO i=1,size(a)
IF (a(i) > 0.0d0 ) THEN
countaa=countaa+1
c(countaa)=a(i)
ic(i+1)=ic(i)+1
jc(countaa)=1
IF (countaa<100) PRINT *,'checkcheckcheck', a(i), &
countaa,jc(countaa),c(countaa),jc(1:5)
ELSE
ic(i+1)=ic(i)
END IF
END DO
PRINT *, 'JCJCJCJC',jc(1:5)
END IF
IF (myid==7) THEN
WRITE(filename,'("sparsedens_dcheck",I1,".txt")') myid+1
OPEN(UNIT=212101, FILE="/home/wenya/Workspace/Model4/valuef/"//filename,ACTION='write',status='replace')
DO i=1,counta+1
IF (i<=counta) THEN
WRITE(212101,*) c(i),jc(i)
ELSE
WRITE(212101,*) 0.0D0,0
END IF
END DO
CLOSE(212101)
END IF
return
END SUBROUTINE vsparse
END MODULE SPARSEM
So the three print jc codes shall give 1 1 1 1 1.... Yet starting from the second print jc code, the result is 6750960 6750691 6750692 .... The array of jc has size 9,000,000. And I know the first 2250000 element is 0.
To replicate this problem, here is the main program
PROGRAM MAIN
USE SPARSEM
IMPICIT NONE
REAL(8):: dens_last(9000000)
REAL(8), ALLOCATABLE :: dens(:)
INTEGER, ALLOCATABLE :: ic(:),jc(:)
INTEGER:: i
dens_last(1:2250000)=0.0d0
dens_last(2250001:9000000)=1.0d0/6750000.0d0
ncount=count(dens_last>0.0d0)
ALLOCATE(dens(ncount), ic(9000000+1), jc(ncount)_
CALL VSPASEM(dens_last, dens, jc, ic, ncount,ierr)
DEALLOCATE(dens,ic,jc)
END PROGRAM MAIN
I am using gfortran 6.3.0 and openmpi latest version on a UBUNTU 17.04 computer. Although openmpi is not used in this example, it's used in the rest of the program. Any thoughts? Thanks!
Fortran 2003 has square bracket syntax for array concatenation, Intel fortran compiler supports it too. I wrote a simple code here for matrix concatenation:
program matrix
implicit none
real,dimension (3,3) :: mat1,mat2
real,dimension(3,6):: mat3
integer i
mat1=reshape( (/1,2,3,4,5,6,7,8,9/),(/3,3/))
mat2=reshape( (/1,2,3,4,5,6,7,8,9/),(/3,3/))
mat3=[mat1,mat2]
!display
do i=1,3,1
write(*,10) mat3(i,:)
10 format(F10.4)
end do
end program
But I get error as
mat3=[mat1,mat2]
Error: Incompatible ranks 2 and 1 in assignment
I expect the output as
1 2 3 1 2 3
4 5 6 4 5 6
7 8 9 7 8 9
Can someone comment where am I going wrong? What is rank 2 and 1 here? I guess all arrays have rank 2.
The array concatenation in fortran 2003 doesn't work as you think. When you concatenate, it's not going to stack the two arrays side by side. It will pick elements from the first array one by one and put into a one-dimensional array. Then it will do the same thing with the second array but it will append this to the 1-D form of first array.
The following code works.
program matrix
implicit none
real,dimension (3,3) :: mat1,mat2
real,dimension(18) :: mat3
integer i
mat1=reshape( (/1,2,3,4,5,6,7,8,9/),(/3,3/))
mat2=reshape( (/1,2,3,4,5,6,7,8,9/),(/3,3/))
mat3=[mat1,mat2]
print*, shape([mat1,mat2]) !check shape of concatenated array
!display
do i=1,18,1
write(*,10) mat3(i)
10 format(F10.4)
end do
end program
However, the result you wanted can be achieved using following code
program matrix
implicit none
real,dimension (3,3) :: mat1,mat2
real,dimension(3,6) :: mat3
integer i
mat1=reshape( (/1,2,3,4,5,6,7,8,9/),(/3,3/))
mat2=reshape( (/1,2,3,4,5,6,7,8,9/),(/3,3/))
do i=1,3
mat3(i,:)=[mat1(:,i),mat2(:,i)]
enddo
!display
do i=1,3,1
write(*,*) mat3(i,:)
end do
end program
Another way could simply be to
mat3(:,1:3) = mat1
mat3(:,4:6) = mat2
I dont know which is faster, this or the do loop above...
Fill it using 1-D arrays then reshape your mat3.