For Programmers: Free Programming Magazines  


Home > Archive > Fortran > September 2005 > flexible input parameter file









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author flexible input parameter file
SC Huang

2005-09-13, 6:59 pm


Hi,

I am trying to find a way to be able to read an input file that
contains both comments and simulation parameters for a Fortran code.
Currently my Fortran code looks like the following:

integer :: nstep
real :: x1,x2
open(10,file="fr.in",form="formatted")

read(10,fmt='(//)')
read(10,fmt=* ) nstep
read(10,fmt='(/)')
read(10,fmt=* ) x1, x2
...

to read in parameters "nstep", "x1", and "x2" from the following input
file:

#---------------------------------------------------
# NSTEP -- number of time steps
#
5000
#---------------------------------------------------
# X1,X2 -- interval
0.0 0.1

In the input file above, it was intended to have comment lines, so
that it is easy to understand and read (for human). This seems to be a
standard practice and it works well.

Now, the "problem" that I have is: when I add one additional comment
line to the input file, e.g. change the input file above to (see the
fourth line above "100"):

#---------------------------------------------------
# NSTEP -- number of time steps
#
# ====> this is the added new line <=====
5000
#---------------------------------------------------
# X1,X2 -- interval
0.0 0.1

I will have to change the Fortran source code, i.e., change the line

read(10,fmt='(//)')

to

read(10,fmt='(///)')

in order to account for the new comment line (i.e. to "skip" the
additional comment line in order to read the input parameter "nstep").

My question is: is there a smart/neat way (in Fortran) that allow the
user to add comment/blank lines in the input file without changing the
source code?

The ideal situation that I have in mind is to make the Fortran code be
able to read input files with arbitrary comment/blank lines, just like
the standard configuration files in Unix/Linux systems
(e.g. /etc/fstab, in which one can add arbitrary number of
comment/blank lines with a leading "#" at will, followed by the actual
parameters required by the Fortran code).

It is possible to achieve the same by using an external script file
(shell script, perl, etc, or even a C code), for pre-processing the
comment/blank lines, but it would be more convenient if it can be done
totally in Fortran.

Thanks in advance for any suggestions.

SC
FJRA

2005-09-13, 9:56 pm

Hi, what I do, is to read it as a character line, and verify the first
non space character, if it is # in your case, it is a comment (BTW, I
use "!", instead of "#" for comments in my parameter files :) ), if it
is not, use internal read. But you would have to know the order of the
parameters, or have some kind of identifier at the beginning of each
non comment line, to know how to read the character string.

FJRA

SC Huang

2005-09-14, 7:57 am


> use "!", instead of "#" for comments in my parameter files :) ), if it
> is not, use internal read. But you would have to know the order of the
> parameters, or have some kind of identifier at the beginning of each
> non comment line, to know how to read the character string.



Hi,

Thank you for your hints/suggestion. Could you say more about
"internal read" you mentioned in the previous post? (I have not
figured out what it is exactly...) Do you by any chance have a code
fragment that shows how this can be done (or any link for related
examples so that I can read about it myself), if you don't mind?

Thanks!!

SC


Edward N Bromhead

2005-09-14, 7:57 am


"SC Huang" <schuang21@yahoo.com> wrote in message
news:dg8cho$mhm$1@zinnia.noc.ucla.edu...
>
>
>
> Hi,
>
> Thank you for your hints/suggestion. Could you say more about
> "internal read" you mentioned in the previous post? (I have not
> figured out what it is exactly...) Do you by any chance have a code
> fragment that shows how this can be done (or any link for related
> examples so that I can read about it myself), if you don't mind?
>
> Thanks!!
>
> SC


Internal read/write has been around since Fortran 77, and even longer if you
count ENCODE/DECODE which was a widely available extension before that. You
will probably get advice on it from this group. But even if you can't master
it, there is a simpler (for you) route.

Read only the first character, using A1 format. Check if it is your comment
character. If it is, go to the next line. If not, then BACKSPACE, and
re-read the line with your numeric reading FORMATs.

Eddie B


SC Huang

2005-09-14, 7:57 am

On 2005-09-14, Edward N Bromhead
<edward.bromhead@deletethisbitbinternet.com> wrote: > > Read only the
first character, using A1 format. Check if it is your comment >
character. If it is, go to the next line. If not, then BACKSPACE, and
> re-read the line with your numeric reading FORMATs.



Thank you for your explanation. I got the idea.

