Fortran New Output File - fortran

I'm new to Fortran, and trying to repurpose a bit of code that is part of a larger program I've inherited. When the program is run, it prompts for output file names. I would prefer to specify these output file names directly in the code, so I can run the program in parallel/all at once (the run time of the program is about 15 hours, and needs to be run for 66 different files, so I would prefer to run them all at once as opposed to one after another because that would take quite a long time).
The bit of code I'm working with looks like this:
24 print *,'Enter output filename'
25 read(*,*) fout
26 print *,'Enter parameter estimate output filename'
27 read(*,*) foutb
28 print *,'Enter seed for random number generator'
29 read(*,*) idum
30 if(idum.gt.0) idum = -idum
Everything I've tried gives me:
At line 25 of file v1.f95:
Fortran runtime error: End of file
I've checked that I have proper line endings.
Any suggestions?

If I understand the question correctly, you want to pass a number of output filenames/other variables to your program at runtime. This could be handled by using a simple namelist input file, and passing this single file to the program. The code would look like, for example:
character(20) :: file1, file2, file3
integer :: idum
namelist /input/ file1, file2, file3, idum
read(unit = iunit, nml = input)
where iunit is the I/O unit connected to the previously opened input file. The contents of this file would be like
&input ! Name of corresponding namelist group
file1 = 'file1.out',
file2 = 'file2.out',
file3 = 'file3.out',
idum = 1
/
Namelist files are very easy to handle. They don't care about the order of entries, record length or comments. You can omit any variables in the namelist file (their value will not be modified), or include multiple namelists (even of the same name) in a single file.

perhaps the simplest possible solution for you, assuming you have only a
few simple read(*,*)'s you can leave the code alone and simply pipe
the required strings to standard input
echo "file1\nfile2\n3" | executable
(tested under csh.. you might need to tweak a bit for a different shell)
The error message BTW makes me think you were already reading from a stdin pipe
rather than a terminal and some prior read exhausted the input.

