How to compile a Fortran subroutine - fortran

I have a small fortran subroutine that I got from here: How to call a Fortran program from R I saved it on C:\Fortran\horner.f90, however, when I try compile it using the command line I get an error saying that R is not recognized. See screenshots below. I do have Rtools installed and on my PATH. Am I missing something? Thanks for any pointers.
And this is the error I get:
Here is the horner.f90 file as well:
subroutine horner(n, a, x, y)
implicit none
integer :: n, i
double precision :: a(n), x, y
y = a(n)
do i = n - 1, 1, -1
y = y * x + a(i)
end do
end subroutine
UPDATE:
Here is a screenshot of where my R icon properties look like:

In the "Edit environment variable" window, it should be one entry per path, and not several paths separated by a ;.
This window was enhanced in Windows 10, in previous versions of Windows you had to type everything as one line, managing the ; separator yourself. But this no longer holds.
When you type, say C:\a;C:\b as one entry here, then in a command line the path will have ...;"C:\a;C:\b", that is it will consider "C:\a;C:\b" as one single string describing a path, which is of course wrong, and the Console won't find anything in these directories.

Related

How to send command line input to a Fortran subroutine? [duplicate]

GCC version 4.6
The Problem: To find a way to feed in parameters to the executable, say a.out, from the command line - more specifically feed in an array of double precision numbers.
Attempt: Using the READ(*,*) command, which is older in the standard:
Program test.f -
PROGRAM MAIN
REAL(8) :: A,B
READ(*,*) A,B
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
The execution -
$ gfortran test.f
$ ./a.out 3.D0 1.D0
This did not work. On a bit of soul-searching, found that
$./a.out
3.d0,1.d0
4.0000000000000000 0
does work, but the second line is an input prompt, and the objective of getting this done in one-line is not achieved. Also the COMMAND_ARGUMENT_COUNT() shows that the numbers fed into the input prompt don't really count as 'command line arguments', unlike PERL.
If you want to get the arguments fed to your program on the command line, use the (since Fortran 2003) standard intrinsic subroutine GET_COMMAND_ARGUMENT. Something like this might work
PROGRAM MAIN
REAL(8) :: A,B
integer :: num_args, ix
character(len=12), dimension(:), allocatable :: args
num_args = command_argument_count()
allocate(args(num_args)) ! I've omitted checking the return status of the allocation
do ix = 1, num_args
call get_command_argument(ix,args(ix))
! now parse the argument as you wish
end do
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
Note:
The second argument to the subroutine get_command_argument is a character variable which you'll have to parse to turn into a real (or whatever). Note also that I've allowed only 12 characters in each element of the args array, you may want to fiddle around with that.
As you've already figured out read isn't used for reading command line arguments in Fortran programs.
Since you want to read an array of real numbers, you might be better off using the approach you've already figured out, that is reading them from the terminal after the program has started, it's up to you.
The easiest way is to use a library. There is FLAP or f90getopt available. Both are open source and licensed under free licenses.
The latter is written by Mark Gates and me, just one module and can be learned in minutes but contains all what is needed to parse GNU- and POSIX-like command-line options. The first is more sophisticated and can be used even in closed-source projects. Check them out.
Furthermore libraries at https://fortranwiki.org/fortran/show/Command-line+arguments
What READ (*,*) does is that it reads from the standard input. For example, the characters entered using the keyboard.
As the question shows COMMAND_ARGUMENT_COUNT() can be used to get the number of the command line arguments.
The accepted answer by High Performance Mark show how to retrieve the individual command line arguments separated by blanks as individual character strings using GET_COMMAND_ARGUMENT(). One can also get the whole command line using GET_COMMAND(). One then has to somehow parse that character-based information into the data in your program.
I very simple cases you just need the program requires, for example, two numbers, so you read one number from arg 1 and another form arg 2. That is simple. Or you can read a triplet of numbers from a single argument if they are comma-separated like 1,2,3 using a simple read(arg,*) nums(1:3).
For general complicated command line parsing one uses libraries such as those mentioned in the answer by Hani. You have set them up so that the library knows the expected syntax of the command line arguments and the data it should fill with the values.
There is a middle ground, that is still relatively simple, but one already have multiple arguments, that correspond to Fortran variables in the program, that may or may not be present. In that case one can use the namelist for the syntax and for the parsing.
Here is an example, the man point is the namelist /cmd/ name, point, flag:
implicit none
real :: point(3)
logical :: flag
character(256) :: name
character(1024) :: command_line
call read_command_line
call parse_command_line
print *, point
print *, "'",trim(name),"'"
print *, flag
contains
subroutine read_command_line
integer :: exenamelength
integer :: io, io2
command_line = ""
call get_command(command = command_line,status = io)
if (io==0) then
call get_command_argument(0,length = exenamelength,status = io2)
if (io2==0) then
command_line = "&cmd "//adjustl(trim(command_line(exenamelength+1:)))//" /"
else
command_line = "&cmd "//adjustl(trim(command_line))//" /"
end if
else
write(*,*) io,"Error getting command line."
end if
end subroutine
subroutine parse_command_line
character(256) :: msg
namelist /cmd/ name, point, flag
integer :: io
if (len_trim(command_line)>0) then
msg = ''
read(command_line,nml = cmd,iostat = io,iomsg = msg)
if (io/=0) then
error stop "Error parsing the command line or cmd.conf " // msg
end if
end if
end subroutine
end
Usage in bash:
> ./command flag=T name=\"data.txt\" point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
or
> ./command flag=T name='"data.txt"' point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
Escaping the quotes for the string is unfortunately necessary, because bash eats the first quotes.