But may I ask how to "backspace" in Fortran? I only know read
"forward" in Fortran...:-(

Thanks!

SC

Jan Vorbrüggen

2005-09-14, 7:57 am

> But may I ask how to "backspace" in Fortran? I only know read
> "forward" in Fortran...:-(


There is a BACKSPACE statement that takes a LUN as an argument, IIRC.
Have a look at your compiler's documentation, or at that of CVF which
is available via the web.

Jan
Harold Stevens

2005-09-14, 7:57 am

In <1126656240.455596.170800@f14g2000cwb.googlegroups.com> FJRA:

> Hi, what I do, is to read it as a character line, and verify the first
> non space character, if it is # in your case, it is a comment


Here's my naive approach to this very common type of input filtering...

If the input "text" file contains records of two and only two types:

1. Any invalid numeric data anywhere ("headers", including empty)
2. Valid numeric data only, everywhere (non-"headers")

Something like this will skip all "headers" (anywhere), but read numerics:

integer input
data input/5/ ! I/O unit for read
real a,b,c ! numerics

1 read(input,*,err=1,end=2)a,b,c
write(*,*)a,b,c ! etc.
goto 1

2 write(*,*)'End of input'

end

There are the usual caveats about partially complete numeric lines, etc.

(It isn't particularly pretty, but I've used it happily for years)

--
Regards, Weird (Harold Stevens) * IMPORTANT EMAIL INFO FOLLOWS *
Pardon any bogus email addresses (wookie) in place for spambots.
Really, it's (wyrd) at airmail, dotted with net. DO NOT SPAM IT.
Kids jumping ship? Looking to hire an old-school type? Email me.
Ugo

2005-09-14, 7:00 pm

A possible solution to read numerical data skipping the comments is
this: use a input file format where the comments follows the data in
the same line, and read the numerical values with list oriented format.
Example of input file:
------

300 Kelvin temperature

50 atoms

1000 iterations
1.0e-14 time step (total simulated time = N.of iterations*time
step)
200. 400. 400.0 Sizes along x, y and z
------

Then you can read the data, e.g. from unit 10, in this way:

read(unit=10, fmt=*) temper ! It reads 300.0
read(10,*) natoms ! it skips the empty line and reads 50
read(10,*) niter ! niter=1000
read(10,*) dt ! dt=1.e-14
read(10,*) sx, sy, sz ! Three values in a line

(I hope that the google groups do not mess with the line folding).

In the past I also programmed a few fortran 77 routines to read lines
in the format:

# Comment
! Another comment
* Even one more comment
temperature = 300.0

atoms = 50 a trailing comment
iterations=1000

Below is the code (obviously it can be written better in Fortran 95,
e.g. by using the proper intrinsic functions).
If you use fortran 95 consider also the namelists, where comments can
be added inside (but not in fortran 90)
------ THE CODE -----
double precision function dgimme(chiave)
! This function reads a line from the input file, scans it to see
! if it really contains the value of the quantity with name chiave,
! and if the line is correct, the function returns the number.
! Lines starting with * (or with another comment marker) are ignored.
! Example: if we call the function with
! t=dgimme('Temperature')
! a correct input line is
! ' Temperature = 310.0d0 any_comment '
! Spaces or tabs between the words can be freely added.
! Restriction: the value must be written entirely before
! the 257th character of the line
character(len=*) chiave
character(len=256) linea
integer i, j, k
logical is_comment
integer ilprimo, lultimo
external is_comment, ilprimo, lultimo

! Get a line
100 read (1,'(a256)') linea
! Get the beginning of the string
i=ilprimo(linea)
if (i.eq.0) goto 100
! Check if it starts with *. In this case get another one line
if (is_comment(linea(i:i))) goto 100

! Get the position of the '=' sign
j=index(linea,'=')
if (j .eq. 0 ) then
print *,'Bad input data while reading ', chiave
print *, 'No equal sign. The input line is'
print *, linea
stop
endif

! Get the end of the first word
k=lultimo(linea(:j-1))
if (k.eq.0) then
print *,'Bad input data while reading ', chiave
print *,'The line has no keyword before the = sign.'
print *,'The input line is'
print *, linea
stop
endif

! compare the first word with the required string
if ( (linea(i:k) .ne. chiave) ) then
print *,'Bad input data while reading ', chiave
print *, 'Wrong variable name. The input line is'
print *, linea
stop
endif

! Read the number, finally
read(linea(j+1:),*) dgimme
return

end

integer function igimme(chiave)
! Same as the function dgimme, but provides an integer instead
! of a double precision value.
character(len=*) chiave
character(len=256) linea
integer i, j, k
logical is_comment
integer ilprimo, lultimo
external is_comment, ilprimo, lultimo

! Get a line
100 read (1,'(a256)') linea
! Get the beginning of the string
i=ilprimo(linea)
if (i.eq.0) goto 100
! Check if it starts with *. In this case get another one line
if (is_comment(linea(i:i))) goto 100

! Get the position of the '=' sign
j=index(linea,'=')
if (j .eq. 0 ) then
print *,'Bad input data while reading ', chiave
print *, 'No equal sign. The input line is'
print *, linea
stop
endif

! Get the end of the first word
k=lultimo(linea(:j-1))
if (k.eq.0) then
print *,'Bad input data while reading ', chiave
print *,'The line has no keyword before the = sign.'
print *,'The input line is'
print *, linea
stop
endif

! compare the first word with the required string
if ( (linea(i:k) .ne. chiave) ) then
print *,'Bad input data while reading ', chiave
print *, 'Wrong varible name. The input line is'
print *, linea
stop
endif


! Read the number, finally
read(linea(j+1:),*) igimme
return

end


integer function ilprimo(stringa)
! Provides the position of the first non-blank character inside
stringa
! If stringa only contains spaces and/or tabs, it returns 0
character(len=*) stringa
ilprimo=0
700 ilprimo=ilprimo+1
if (ilprimo.gt.len(stringa)) then
ilprimo=0
return
endif
if ( (stringa(ilprimo:ilprimo) .eq. ' ')
&
& .or. (stringa(ilprimo:ilprimo) .eq. char(9)) )
&
& goto 700
return
end



integer function lultimo(stringa)
! Provides the position of the last non-blank character inside stringa
! If stringa only contains spaces and/or tabs, it returns 0
character(len=*) stringa
lultimo=len(stringa)+1
700 lultimo=lultimo-1
if (lultimo.eq.0) then
return
endif
if ( (stringa(lultimo:lultimo) .eq. ' ')
&
& .or. (stringa(lultimo:lultimo) .eq. char(9)) )
&
& goto 700
return
end



subroutine skipstars(launit)
! Skip all the next lines from unit=launit starting with a star '*'
! or with any other character defined as a comment by is_comment
integer launit, i
character(len=256) linea
integer ilprimo
logical is_comment
external ilprimo, is_comment
3333 read(unit=launit,fmt='(a)',end=4444) linea
i = ilprimo(linea)
if (is_comment(linea(i:i))) goto 3333
backspace(launit)
4444 return
end



logical function is_comment(caratt)
! Defines the characters which start a line of comment
character(len=1) caratt
if (caratt.eq.'*' .or. caratt.eq.'#' .or. caratt.eq.'!') then
is_comment = .true.
else
is_comment = .false.
endif
return
end

Paul Van Delst

2005-09-14, 7:00 pm

SC Huang wrote:
> Hi,
>
> I am trying to find a way to be able to read an input file that
> contains both comments and simulation parameters for a Fortran code.
> Currently my Fortran code looks like the following:
>
> integer :: nstep
> real :: x1,x2
> open(10,file="fr.in",form="formatted")
>
> read(10,fmt='(//)')
> read(10,fmt=* ) nstep
> read(10,fmt='(/)')
> read(10,fmt=* ) x1, x2
> ...
>
> to read in parameters "nstep", "x1", and "x2" from the following input
> file:
>
> #---------------------------------------------------
> # NSTEP -- number of time steps
> #
> 5000
> #---------------------------------------------------
> # X1,X2 -- interval
> 0.0 0.1
>
> In the input file above, it was intended to have comment lines, so
> that it is easy to understand and read (for human). This seems to be a
> standard practice and it works well.
>
> Now, the "problem" that I have is: when I add one additional comment
> line to the input file, e.g. change the input file above to (see the
> fourth line above "100"):
>
> #---------------------------------------------------
> # NSTEP -- number of time steps
> #
> # ====> this is the added new line <=====
> 5000
> #---------------------------------------------------
> # X1,X2 -- interval
> 0.0 0.1
>
> I will have to change the Fortran source code, i.e., change the line
>
> read(10,fmt='(//)')
>
> to
>
> read(10,fmt='(///)')
>
> in order to account for the new comment line (i.e. to "skip" the
> additional comment line in order to read the input parameter "nstep").
>
> My question is: is there a smart/neat way (in Fortran) that allow the
> user to add comment/blank lines in the input file without changing the
> source code?
>
> The ideal situation that I have in mind is to make the Fortran code be
> able to read input files with arbitrary comment/blank lines, just like
> the standard configuration files in Unix/Linux systems
> (e.g. /etc/fstab, in which one can add arbitrary number of
> comment/blank lines with a leading "#" at will, followed by the actual
> parameters required by the Fortran code).
>
> It is possible to achieve the same by using an external script file
> (shell script, perl, etc, or even a C code), for pre-processing the
> comment/blank lines, but it would be more convenient if it can be done
> totally in Fortran.
>
> Thanks in advance for any suggestions.


Here's how I would approach the problem (the code below is snipped from a larger code module that
reads into a linked list so I've modified it slightly so beware of a simple copy-n-paste - it
probably won't compile. And I've removed all the error reporting code too). The file has already
been opened and here are some relevant declarations (apart from the list itself):

INTEGER, PRIVATE, PARAMETER :: STRLEN = 5000
CHARACTER( STRLEN ) :: Line_Buffer
INTEGER :: IO_Status
INTEGER :: List_FileID
INTEGER :: Line_Read_Count
INTEGER :: n, n_Entries

BTW, there's no need to use a list as I have done. A simple allocatable array will work just fine
too, but by using a derived data type, the allocation can occur within the read funtion/routine
(assuming your comiler doesn't handle the allocatable dummy args)

! -- Initialise counters
Line_Read_Count = 0
n = 0

! -- Begin open loop
Read_Entries_Loop: DO

! -- Increment line read count
Line_Read_Count = Line_Read_Count + 1

! -- Read a line of the file
Line_Buffer = ' '
READ( List_FileID, FMT = '( a )', &
IOSTAT = IO_Status ) Line_Buffer

! -- Check for an error
IF ( IO_Status > 0 ) THEN
CLOSE( List_FileID )
RETURN
END IF

! -- Check for end-of-file
IF ( IO_Status < 0 ) THEN
CLOSE( List_FileID )
EXIT Read_Entries_Loop
END IF

! -- Update entry counter and list if this is NOT a comment or blank line
IF ( Line_Buffer(1:1) /= '!' .AND. LEN_TRIM(Line_Buffer) /= 0 ) THEN

n = n + 1

! -- Too many list entries!?
*** Note, n_Entries is determined previously by counting the number
*** of valid lines in the file. It's a two pass method since my usage
*** is pretty simply
*** usage isn't a time
IF ( n > n_Entries ) THEN
CLOSE( List_FileID )
RETURN
END IF


! -- Assign the entry.
*** For CHARACTER list use the following:
List%Entry( n ) = TRIM( ADJUSTL( Line_Buffer ) )
*** For INTEGER list use the following:
Line_Buffer = ADJUSTL( Line_Buffer )
READ( Line_Buffer, '( i10 )' ) List%Entry( n )
*** etc. for other data types

END IF


END DO Read_Entries_Loop

cheers,

paulv

--
Paul van Delst
CIMSS @ NOAA/NCEP/EMC
Herman D. Knoble

2005-09-14, 7:00 pm

SC: One way to do this would be, instead of list directed
(or formatted) input, use Namelist input but (temporarily) with comments. To
process this commented Namelist file use a single read loop to copy the input
file to another file, while preprocessing the comments out.
What's left would be a bona fide Namelist file which you'd then process
with a normal Namelist read, using the variable names within your program
nstep, x1, and x2.

Skip Knoble


On Tue, 13 Sep 2005 23:42:17 +0000 (UTC), SC Huang <schuang21@yahoo.com> wrote:

-|
-|Hi,
-|
-|I am trying to find a way to be able to read an input file that
-|contains both comments and simulation parameters for a Fortran code.
-|Currently my Fortran code looks like the following:
-|
-| integer :: nstep
-| real :: x1,x2
-| open(10,file="fr.in",form="formatted")
-|
-| read(10,fmt='(//)')
-| read(10,fmt=* ) nstep
-| read(10,fmt='(/)')
-| read(10,fmt=* ) x1, x2
-| ...
-|
-|to read in parameters "nstep", "x1", and "x2" from the following input
-|file:
-|
-|#---------------------------------------------------
-|# NSTEP -- number of time steps
-|#
-| 5000
-|#---------------------------------------------------
-|# X1,X2 -- interval
-| 0.0 0.1
-|
-|In the input file above, it was intended to have comment lines, so
-|that it is easy to understand and read (for human). This seems to be a
-|standard practice and it works well.
-|
-|Now, the "problem" that I have is: when I add one additional comment
-|line to the input file, e.g. change the input file above to (see the
-|fourth line above "100"):
-|
-|#---------------------------------------------------
-|# NSTEP -- number of time steps
-|#
-|# ====> this is the added new line <=====
-| 5000
-|#---------------------------------------------------
-|# X1,X2 -- interval
-| 0.0 0.1
-|
-|I will have to change the Fortran source code, i.e., change the line
-|
-| read(10,fmt='(//)')
-|
-|to
-|
-| read(10,fmt='(///)')
-|
-|in order to account for the new comment line (i.e. to "skip" the
-|additional comment line in order to read the input parameter "nstep").
-|
-|My question is: is there a smart/neat way (in Fortran) that allow the
-|user to add comment/blank lines in the input file without changing the
-|source code?
-|
-|The ideal situation that I have in mind is to make the Fortran code be
-|able to read input files with arbitrary comment/blank lines, just like
-|the standard configuration files in Unix/Linux systems
-|(e.g. /etc/fstab, in which one can add arbitrary number of
-|comment/blank lines with a leading "#" at will, followed by the actual
-|parameters required by the Fortran code).
-|
-|It is possible to achieve the same by using an external script file
-|(shell script, perl, etc, or even a C code), for pre-processing the
-|comment/blank lines, but it would be more convenient if it can be done
-|totally in Fortran.
-|
-|Thanks in advance for any suggestions.
-|
-|SC

Richard E Maine

2005-09-14, 7:00 pm

In article <dg8ir1$mg5$1@nwrdmz03.dmz.ncs.ea.ibs-infra.bt.com>,
"Edward N Bromhead" <edward.bromhead@deletethisbitbinternet.com>
wrote:

> Internal read/write has been around since Fortran 77, and even longer if you
> count ENCODE/DECODE which was a widely available extension before that.


And it is incredibly simple in concept (at least as of f90, when the
restriction against list-directed internal I/O was lifted). I sometimes
think that the hardest thing about it is the daunting terminology of
"internal read", which puts some people off.

An internal read just uses a character variable in place of a file.
That's what the syntax looks like (the character variable goes where the
file unit number otherwise is). And if you think of it like that, you'll
get most of the basics right. Others will likely provide code samples,
but really, that's all it is.

> Read only the first character, using A1 format. Check if it is your comment
> character. If it is, go to the next line. If not, then BACKSPACE, and
> re-read the line with your numeric reading FORMATs.


Been there. Done that. Don't want to go back. :-(

That's what I used to do sometimes in f66 days. I strongly recommend
against it. My bruises testify that there are many nonobvious problems
with it. Internal I/O was a huge improvement.

You probably don't care too much what it can do to performance because
you probably aren't reading files large enough for it to matter much.
And you also probably aren't reading from something like a tape drive.
I've seen operators complain to f66 programmers about physically abusing
the poor tape drives with excessive backspacing.

What you might care more about is that some "files" can't be backspaced
at all, and they are "files" that you might well end up using. The
Fortran standard acknowledges this and allows implementations to reject
I/O operations that aren't supported for a particular file. Prime
examples include terminals and pipes. Perhaps some operating systems can
handle backspacing of some cases of those, but in general you can't
count on it.

I recommend using backspace only as a last resort. And if you do break
down and use it, make sure to carefully consider what limitations that
imposes on your program.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
glen herrmannsfeldt

2005-09-14, 7:00 pm

Herman D. Knoble wrote:

> SC: One way to do this would be, instead of list directed
> (or formatted) input, use Namelist input but (temporarily) with comments. To
> process this commented Namelist file use a single read loop to copy the input
> file to another file, while preprocessing the comments out.
> What's left would be a bona fide Namelist file which you'd then process
> with a normal Namelist read, using the variable names within your program
> nstep, x1, and x2.


NAMELIST that I used to know would read until it found a record
containing & followed by the namelist name. That allowed for comments.
It seems that the current standard allows for namelist comments using
the ! character, with a comment until the end of record. This can be
before the start, or between any namelist items.

No need for the temporary file!

-- glen

Herman D. Knoble

2005-09-14, 7:00 pm

Glen: Thanks. I did not know that. I looked up NameList in "Fortran 95/2003 Explained"
and sure enough, the comments are now a part of Namelist. Should have done that
before my post! At any rate, Namelist is even a better solution to the original
problem.

Again, thanks.
Skip

On Wed, 14 Sep 2005 09:21:01 -0700, glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:

-|Herman D. Knoble wrote:
-|
-|> SC: One way to do this would be, instead of list directed
-|> (or formatted) input, use Namelist input but (temporarily) with comments. To
-|> process this commented Namelist file use a single read loop to copy the input
-|> file to another file, while preprocessing the comments out.
-|> What's left would be a bona fide Namelist file which you'd then process
-|> with a normal Namelist read, using the variable names within your program
-|> nstep, x1, and x2.
-|
-|NAMELIST that I used to know would read until it found a record
-|containing & followed by the namelist name. That allowed for comments.
-|It seems that the current standard allows for namelist comments using
-|the ! character, with a comment until the end of record. This can be
-|before the start, or between any namelist items.
-|
-|No need for the temporary file!
-|
-|-- glen

Madhusudan Singh

2005-09-14, 7:00 pm

SC Huang wrote:

>
> Hi,
>
> I am trying to find a way to be able to read an input file that
> contains both comments and simulation parameters for a Fortran code.
> Currently my Fortran code looks like the following:
>
> integer :: nstep
> real :: x1,x2
> open(10,file="fr.in",form="formatted")
>
> read(10,fmt='(//)')
> read(10,fmt=* ) nstep
> read(10,fmt='(/)')
> read(10,fmt=* ) x1, x2
> ...
>
> to read in parameters "nstep", "x1", and "x2" from the following input
> file:
>
> #---------------------------------------------------
> # NSTEP -- number of time steps
> #
> 5000
> #---------------------------------------------------
> # X1,X2 -- interval
> 0.0 0.1
>
> In the input file above, it was intended to have comment lines, so
> that it is easy to understand and read (for human). This seems to be a
> standard practice and it works well.
>
> Now, the "problem" that I have is: when I add one additional comment
> line to the input file, e.g. change the input file above to (see the
> fourth line above "100"):
>
> #---------------------------------------------------
> # NSTEP -- number of time steps
> #
> # ====> this is the added new line <=====
> 5000
> #---------------------------------------------------
> # X1,X2 -- interval
> 0.0 0.1
>
> I will have to change the Fortran source code, i.e., change the line
>
> read(10,fmt='(//)')
>
> to
>
> read(10,fmt='(///)')
>
> in order to account for the new comment line (i.e. to "skip" the
> additional comment line in order to read the input parameter "nstep").
>
> My question is: is there a smart/neat way (in Fortran) that allow the
> user to add comment/blank lines in the input file without changing the
> source code?
>
> The ideal situation that I have in mind is to make the Fortran code be
> able to read input files with arbitrary comment/blank lines, just like
> the standard configuration files in Unix/Linux systems
> (e.g. /etc/fstab, in which one can add arbitrary number of
> comment/blank lines with a leading "#" at will, followed by the actual
> parameters required by the Fortran code).
>
> It is possible to achieve the same by using an external script file
> (shell script, perl, etc, or even a C code), for pre-processing the
> comment/blank lines, but it would be more convenient if it can be done
> totally in Fortran.
>
> Thanks in advance for any suggestions.
>
> SC


Before each parameter, place a character string that starts with, say, a $
character, followed by a fixed length character string that identifies the
parameter to be read.

For instance :

$velocity
5.000e-06

In your code (in a while loop), look for the occurence of the $ sign
followed by a fixed character string which would identify which parameter
you were reading. You can also handle error conditions, lack of full
specification, etc.

I have used this approach in all my code, and it really works well.
glen herrmannsfeldt

2005-09-14, 7:00 pm

Madhusudan Singh wrote:

(snip)

> Before each parameter, place a character string that starts with, say, a $
> character, followed by a fixed length character string that identifies the
> parameter to be read.


> For instance :


> $velocity
> 5.000e-06



You mean like reinventing NAMELIST, though slightly less convenient in
having the value on the next line.

-- glen

SC Huang

2005-09-15, 6:59 pm

Thank you all for suggestions! After some trials, it appears that the
NAMELIST approach is the simplest solution for my original problem.
In the following, a simple sample code that I tested is listed below,
in case some "rookies" (like me) are looking for the same
solution. :-)