I think your error comes from the fact that fout cannot be read without a character string as the format specifier. Try this on line 25 (and in other read's)
read(*,'(a)') fout
You could improve on that if you copy the length from the definition of fout, like so (guessing the size)
CHARACTER fout(25)
.
.
.
read(*,'(a25)') fout
You are reading from the standard input (this is the asterisk in the first argument). I assume your input file is ASCII text. Like you have it now, you could specify the names of the output files on the first two lines of the file, then a third line for idum, then the rest of the input (if you have any).
Say your executable is my_program.exe and your input file (with the three lines mentioned above) is my_input_file.txt, you could redirect the input file to standard input like this
%> my_program.exe < my_input_file.txt

Related

How to read .inp file in c++?

I have a dataset, a ".inp" format file, and I need to read this file in c++. However, the fopen() fread() method seemed to fail and read the wrong data(e.g. the first integer should be 262144, the fread yields an integer much larger than this nevertheless).
To be more specific, my ".inp" file contains a few integers and float points, how can I read them successfully in c++?
enter image description here
This is the screenshot of the "*.inp" file from Notepad++. Basically this is a text file.
I solved it by coping the data into a txt. However, I am still not aware how to read "*.inp"
I found some info about INP file extension. It seems like there are multiple variances of it, each meant to be used for different purpose. Where is your file coming from? As for soultion, if you can't open the file using fopen/fstream normally, you could treat it as binary and read each value in the way you specify. Other than that, I could think of calling system functions to get file contents (like cat in linux for example), then if there are some random characters, you could parse your string to ommit them.
Here is example of how to call cat in C++:
Simple way to call 'cat' from c++?

How do I read data from a file with description and blank lines with Fortran 77?

I am new to Fortran 77. I need to read the data from a given text file into two arrays, but there are some lines that either are blank or contain descriptive information on the data set before the lines containing the data I need to read. How do I skip those lines?
Also, is there a way my code can count the number of lines containing the data I'm interested in in that file? Or do I necessarily have to count them by hand to build my do-loops for reading the data?
I have tried to find examples online and in Schaum's Programming with Fortran 77, but couldn't find anything too specific on that.
Part of the file I need to read data from follows below. I need to build an array with the entries under each column.
Data from fig. 3 in Klapdor et al., MPLA_17(2002)2409
E(keV) counts_in_bin
2031.5 5.4
2032.5 0
2033.5 0
I am assuming this question is very basic, but I've been fighting with this for a while now, so I thought I would ask.
If you know where the lines are that you don't need/want to read, you can advance the IO with a call to read with no input items.
You can use:
read(input-unit,*)
to read a line from your input file, discard its contents and advance IO to the next line.
It has been a long time since I have looked at F77 code, but in general if your read statement in a DO loop can deal with finding empty lines, or even a record that contains only blanks, then you could write logic to trap that condition and go to a break or continue statement. I just don't recall if read can deal with the situation intelligently.
Alternatively, if you are using a UNIX shell and coreutils, you can use sed to remove empty line, /^$/
or /^ *$/ to preprocess the file before you send it onto F77
Something like
$ sed infile -e 'd/^$/;d/^ *$/' > outfile
It should look something like this:-
C Initialise
integer i
character*80 t1,t2,t3
real*8 x,y
open(unit=1,file='qdata.txt')
C Read headers
read(1,100)t1
100 format(A80)
write(6,*) t1
read(1,100)t2
write(6,*) t2
read(1,100)t3
write(6,*) t3
write(6,*)
C Read data
do 10 i=1,10
read(1,*,end=99) x,y
write(6,*) x,y
10 continue
99 continue
end
So I've used a classic formatted read to read in the header lines, then free-format to read the numbers. The free-format read with the asterisk skips white space including blank lines so it does what you want, and when there is no more data it will go to statement 99 and finish.
The output looks like this:-
Data from fig. 3 in Klapdor et al., MPLA_17(2002)2409
E(keV) counts_in_bin
2031.5000000000000 5.4000000000000004
2032.5000000000000 0.0000000000000000
2033.5000000000000 0.0000000000000000

Standard Input and Command line file in Fortran77

I've been given the challenge to port a Fortran 77 program into C#.
I've found out that read(5,*) read from the standard input, i.e. the keyboard.
Now I'm trying to understand how the following works:
1. When I run the program, I have to run it as cheeseCalc<blue.dat>output.txt
, which read a blue.dat file and produces a output.txt file. How does read work in this case?
In the same program, there is READ(5,* )IDUM and later it also has read(5,*)idum,idum,tinit. What is happening in this case?
The blue.dat file has the following lines:
HEAD make new cake
INPUT VARIABLES
MFED MASS-FEED 30 ;1001 1 100 PEOPLE TO FEED
TOVE TEMP-IN-OVEN 150.0 ;1001 20 100 TEMPERATURE OF OVEN, C
UPDATED: Just for context, the initial lines of code in the program are:
program cheeseCalc
CHARACTER*76 IDENT
CHARACTER*1 IDUM
READ(5,104)IDENT
104 FORMAT(4X,A)
READ(5,*)IDUM
c write start record
write(6,102)IDENT
102 format('**START',/,4X,A,/)
read(5,*)idum,idum,frate
110 format(f10.0)
frate2=frate/3.6
read(5,*)idum,idum,tempo
* Do calculation *
write(6,*)frate2,tempo
end
Any help will be appreciated!! Thanks!
The full detail of the general read statement is documented elsewhere, but there is an idiom here which is perhaps worth elaborating on.
The statement read(5,*) ... is list-directed input from the external unit number 5. Let's assume (it's not guaranteed, but it's likely and you seem happy with that for your setup) that this external unit is standard input.
The idiomatic part is the repeated use of a single variable in an input list such as
read(5,*) idum, idum, ...
This (and the fact that idum is an (awfully named) length-1 character variable) signifies that the user doesn't care about the input in the first two fields). The first string, delimited by blanks, is read then the first character is assigned to idum. Then idum is immediately set to the first character of the next string.
The purpose of this is to set the place in the record to the third field, which is read into the (real) variable frate (in the first case).
Equally
read(5,*) idum
is just skipping the second line (strictly, reading the first character, but that's not used anywhere before the next read into idum): the first blank-delimited field is read but the next read moves on to the next line rather than continuing with that one.

How to remove leading space when printing with write?

Suppose I have the following code
program fortran
open(900, FILE='SOMETHING')
write(900, *) '21'
end program fortran
The file form will be
21
that is, there is a space before the number. How to get rid of that space?
You can write it as a string:
PROGRAM fortran
OPEN(900,FILE='SOMETHING')
WRITE(900,'(a)') '21'
END PROGRAM FORTRAN
> cat SOMETHING
21
To respond to the comment:
The more explicit way of doing that would be to write the number into a string (you could also use list-directed I/O for this step), remove whitespaces from the string trim and finally output the left-adjusted adjustl:
program test
character(len=23) :: str
write(str,'(ES23.15 E3)') 1.23d0
write(*,'(a)') adjustl(trim(str))
write(str,'(ES14.7 E2)') 0.12e0
write(*,'(a)') adjustl(trim(str))
end program
> ./a.out
1.230000000000000E+000
1.2000000E-01
This solution is probably more complicated then necessary, but it is a very flexible approach that can be extended easily for arbitrary purposes and formats.
In list-directed format (the * in write(unit,*)) the compiler typically inserts a leading space. The first column used to be used to control line printers but that is now deleted from Fortran.
You can use any explicit format you want to get rid of the leading space. For example the general g0 one or the string specific a or the integer-specific i.

Writing on the same line in FORTRAN

In Fortran, each time one uses WRITE a new line is produced. In order to control the working of a program that is being executed, I would like to write on screen the current value of a variable, but always on the same line (erasing the previous value and starting at the beginning of the line). That is, something like
1 CONTINUE
"update the value of a"
WRITE(*,*) a
BACKSPACE "screen"
GOTO 1
Something like WRITE(*,*,ADVANCE='NO') (incorrect anyway) is not quite what I
need: this would write all the values of a one after another on a very long
line.
A trick that I was shown for what you want is as follows
do l=1,lmax
...update a...
write(*,'(1a1,<type>,$)') char(13), a
enddo
where <type> is your format specifier for a (i.e., i0 for integer).
The key is the char(13), which is the carriage return, and the $ in the format descriptor. I really don't know if there is a name for $, I just know that it works for displaying on the screen--for output to file you get an a on each line.