Compiling Legacy Fortran Code with (more) Modern Fortran Code

I have been working with some old legacy code in Fortran used by a colleague. The actual code is proprietary, so the examples I use here are abbreviated compared to the code I'm working with.
Some of the procedures individually defined in *.f files included a file called variables.h:
Example contents of variables.h:
c VARIABLE DIMENSIONS FOR MODEL
c height_dim -- number of vertical (z) steps
c length_dim -- number of horizontal (x) steps
c width_dim -- number of horizontal (y) steps
INTEGER height_dim, length_dim, width_dim, nmodes, styleFlag
PARAMETER (height_dim=80, length_dim=50, width_dim=40)
PARAMETER (nmodes = 4,
$ styleFlag = 3)
I changed that to the following:
! VARIABLE DIMENSIONS FOR MODEL
! height_dim -- number of vertical (z) steps
! length_dim -- number of horizontal (x) steps
! width_dim -- number of horizontal (y) steps
INTEGER height_dim, length_dim, width_dim, nmodes, styleFlag
PARAMETER (height_dim=80, length_dim=50, width_dim=40)
PARAMETER (nmodes = 4, styleFlag = 3)
An example routine that uses these might be the following, called initial_conditions.f:
c This sets up the PDE's initial conditions
subroutine initial_conditions( temperature, density )
IMPLICIT NONE
INCLUDE 'variables.h'
real*8 temperature(height_dim,length_dim,width_dim)
real*8 density(height_dim)
temperature = 273.15D0
density = 1.0D0
return
end
I tried to compile a test routine written in F90 (or newer?) that included dimensions.h, but the compiler didn't like the fixed-form comments being included into the free-form *.f90 source file, so I changed all comments from c to !. Then I was able to compile my test program successfully. Let's call it test.f90:
program test
implicit none
include 'variables.h'
real*8, dimension(height_dim,length_dim,width_dim) :: vx, vy, vz
! <<Initialize data...>>
! << Output data...>>
end program test
Unfortunately, now the original code doesn't compile. It seems that code doesn't like commented lines to begin with ! (based on the fact that that was all I changed), but the actual errors it gives are the following:
variables.h(8): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: =
PARAMETER (nmodes = 4, styleFlag = 3)
------------------------------------------^
variables.h(5): error #6219: This variable, used in a specification expression, must be a dummy argument, a COMMON block object, or an object accessible through host or use association. [NMODES]
INTEGER height_dim, length_dim, width_dim, nmodes, styleFlag
---------------------------------------------^
What in the world is going on, and how can it be fixed?!
I imagine that comment styles are incompatible (free-form fortran thinks c is a variable, not a comment?), but I have no idea how it would produce these errors.

