Related
This question already has answers here:
Unclassifiable statement and other errors in an IF in Fortran
(1 answer)
"unclassifiable statement" at if statement [duplicate]
(1 answer)
Closed 2 years ago.
I'm just starting out with Fortran and tried to write a basic program but have been getting tons of errors that I don't understand. Please check the following. I've referred to other such questions but to no avail.
program roots
real a,b,c
real disc
real root1,root2
write (*,*) , "Please provide a, b and c"
read (*,*) ,a,b,c
disc = b**2 -4.0*a*c
if disc < 0
print *,"No real roots"
else if disc = 0
print *,"Equal roots"
root1 = -b/2
print *,"root is :" ,root1
else
print *,"2 real roots"
2*root1 = -b + sqrt(b**2 - 4.0*a*c)
2*root2 = -b - sqrt(b**2 - 4.0*a*c)
print *,"root 1 is:" , root1
print *,"root 2 is:" , root2
end roots
errors:
Error: Unclassifiable statement at (1)
Error: Unexpected junk after ELSE statement at (1)
Error: Unexpected ELSE statement at (1)
Error: Non-numeric character in statement label at (1)
Error: Non-numeric character in statement label at (1)
Error: Expecting END PROGRAM statement at (1)
There were mulitple mistakes in your code.
First of all: always use implicit none otherwise undefined variables might have implicit data types which is hard to debug.
Your if .. end if block had multiple mistakes. Compare both codes.
program roots
implicit none
real a,b,c
real disc
real root1,root2
print *, "Please provide a, b and c"
read (*,*) a,b,c
disc = b**2 -4.0*a*c
if (disc < 0) then
print *, "No real roots"
else if (disc == 0) then
print *, "Equal roots"
root1 = -b/2
print *, "root is :", root1
else
print *,"2 real roots"
root1 = (-b + sqrt(b**2 - 4.0*a*c)) / 2
root2 = (-b - sqrt(b**2 - 4.0*a*c)) / 2
print *, "root 1 is:", root1
print *, "root 2 is:", root2
end if
end program
I am very new in Fortran and I am stuck with the following program to find roots using quadratic equation.
It is showing the following error:
d = sqrt(bsq \xE2\x80\x93 ac4)
1
Error: Syntax error in argument list at (1)
program quadratic
implicit none
real :: a, b, c, root1, root2
real :: bsq, ac4, d
print *, 'Please enter the coefficients a, b, and c as real numbers'
read *, a, b, c
bsq = b*b
ac4 = 4*a*c
if ( bsq < ac4) then
d = sqrt(bsq – ac4)
root1 = (-b+d)/(2*a)
root2 = (-b+d)/(2*a)
print *, 'The real roots are ', root1, root2
else if ( root1==root2) then
root1 = root2
print *, 'There is one real root which is ', root1
else
print *, 'There are no real roots'
end if
end program quadratic
You need a minus sign between bsq and ac4, not a dash. Look closely.
Minus sign: -
Dash: –
I am performing an SVD of a matrix using the LAPACK library and then multiplying the matrices to double check that they are correct. See the code below
subroutine svd_and_dgemm() ! -- Matrix decomp: A = USV^t
implicit none
integer,parameter :: m = 2
integer,parameter :: n = 3
integer i,info,lda,ldu,ldv,lwork,l,lds,ldc,ldvt,ldd
real*8 :: a(m,n),a_copy(m,n),sdiag(min(m,n)),s(m,n),u(m,m),vt(n,n),alpha,beta,c(m,n),d(m,n)
character jobu, jobv, transu, transs
real*8, allocatable, dimension ( : ) :: work
lwork = max(1,3*min(m,n) + max(m,n), 5*min(m,n))
allocate (work(lwork))
a = reshape((/3,1,1,-1,3,1/),shape(a),order=(/2, 1/)) !column-wise
print*,'A'
print*, a(1,1), a(1,2), a(1,3)
print*, a(2,1), a(2,2), a(2,3)
jobu = 'A'
jobv = 'A'
lda = m
ldu = m
ldv = n
a_copy = a
call dgesvd (jobu, jobv, m, n, a_copy, lda, sdiag, u, ldu, vt, ldv, work, lwork, info)
if ( info /= 0 ) then
write ( *, '(a)' ) ' '
write ( *, '(a)' ) 'R8MAT_SVD_LAPACK - Failure!'
write ( *, '(a)' ) ' The SVD could not be calculated.'
write ( *, '(a)' ) ' LAPACK routine DGESVD returned a nonzero'
write ( *, '(a,i8)' ) ' value of the error flag, INFO = ', info
return
end if
!
! Make the MxN matrix S from the diagonal values in SDIAG.
s(1:m,1:n) = 0.0D+00
do i = 1, min ( m, n )
s(i,i) = sdiag(i)
end do
print*,'U'
print*, u(1,1), u(1,2)
print*, u(2,1), u(2,2)
print*,'S'
print*, s(1,1), s(1,2), s(1,3)
print*, s(2,1), s(2,2), s(2,3)
print*,'Vt'
print*, vt(1,1), vt(1,2), vt(1,3)
print*, vt(2,1), vt(2,2), vt(2,3)
print*, vt(3,1), vt(3,2), vt(3,3)
deallocate (work)
! -- Verify SVD: A = USV^t
! -- Compute C = US
transu = 'N'
transs = 'N'
ldu = m; lds = m; ldc = m
alpha = 1.; beta = 1.
call dgemm(transu,transs,m,n,m,alpha,u,ldu,s,lds,beta,c,ldc)
! -- Compute A = D = CV^t
l = m ! nrows C
ldvt = n; ldd = m
call dgemm(transu,transs,m,n,n,alpha,c,ldc,vt,ldvt,beta,d,ldd)
print*,'C'
print*, c(1,1), c(1,2), c(1,3)
print*, c(2,1), c(2,2), c(2,3)
print*,'D'
print*, d(1,1), d(1,2), d(1,3)
print*, d(2,1), d(2,2), d(2,3)
end subroutine svd_and_dgemm
The output I get is
A
3.0000000000000000 1.0000000000000000 1.0000000000000000
-1.0000000000000000 3.0000000000000000 1.0000000000000000
U
-0.70710678118654835 -0.70710678118654657
-0.70710678118654668 0.70710678118654846
S
3.4641016151377553 0.0000000000000000 0.0000000000000000
0.0000000000000000 3.1622776601683795 0.0000000000000000
Vt
-0.40824829046386402 -0.81649658092772526 -0.40824829046386291
-0.89442719099991508 0.44721359549995882 5.2735593669694936E-016
-0.18257418583505536 -0.36514837167011066 0.91287092917527679
C
-2.4494897427831814 -2.2360679774997867 0.0000000000000000
-2.4494897427831757 2.2360679774997929 0.0000000000000000
D
2.9999999999999991 1.0000000000000002 0.99999999999999989
NaN 2.9999999999999991 1.0000000000000000
So I am not sure where is this NaN coming from. The odd thing is that if before printing D in such way I print it as follows:
print*,'D'
print*, d
Then I don't get the NaN anymore, so the output for D is
D
2.9999999999999991 -0.99999999999999933 1.0000000000000002 2.9999999999999991 0.99999999999999989 1.0000000000000000
D
2.9999999999999991 1.0000000000000002 0.99999999999999989
-0.99999999999999933 2.9999999999999991 1.0000000000000000
Any idea why is this happening?
PS: Information for the dgesvd (LAPACK) and dgemm (BLAS) subroutines.
So from our comments dialogue it seems like you have a problem that stems from not initializing an array. It is always good practice to do this, and in situations where you do operations like var = var +1 it is required. If you are unlucky your program will work fine anyway. But then strange things happen once in a while when some garbage happened to reside in memory where the array gets allocated.
A double should be initialized like this
array = 0.0d0 ! for double precision
or
array = 0 ! ok for single,double and integer
Initialize single precision but not double precision like this:
array = 0.0 ! single (not double) precision.
or this
array = 0.0e0 ! single (not double) precision.
I recommend the page fortran90.org.
i would like someone to assist in converting this code to C++
c ----------------------------------------------------------------------
c Calculate pressure based on the generalized Peng-Robinson equation of state.
c for water.
c Variables Used ...
c T ... temperature (K)
c P ... vapor pressure (MPa)
c V ... volume (m^3/kmol)
c ----------------------------------------------------------------------
c Instructor: Nam Sun Wang
c ----------------------------------------------------------------------
common /cblock/T
c Program Header -------------------------------------------------------
print *, 'This program calculates pressure based on the'
print *, 'generalized Peng-Robinson equation of state for water.'
print *, ' '
c Temperature ----------------------------------------------------------
print *, 'Enter temperature (K): '
read *, T
c Generate a table of P at different values of V in 0.5 increments.
print *, ' '
print *, '------------------------'
print *, ' Volume Pressure '
print *, '(m^3/kmol) (MPa) '
print *, '------------------------'
c xx.x123456789012345678 --- ruler
do i=1, 100
V = 0.5*float(i)
print 650, V, P(V)
end do
c Some formats ---------------------------------------------------------
650 format(f7.1, 1p, e18.6)
end
c ----------------------------------------------------------------------
function P(V)
c ----------------------------------------------------------------------
c Calculate pressure based on the generalized Peng-Robinson equation of state.
c for water.
c ----------------------------------------------------------------------
common /cblock/T
c Gas Constant ---------------------------------------------------------
R = 8.314E-3 ! (in MPa m3/kmol K)
c Critical parameters for water ----------------------------------------
Tc = 647.3 ! (critical temperature in K)
Pc = 22.048 ! (critical pressure in MPa)
w = 0.344 ! (acentric factor, dimensionless)
c Peng-Robinson EOS parameters -----------------------------------------
xk = 0.37464 + 1.54226*w - 0.26992*w*w
alpha = ( 1. + xk*(1.-sqrt(T/Tc)) )**2
a = 0.45724*R*R*Tc*Tc*alpha/Pc
b = 0.07780*R*Tc/Pc
P = R*T/(V-b) - a/(V*(V+b)+b*(V-b))
end
Here are Some conversions for you, have a go and then post your results. We can then help you complete it.
a message
print *, '...'
replace with
cout << "..."
a counted loop
do i=1, 100
...
end do
replace with
for(int i = 1; i <= 100; ++i) {
....
}
a comment
.... ! A comment
replace with
....; // a comment
a variable
X = 99.879
replace with
float X = 99.879
a function
function P(V)
.
.
.
P = .... ! the result
replace with
double P(double V){
.
.
.
return ....; // the result
}
I know this is late but I came here looking for an answer and found another solution.
Try the package f2c. I just used it on your code sample and it worked perfectly. Although it is a bit ugly as it links to libraries that emulate Fortran functions like print but you could just use the main logic part and do the I/O yourself.
I'm attempting my first program in Fortran, trying to solve a quadratic equation. I have double and triple checked my code and don't see anything wrong. I keep getting "Invalid character in name at (1)" and "Unclassifiable statement at (1)" at various locations. What is wrong with the code?
! This program solves quadratic equations
! of the form ax^2 + bx + c = 0.
! Record:
! Name: Date: Notes:
! Damon Robles 4/3/10 Original Code
PROGRAM quad_solv
IMPLICIT NONE
! Variables
REAL :: a, b, c
REAL :: discrim, root1, root2,
COMPLEX :: comp1, comp2
CHARACTER(len=1) :: correct
! Prompt user for coefficients.
WRITE(*,*) "This program solves quadratic equations "
WRITE(*,*) "of the form ax^2 + bx + c = 0. "
WRITE(*,*) "Please enter the coefficients a, b, and "
WRITE(*,*) "c, separated by commas:"
READ(*,*) a, b, c
WRITE(*,*) "Is this correct: a = ", a, " b = ", b
WRITE(*,*) " c = ", c, " [Y/N]? "
READ(*,*) correct
IF correct = N STOP
IF correct = Y THEN
! Definition
discrim = b**2 - 4*a*c
! Calculations
IF discrim > 0 THEN
root1 = (-b + sqrt(discrim))/(2*a)
root2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "This equation has two real roots. "
WRITE(*,*) "x1 = ", root1
WRITE(*,*) "x2 = ", root2
IF discrim = 0 THEN
root1 = -b/(2*a)
WRITE(*,*) "This equation has a double root. "
WRITE(*,*) "x1 = ", root1
IF discrim < 0 THEN
comp1 = (-b + sqrt(discrim))/(2*a)
comp2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "x1 = ", comp1
WRITE(*,*) "x2 = ", comp2
PROGRAM END quad_solv
Re the additional question of how to loop back to redo input -- an example program demonstrating loop features of Fortran >= 90. The loop is apparently infinite -- exit controlled by the IF statement exits the loop and makes the loop finite. Also shown is the cycle control, which is used if invalid input is encountered, which would otherwise crash the program. (For example, type "A" as input to the first read, instead of a number.) In this case, the iostat variable acquires a non-zero value, the IF statement activates the cycle, and the rest of the DO loop is skipped, so that the loop cycles anew.
program test_readdata
real :: a, b, c
integer :: ReturnCode
character (len=1) :: correct
ReadData: do
write (*, '( "This program solves quadratic equations of the form ax^2 + bx + c = 0. " )' )
write (*, '( "Please enter the coefficients a, b, and c, separated by commas: " )', advance='no' )
read (*,*, iostat=ReturnCode) a, b, c
if ( ReturnCode /= 0 ) cycle ReadData
write (*,*) "Is this correct: a = ", a, " b = ", b, " c = ", c
write (*, '( "Enter Y or N: " )', advance='no' )
read (*,*, iostat=ReturnCode) correct
if ( ReturnCode /= 0 ) cycle ReadData
if ( correct == 'Y' .or. correct == 'y' ) exit ReadData
end do ReadData
stop
end program test_readdata
My book recommendation: Fortran 95/2003 explained by Metcalf, Reid and Cohen.
The first thing I noticed with your code is the syntax error at the end of your program.
END
should have preceded the word program
Doesn't your editor highlight your syntax errors?
You can get the student version of ELF 90 pretty inexpensively and it's a good place to start. I would then upgrade to Lahey ELF 95 with the Visual Studio and algorithm flow chart generator which color codes the pathways of the passing of the values.
So many errors... It seems you don't know Fortran basics...
With minimal corrections
! This program solves quadratic equations
! of the form ax^2 + bx + c = 0.
! Record:
! Name: Date: Notes:
! Damon Robles 4/3/10 Original Code
PROGRAM quad_solv
IMPLICIT NONE
! Variables
REAL :: a, b, c
REAL :: discrim, root1, root2
COMPLEX :: comp1, comp2
CHARACTER(len=1) :: correct
! Prompt user for coefficients.
WRITE(*,*) "This program solves quadratic equations "
WRITE(*,*) "of the form ax^2 + bx + c = 0. "
WRITE(*,*) "Please enter the coefficients a, b, and "
WRITE(*,*) "c, separated by commas:"
READ(*,*) a, b, c
WRITE(*,*) "Is this correct: a = ", a, " b = ", b
WRITE(*,*) " c = ", c, " [Y/N]? "
READ(*,*) correct
IF (correct == 'N') STOP
IF (correct == 'Y') THEN
! Definition
discrim = b**2 - 4*a*c
! Calculations
IF (discrim > 0) THEN
root1 = (-b + sqrt(discrim))/(2*a)
root2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "This equation has two real roots. "
WRITE(*,*) "x1 = ", root1
WRITE(*,*) "x2 = ", root2
ELSEIF (discrim == 0) THEN
root1 = -b/(2*a)
WRITE(*,*) "This equation has a double root. "
WRITE(*,*) "x1 = ", root1
ELSE
comp1 = (-b + sqrt(discrim))/(2*a)
comp2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "x1 = ", comp1
WRITE(*,*) "x2 = ", comp2
END IF
END IF
END PROGRAM quad_solv
P.S. I didn't check the correctness.
P.P.S. Always indent your code to make it readable and don't use STOP statement. Each program (or subroutine) should have one entry and one exit. The only right place for STOP is exactly before END PROGRAM statement where it is redundant. So don't use STOP at all.
Some changes: correct IF syntax; constants to be real numbers rather than integers, when appropriate:
IF (CORRECT == "N" ) stop
if ( discrim > 0.0 ) then
Apply at additional locations, and you should be very close. Good luck.
It can be a poor algorithm to test a floating point number for having an exact value. What if rounding error makes disrim have the value 1.0E-30, when perfect arithmetic would give the value zero and indicate a double root?