To creates a namelist called "global", which contains two real numbers
(x1,x2):

real :: x1,x2
integer :: fid=20
namelist /global/ x1,x2

open(fid,file="nlist.in",form="formatted")
read(fid, NML=global)
close(fid)

The input file "nlist.in" looks like:

#
# input file for nlist.f
#

&global

!* time step size

x2= 0.2

!* number of time step

x1= 0.1
/

To print out the whole namelist (for checking), I used:

write(*, NML=global)

One can also print out variables x1 or x2 as usual:

write(*, '(f10.3)') x1


Note that the order of x1 and x2 in the input file "nlist.in" does not
matter. This is a good feature for having more freedom in input file
format.

Thank you all again. The NAMELIST usage has been an eye-opener for
me! :-)

Herman D. Knoble

2005-09-15, 6:59 pm

Or as Glen pointed out the input file could look like:
&global
x2 = 0.2 !Time Step size
x1 = 0.1 !Number of Time Step
/

Skip

On Thu, 15 Sep 2005 17:52:56 +0000 (UTC), SC Huang <schuang21@yahoo.com> wrote:

-|Thank you all for suggestions! After some trials, it appears that the
-|NAMELIST approach is the simplest solution for my original problem.
-|In the following, a simple sample code that I tested is listed below,
-|in case some "rookies" (like me) are looking for the same
-|solution. :-)
-|
-|To creates a namelist called "global", which contains two real numbers
-|(x1,x2):
-|
-| real :: x1,x2
-| integer :: fid=20
-| namelist /global/ x1,x2
-|
-| open(fid,file="nlist.in",form="formatted")
-| read(fid, NML=global)
-| close(fid)
-|
-|The input file "nlist.in" looks like:
-|
-|#
-|# input file for nlist.f
-|#
-|
-|&global
-|
-| !* time step size
-|
-| x2= 0.2
-|
-| !* number of time step
-|
-| x1= 0.1
-|/
-|
-|To print out the whole namelist (for checking), I used:
-|
-| write(*, NML=global)
-|
-|One can also print out variables x1 or x2 as usual:
-|
-| write(*, '(f10.3)') x1
-|
-|
-|Note that the order of x1 and x2 in the input file "nlist.in" does not
-|matter. This is a good feature for having more freedom in input file
-|format.
-|
-|Thank you all again. The NAMELIST usage has been an eye-opener for
-|me! :-)

