[ previous ] [ contents ] [ next ]
As discussed at some detail in [17, 19], the program is an application of the simple meta language arfg for building Fortran 90 code from any selection of source files each of which corresponds to a specific functional concept («main part») and implements a given set of approximations. By applying arfg in fixed-point mode to the collection of source files, information is allowed to flow freely between the main parts and effectively gives rise to Fortran 90 code incorporating as much information about the target system and the approximations adopted as is feasible; compiling the Fortran 90 code then produces an executable that reads any further data from options files, solves the HRT equations in the approximation chosen all the way to Q=0, and saves the results in one of several file formats.
The arfg source code as well as the Fortran 90 code and the compiled executable are all organized in or below the three code directories iso.arfg, share.arfg, and util.arfg. Of these, share.arfg is only meant to hold files that must be shared between all the HRT programs, ar-HRT-1 and the utilities in particular. If you plan to change any of the files customarily located in or below share.arfg and your file system does not support links, it is of utmost importance that you maintain synchronization; otherwise, you run the risk of not being able to access the data calculated.
In the two directories meant to be used for constructing and compiling programs, viz. iso.arfg and util.arfg, the arfg source files corresponding to a main part with several different incarnations are contained in sub-directories the names of which are derived from the names of the main parts by a prepended dot and the appended ending .arfg; on the other hand, main parts with only one version are stored (or linked to; cf. share.arfg) in iso.arfg or util.arfg directly, with filenames consisting of the name of the main part and the ending .arfg.
Under iso.arfg and util.arfg you will find directories .f90: this is where the Fortran 90 code as well as auxiliary files and the executable go; with a definition for sub compile_f90 similar to the one given in the installation instructions, an additional symbolic link to the executable will be placed in the same directory where the arfg source resides, provided the Makefile is used so that the compilation proceeds via the script compile-program placed in the .f90 directory. - In the .opt subdirectory to directory .f90 you will find templates for the options files and void definitions of all hooks present in the current code base.
The directory share.arfg/.m4 (linked into iso.arfg and util.arfg) holds a set of files with m4 definitions that are used by arfg.
As noted in its description, arfg is a framework for defining a simple meta language implemented via the combination of various filters. In the following we only give a rudimentary overview of the definitions used in order to allow for easy orientation of where some feature is implemented; those proficient in all the languages combined should find this a sufficient starting point for reading the code.
In accordance with the documentation of arfg, in ar-HRT-1 the definition of the meta language is accomplished via the following files:
The pseudo data types mentioned are
In several cases, special test code is included; use the commands
to turn test code on or off, respectively; for simple commands, a line like
will expand to code or yield a blank line. According to .arfg-rewrite, #? works by calling the m4 macro m4_testcode() that is convenient for more complicated constructions.
As opposed to options, compile time parameters provide customization settings that are not likely to change once a satisfactory setting has been found (e. g., the customization factors to NumericalPrecision (denoted ε# in [17, 18, 19])) or that have to be taken into account already during code construction for reasons of simplicity and efficiency (such as, e. g., the number of basis functions in a LOGA/ORPA-like closure); usually, some (hopefully) reasonable default behavior is provided. Conventionally, these definitions are placed in file .compile-time-parameters.
The precise set of compile time parameters that can meaningfully be used depends, of course, on the set of main part versions chosen. In order to find out about them, look at the calls to m4 macro ctp_def() in the arfg code; the compile time parameters used are also saved as part of the automatic documentation.
In addition, the following parameters are always considered by the underlying m4 macro packages and the definition of the meta language:
In addition, any logarithmic digests you might want to generate are to be declared here; e. g., for producing a digest based upon the variation of the inverse compressibility you might add the following:
enable_logarithmic_digest__name_triggerTnode_setfilename_factor( `kappa', `$1%rho%ansatzResults%invKappaT')
This will result in a vastly expanded options template file .f90/.opt/run.tmpl documenting the file format; q. v. m4-file logdigest.m4.
Compile time parameters are, of course, just some m4 macros that may or may not be defined; consequently, you may want to introduce additional ones. This is, indeed, the case with the sample definition of the Perl sub compile_f90 given earlier: as noted there, this introduces an additional flag compile__with_debugging (that has to be one of either `yes' or `no') to determine which set of compiler flags should be used in compiling the program.
The hook mechanism is a very simple but powerful tool for minimally invasive modification of the resulting Fortran code: whereever a hook is declared, the contents of a specific m4 macro, if defined, are inserted into the program text at the m4 stage. This means that further macro expansion may take place; on the other hand, the special syntax provided by .arfg-rewrite is not available. Hook definitions are customarily stored in .hooks; this file is read as part of a comment so that only the m4 commands in there have an effect provided you refrain from direct manipulation of the diversions.
Thus if, e. g., you want to add some code at a specific position in the code for, say, testing, rather than inserting the corresponding statements directly into the arfg file, you would only declare a hook there; as hooks without a defined replacement text are ignored, there is no need to remove the hook declaration once you no longer need the additional code. If this affects, say, main part «ansatz», you would insert
into ansatz.arfg, where label is an identifier that is unique to ansatz.arfg. Application of .arfg-rewrite will then translate this into m4 code that instead dumps the contents of m4 macro `hook ansatz:label'. To use this to print, say, the value of some #real variable var, you might put the following definition into your .hooks:
m4_define(`hook ansatz:label', `print *, var')
or even the more elaborate (and somewhat baroque)
m4_define(`hook ansatz:label', `log([Hello], `The value of var at this point of the program & &happens to be "//trim(realString(var))//".')')
This example also serves to illustrate some basic features of log(); for the details, see .arfg-pre.
In addition to the manual declaration of hooks, there is also a host of automatically declared hooks (cf. .arfg-rewrite). These behave, and are to be used, in exactly the same way as manually declared ones; the only difference is that there is no #hook statement.
Hook names should be unique; however, the system has no simple way of enforcing this condition, so it is up to you to check that your hook label is, indeed, unique within that main part; using a descriptive label will help with this.
As part of the information compiled during code construction, the file .f90/.opt/hooks-template.m4 will be built; it contains empty definitions for all the hooks - automatically or manually declared ones alike - in the code base; in the above example, the entry
would be listed. In a typical situation this will contain several hundred hooks, only few of which are likely to be used at any given instance. Also bear in mind that some facilities, caching in particular, are implemented via hooks and thus may interfere with your definitions.
One problem that sometimes arises with the hooks mechanism just sketched stems from the wish to safely and automatically generate alternative code that is valid only for certain combinations of main parts: while this can easily be implemented manually via hooks , and some automatic declaration based on the presence of a specific version of some other main part is feasible, it does not sit well with the main-part locality of simple hooks and soon becomes cumbersome.
In order to overcome this difficulty, a «properties / capabilities» mechanism was introduced (cf. m4-file capabilities.m4): Now any main part may export properties, and any main part may check any other main part's properties. If some main part maintains a list of capabilities, it is then simple to check whether the capabilities present match the properties exported by any of the other main parts, and code can be modified accordingly.
In order to be able to build the Fortran code, you first have to select the main part versions to be used and provide whatever information is to enter the code construction phase. Note that the following assumes that code construction will always take place in the directory iso.arfg produced during installation, or in a directory mirroring the structure set up there.
The complete list of main parts of ar-HRT-1's version 5.20030128a can be found elsewhere. While those of the main parts that are provided in only one version should permanently reside in iso.arfg or share.arfg, in those cases where several versions may be selected you first have to copy or link the correct files in place. Thus, e. g., in order to use version 20010313-ar of main part «ansatz», you might issue the command:
ln -sf .ansatz.arfg/20010313-ar ansatz.arfg
In the end, some version of every main part must be present in the build directory.
As described above, you should define all the hooks and set all the compile-time parameters you need.
Code construction proceeds by repeated application of the arfg script to all the arfg files until the output files in .f90 no longer change; the latter criterion is usually checked via the files' md5 checksums.
As the system works by accumulating information in a host of auxiliary files and missing files generally indicate some failure of the scripts, starting from an empty .f90 subdirectory (as in make code, make program, or after make clean) means that you will get a large number of error messages during the first round of applications of arfg; if these error messages do not go away after one or two cycles, this indicates a true error and you should investigate its reason.
If error conditions are detected during code construction, you will often see a short notice being issued in the process. Usually, however, this will also result in some text being inserted into the Fortran code that does not conform to Fortran 90 syntax rules and is thus guaranteed to make compilation fail.
After code construction the subdirectory .f90/.opt/ will hold files with some of the information accumulated in the course of the procedure; this comprises the list hooks.m4 of hooks mentioned earlier as well as the template files master.tmpl, system.tmpl, isotherm.tmpl, and run.tmpl for the master, system, isotherm, and run options files; the latter hold some commentary and a list of all valid options understood by the program, occasionally amended by some instructions to their use. - Similarly, using your definition of the Perl sub compile_f90, a file .f90/compile-program is written containing the commands necessary for compiling the program.
Provided a suitable make program is installed, you can use the command
to construct the Fortran 90 code in the .f90 subdirectory. Alternatively, a previous (partial) build of the Fortran code can be updated by issuing
If you want to explicitly clean out the files under .f90/, use
Other useful targets can be found in the Makefile (share.arfg/Makefile).
The simplest way to compile the Fortran 90 code is to call
combines the functionality of make code and make compile. The compiling step works by calling the shell script written during code construction.
If you are unable to compile the Fortran 90 code produced by arfg, you may have a wrong definition of the Perl sub compile_f90 (be sure to check the compiler flags); try to compile manually and adapt its definition. Otherwise, the problem must already have occurred before; if you get syntax errors, check the Fortran files for any errors of the code construction process and fix them in the arfg source. Note that the Fortran code is not intended for human inspection; consequently, it is largely unreadable and undocumented, and unsafe techniques like variable re-use in different contexts etc. may be used; simply changing the Fortran code without a full understanding of the whole program is an almost certain way to desaster. Problems must be fixed in the arfg source and never in the Fortran code. If you modify or complement the arfg source, be sure to first understand the way the meta language works; reading through the files listed above is a good starting point, and a good working knowledge of all the languages used by arfg is of paramount importance.
At any invocation, the ar-HRT-1 executable will read a number of options files containing additional information; the syntax is documented in Module OptionsHandler in main part «basics» (file share.arfg/basics.arfg) but should be obvious from the template files; the usual sequence of reading the options files, as well as a set up often more convenient, are shortly described in the installation instructions. These files hold some information to be read at run time such as, e. g., the temperature or some potential parameters. The system template file is intended for settings specific to the physical model used; the isotherm template file is intended for settings specific to the isotherm considered, most importantly the temperature and the output file name; and the run options file is intended for information governing the run-time behavior, the amount and kind of information logged in particular. The master options file indicates the locations of the other options files.
The options so found are then handed to all the main parts in turn for initialization. Equipped with this information, the program then aspires to solve the HRT equations in an iterated full approximation scheme as discussed in [17, 19]; if an error condition occurrs, some error message indicating the code block and the arfg source file where it is defined is handed to log() and will be displayed or suppressed, depending on your setting for compile time parameter `__quiet__' and the run-time options you used.
If you defined a file name, at the end of the calculation the results will be saved. Based on the low-level module used for processing the file we have to distinguish between the following formats
The information actually saved in such a file depends on whether or not you define an extra file for the system's description: a complete account of all relevant settings and documentation strings is either written to that file or saved together in the header of the any isotherm file. In addition to this general information, selected components of the solution vector will be saved, where the following cases must be distinguished:
The file names for the full data and the logarithmic digests are derived from some base name; the run options file provides ample documentation on this point.
Note that the calculation's results will silently be discarded if you do not define a file to save them; on the other hand, existing files will be overwritten mercilessly.
[ previous ] [ contents ] [ next ]
Copyright © 2002-2003 by Albert REINER. All rights reserved.