The Fortran compiler reports an error
Expected right parenthesis in expression at (1)
What does it mean?
program energy
real::Es=0.4,Ep=-0.4,ts=0.2,tsp=2.0
integer::Nx=100
real::kx(101)
real::ky
kx(1)=-0.50
do i=1,Nx
kx(i+1)=kx(1)+i*(1.00/Nx)
end do
print*, 'Enter value for ky'
read*,ky
do i=1,101
! "The error mentions it in the next line in terminal"
Epos(i)=sqrt(-Es*(Ep+2*ts*(cos(kx(i))+cos(ky)))-(2*ts*(cos(kx(i))+cos(ky))*(Ep-2*ts*(cos(kx(i))+cos(ky))))+(4*tsp**2)*((sin(kx(i)))**2 +(sin(ky))**2)))
end do
write(*,*) Epos
end program energy
Your line is too long... You can either specify -ffree-line-length-0 for gfortran to remove the limit, or (what I would prefer), break your lines using &:
Epos(i)=sqrt( - Es*(Ep+2*ts*(cos(kx(i))+cos(ky))) &
- (2*ts*(cos(kx(i))+cos(ky))*(Ep-2*ts*(cos(kx(i))+cos(ky)))) &
+ (4*tsp**2)*((sin(kx(i)))**2 +(sin(ky))**2) )
There are two additional issues with your code:
One right bracket too much
Missing declaration of Epos
Related
I start learning Fortran and I'm doing a little case test program where the user types two real numbers and selects an arithmetic operators (from + - * /). The following error appears when the user selects "*"
F6502 : read <con> - positive integer expected in repeat field
and if the user selects "/" the compiler executes the default case, and displays this message
invalid operator, thanks
the result is 0.000000E+00
The program is as follows.
program operateur
implicit none
CHARACTER(LEN=1) :: oper
real::a,b,res
print*,'Give the first number a :'
read*,a
print*,'Give the second number b :'
read*,b
print*,'which operation ?'
read*,oper
!print*,'donnez a,b,oper :'
! read(*,*)a,b,oper
select case (oper)
case ('+')
res=a+b
case ('-')
res=a-b
case ('*')
res=a*b
case ('/')
res=a/b
case default
print*, "Invalid Operator, thanks"
end select
print*,'the result is ',res
end program operateur
FORTRAN input and output formatting rules are rather involved. Each input and ouptut statement has two arguments that have special meaning. For example
READ (10,"(2I10)") m,n
The first argument is a file descriptor. Here it is 10. The second argument "(2I10)" is the format specifier. If you give an asterisk (*) as a format specifier you switch on the list-directed formatting mode.
List directed input as the name suggests is controlled by the argument list of the input operator.
1. Why asterisk (*) is special in list-directed input mode?
The input list is split into one or more input records. Each input record is of the form c, k*c or k* where c is a literal constant, and k is an integer literal constant. For example,
5*1.01
as an instance of k*c scheme is interpreted as 5 copies of number 1.01
5*
is interpreted as 5 copies of null input record.
The symbol asterisk (*) has a special meaning in list-directed input mode. Some compiler runtimes would report a runtime error when they encounter asterisk without an integer constant in list-directed input, other compilers would read an asterisk. For instance GNU Fortran compiler is known for standards compliance, so its runtime would accept *. Other compiler runtimes might fail.
2. What's up with slash (/)?
A comma (,), a slash (/) and a sequence of one or more blanks ( ) are considered record separators in list-directed input mode.
There is no simple way to input a slash on its own in this mode.
3. Possible solution: specify format explicitly
What you can do to make the runtime accept a single slash or an asterisk is to leave the list-directed input mode by specifying the format explicitly:
read (*,"(A1)") oper
should let you input any single character.
Ok then the correct source code is
program operateur
implicit none
CHARACTER(LEN=1) :: oper
real::a,b,res
print*,'Give the first number a :'
read*,a
print*,'Give the second number b :'
read*,b
print*,'which operation ?'
read (*,"(A1)") oper
select case (oper)
case ('+')
res=a+b
case ('-')
res=a-b
case ('*')
res=a*b
case ('/')
res=a/b
case default
print*, "Invalid Operator, thanks"
end select
print*,'the result is ',res
end program operateur
I have a file which has values of pressure at every element. I require the element number (ELNO) and pressure (PLOAD) and pass through a subroutine. I am not able to read them separately from the file.
The data would read like given below starting with S175..
I want to be able to read this file, say A0001.txt, and read the lines one-by-one. When reading the lines I want to store the number after the first dot, for eg 1007, 1008 etc into a variable ELNO and the number after the last comma in a variable PLOAD in a loop. This is because I will require each value of ELNO and check a condition with the IF loop.
My problem is reading the file and storing in a variable like ELNO(i) something like that. The name S175 is constant.
I think I understand the logic. I have to store each like as a string and start iterating from the 6th position in the string till it finds the first "," and store that in ELNO(i). But I am new to FORTRAN and not able to get it. I have been trying for the past week learning FORTRAN to do this. But, not able to do this problem.
I tried a code like this below but its not reading line by line since I did not put it under a loop I guess.
S175.1007,P,0.221948
S175.1008,P,0.221943
S175.1009,P,0.221929
S175.1010,P,0.222287
S175.1018,P,0.222438
S175.1019,P,0.222425
.....
.....
.....
.....
.....
S175.13000,P,-1990
S175.13001,P,-1980
S175.13002,P,-2009
PROGRAM BARGE
implicit none
CHARACTER X*80
OPEN(UNIT=60, FILE="A0001.txt", ACCESS='SEQUENTIAL', ACTION='READ')
READ(UNIT=60, FMT='(A)', END=10)X
10 OPEN(UNIT=61, FILE="2.txt", ACTION="write")
WRITE (UNIT=61,FMT='(A)')X
END PROGRAM BARGE
Thank you everyone. I have completed it myself. There might be an easier and faster method but this works fine. Let me know if there is a more efficient method. I could learn. :)
PROGRAM BARGE
implicit none
CHARACTER PRES*80
INTEGER :: SUCCESS
INTEGER :: K, L, M, ELNO ! K is for the element number,L is word P and M is for pressure value
REAL :: PLOAD
OPEN(UNIT=60, FILE="1.txt", ACCESS='SEQUENTIAL', ACTION='READ')
DO
READ(UNIT=60, FMT='(A)', IOSTAT=SUCCESS)PRES
IF (SUCCESS.NE.0) EXIT
K=6
DO WHILE (PRES(K:K) .NE. ',')
K=K+1
END DO
READ(PRES(6:K-1), *) ELNO
PRINT *, ELNO ! ELEMENT NUMBER
L=K+1
DO WHILE (PRES(L:L) .NE. ',')
L=L+1
END DO
M=L+1
DO WHILE (PRES(M:M) .NE. ' ')
M=M+1
END DO
READ(PRES(L+1:M-1), *) PLOAD ! PRESSURE ON THE ELEMENT
PRINT *, PLOAD
OPEN(UNIT=61, FILE="2.txt", ACTION="write")
WRITE (UNIT=61,FMT='(A)')PRES
END DO
READ (*,*) PRES
END PROGRAM BARGE
It would be easy to use Fortran's list-directed input to read the data items from a line such as S175.1019,P,0.222425. The following snippet can replace the do loop in OP's own answer:
DO
READ(UNIT=60, FMT='(A)', IOSTAT=SUCCESS) PRES
IF (SUCCESS.NE.0) EXIT
READ(PRES(6:),*) ELNO, P, PLOAD
WRITE(*,*) ELNO, PLOAD
END DO
For this to work you have to include a declaration such as
CHARACTER(LEN=1) :: P
to catch the letter P in each line of the input file. The important line is this one
READ(PRES(6:),*) ELNO, P, PLOAD
which uses the edit descriptor * which tells the compiler / run-time to figure out how to read values for the three variables (one integer, one character, one real) from the 6th and following characters in the line PRES.
Fortunately, with a nice clean input file such as the one shown the compiler has no trouble reading the values, all the scanning for occurrences of , is unnecessary. If, for another application, you ever need to search a line for occurrences of a character use the intrinsic function index.
for example I have the following code
Module MPI
Use MPI
!
! MPI info
If (true) Then
Print *, ''
! empty line 1
! empty line 2
End If
Integer ithread, nthread, ierr
End Module MPI
The lines start with ! sign which is comment lines in fortran. I want those comment lines have the same indent as their previous line indent.
That is I want this format
Module MPI
Use MPI
!
! MPI info
If (true) Then
Print *, ''
! empty line 1
! empty line 2
End If
Integer ithread, nthread, ierr
End Module MPI
I want to do this in notepad++ using regex. But if there are better choice feel free to answer.
Here is what I have tried: replace ^(\s*)(.*?\r\n)\s*\! as $1$2$1!. However it produce
Module MPI
Use MPI
!
! MPI info
If (true) Then
Print *, ''
! empty line 1
! empty line 2
End If
Integer ithread, nthread, ierr
End Module MPI
There is still two lines not right. It seems that though the pattern ^(\s*)(.*?\r\n)\s*\! matches this line, however, it just skip it for the regex engine already matched previous lines.
My question is how to solve this indent problem with regex?
Using the search text ^( +)(.*\R)(!) and the replace text \1\2\1\3 then clicking on "Replace all" twice does what is wanted on the sample text. I cannot see a way of doing this in one pass.
The expression looks for a line with leading spaces followed by a line starting with a !. The capture groups are the leading spaces in \1, the rest of that line including the newline in \2 and the leading ! in \3. The replacement just assembles the captures in the right order. Note that you could omit the capture group around the ! and just have an explicit `! in the replacement, but I like to use captures in such contexts as they often allow for shorter replacements (although not in this case) and easier enhancements.
Since the engine is already passed on a comment line to indent it, I think it is impossible to use the same entire edited line for the next match to get the number of spaces. So I think you have to repeat the same replacement more times. Try with:
^(\s*)([^!\s].*?\r\n(\1\!.*?\r\n)*)\s*\!
always replacing it with $1$2$1!.
Like I said in the comment, if you have at most N consecutive comment lines, you will click on the "replace all" button N times
Further question from my last post: What is this error in fortran and how to stop the program when it occurs?
In my last post, I want to figure out how to identify the reading error when there is not enough elements in the input file which can be solved by using an iostat in the read statement.
My new code is:
program main
implicit none
integer ioerr, switch_1(3), switch_2, i, readerr
open(100, FILE='./input_error.gr', ACTION='READ', IOSTAT=ioerr)
if (ioerr == 0) then
read(100, *, iostat=readerr) (switch_1(i), i=1,3)
if(readerr .ne. 0) then
write(*,*) 'switch 1 wrong'
stop
end if
write(*,*) 'Switch_1 is: ', switch_1
read(100,*,iostat=readerr) switch_2
if(readerr .ne. 0) then
write(*,*) 'switch 2 wrong'
stop
end if
write(*,*) 'Switch_2 is: ', switch_2
else
write(*,*) 'File not read'
end if
end program main
my input file looks like this:
1,2,3
1
My new question is when there is less than three elements in the first line, the program will automatically read elements in the next line for Switch_1 and Switch_2 will have nothing to read and as the program is coded, it will return "Switch 2 wrong".
For example, when the input is like this:
1,3
2
However, what is really wrong is switch_1. Since there is not enough elements for switch_1, it goes to the next line the fill the last position of the array. This is not what I want. What I want is limit the reading in one line so the program will not read another line automatically, and in this case the program can stop at switch_1 and give me 'Switch 1 wrong. Is it possible?
I typically solve this problem by reading the line into a string first, and then attempting to read numbers from the string. For example,
character(len=200) :: str ! Long enough to hold a whole line
integer :: i(3), ier, fid
fid = 100
open(fid, FILE='./input_error.gr', ACTION='READ')
! -- Read a *single* line, and put it all into str
read(fid,'(a)') str
! -- Read str into integer array i
read(str,*,iostat=ier) i(1:3)
! -- Check if the line actually contained 3 integers
if (ier /= 0) then
write(*,*) 'Unsuccessful read'
endif
The read statement is therefore only able to use the current line because that is all str contains.
I figure out that if I add a comment at the end of each line, since character a is different data type, it will not be read as integer numbers. The advantage is when there is not enough elements for each switches, the program will read the comment first instead of reading the next line and give the right error message.
For example, make the input like:
1,2,3 ! Switch 1
4 ! Switch 2
with this structure, even if there is not enough input elements for switch 1, it is not reading 4 as the third element, instead, it is reading the comment, "! Switch 1" which will definitely return an error for Switch 1. This is exactly what I want and this works fine with number reading procedures. However, if the data type of switch_1 is character in the beginning, what will happen? It will not stop at numbers.
I have an old Fortran program for reading records from text files. The records are of the form:
record_type field1 field2 ... fieldN ;
These records might spread over several lines, the character ; shows that the record has finished. The old code is:
2 read(data,"(a130)",end=3)line
shift=adrec(nbrec)-1
read(line,*,end=1)typrec(nbrec),(field(shift+i),i=1,65)
1 do
do j=shift+1,shift+i-1
k=index(field(j),';')
if(k .ne. 0)then
if(k .eq. 1)then
adrec(nbrec+1)=j
else
field(j)(k:)=''
adrec(nbrec+1)=j+1
endif
go to 2
endif
endo
read(data,"(a130)")line
read(line,*,end=1)(field(shift+i),i=1,65)
enddo
3 continue
This code works with Intel Compiler (ifort) as it is. With gfortran it fails! The first problem is that the implicit read on the third line, with ifort, gives i to be equal to the number of fields actually read, while in gfortran it always gives 65. The second problem is that in the same implicit read, with ifort, the character ; is read as a normal field but with gfortran is skipped.
Anyone can help me solve these two problems? Any other ideas for replacing the code all together are also welcome.
Does this work? Aside from do while (and exit control structures...), this is f77 compliant (I think). The do whiles could relatively easily be replaced by goto/continue if necessary. I don't know what type you ultimately want the strings to be, so I return strings (and assume a field can't be longer than 24 characters)...I also assume a "line" can't be longer than 1024 characters.
Sorry about the lack of comments, but the function names are descriptive enough I think. Generally, I think it is a good idea to use functions/subroutines when programming as that makes the code much more readible...
program main
character*1024 line
integer stat,stat2,i,nf
character*24 fld
character*16 fmt
open(unit=21,file='test.dat',status='old')
stat=0
do while(stat.eq.0)
call readline(21,line,stat)
stat2=0
i=1
do while(.true.)
call getfield(line,fld,stat2)
if(stat2.ne.0) exit
i=i+1
write(*,*) i,stat2,fld
enddo
write(*,*) " "
enddo
end
subroutine getfield(line,field,stat)
integer l,i,stat
character*(*) line,field
!Get first field and shift the line
l=1
if(line.eq.' ')then
stat=1
else
stat=0
endif
do while (line(l:l).eq.' ')
l=l+1
enddo
i=l
do while (line(i:i).ne.' ')
i=i+1
enddo
if((line(l:l).eq.'"').or.(line(l:l).eq."'"))then
do while(line(i:i).ne.line(l:l))
i=i+1
enddo
endif
field=line(l:i)
line=line(i+1:)
return
end
subroutine readline(unit,line,stat)
integer unit
character*(*) line
integer stat,i
!read one "line" Lines are sequences seperated by ';' (can have newlines in there)
stat=0
i=1
do while (.true.)
read(unit,'(A)',end=100) line(i:)
i=index(line,';')
if(i.eq.0)then
i=len_trim(line)+2
else
line(i:)=' ' !remove the trailing semicolon.
exit
endif
enddo
return
100 continue
stat=1
return
end