SC Huang

2005-09-15, 6:59 pm

Yes! That's a perfect concise format for short comments.

SC


On 2005-09-15, Herman D Knoble <SkipKnobleLESS@SPAMpsu.DOT.edu> wrote:
> Or as Glen pointed out the input file could look like:
> &global
> x2 = 0.2 !Time Step size
> x1 = 0.1 !Number of Time Step
> /
>
> Skip
>
> On Thu, 15 Sep 2005 17:52:56 +0000 (UTC), SC Huang <schuang21@yahoo.com> wrote:
>
> -|Thank you all for suggestions! After some trials, it appears that the
> -|NAMELIST approach is the simplest solution for my original problem.
> -|In the following, a simple sample code that I tested is listed below,
> -|in case some "rookies" (like me) are looking for the same
> -|solution. :-)
> -|
> -|To creates a namelist called "global", which contains two real numbers
> -|(x1,x2):
> -|
> -| real :: x1,x2
> -| integer :: fid=20
> -| namelist /global/ x1,x2
> -|
> -| open(fid,file="nlist.in",form="formatted")
> -| read(fid, NML=global)
> -| close(fid)
> -|
> -|The input file "nlist.in" looks like:
> -|
> -|#
> -|# input file for nlist.f
> -|#
> -|
> -|&global
> -|
> -| !* time step size
> -|
> -| x2= 0.2
> -|
> -| !* number of time step
> -|
> -| x1= 0.1
> -|/
> -|
> -|To print out the whole namelist (for checking), I used:
> -|
> -| write(*, NML=global)
> -|
> -|One can also print out variables x1 or x2 as usual:
> -|
> -| write(*, '(f10.3)') x1
> -|
> -|
> -|Note that the order of x1 and x2 in the input file "nlist.in" does not
> -|matter. This is a good feature for having more freedom in input file
> -|format.
> -|
> -|Thank you all again. The NAMELIST usage has been an eye-opener for
> -|me! :-)
>