Command line arguments in fortran (a filename, an integer, and another filename) [duplicate]

GCC version 4.6
The Problem: To find a way to feed in parameters to the executable, say a.out, from the command line - more specifically feed in an array of double precision numbers.
Attempt: Using the READ(*,*) command, which is older in the standard:
Program test.f -
PROGRAM MAIN
REAL(8) :: A,B
READ(*,*) A,B
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
The execution -
$ gfortran test.f
$ ./a.out 3.D0 1.D0
This did not work. On a bit of soul-searching, found that
$./a.out
3.d0,1.d0
4.0000000000000000 0
does work, but the second line is an input prompt, and the objective of getting this done in one-line is not achieved. Also the COMMAND_ARGUMENT_COUNT() shows that the numbers fed into the input prompt don't really count as 'command line arguments', unlike PERL.
If you want to get the arguments fed to your program on the command line, use the (since Fortran 2003) standard intrinsic subroutine GET_COMMAND_ARGUMENT. Something like this might work
PROGRAM MAIN
REAL(8) :: A,B
integer :: num_args, ix
character(len=12), dimension(:), allocatable :: args
num_args = command_argument_count()
allocate(args(num_args)) ! I've omitted checking the return status of the allocation
do ix = 1, num_args
call get_command_argument(ix,args(ix))
! now parse the argument as you wish
end do
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
Note:
The second argument to the subroutine get_command_argument is a character variable which you'll have to parse to turn into a real (or whatever). Note also that I've allowed only 12 characters in each element of the args array, you may want to fiddle around with that.
As you've already figured out read isn't used for reading command line arguments in Fortran programs.
Since you want to read an array of real numbers, you might be better off using the approach you've already figured out, that is reading them from the terminal after the program has started, it's up to you.
The easiest way is to use a library. There is FLAP or f90getopt available. Both are open source and licensed under free licenses.
The latter is written by Mark Gates and me, just one module and can be learned in minutes but contains all what is needed to parse GNU- and POSIX-like command-line options. The first is more sophisticated and can be used even in closed-source projects. Check them out.
Furthermore libraries at https://fortranwiki.org/fortran/show/Command-line+arguments
What READ (*,*) does is that it reads from the standard input. For example, the characters entered using the keyboard.
As the question shows COMMAND_ARGUMENT_COUNT() can be used to get the number of the command line arguments.
The accepted answer by High Performance Mark show how to retrieve the individual command line arguments separated by blanks as individual character strings using GET_COMMAND_ARGUMENT(). One can also get the whole command line using GET_COMMAND(). One then has to somehow parse that character-based information into the data in your program.
I very simple cases you just need the program requires, for example, two numbers, so you read one number from arg 1 and another form arg 2. That is simple. Or you can read a triplet of numbers from a single argument if they are comma-separated like 1,2,3 using a simple read(arg,*) nums(1:3).
For general complicated command line parsing one uses libraries such as those mentioned in the answer by Hani. You have set them up so that the library knows the expected syntax of the command line arguments and the data it should fill with the values.
There is a middle ground, that is still relatively simple, but one already have multiple arguments, that correspond to Fortran variables in the program, that may or may not be present. In that case one can use the namelist for the syntax and for the parsing.
Here is an example, the man point is the namelist /cmd/ name, point, flag:
implicit none
real :: point(3)
logical :: flag
character(256) :: name
character(1024) :: command_line
call read_command_line
call parse_command_line
print *, point
print *, "'",trim(name),"'"
print *, flag
contains
subroutine read_command_line
integer :: exenamelength
integer :: io, io2
command_line = ""
call get_command(command = command_line,status = io)
if (io==0) then
call get_command_argument(0,length = exenamelength,status = io2)
if (io2==0) then
command_line = "&cmd "//adjustl(trim(command_line(exenamelength+1:)))//" /"
else
command_line = "&cmd "//adjustl(trim(command_line))//" /"
end if
else
write(*,*) io,"Error getting command line."
end if
end subroutine
subroutine parse_command_line
character(256) :: msg
namelist /cmd/ name, point, flag
integer :: io
if (len_trim(command_line)>0) then
msg = ''
read(command_line,nml = cmd,iostat = io,iomsg = msg)
if (io/=0) then
error stop "Error parsing the command line or cmd.conf " // msg
end if
end if
end subroutine
end
Usage in bash:
> ./command flag=T name=\"data.txt\" point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
or
> ./command flag=T name='"data.txt"' point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
Escaping the quotes for the string is unfortunately necessary, because bash eats the first quotes.

