forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Keyword driven input in Fortran

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
aerotex



Joined: 05 Jul 2007
Posts: 10

PostPosted: Tue Jan 27, 2009 7:58 pm    Post subject: Keyword driven input in Fortran Reply with quote

Is there a way to use keywords in an input file for a Fortran code, so that the entries can be listed in any order, and entries can be left out if not required?

My current input file is along the lines of:

60.10 Velocity
0 Verbose output (0 is false, 1 is true)
1.091 Chord

i.e. the inputs are in a specific order and are all required. I would like to do something along the lines of:

$chord = 1.091
$velocity = 60.1

(where the verbose input can be left out as it is false, and it would not matter what order the inputs were listed, as they are discerned by their keyword, starting with $).

Is this possible in Fortran (I believe I have seen it done in C++), and if so, can anyone recommend a good source of information on how to achieve it?

Many thanks

Richard
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Tue Jan 27, 2009 9:13 pm    Post subject: Reply with quote

Richard,

Read each line into a CHARACTER variable, and then work out what the heck it all means by a process of deconstruction - looking at characters and groups of characters. A computer scientist would call this "parsing".

It is always easier to do this if you use a token (such as your $) that denotes the start of the descriptor, and another (such as =) that denotes the end of the descriptor and beginning of the value.

May I suggest that you also add another token (such as ;) at the end of the line, so that you simply need to find the positions in the string where descriptor and value end.

Then extract the substrings, and remove blanks. Start with the descriptor, and change all to the same case. Then compare to your valid descriptors - possibly using length as a factor. Finally, when you have found the descriptor, you will know whether to look for an INTEGER or REAL (or COMPLEX etc) value. Extract that from the substring using an internal read (e.g. READ(SUBSTRING, ... etc)

If you want to be able to use:

value=descriptor or
descriptor=value

interchangeably, then you have a more difficult job than if all lines are the same way round. It is a little more involved if you want to extract multiple values, but lots more complex if you wish to parse expressions like

3.5 + 2.3*sin(30)

I've seen code to do that advertised on the web, but I can't find it now.

You have to be prepared to handle errors at every stage.

Hope this helps.

Eddie
Back to top
View user's profile Send private message
aerotex



Joined: 05 Jul 2007
Posts: 10

PostPosted: Tue Jan 27, 2009 9:37 pm    Post subject: Reply with quote

Eddie,

Thanks very much. I was hoping there was a simpler way to do it than a forced comparison, but that was obviously wishful thinking!

I can stipulate the form of descriptor=variable to simplify slightly, and I do not need to read any complex statements such as the example you gave.

Thanks for the tips on how to deconstruct it all.

Richard
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Jan 27, 2009 10:35 pm    Post subject: Reply with quote

Richard,

You could also try NAMELIST formatting, as this may more easily provide what you want.

I've used my own parsing routines for reading free format named variables, as Eddie has suggested, but that has been a project over many years.

If anyone has had success with NAMELIST, I'd like to know.

John
Back to top
View user's profile Send private message
aerotex



Joined: 05 Jul 2007
Posts: 10

PostPosted: Wed Jan 28, 2009 8:56 am    Post subject: Reply with quote

I have used the NAMELIST method in previous programmes. However, in this case it doesn't really offer me the flexibility I am after. Also, some other users do not seem to like the input method, finding it unclear.
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Wed Jan 28, 2009 3:46 pm    Post subject: Reply with quote

I always thought that namelist was one of the daftest bits of Fortran, as it required the user to know the variable names inside a program, which you wouldn't necessarily want to put all that in the "user manual". That namelist keeps on being part of fortran, whereas really useful and traditional things go on the list for deletion, always strikes me as bonkers.
The substring notation even in Fortran-77 is enough to do the basic job.
You don't necessarily have to blindly sort through all possible keywords (say) alphabetically. You can do a preliminary sort based on length, and another based on initial letter.
Fortunately, you can do the most elaborate things in very little time on a modern PC.
Perhaps the first job is to write down a list of possible keywords, and see what patterns there are. I used to do such things on the back of old computer cards ....

Eddie
Back to top
View user's profile Send private message
brucebowler
Guest





PostPosted: Thu Jan 29, 2009 2:46 pm    Post subject: Re: Reply with quote

LitusSaxonicum wrote:
I always thought that namelist was one of the daftest bits of Fortran, as it required the user to know the variable names inside a program, which you wouldn't necessarily want to put all that in the "user manual".


And how is that different than what the O/P wants, which is to have the user provide a keyword based input where the user needs to know the keywords (or variables :-). It's up to the programmer to make the names meaningful (and then only those the programmer specifies as enter-able via namelist).


LitusSaxonicum wrote:
That namelist keeps on being part of fortran, whereas really useful and traditional things go on the list for deletion, always strikes me as bonkers.


That useful things get on the list strikes me as bonkers as well. If namelist makes it to the list, that will be the MOST bonkers decision IMHO.

Bruce
Back to top
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Thu Jan 29, 2009 10:56 pm    Post subject: Reply with quote

Bruce,

You obviously use NAMELIST, or like it, or both. Your comments taking me to task made me do several bits of research to see if my opinion was unsupportable. In FTN95, as the CHM file tells us:

"Although not described here, namelist input has been extended to allow comments to follow one or more object name / value pairs on a line. This allows users to document how a namelist input file is structured, which values are valid, and the meaning of certain values. Each line in the namelist input may contain information about name / value pairs. This additional information may improve the documentation of the input file."

I couldn't actually remember the precise syntax for namelist (obviously, as I don't use it), so I looked back at the user manuals for several earlier versions of fortran I have used, and trawled through a number of books. I had a recollection that namelist was not widely supported. It is now too difficult to check various mainframes, but I started to look through the manuals for some old PC compilers. The manual for FTN77/386 does not mention it. Nor Digital Research Fortran 77, Nor MS Fortran 77 version 1.3, 3.1 or 5.1. Nor Prospero Fortran for GEM ... It is in Fortran Powerstation 1.0 (which is fortran-77), although there it has bizarre behaviour, possibly (depending on compiler settings) truncating the namelist names to 6 characters. Finally finding namelist stopped me from researching several other compilers' manuals tonight.

