The
DESL
software package includes the means by which a
compatible stand-alone executable can be created.
Using the
Compaq
Visual Fortran (CVF) compiler or Unix/Linux/OS-X Fortran compiler
and user-supplied
Fortran code, linking it with a provided .OBJ or .o file, a
DESL-compatible
stand-alone executable can be produced.
Most all DESL commands which process existing files and create new files
utilize the files option and most also can use the
newfiles options. Similarly, the executable produced using
the extra.obj or extra.o precompiled object file
can also accept options which allow the specification of the names of
files and new files.
The full list of option names and their meanings is given in
the table below :
(
ZV)
The DESL extra Command.
| Option Name | Description | ||||
|---|---|---|---|---|---|
| -f | Required. The list of file names. Up to 200 file names can be specified. Each file must be specified individually. Each up-to 256-character file name specified will be processed in the order in which it was specified. | ||||
| -n |
Optional. The list of new file names. Up to 200 new
file names can be specified.
Each new file must be specified individually.
Each up-to 256-character new file name specified will be created
in the order in which it was specified whether it exists or not.
If no -n is specified any new files generated will, as in DESL, create new files which have the names "genK", where "K" is a unique numeric suffix. |
||||
| -m |
Optional. Names a "map file" to use. A map file is an ASCII file
which handles a cross referencing of the internal and external
SIF variable names.
The possible contents of a map file are discussed below. |
||||
| -e | Optional. A switch to indicate whether the names of the generated new files are to be reported or not. | ||||
| -s |
Optional. Name of the "setup" file to use. A setup file
is an ASCII containing information to be available to the
executable at run time.
The possible contents of a setup file are discussed below. |
||||
|
|
||||
| -x |
Optional. List of arbitrary items that are stored and accessible to the user
code.
... -x xrt 12.6 3.45 alpha ...
|
The following execution of the Compaq Fortran compiler or Unix/Linux/OS-X Fortran compiler compiles the user code user.for or user.f, links it with the supplied extra.obj or extra.o code and produces (assuming no errors) user.exe or user.x.
ViGYAN offers a consultation service which includes compilation and linking of user source code for those who are without the Compaq Fortran compiler on their PC.
In the below discussion the blue left hand side of the tables gives the PC information while the red right hand side of the tables gives the Unix/Linux/OS-X information.
f90 user.for extra.obj > comperr
|
(for Solaris)
|
The file comperr will contain a report of the results of the compilation. Errors will be reported in the file also.
Similarly, the following presents the contents of extra.bat PC/Unix batch/script file which could be could be used to accomplish the production of the user.exe or user.x executable, as in the case above, in a more general form :
if exist %1.exe del %1.exe
f90 %1.for extra.obj > comperr
del %1.obj
|
(for Solaris)
while test -f $1.x
do rm $1.x
done
f77 -Bstatic -o $1.x $1.f extra.o 2>comperr
rm $1.o
(for SGI)
while test -f $1.x
do rm $1.x
done
f77 -static -o $1.x $1.f extra.o 2>comperr
rm $1.o
(for HP)
while test -f $1.x
do rm $1.x
done
f77 +E1 -K -o $1.x $1.f extra.o 2>comperr
rm $1.o
(for Red Hat Linux or Mac OS-X)
while test -f $1.x
do rm $1.x
done
g77 -fno-automatic -o $1.x $1.f extra.o 2>comperr
rm $1.o
|
The use of extra.bat might be, in a case similar to the previous example :
extra.bat user
|
extra.bat user
|
The above, if successful, would result in the production of user.exe or user.x.
Both of the above cases assume that there is a path already defined in the environment such that the specification of f90 will access the Compaq Fortran compiler and f77/g77 will access the Unix/Linux/OS-X Fortran compiler.
Once such an executable has been successfully produced it could be used in a manner such as :
user.exe -f run10 run14 -n newrun10 newrun14 -s setup33a -e
|
user.x -f run10 run14 -n newrun10 newrun14 -s setup33a -e
|
It could be very convenient to directly or indirectly use the system DESL command to execute this user.exe or user.x (or any other) code from within a DESL script.
Fortran code to be compiled and linked with the supplied extra.obj object file needs to adhere to certain conventions.
The first line of the user code needs to be :
subroutine user (void)
If the user employs a setup file (described below) then
immediately after the first line should be :
common /sn/ key,name(100000),mapnam(20000)
common /sv/ n,data(200000),inam,nmap,map(20000)
character key*4,name*8,mapnam*8
Access may be needed to the program integer variable "inam".
|
The whole code segment supplied by the user can begin with the line indicated above but can be as complex as is necessary. There are several resrtictions on what the user can include in their code, however.
The logical unit numbers which will be in use and should, therefore, not be used from within the user code are : 98 and 99.
The named common blocks which should not be used from within the user code are : globlv, globlv, usrv, usrn, luns, sn, sv, frfn, and frfv.
The subroutines already defined in the supplied extra.obj or extra.o file are init, dep, gsetup, mbuild, mapin, mapout, acget, acput, sget, ssget, sput, getargx, rtchar, sifrw, locvars, sbpath, notab, frfld, ucas, adder8, and vblget. These same subroutine names should not be redefined in the user's code.
| . |
(Begin modifications on 022203)
Except in the case of entry into the user's code after the processing
of each file, caused by the "-last" option,
(End modifications on 022203) |
if the single precision real argument "void" is not 0. upon returning from the subroutine, the record will not be written to the new file. The argument "void" always comes into the subroutine being set to 0.
| . |
(Begin modifications on 022203)
In the case of having specified an effective "-last" option the value
of the "void" argument may be non-zero. See above discussion of the
"-last" option.
(End modifications on 022203) |
All SIF variables are single precision real variables and can be referenced by an up-to-8-character name of any case; the case of the SIF names are assumed to always be upper.
| . |
(Begin modifications on 052105)
In the user code that uses the "extra" stub, implicit variable declarations
are in the vein of the older Fortran versions wherein variables starting
with the letters I-N were (*4) integers and the rest of the variable names
represented real (*4) variables.
(End modifications on 052105) |
The whole intent of the user code to be executed is to be called each time a SIF record is read from the file(s) specified via the -f argument.
A brief discussion of the internals of the capability to use the extra.obj with the user code must include the manner in which the variables are tracked by name as the SIF files are processed. The nature of a SIF file is such that at least the first record is composed of names of variables. The remaining records are composed of the corresponding data values for those variables named in the names record, in the same order. The remaining records can also contain additional names records, in which case a resorting operation is implied from that point forward as the file is processed.
The user code references each SIF variable by name. Rather than having to relocate each SIF variable each time one is referenced, to save time and gain efficiency the locations of the variables sought via the calls to sget and sput, as described below, are set only at each encounter of a names record. This type of mapping assumes that the order of the programatic sequence of calls to sget and sput does not change from record to record processing.
The implication here is that the user should not put any calls to sget or sput within a block of code which will not get executed for each SIF record processed.
| . |
(Begin modifications on 052105) One- and two-dimensional table lookup/interpolation capability has been added to "extra". A table file is used to define the one or more tables that are to be referenceable from within the user code. The form of such a table file is like that used by the eqn command. The subroutine that loads the table(s) from the table file is "tbld" and the specifics are shown below:
subroutine tbld (tabfile,itflg)
1. tabfile ..... name of the table file (character*16)
2. itflg ....... return flag (integer*4)
0 ....... OK
other ... Problem, message issued
The subroutines that perform the table one- or two-dimensional
interpolation are "table1" and "table2" and the
specifics are shown below:
subroutine table1 (tbnam,tv1,xdv,irdr1,noextrap,
. setval,itflg)
1. tbnam ........ name of the table in which to interp/extrap (in)
(character*8)
2. tv1 .......... incoming value of the IV (real*4)
3. xdv .......... outgoing value of the DV (real*4)
4. irdr1 ........ order of the interpolation (integer*4)
5. noextrap ..... allow extrap (integer*4)
0 ........ allowed
1 ........ NOT allowed
6. itflg ........ return flag
0 ....... OK
other ... Failure, message issued
subroutine table2 (tbnam,tv1,tv2,xdv,irdr1,irdr2,noextrap,
. setval,itflg)
1. tbnam ........ name of the table in which to interp/extrap (in)
(character*8)
2. tv1 .......... incoming value of the IV #1 (real*4)
2. tv2 .......... incoming value of the IV #2 (real*4)
4. xdv .......... outgoing value of the DV (real*4)
5. irdr1 ........ order of the interpolation for IV #1 (integer*4)
5. irdr2 ........ order of the interpolation for IV #2 (integer*4)
7. noextrap ..... allow extrap (integer*4)
0 ........ allowed
1 ........ NOT allowed
8. itflg ........ return flag
0 ....... OK
other ... Failure, message issued
The subroutines that perform the table one- and two-dimensional lookup are "match1" and "match2" and the specifics are shown below:
subroutine match1 (tbnam,xiv1,xdv,tol,mode,setval,itflg)
tbnam ........... name of the table in which to do lookup
(character*8)
xiv1 ............ incoming value of the IV (real*4)
xdv ............. outgoing value of the DV (real*4)
tol ............. IV tolerance value (real*4)
If mode=2 contains returned |difference|
mode ............ hunting mode (integer*4)
mode .... 1 use tol value to search for match
2 find the DV that corresponds to the
IV value that is closest to the IV value
specified.
itflg ........... success flag (integer*4)
itflg .... 0 => OK
Other => Failure, message issued
subroutine match2 (tbnam,tv1,tv2,xdv,tol1,tol2,mode1,mode2,
. setval,itflg)
tbnam ........... name of the table in which to do lookup
(character*8)
tv1 ............. incoming value of the IV #1 (real*4)
tv2 ............. incoming value of the IV #2 (real*4)
xdv ............. outgoing value of the DV (real*4)
tol1 ............ IV #1 tolerance value (real*4)
If mode1=2 contains returned |IV #1 difference|
tol2 ............ IV #2 tolerance value (real*4)
If mode2=2 contains returned |IV #2 difference|
mode1 ........... hunting mode for IV #1 (integer*4)
mode1 ... 1 use tol value to search for match
2 find the DV that corresponds to the
IV value that is closest to the IV #1
value specified.
mode2 ........... hunting mode for IV #2 (integer*4)
mode2 ... 1 use tol value to search for match
2 find the DV that corresponds to the
IV value that is closest to the IV #2
value specified.
itflg ........... success flag (integer*4)
itflg .... 0 => OK
Other => Failure, message issued
(End modifications on 052105) |
Each SIF file specified is processed in its entirety before the next SIF file is processed.
As is the case with the standard DESL functions, variables are referenced by name such that their values can be used and/or set. Each SIF record processed can have none, some or all of its SIF variables used and/or modified. Both of these operations happen via the use of the sget and sput routines supplied in the extra.obj file.
A short example will serve to indicate the general manner in which SIF file variables are accessed from the file being read and returned to the new file being written.
subroutine user (void)
c
c Pull from the SIF file the value for the variable named "ALPHA"
c Store its value in the program variable "alfa"
c
call sget (1,'alpha',alfa)
c
c Calculate a new quantity = ALPHA squared, with the program
c variable name "a2".
c
a2=alfa*alfa
c
c Put on the new SIF file the value for the variable named "ALPHA2"
c which is stored in the program variable "a2".
c
call put (1,'alpha2',a2)
return
end
Here, the SIF variable alpha ( or "ALPHA" : uppercase always assumed) will have its value extracted from the SIF record and brought into the subroutine as a single precision, real variable named alfa. Its name could have been any real program variable. The value of alfa is used to define a new (implicitly) real variable a2. This new variable a2 is then added to the SIF record being written to the new SIF file. The subroutine then ends.
The keys to the usefulness of the extra programming is that the user has the ability to extract and add variables to the file(s) being read and written. The subroutines sget and sput offer these capabilities. These subroutines are the means by which the user's code interacts with the SIF file information.
Each of these two subroutines has the same number of arguments and the subroutines' respective arguments have the same basic definitions.
The first argument is an integer representing the number of variables to extract. Most of the time this value will be 1. If, however, it is desired to read/write more than one variable value, this number can then be the number of variables to read/write.
The following table summarizes the possible argument settings and their implications. If the absolute value of the first argument is greater than 1, then it is implied that the second and third subroutine arguments are arrays, dimensioned large enough to hold the specified number of items.
| Argument |
subroutine sget (num,name,value) subroutine sput (num,name,value) |
||
|
num : integer |
>0 : Forward SIF name search | =0 Return LOCATION of name in SIF record (applicable to sget only) | <0 : Backward SIF name search |
|
name : character*8 |
Name(s) to find | ||
|
value : single precision real, real*4 |
Value(s) of name(s) | Location of (first) name | Value(s) of name(s) |
A backward search through the SIF information, as indicated by a negative value of num, implies that the user wishes to have the variable(s) in question located in the unconventional manner of looking from the end of the record forward. If no variable is replicated on the SIF file, it is not important which direction is used in the search. If, however, there are duplicate variable names (which is always a bad idea) on the SIF file, then the direction being used in the search is very important. (which is always a bad idea) on the SIF file, then the direction being used in the search is very important.
If |num| is greater than 1, then special situations arise. When more than 1 variable is to be returned by sget or set by sput then the second name subroutine argument in each case must be an array. At least the first element (name) in the array must be defined. If any of the subsequent elements (names) are not defined ( are blank) then it is assumed that the name which would have been it its place would have been a name equal to the most previous non-blank name with an incremented numeric suffix.
For example, if name(1) = "CP1" and name(2) = blank and name(3) = "CP3", then sget and sput woule each assume that name(2) would be "CP2", if num was 3.
Similarly, if num was 200, it might be very convenient to not have to define all of the respective variable names being gotten or set. In this case, name(1) = "CP23", with num = 200 would imply that name(2) = "CP24", name(3) = "CP25", ... , name(200)="CP222".
There are examples of the use of the extra procedure.
Two new variables have been added to the SIF files being processed to track the current file and record numbers. These variables are known as FILCOUNT and RECCOUNT, respecitvely.
FILCOUNT has values from 1 to the number of files to be processed, being incremented by one as each new file is processed.
RECCOUNT has values from 1 to the number of DATA records being processed per file, being incremented by one as each new DATA record, successfully passing through any active global or file-specific conditions, is processed.
Each of these variables is accessible via "sget" calls.
In the context of the use of an executable created via the extra procedure the possibility of having information which resides on a "setup" file be accessible to that executable is one which can add tremendously to its overall effectiveness.
Usually a setup file will contain information which only needs to deciphered once, or once per change in NAMEs record. The inam integer variable which is contained in the sv common block, as described above, can be used to determine whether it is a time to (re)interpret the setup file or not. If the value of inam is 1 then the calls to acget, as described below, should be made. Otherwise, no calls to acget need to be made.
A setup file, in this case, is really only an ASCII file which contains lines of information which the executable can gain access to through the use of provided subroutines.
The structure of this file is free form; one or more blank spaces separate the individual entities.
| . |
(Begin modifications on 022203) A setup file (section) is begun by a line that has the string "setup" and can, optionally, be followed by a setup file subset name. If no subset name is specified the entire setup file is used. A setup file section is effective until the next occurrence of a line beginning with the string "setup" or the end of the file. If the "-s" option names a setup file AND a setup file subset name, then at the occurrence of a "setup" line the subset name also must match that desired or the setup file is not processed. A typical "setup" structure looks like :
setup setsub1
.
.
.
setup setsub2
.
.
.
(end of file)
where the subset names are optional.
(End modifications on 022203) |
Lines which contain only an asterisk or which begin with an asterisk followed by at least one blank are considered to be comments and are ignored.
There are basically two different forms of information which can be included on a setup file :
SIF constant information is always in the form of the letter C or string CONSTANT followed by one or more pairs of fields, each pair consisting of one SIF_name field and one SIF_value field.
For example, the following is a legitimate section of a setup file containing SIF constant information :
C ROLL1 45.9 CONSTANT PITCH3 -.02 ALPHAX 3.444
The SIF constant information on a setup file will overstore
any SIF information read in on the file being processed. The normal
flow of extra operations is :
Arbitrary constant information in a setup file is all non-comment lines which do not define SIF constants.
Usually a setup file will contain information which only needs to deciphered once, or in a worst case, only when a new names has been encountered. The inam integer variable which is contained in the sv common block, as described above, can be used to determine whether it is a time to (re)interpret the setup file or not. If the value of inam is 1 then the calls to acget, as described below, should be made. Otherwise, no calls to acget need to be made.
Each arbitrary constant field causes both a NAME and a VALUE to be stored internally for each item. Of course, only one of them is meaningful - i.e., either a field is a string (name) or it is a value.
Most important is the fact that, unlike the SIF information, the arbitrary constant information is always stored in the order in which it was originally encountered. The fact that the information is stored in its original order allows the user to develop their code to interrogate this information on know relative locations of particular strings in that information.
The subroutine which is available for use to extract information from the stored setup file information is named acget. Its use is simliar to the use of sget as described earlier.
The subroutine acget has three arguments, as shown in the
example call :
call acget (i,name,value)
.
The first argument is an integer flag. This flag can be either 0 or a positive number. A value of 0 indicates that the user wishes only to locate the second argument, a name of 8 or fewer characters, in the set of arbitrary constants. When found, the third argument, value, is set to the location of the desired name.
If the first argument is a positive number then the name and value of the arbitrary constant information at that location is returned. It is up to the user's code to contain the logic to make proper use of the returned information. If the original field had been a name, then the corresponding value stored would have been -999. If the original field had been a value the corresponding stored name would have been the string EMPTY.
An example of the use of acget is as follows :
c
c See if it is a time to need to call acget
c
if(inam.eq.1) then
c
c Get the LOCATION of the string "ngb". Store its location
c in the real program variable "xngb".
c
call acget (0,'ngb',xngb)
c
endif
c
This call to acget will look for the arbitrary constant string ngb in the total set of arbitrary constant material and return it's location in the program variable xngb.
If the setup file had only contained the lines :
ngb 4
yaws yaw
thetas pitch
phis roll
thetab pitch
then the location returned as xngb would have been 1, since ngb was the first arbitrary constant encountered in the set up file. Because the user would have expected some logical structure to the material in the setup file it might be expected that the field following the location of ngb is a value. So, to then extract the value which is in the location just after the location of ngb the following call to acget could be used, which repeats the acget call :
c
c See if it is a time to need to call acget
c
if(inam.eq.1) then
c
c Get the LOCATION of the string "ngb". Store its location
c in the real program variable "xngb".
c
call acget (0,'ngb',xngb)
c
c Convert xngb to integer and add 1 to get to the location of the
c value after "ngb" (= 4 in this case).
c
ixngb=xngb+1
call acget (ixngb,namex,valuex)
c
endif
c
The value thus returned in the variable "valuex" would be 4., the value stored at the location equal to the location of "ngb" + 1.
Each field (blank delimited item) which composes the total set of arbitrary constant specifications counts as one item. Each item is stored as both a NAME and a VALUE internally - i.e., two items per field.
| . |
(Begin modifications on 041403)
Each SIF constant NAME counts as one storage item. There can only be a
total of 20000 arbitrary and SIF constant items per execution.
(End modifications on 041403) |
The names which are used in the sget and sput subroutine calls are normally the names the user expects to find on the SIF file. If, however, a name used in either subroutine call is different from what its corresponding file variable name is, a map file can handle this name correspondence.
Most often the need for a map file occurs when there is code, referencing "standard" variables (example : Normal Force = "nf"), running to process files which may contain non-standard variable names (example : Normal Force = "LIFT"), as in the map file example below.
*
* ------ Map file for Test 55 ------
*
* internal external
*
ptotal ptinf
ttotal ttinf
nf lift
af drag
pm pitch
rm roll
ym yaw
sf side
*
The structure of this file is free form. One or more blank spaces separate the individual entities. Lines which contain only an asterisk or which begin with an asterisk followed by at least one blank are considered to be comments and are ignored.
Other lines should contain two fields each : the first one being the name of the variable as referenced from within the program (via the sget/sput subroutine calls) and the second one being the name of the corresponding variable as it exists on the SIF file(s) being processed.
For this example map file if the user's code had contained a line like :
call sget (1,'nf',xnf)
then the name actually looked for on the file would have been "lift", because "nf" corresponded to "lift" in the map file.
30 Research Drive
Hampton, VA 23666
Voice: (757) 865-1400
Toll Free: (800) 288-3998
FAX: (757) 865-8177
© 1999 ViGYAN, Inc.