I am writing following fortran 90 program and compiling with GNU Fortran Compiler. However, I am getting some errors that I can't resolve. Can someone explain me where I am going wrong?
PROGRAM FILE1
IMPLICIT NONE
INTEGER:: status,a,b,c,i,j
a=5
b=6
c=1
REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1
ALLOCATE (arr1(a,b))
DO i=1,a,1
DO j=1,b,1
arr1(i,j)=c
c=c+1
END DO
END DO
DO i=1,a,1
DO j=1,b,1
WRITE (*,100,ADVANCE=NO) arr1(i,j)
100 FORMAT (1X,I4.1)
END DO
WRITE (*,110)
110 FORMAT ('',/)
END DO
DEALLOCATE(arr1)
END PROGRAM
I got several errors, e.g. in statement REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1 Error: Unexpected data declaration statement at (1). I checked syntax from several sources, but no luck. There is error in statement WRITE (*,100,ADVANCE=NO) arr1(i,j) too. Can someone comment?
The posted code has a couple of issues:
you need to define all your variables before you execute any other statement.
a=5
b=6
c=1
should come after your last variable definition:
REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1
You need to quote NO in the WRITE statement:
WRITE (*,100,ADVANCE="NO") arr1(i,j)
Since you are writing a REAL value, you need to give a floating point format in such as f or g
100 FORMAT (1X,f7.3)
The working code would be:
PROGRAM FILE1
IMPLICIT NONE
INTEGER:: status,a,b,c,i,j
REAL,ALLOCATABLE,DIMENSION (:,:) :: arr1
a=5
b=6
c=1
ALLOCATE (arr1(a,b))
DO i=1,a,1
DO j=1,b,1
arr1(i,j)=c
c=c+1
END DO
END DO
DO i=1,a,1
DO j=1,b,1
WRITE (*,100,ADVANCE="NO") arr1(i,j)
100 FORMAT (1X,f7.3)
END DO
WRITE (*,110)
110 FORMAT ('',/)
END DO
DEALLOCATE(arr1)
END PROGRAM
Related
subroutine iswap (file,b)
implicit none
integer b,m
character*(*) file
m=1
do while (file(m:).ne.' ')
m=m+1
enddo
m=m-1
open(1, File = file(1:m),form='formatted')
write (1,*) b
close(1)
end
subroutine iswap1 (file,b1,c1)
implicit none
integer m,b1,c1
character*6 file
m=1
do while (file(m:).ne.' ')
m=m+1
enddo
m=m-1
call iswap(file(1:m)//'.jk',b1)
call iswap(file(1:m)//'.bk',c1)
end
program callex
implicit none
character*6 unit
call iswap1(unit,2,3)
end
I'm trying to write the code that generates two files ".jk" and ".bk", each containing the value 2 and 3. The code I wrote is not not creating any file. Could you please guide me in correcting this code keeping the code format same? The main program calls "iswap1" subroutine, which then calls "iswap2" subroutine that writes values to files with the extension mentioned in "iswap1" subroutine. Thanks!
Here's the code roughly written in idiomatic modern Fortran:
program callex
implicit none
character(len=80) :: fname = "thefile"
call iswap1(fname,2,3)
contains
subroutine iswap (file,b)
implicit none
integer, intent(in) :: b
character(len=*), intent(in) :: file
integer :: unit
open(newunit=unit, File = file ,form='formatted')
write (unit,*) b
close(unit)
end subroutine iswap
subroutine iswap1 (file,b1,c1)
implicit none
integer, intent(in) :: b1,c1
character(len=*), intent(in) :: file
call iswap(trim(file)//'.jk',b1)
call iswap(trim(file)//'.bk',c1)
end subroutine iswap1
end program callex
Some notable changes from your original version:
Use contained procedures to get argument checking.
character variables declared with length per modern syntax.
Initial character variable, fname initialized (and made a bit longer because why not). Also I initialized fname to a non-empty string because otherwise on Unix type systems the generated files will be hidden as the name would start with ..
Dummy character variables declared with len=* meaning they get the length from the caller.
Declare intent for dummy arguments.
Use trim instead of a loop to get rid of trailing spaces.
Use NEWUNIT= when opening units rather than manually allocating unit numbers.
subroutine iswap (file, b)
integer b
open(1,file = "file",status='unknown',form="unformatted")
write (1) b
close(1)
end
program callex
open(22, file = 'data1.dat')
call iswap(file,2)
close(22)
stop
end
Output: empty dat1.dat file
I'm completely new to Fortran. I'm trying to write the code that produces an output file "dat1.dat" containing the value of b, i.e 2, by using the "iswap" subroutine, but I'm getting an empty file. Could you please tell me the mistake I made in the code?
Thanks in advance.
By
open(1,file = "file",status='unknown',form="unformatted")
you are opening (creating if does not exiat) creating a file called "file"
and by
write (1) b
you write the value of b to this file.
The file "data1.dat" is opened under unit 22 so you have to write to that unit if you want to write to this file.
write (22) b
There is no reason to open and close another file called "file" in your subroutine.
It is also very important to use implicit none. Otherwise you have will be surprised by having undeclared stuff like the file variable you use in call iswap(file,2).
You can pass the unit number to your subroutine
subroutine iswap (unit, b)
implicit none
integer unit, b
write (unit) b
end
program callex
implicit none
open(22, file = 'data1.dat')
call iswap(22,2)
close(22)
end
There is no reason for the stop statement before the end. It is useless and may indoce some surprising messages like the signalling FPE exceptions.
Finally, you should to learn how to put your subroutines into a module as soon as possible. I strongly suggest to avoid external subroutines if at all possible. Also use some consistent indentation (spaces at the start of the lines) so that the structure is better visible.
module subs
implicit none
contains
subroutine iswap (unit, b)
integer, intent(in) :: unit, b
write(unit) b
end subroutine
end module
program callex
use subs
implicit none
open(22, file = 'data1.dat')
call iswap(22, 2)
close(22)
end program
It is also quite useless to use status="unknown". If you want to specify status, choose something specific "old", "new", "replace", otherwise just leave it out. There are many other specifiers in the open statement that are worth learning, like action (read/write) and others that control other modes for binary files. This is not a place to show them, they are explained in various manuals, tutorials and textbooks.
I'm new to Fortran. I was given a file that is supposed to be in Fortran 90, but written to be compiled with the Lahey Fujitsu compiler (the sparse documentation states that it should be compiled with lf95 filename.f -out compiled_name #imsllf95.cmd). However, some lines are commented with c, which as I understand was the way to comment in Fortran 77. Also, matrices are declared like REAL*8, DIMENSION(23,8) :: xxx19, which again I think is from Fortran 77.
For the most part, I can compile the file with gfortran or ifort except for a section that requires the computation of a matrix inverse. Apparently, in the LF95 compiler (using a propietary module IMSLF90), a matrix inverse was computed with .i.. If I delete those inversions, the file compiles and runs with no problem (apart from the fact that it gives the wrong result).
I'm trying to find the version of Fortran this code is written in, so that I can then search for some code written in that same version so that I can invert the matrices in the code.
EDIT: The file has extension .f, even though the compiling instructions seem to imply that it is Fortran 95.
Here I have some sections of the code:
PROGRAM estimate_group
implicit none
INTEGER :: i,j,k,full,group1
REAL*8, DIMENSION(500) :: theta_start,theta_input
OPEN(68, STATUS="REPLACE",file='fit_measures.txt')
c OPEN(68, file='fit_measures.txt')
REWIND(68)
DO full=1,1
PRINT *, "=================================="
PRINT *, "FULL LOOP #: ", full
PRINT *, "=================================="
WRITE(68, *) "=================================="
WRITE(68, *) "FULL LOOP #: ", full
WRITE(68, *) "=================================="
DO group1=2,28
c Additional If statement to focus on top level and scale
c IF ( ((group1>=22) .AND. (group1<=28)) .OR. (group1==2)) THEN
IF ( group1==2) THEN
c READING IN THETA VECTOR FROM PREVIOUS ITERATIONS
c (starting values taken from prior runs theta output)
c ====================================================
IF ((group1==2) .AND. (full==1)) THEN
theta_input=0.0*theta_input
OPEN(67, file='theta_input1.txt')
REWIND(67)
DO i=1,500
READ(67,*) theta_input(i)
END DO
ELSE
theta_input=0.0*theta_input
OPEN(66,file='theta_input.txt')
REWIND(66)
DO i=1,500
READ(66,*) theta_input(i)
END DO
END IF
SUBROUTINE estimate(group1, theta_start)
INTEGER, INTENT(IN) :: group1
REAL*8, INTENT(IN), DIMENSION(500) :: theta_start
c Variable Declarations:\
INTEGER :: i,j,k,m,l,t0,i0,improve,max_m
REAL*8, DIMENSION(23,8) :: xxx19
xxx19(1:23,1) = (/554.0,541.1,583.3,593.2,615.8,582.0,582.5,546.5,
& 538.4,494.1,503.3,494.1,486.9,478.6,432.6,439.6,
& 380.4,355.4,305.9,271.8,254.6,208.8,202.8/)
Real*8 is not part of Fortran, and has never been part of Fortran. So the strict answer to your question is it is not Fortran of any vintage.
However going on what you have shown apart from Real*8 it is Fortran 90 or later. Fixed source form is still part of the language (though I would fail any students I have for using it) so it not an indicator of the vintage of the code. However after a quick look at the above I can see the following features which came into the standard language in Fortran 90:
Mixed case (outside character variables and constants)
Underscore in symbol name
Implicit None
:: in variable declarations and comma separated attribute lists
Variable names longer than 6 characters
Double inverted commas (") to delimit character strings
Do ... End Do (I assume you have missed out the End Do for some reason as otherwise the fragments above make no sense whatsoever)
== to test equality
Intent for dummy arguments
Array sections
Array constructors
There may be others.
I was trying to test my cryptography algorithm by [diehard tests] (http://stat.fsu.edu/pub/diehard/), that I realized my input file must be an unformatted and direct access file.
So I tried to write a simple program in Fortran to read from a file and write it to another.
First of all, is it the only way to make an unformatted or direct access file ?
If it is so, I've got this Error
open(unit=2, file='unf.BIN',RECL=rl , form='UNFORMATTED', access='direct')
1
Error: Syntax error in OPEN statement at (1)
I use RECL because of some missing RECL parameter in Open statement errors.(Fortran 90, Compiling program: Error messages)
Here is my Fortran code:
program BinaryWriter
implicit none
integer :: i
integer :: p
open(unit=1,file='encout')
open(unit=2, file='unf.BIN',RECL=rl , form='UNFORMATTED', access='direct')
do i=1 ,256
read (8,'(i1)') p
write(*,*) p
end do
close(1)
close(2)
end program BinaryWriter
Two things:
1) Please stop using unit numbers less than 10. Virtually all modern Fortran compilers do now have the newunit identifier, which, instead of the old unit actually picks an unused value, so always use a variable there. But even if you want to use unit, set it to a value of 10 or more.
2) For direct access, the program needs the record length. So if you have access="direct", you also need an recl=<some integer value> to tell the compiler where a new record starts.
Now in your case, you have a RECL=rl entry in the open statement, but I can't see what rl is. It needs to be a positive integer.
Edit to add: As #IanH pointed out in a comment below your question, it is possible that you are using fixed form fortran. This might be caused by the file extension of your source code file being .f or .f77. In that case, you'd have to wrap your lines manually:
program dir
implicit none
integer :: rl
open(unit=20, file='delme.bin', recl=<the record length>,
& form='unformatted', access='direct')
close(20)
end program dir
Note that the & is in the 6th position of the line. Fortran 77 code usually uses a + there, but & is also compatible with newer Fortran versions, that's why I prefer it. F77 standard is just any character in that 6th spot.
I'm learning Fortran for a new job and started writing some very, very basic programs. To compile, I'm using gcc version 4.6.2, and I'm working on Linux Suse OS (if that matters at all). I believe the version of Fortran I'm using is F90 or F95. The code is written using the VIM text editor.
Here is the program I've written
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
That's it! Oh, and the lines are indented, They start on column 8, so indentation isn't an issue.
UPDATE 1
I have tried doing this like so:
PROGRAM print_stuff
print *, z
END PROGRAM print_stuff
I also tried adding the IMPLICIT NONE statement to all of that and didn't get a change in the error.
END UPDATE 1
I save, quit, and compile. The compiler returns this error:
Error: Unexpected end of file in 'practice1.f'
Anyone know what the problem is? I've even tried removing the print statement and just having the variable declarations but the same error occurs. It's keeping me from practicing Fortran at all!
Your first version
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
is NOT a valid Fortran program. Every valid program ends with the end statement. A 'program' without an end statement is not syntactically correct. Keep reading your introductory tutorial.
I suggest you get into the habit of starting your programs with a program statement, with a name, such as
program myprog
and ending them with
end program myprog
Strictly, neither the program statement nor a program name is necessary but they do make things look a bit more comprehensible.
Oh, and while I'm writing ... don't get into the habit of starting lines at column 8, that smacks of the now out-dated fixed-form source. If you are using a reasonable compiler (such as gcc) give your filenames the .f90 suffix and let your source code run free. All the while observing good habits of indentation of course.
EDIT in response to OP's edits
PROGRAM print_stuff
print *, z
END PROGRAM print_stuff
and
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
END
are both syntactically correct. Both gfortran (v4.1.2) and Intel Fortran (v13.0.1) compile both correctly and produce executables which execute.