Turning to my textbook collection, I had a look in Metcalf's Effective Fortran 77, which doesn't mention namelist. I looked in Metcalf's Fortran Optimization - no namelist. In Kruger's Efficient Fortran Programming - no namelist. It does get a little over a page in Metcalf and Reid's Fortran 8x Explained, although that is not a user manual, and Fortran-90 had some differences when it eventually came out. I began to wonder if it was new to fortran-90. But I couldn't credit that, as I clearly remembered reading it in the CDC-6400 manual when even fortran-77 was esoteric, and had a vague memory of seeing it in McCracken, and in a Fortran-66 compiler I had with my first PC. Finally, in Willé's Advanced Scientific Fortran I found the answer. In the half-page devoted to namelist, I read "Another useful addition to Fortran 90 is the NAMELIST construct", and later "The reader should note that, although supported by many Fortran 77 compilers, the exact form of the records read and written by NAMELIST was not standardised until Fortran 90". The "many" presumably didn't include most of those for the PC!

At least now I know the underlying reason for my prejudice: namelist wasn't always available, and even when it was, it was non-standard. Since fortran-90, it has been standard, which I suppose has given me over a decade and a half to find out about it and change my mind. But where on earth do I find out about FTN95's implementation, or its extensions so tantalisingly described in the quote above, so that discovering the truth I may recant? (Please don't point me at the ANSI standard. That too is not a user guide).

So, my flip remark about namelist being daft relates to the many years when it was non-standard, or not included in some compilers. Things are better now ... Oh Dear ... namelist in FTN95 is also non-standard!

Returning to those things scheduled for termination, am I not correct in thinking that the list is ever-changing? Progress is one thing, but backwards compatibility is often useful. I could give many examples both inside and outside the computing field. To paraphrase a well known saying "if it ain't broke, don't break it"!

Best regards

Eddie

PS. So how about posting a code snippet?
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Fri Jan 30, 2009 12:13 am    Post subject: Reply with quote

Thanks Eddie and Bruce for your comments.

I have long had a project of improved free format input, both for data presentation and programming style and in the last few months I have been trying to find some free time to progress my latest effort. So my interest in this subject.

I have not had the time to put into testing NAMELIST, but as an overview it does look a bit clumsy. Bruce, any experience of this ?

I've certainly developed input line parsing routines, including the use of +-*/, but not functions. This was included to improve the definition of values, by including equations which clarify the value or for unit conversion. The result of this routine is a list of tokens and values, to be later analysed wrt the input requirement.

The hardest part of free format input is error checking and confirmation of a minimum amount of supplied data. Here again my impression was NAMELIST does not help.

Any comments ?

John
Back to top
View user's profile Send private message
brucebowler
Guest





PostPosted: Fri Jan 30, 2009 2:36 pm    Post subject: Reply with quote

You asked, here's a code snippet...

Code:
subroutine readOptFile(filename)
implicit none
character (len=*), intent(in) :: filename

include '\mergedata\commoncode\includes\optcommon.inc'
include '\mergedata\commoncode\includes\unitcommon.inc'

logical :: fileExists

namelist /optlist/ &
ac9Cals, ac9ScatterType, &
ac9pretime,ac9posttime, ac9PreTemp, ac9PostTemp, ac9prea,ac9prec,ac9posta,ac9postc,&
ac9NumGooses,ac9Gooses, &
dawnCals, dawnpretime,dawnposttime,dawnprecal,dawnpostcal, &
chlCals, chlType, chlStart, chlEnd, chlCoeffCount, chlCoeff, &
hsNumSweeps, hsSweeps, &
gmtoffsethours, hscatinifile, sasinifile, firstStation

inquire (filename, exist=fileExists)

hsSweeps     = 0
ac9Gooses    = 0
chlType      = 0
chlCoeffCount= 0
chlStart     = 0
chlEnd       = 0
chlCoeff     = 0

if (fileExists) then
  open (unit=optunit,file=filename,status='readonly')
  read (optunit, nml=optlist)
  close (unit=optunit)
end if

return
end


The input file looks like this

Code:
&optlist
!
! ac9ScatterType = 1 -> a(l) = a(l) - a(715)
! ac9ScatterType = 3 -> a(l) = a(l) - (a(715)/b(715))*b(l)
! ac9ScatterType = 0 -> no scatter correction
!
! ac9gooses and hssweeps are of the form
!  xxx(n,1:3) = time at start of seq, time at end of seq, time at start of next seq
!               "start of seq" is start of data  or 1st valid data after an event
!               "end of seq" is last valid data point prior to an event
!           "event" is sweeping the HS2 or goosing the ac9
!
! chlCoeff - coefficients of the calibration eqn, starting with constant, ending with x^n
! chlType = 1 indicates a chl vs fl relationship. 
! chlType = 2 indicates a chl/fl vs time relationship
!
chlCoeff(1,1:5) = 1.4305, -15.359, 69.454, -101.1, 46.416
chlType = 2
chlStart = 0
chlEnd = 1
chlCoeffCount = 5
chlCals = 1

ac9Cals = 1
ac9ScatterType = 3
ac9PreTime  = 071.4215
ac9PostTime = 072.7431
!ac9PreTemp  = 18.0 ! not recorded
ac9PreTemp  = 14.8

gmtoffsethours = 4
hscatinifile="hydroscat.040416"
sasinifile="sas3332k.060307"
firstStation = 4

/


Note the comments.
Note that not all the variables need to be specified in the input file
Note that the user only needs to know about the variables specified in the "namelist /optlist/" statement.
Note that you can have integer, float and string variables
Note that you can specify specific elements of an array.

I'm reasonably certain that you can have logical variables as well as the ones I mentioned above, but I haven't done that and it would not surprise me if there's a way to deal with structures and parts of structures but, again, I haven't tried it so I can't provide examples.

All "do-able" with a private parser, but why bother, when it exists in the standard?
Back to top
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Fri Jan 30, 2009 4:05 pm    Post subject: Reply with quote

Hi Bruce,

Thanks for rising to the challenge. Code snippet was a very useful and informative illustration of the method.

Is the ! comment prefix an FTN95 extension? What are the allowed separators for multiple items on a line, and what FTN95 extensions, if any, are there?

What happens if the user mistypes a name? (Yup, it crashes, as always with fortran). What happens if there is an error trapped with ERR= ... where does one pick up again in the datafile - the next line, or the end of the namelist group? If the latter, then how is that defined (with the solidus?)? Are the remaining items in the namelist simply ignored (I think so)? How does one find out (It looks like you can't)? (Comparing the value to the previously held one doesn't tell you if the namelist value wasn't specified, was ignored because an earlier value had an error, or had the same value as before. You can go back and parse the items one at a time!).

Can you format a namelist on output?

I still don't think it's for me. Thanks for your trouble.

Regards

Eddie
Back to top
View user's profile Send private message
brucebowler
Guest





PostPosted: Fri Jan 30, 2009 4:49 pm    Post subject: Re: Reply with quote

LitusSaxonicum wrote:
Hi Bruce,

Thanks for rising to the challenge. Code snippet was a very useful and informative illustration of the method.


No problem, glad to be of help...

LitusSaxonicum wrote:
Is the ! comment prefix an FTN95 extension? What are the allowed separators for multiple items on a line, and what FTN95 extensions, if any, are there?


Yes, the comment is a FTN95 enhancement. I believe that the comma is the only permitted separator. Note that one can also put multiple variables on one line, thus
Code:
&opt a=1,b=2/

is a valid input file

LitusSaxonicum wrote:
What happens if the user mistypes a name? (Yup, it crashes, as always with fortran). What happens if there is an error trapped with ERR= ... where does one pick up again in the datafile - the next line, or the end of the namelist group? If the latter, then how is that defined (with the solidus?)? Are the remaining items in the namelist simply ignored (I think so)? How does one find out (It looks like you can't)? (Comparing the value to the previously held one doesn't tell you if the namelist value wasn't specified, was ignored because an earlier value had an error, or had the same value as before. You can go back and parse the items one at a time!).


I don't know, I don't make errors :-) I believe it picks up at the end of the group (yes, defined by the slash), and yes, it can be a "challenge" to find where the error is.

LitusSaxonicum wrote:
Can you format a namelist on output?


If you write a namelist, it will format it so it's suitable for input by another read statement. It may not be pretty, but it works.


LitusSaxonicum wrote:
I still don't think it's for me. Thanks for your trouble.


Your loss :-)
Back to top
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Fri Jan 30, 2009 5:44 pm    Post subject: Reply with quote

My try also accepted ; as a separator.

To ERR is human ...

E
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group