Why do I keep getting a "warning skipping unreadable file" message with Gnuplot when plotting a .dat file I made using Fortran?

Here is the code
program plotting
implicit none
real, parameter :: pi = 3.141592
integer, parameter :: n=100
real, dimension(1:n) :: x,y
real :: a=0.0, b= 2*pi
real :: increment
integer:: i
increment = (b-a)/(real(n)-1)
x(1) = 0.0
do i =2 , n
x(i) = x(i-1) + increment
end do
y = sin(x)
open(unit=25, file='sineplot.dat')
do i=1, n
write(25, *) x(i), y(i)
end do
close (unit=25)
end program
But then when I go into GNU plot and type in :
plot 'sineplot.dat' using 1:2
The following message displays:
Warning skipping unreadable file "sineplot.dat"
No data in plot
I've checked the data file and it looks correct, I am thinking that the problem is the terminal type, it is set to the default 'wxt' but I don't know if this is what I should be using for this problem using windows 8.1.
Works for me using gnuplot 5.0 and Windows 7.
You can try the following in a command prompt, but I tried wxt and windows and both work fine for me:
gnuplot -p -e "set terminal windows; plot 'sineplot.dat' u 1:2"
Could you post your sineplot.dat file?
What separates the columns in your file ( sorry, I don't know fortran). You may have to use set datafile separator "<sep>" if your columns are not separated by whitespace.
I am facing a similar problem. When I typed vi file name.dat i noticed that the file does not exits in that folder rather it is file name.dat\ which is the that is saved in that particular folder. Just renamed the file and it work.

Modern Fortran: Output format without label

I am looking for a way to specify the output format without using a label.
To understand what I mean, with label:
write(*,1001) icount, x, y
1001 format (i5,f5.2,e12.3)
Without label should be that I put format (i5,f5.2,e12.3) somewhere in the write statement, something like write(*,format(i5,f5.2,e12.3)) icount, x, y
I think I saw this somewhere recently but unfortunately I cannot find this again. If it exists it is a feature of a newer Fortran version. Maybe Fortran 90? maybe Fortran 2008?
Try
write(*,'(i5,f5.2,e12.3)') icount, x, y
As #Jeff Irwin suggests, one can save format in a character string and
pass it to write or print.
character(*), parameter :: fmt1 = "(i5,f5.2,e12.3)"
!! character(100) :: fmt1 = ... !! to use a non-constant string
write(*,fmt1) icount, x, y
write(*,fmt=fmt1) i2, x2, y2 !! fmt= may be attached for clarity
Since fmt1 is a usual character string, it can also be stored as module
variables, type components, or passed as subroutine arguments, for example.