I have written a simple test program to try subroutines and the call statement in Fortran. I am using gfortran compiler in GNU/Linux. I have declared 14 parameters which are numbered accordingly in my code. While my code works PERFECTLY WELL when I try to pass 11 of those arguments through the call statement, I encounter a rather strange 'SYNTAX ERROR' when I try to include a 12th argument and I try to pass 12 arguments through the call statement. What might the problem be and how might I fix it? Here is the program I am talking about
`
program test
IMPLICIT REAL*4(A-B,D-H,O-Z)
IMPLICIT COMPLEX(C)
COMPLEX*16 CQC,CQV
parameter k1=2
parameter k2=2
parameter k3=2
parameter k4=2
parameter k5=2
parameter k6=2
parameter k7=2
parameter k8=2
parameter k9=2
parameter k10=2
parameter k11=2
parameter k12=2
parameter k13=2
parameter k14=2
call bins(k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12)
end program
subroutine bins(k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12)
integer k1, k2, k3, k4, k5
end subroutine `
Following is the error that I get when I include k12 in the 'call' statement and then compile it:
`
siddharth#siddharth-VBox:~/Desktop/Codes$ gfortran test6.for -o test6.out
test6.for:23.72:
call bins(k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12
1
Error: Syntax error in argument list at (1)
test6.for:29.72:
subroutine bins(k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k1
1
Error: Unexpected junk in formal argument list at (1)
test6.for:2.72:
program test
1
test6.for:31.72:
integer k1, k2, k3, k4, k5
2
Error: Two main PROGRAMs at (1) and (2)
`
I reiterate that I don't encounter any problems in compiling when I include the arguments k1 to k11 in the call statement, its just the introduction of a 12th argument that introduces the problem. Any help will be appreciated.
Files with a .for or .f extension, by convention, are treated as fixed form source. Statements on fixed form lines must go in between columns 7 and 72, inclusive. Note the column position in the error message - the end of your statement is being chopped off.
Fixed form source is also not sensitive to whitespace. All the parameter kxxx assignment statements before the call statement don't do what you think.
Do not use fixed form source unless you are modifying existing legacy code.
Do not use implicit typing unless you are modifying existing legacy code (or perhaps engaging in some esoteric application of generic programming). IMPLICIT NONE is your best friend.
Related
This question already has answers here:
Segmentation fault with optional arguments in Fortran functions
(1 answer)
Fortran 2003 / 2008: Elegant default arguments?
(7 answers)
Closed 4 years ago.
I want to use a function's parameter with attribute "value". It is an optional parameter and I want to use it when it has not been passed. I expect that there is a local variable associated with the optional parameter, because the optional paramter is passed by value and not by reference. But strange things occurr when I try to do it.
In the example below, the string "Hello" should be printed, but the contents of the character parameter "Str" seems to be empty.
module test_value_mod
implicit none
contains
subroutine printStr(Str, AddTip)
! Declaration of parameters
character(len=*), intent(in) :: Str
logical, optional, value :: AddTip
if (.not. present(AddTip)) AddTip = .False.
write (*,*) 'Str: ', Str
if (AddTip) write (*,*) 'Tip is printed.'
end subroutine printStr
end module test_value_mod
program test_value_prog
use test_value_mod
implicit none
call printStr('Hello')
end program test_value_prog
However, when I pass the charaacter length as another parameter, there is no problem:
module test_value_mod
implicit none
contains
subroutine printStr(Str, LenStr, AddTip)
! Declaration of parameters
integer, intent(in) :: LenStr
character(len=LenStr), intent(in) :: Str
logical, optional, value :: AddTip
if (.not. present(AddTip)) AddTip = .False.
write (*,*) 'Str: ', Str
if (AddTip) write (*,*) 'Tip is printed.'
end subroutine printStr
end module test_value_mod
program test_value_prog
use test_value_mod
implicit none
call printStr('Hello', len_trim('Hello'))
end program test_value_prog
I use gfortran 7.3.0. But if I compile with ifort 17.0.4, I get the following error for the two examples given above:
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image PC Routine Line Source
test_value_passin 0000000000402C64 Unknown Unknown Unknown
libpthread-2.17.s 00007EFDA90825E0 Unknown Unknown Unknown
test_value_passin 000000000040288D test_value_mod_mp 15 test_value_passing.f08
test_value_passin 0000000000402A08 MAIN__ 29 test_value_passing.f08
test_value_passin 00000000004027CE Unknown Unknown Unknown
libc-2.17.so 00007EFDA8CD1C05 __libc_start_main Unknown Unknown
test_value_passin 00000000004026E9 Unknown Unknown Unknown
Line 15 in "test_value_mod_mp" is:
if (.not. present(AddTip)) AddTip = .False.
So, I think that the use of an optional paramter pased by value when it has not been actually provided, is invalid. But, however, gcc permits it, failing only if you provide another input paramter of type character of assumed length.
Could anybody clarify?
I am not familiar with errors in Fortran. Could you please explain what are these errors?
int.f90(18): error #5082: Syntax error, found IDENTIFIER 'K' when expecting one of: ( % : . = =>
do k=0.0 to m
---^
int.f90(19): error #5082: Syntax error, found IDENTIFIER 'Q' when expecting one of: ( % : . = =>
do q=1 to m-1
----^
int.f90(20): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ) ,
f1=1/(2*pi)*(sqrt((k**2)+(Q**2)-(2*k*cos(t)))
----------------------------------------------^
int.f90(24): error #5082: Syntax error, found IDENTIFIER 'I' when expecting one of: ( % : . = =>
do i=1 to m-1
----^
int.f90(4): error #6406: Conflicting attributes or multiple declaration of name. [INT]
function int(f,a,b,int,m)
-------------------^
int.f90(9): error #6418: This name has already been assigned a data type. [M]
integer:: i,m
------------^
int.f90(10): error #6557: An =initialization-expr is missing; an initialization expression is required when using the PARAMETER attribute. [PI]
real,parameter:: pi,pi=3.14
-----------------^
int.f90(10): error #6418: This name has already been assigned a data type. [PI]
real,parameter:: pi,pi=3.14
--------------------^
int.f90(11): error #6557: An =initialization-expr is missing; an initialization expression is required when using the PARAMETER attribute. [EPS]
real,parameter:: eps,eps=1.89
-----------------^
int.f90(11): error #6418: This name has already been assigned a data type. [EPS]
real,parameter:: eps,eps=1.89
---------------------^
int.f90(12): error #6557: An =initialization-expr is missing; an initialization expression is required when using the PARAMETER attribute. [E]
real,parameter:: e,e=1.602*((10)**(-19))
-----------------^
int.f90(12): error #6418: This name has already been assigned a data type. [E]
real,parameter:: e,e=1.602*((10)**(-19))
-------------------^
int.f90(21): error #6099: An ENDDO statement occurred without a corresponding DO or DO WHILE statement.
end do
-^
int.f90(23): error #6099: An ENDDO statement occurred without a corresponding DO or DO WHILE statement.
end do
-^
int.f90(26): error #6410: This name has not been declared as an array or a function. [F2]
s=2*f2(t)+4*f2(t+h)
-----^
int.f90(27): error #6099: An ENDDO statement occurred without a corresponding DO or DO WHILE statement.
end do
-^
and this is my code:
function int(f,a,b,int,m)
implicite none
double precision f1,f2,a,b,m,int,s
double precision h,t
integer:: k,q
integer:: i,m
real,parameter:: pi,pi=3.14
real,parameter:: eps,eps=1.89
real,parameter:: e,e=1.602*((10)**(-19))
a=0.0
b=pi
m=150
s=0.0
h=(b-a)/m
do k=0.0 to m
do q=1 to m-1
f1=1/(2*pi)*(sqrt((k**2)+(Q**2)-(2*k*cos(t)))
end do
f2=((2*pi*(e**2))/eps)*f
end do
do i=1 to m-1
t=a+(i*h)
s=2*f2(t)+4*f2(t+h)
end do
int=(h/3)*(s+f2(a)+f2(b)+4*f2(a+h))
print*,int
return
end function int
Your errors are:
Your loop-control in every one of your do loops is malformed. (Fortran 2008 Cl. 8.1.6.2 R818)
DO loops are specified as (neglecting optional syntax):
do variable=start, end
Note the comma rather than the word to.
Parenthesis must be balanced. (See Fortran 2008 7.1.2.2 R701 ( expr ))
Every left parenthesis ( must have a corresponding right parenthesis ). Your statements assigning f1 and f2 both have more left parenthesis than right parenthesis.
Declaring a variable twice in the same scoping unit is wrong. (Fortran 2008 Cl. 16.3.1 paragraph 3, see also: Cl. 5.2)
To delcare a variable and initialize it, you need only use its name once
real, parameter :: pi=3.14
You call the function int and a dummy variable int. You need to use different names for these.
You declare m as both integer and double precision. You can only declare it as one type, not two.
Of note:
Fix errors starting with the first ones, as later ones can be caused by the compiler throwing out earlier bad statements and will go away when those are fixed.
Real values in do loop variables are deleted in the latest standard, and should be avoided in new code. (Fortran 2008 Annex B.1 2(1)).
Your code demonstrates a lack of understanding in Fortran and you will benefit greatly from finding a Fortran tutorial that covers the basics of variables and loops.
I have a sub routine file as follows
subroutine grids(Ngrids,gridsize,boundx,boundy,boundz,occmatrix,myid)
implicit NONE
integer i,j,k,Ngrids, occmatrix(14,14,10)
integer locx,locy,locz,myid
double precision gridsize,boundx,boundy,boundz
do i = 1, 14
do j = 1, 14
do k = 1, 10
occmatrix(i,j,k) = 0
enddo
enddo
enddo
open (13, file = 'grid_data.9deg')
write(*,'(A,i2)'),' READING GRID FILE ON PROC.....',myid
read(13,*) Ngrids,gridsize
read(13,*) boundx,boundy,boundz
do i = 1, Ngrids
read(13,*) locx, locy, locz
occmatrix(locx,locy,locz) = 1
enddo
close(13)
return
end
It gives the following syntax error in compiling
subroutine grids(Ngrids,gridsize,boundx,boundy,boundz,occmatrix,my
1
Error: Unexpected junk in formal argument list at (1)
It used to run well before
I would believe, your line is to long. Did you add a new argument? Your code looks like free form, but it might be the compiler tried to apply fixed form due to a .f suffix in the filename or something like that. Convince the compiler to assume free formatted source code (by compiler options or usually a .f90 suffix).
Even in free formatted files your line width is limited and you should break longer lines, which would for example look like:
subroutine grids( Ngrids,gridsize,boundx,boundy,boundz, &
& occmatrix,myid )
If you are stuck with fixed format you need to indicate a continuation line by a non blank character in column 6.
Here is how it looks like in fixed form:
subroutine grids(Ngrids,gridsize,boundx,boundy,boundz,
& occmatrix,myid)
Please do not use fixed form anymore! Instead, change your files to end with .f90, most compilers recognize this for free formatted code.
I am working with a FEM program written in Fortran language. It is a mechanical analysis that involves multiple set of material. The important variables are saved into modules that have the following form
MODULE element
implicit none
save
TYPE proel_type
INTEGER:: prop1
INTEGER:: prop2
REAL:: prop3
REAL:: prop4
...
INTEGER, ALLOCATABLE :: list1(:)
REAL, ALLOCATABLE :: array1(:)
...
INTEGER:: LTYPE
...
END TYPE proel_type
TYPE(proel_type), ALLOCATABLE:: proel(:)
INTEGER:: prop1
INTEGER:: prop2
REAL:: prop3
REAL:: prop4
...
INTEGER:: LTYPE
INTEGER:: ISETS
...
END MODULE element
As you can see, proel is an allocatable data structure that contains some information about the properties of the material, the element and so on. This data is taken from a text file through a I/O routine like
SUBROUTINE setdata
USE element
IMPLICIT NONE
ALLOCATE(PROEL(NSETS))
DO ISETS=1,NSETS
... ! here I am loading succefully the string variable STRVAR
! from the text file with data
LTYPE=GETVAL(STRVAR) ! here I retreive the value of LTYPE
PROEL(ISETS)%LTYPE=LTYPE ! here I save the (integer) variable for the set
IF(LTYPE.NE.0)THEN
CALL SETELM
END IF
END DO
END SUBROUTINE
Inside subroutine SETELM I am setting some particular parameters used in the program, but at some point I recall LTYPE saved in PROEL
SUBROUTINE SETELM
USE element
IMPLICIT NONE
LTYPE=PROEL(ISETS)%LTYPE
SELECT CASE(LTYPE)
CASE( 1)
...
CASE( 2)
...
CASE DEFAULT
...
END SELECT
END SUBROUTINE
Now, between the assignment LTYPE=PROEL(ISETS)%LTYPE and the SELECT CASE(LTYPE), the variable LTYPE changes value without any reason. The value is random (in the sense that I do not know where it comes from but it is not like uninitialized vars) and there are no others operations in the middle that work with LTYPE.
I am working with VS2008 and Fortran, so I turned on every warning, but neither compilation nor runtime give some possible hint.
Do you have any idea why is that happening?
I'm trying to write a time variable from a hydrodynamic model into a netcdf file (unlimited dimension variable). I've attached a simplified code example in Fortran90 that highlights my issue.
The subroutine to write the netcdf file is called multiple times during a simulation depending on a user specified output interval (10 times for this example). I can create the file and add attributes for the first time the subroutine is called.
I can't get the start and count variables correct to write the time variable to the file during the subsequent calls of the subroutine. This is the error, at the writing the model time variable, I receive when trying to compile the code: Error: There is no specific function for the generic 'nf90_put_var'
PROGRAM test_netcdf
IMPLICIT NONE
INTEGER :: N
REAL :: time_step = 2.
! Call efdc_netcdf 10 times
DO N=1,10
CALL efdc_netcdf(N, time_step)
time_step=time_step + 1.
ENDDO
END PROGRAM test_netcdf
************************************
! Create NetCDF file and write variables
SUBROUTINE efdc_netcdf(N, time_step)
USE netcdf
IMPLICIT NONE
LOGICAL,SAVE::FIRST_NETCDF=.FALSE.
CHARACTER (len = *), PARAMETER :: FILE_NAME = "efdc_test.nc"
INTEGER :: ncid, status
INTEGER :: time_dimid
INTEGER :: ts_varid, time_varid
INTEGER :: start(1), count(1)
INTEGER :: deltat
INTEGER :: N
REAL :: time_step
start=(/N/)
count=(/1/)
! Create file and add attributes during first call of efdc_netcdf
IF(.NOT.FIRST_NETCDF)THEN
status=nf90_create(FILE_NAME, NF90_CLOBBER, ncid)
! Define global attributes once
status=nf90_put_att(ncid, NF90_GLOBAL, 'format', 'netCDF-3 64bit offset file')
status=nf90_put_att(ncid, NF90_GLOBAL, 'os', 'Linux')
status=nf90_put_att(ncid, NF90_GLOBAL, 'arch', 'x86_64')
! Define deltat variable
status=nf90_def_var(ncid,'deltat',nf90_int,ts_varid)
! Define model time dimension
status=nf90_def_dim(ncid,'efdc_time',nf90_unlimited,time_dimid)
! Define model time variable
status=nf90_def_var(ncid,'efdc_time',nf90_real,time_dimid,time_varid)
status=nf90_enddef(ncid)
! Put deltat during first call
deltat=7
status=nf90_put_var(ncid, ts_varid, deltat)
FIRST_NETCDF=.TRUE.
ENDIF
! Put model time variable
status=nf90_put_var(ncid, time_varid, time_step, start=start, count=count)
! Close file at end of DO loop
IF(N.EQ.10) THEN
status=nf90_close(ncid)
ENDIF
RETURN
END SUBROUTINE efdc_netcdf
The issue is in the line the compiler flags:
status=nf90_put_var(ncid, time_varid, time_step, start=start, count=count)
You are (correctly) trying to write a scalar variable, time_step, into a specific index (start) along variable time_varid, which is defined on a 1-d, infinite-extent dimension. However, in this case, the optional argument count isn't meaningful; you are writing the scalar, and count can only ever be 1. As a result, the fortran bindings for a nf90_put_var() taking a single scalar for input don't have the optional argument defined for count, and that's why you're getting the "no specific function for the generic' nf90_put_var" error from the compiler. This is all perfectly reasonable, but neither the error message nor the docs are super helpful in figuring out how to solve the problem.
You can fix your code by putting the time_step data into a real, dimension(1) variable, and putting that, instead; but easiest is to just get rid of the count specification, which isn't necessary here anyway:
status=nf90_put_var(ncid, time_varid, time_step, start=start)