Edward N Bromhead

2005-09-16, 6:59 pm


"Richard E Maine" <nospam@see.signature> wrote in message
news:nospam-3E19D7.08334314092005@news.supernews.com...
> In article <dg8ir1$mg5$1@nwrdmz03.dmz.ncs.ea.ibs-infra.bt.com>,
> "Edward N Bromhead" <edward.bromhead@deletethisbitbinternet.com>
> wrote:
>
>
> And it is incredibly simple in concept (at least as of f90, when the
> restriction against list-directed internal I/O was lifted). I sometimes
> think that the hardest thing about it is the daunting terminology of
> "internal read", which puts some people off.
>
> An internal read just uses a character variable in place of a file.
> That's what the syntax looks like (the character variable goes where the
> file unit number otherwise is). And if you think of it like that, you'll
> get most of the basics right. Others will likely provide code samples,
> but really, that's all it is.
>
>
> Been there. Done that. Don't want to go back. :-(
>
> That's what I used to do sometimes in f66 days. I strongly recommend
> against it. My bruises testify that there are many nonobvious problems
> with it. Internal I/O was a huge improvement.
>
> You probably don't care too much what it can do to performance because
> you probably aren't reading files large enough for it to matter much.
> And you also probably aren't reading from something like a tape drive.
> I've seen operators complain to f66 programmers about physically abusing
> the poor tape drives with excessive backspacing.
>
> What you might care more about is that some "files" can't be backspaced
> at all, and they are "files" that you might well end up using. The
> Fortran standard acknowledges this and allows implementations to reject
> I/O operations that aren't supported for a particular file. Prime
> examples include terminals and pipes. Perhaps some operating systems can
> handle backspacing of some cases of those, but in general you can't
> count on it.
>
> I recommend using backspace only as a last resort. And if you do break
> down and use it, make sure to carefully consider what limitations that
> imposes on your program.
>
> --
> Richard Maine | Good judgment comes from
> experience;
> email: my first.last at org.domain | experience comes from bad judgment.
> org: nasa, domain: gov | -- Mark Twain


In general, I agree with your comments. BACKSPACE is an awful construct. On
a tape drive system I once used it would ALWAYS stretch the tape, and I had
forgotten that. But I haven't seen a spinning vertically-mounted tape drive
outside of a classic sci-fi movie for about 25 years. In the context of the
OP's question, when he clearly has a human-generated file with lines that
look like cards (in fixed format, what's more!), but just generated by a
text processor, it is genuinely the simplest way forward. The fact that he
doesn't know BACKSPACE, and doesn't know internal file ops, suggests that he
isn't going to get much from an answer that recommends him to change his
compiler, or tries to teach him a whole new set of methodologies dependent
on that change. I also divined (mainly telepathically!) that he wasn't using
a "piped" file, as that would have required a level of expertise he wasn't
displaying. It also didn't look like the input from a terminal - I'm sure
you have read fixed format numeric input from a teletype terminal, but it is
a horrendous, error-prone job. We used to generate paper tapes, and run
those through the reader on a teletype. You could backspace them, but a
character at a time. I wouldn't like to try to backspace a fast paper tape
reader. Those tapes could be rewound (I expect you dislike REWIND as much as
BACKSPACE) but only by putting the tail-end of the tape on a "tape winder"
reel and cranking the handle. If you got it moving really fast you could
generate spectacularly deep paper cuts, and blood-soaked tape tangles.

Regarding list directed I/O ("at least as of f90, when the restriction
against list-directed internal I/O was lifted") I discovered yesterday that
it is an extension offered in Salford's FTN77 for the PC.

Regards

Eddie B







Richard E Maine

2005-09-16, 6:59 pm

In article <dgeqfa$t6t$1@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com>,
"Edward N Bromhead" <edward.bromhead@deletethisbitbinternet.com>
wrote:

> "Richard E Maine" <nospam@see.signature> wrote in message
> news:nospam-3E19D7.08334314092005@news.supernews.com...

[describes problems with using backspace]

> In general, I agree with your comments...
> I also divined (mainly telepathically!) that he wasn't using
> a "piped" file, as...


Yep. I also guessed that. But that doesn't mean that someday in the
future, he or someone else using a derivative of his code might end up
trying to use it with a pipe. I've seen exactly that happen more than
once; indeed, quite a few times. People try to work with an existing
code and ask why it doesn't work with a pipe. That's part of the basis
of my recommendation. Even if backspace works for him today, it becomes
a (probably undocumented) limitation hidden in the code.

> Regarding list directed I/O ("at least as of f90, when the restriction
> against list-directed internal I/O was lifted") I discovered yesterday that
> it is an extension offered in Salford's FTN77 for the PC.


Most (by my estimation) of the more recent f77 compilers seem to allow
that as an extension. Certainly there have been f77 compilers that
didn't. We've had people ask on clf why codes using that didn't work
correctly. But it has been a while (perhaps quite a while). I would
certainly not just assume that it would work with any f77 compiler,
since I've known counter-examples. If I had f77 code using that feature,
I'd document it as one of the code's requirements in a compiler.

But then, the number of sub-f90 compilers relevant to target in a new
code today is getting pretty small. It might well be that they all
support this. I don't know that for sure, as it isn't something I've
surveyed, but it seems at least plausible.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com