NWChem/doc/prog/util.tex
1998-12-11 19:00:16 +00:00

559 lines
21 KiB
TeX

The NWChem {\tt util} directory is a dumping ground for all sorts of useful
things, some of which have been described elsewhere. Here are the rest.
\subsection{Printing utilities}
\subsubsection{{\tt util\_print\_centered}}
\begin{verbatim}
subroutine util_print_centered(unit, string, center, ounder)
integer unit [input]
character*(*) string [input]
integer center [input]
logical ounder [input]
\end{verbatim}
Write the string to speficied Fortran unit centered about the given
column. If {\tt ounder} is \TRUE then the string is underlined.
\subsubsection{{\tt banner}}
\begin{verbatim}
subroutine banner(unit, string, char, top, bot, sides)
integer unit [input]
character*(*) string [input]
character*(1) char [input]
logical top, bot, sides [input]
\end{verbatim}
Write the string to specified Fortran unit flush against the left
margin, optionally enclosing the top/bottom/sides with a box constructed
from the given character. At some point this routine should be renamed
\verb+util_banner+.
\subsubsection{{\tt output}}
\begin{verbatim}
subroutine output (z, rowlow, rowhi, collow, colhi,
rowdim, coldim, nctl)
double precision z(rowdim, coldim)
integer rowlow, rowhi, collow, colhi, rowdim, coldim, nctl
\end{verbatim}
{\tt Output} is a classic routine that prints non-zero rows of a
double precision matrix in formatted form with numbered rows
and columns. The arcane input is as follows;
\begin{itemize}
\item {\tt z} --- matrix to be printed
\item {\tt rowlow} --- row number at which output is to begin
\item {\tt rowhi} --- row number at which output is to end
\item {\tt collow} --- column number at which output is to begin
\item {\tt colhi} --- column number at which output is to end
\item {\tt rowdim} --- number of rows in the matrix
\item {\tt coldim} --- number of columns in the matrix
\item {\tt nctl} --- carriage control flag; 1 for single space 2 for
double space 3 for triple space --- only 1 looks any good.
\end{itemize}
Two examples might help. To print {\tt z(3:6,8:12)}
\begin{verbatim}
double precision z(n,m)
call output(z, 3, 6, 8, 12, n, m, 1)
\end{verbatim}
To print {\tt x(3:12)}
\begin{verbatim}
double precision x(n)
call output(x, 3, 12, 1, 1, n, 1, 1)
\end{verbatim}
\subsection{Error Routines}
\subsubsection{{\tt errquit}}
\label{errquit}
\begin{verbatim}
subroutine errquit(string, status)
character*(*) string
integer status
\end{verbatim}
All fatal errors should result in a call to this routine, which prints
out the string and status value to both standard error and standard
output and attempts to kill all parallel processes and to tidy any
allocated system resources (e.g., system V shared memory). The integer
status may be any non-zero integer that has some meaning to the
programmer.
\subsection{Parallel Communication}
\subsubsection{{\tt util\_char\_ga\_brdcst}}
\begin{verbatim}
subroutine util_char_ga_brdcst(type, string, originator)
integer type [input]
character*(*) string [input/output]
integer originator [input]
\end{verbatim}
The standard broadcast routine {\tt ga\_brdcst} does not work portably
with Fortran character strings for which this routine should be used
instead. The string is broadcast from process \verb+originator+ to all other
processes. Type is the standard message type or tag. All processes
should execute the same call and there is an implied weak
synchronization (i.e., no process can complete this statement until at
least process \verb+originator+ has reached it).
\subsubsection{{\tt fcsnd} and {\tt fcrcv}}
\begin{verbatim}
subroutine fcsnd(type, string, node, sync)
subroutine fcrcv(type, string, slen, nodeselect, nodefrom, sync)
\end{verbatim}
Similarly, the basic point-to-point message-passing routines do not
work portably with Fortran character strings. Here are routines that
work only with character strings. Refer to the standard TCGMSG
documentation for details on the other arguments.
\subsection{Naming Files}
The length of a file name can be large and also system depenedent.
The parameter \verb+NW_MAX_PATH_LEN+ is defined in \verb+util.fh+ to
enable a portable definition. Use it as follows
\begin{verbatim}
#include "util.fh"
character*(nw_max_path_len) filename
\end{verbatim}
For easy management by a use of NWChem, and so that multiple jobs can
run without interaction in the same directory tree, all files should
by default have a common prefix (specified on the {\tt START},
{\tt RESTART}, or {\tt CONTINUE} directive). In addition, files need to be routed to the
correct directory (scratch or permanent) and parallel files need the
process number appended to the name. Routines (should) exist to do
all of these things individually, but one master routine does it all
for you --- wow!
\subsubsection{{\tt util\_file\_name}}
\begin{verbatim}
subroutine util_file_name(stub, oscratch, oparallel, name)
character*(*) stub ! [input] stub name for file
logical oscratch ! [input] T=scratch, F=permanent
logical oparallel ! [input] T=append .<nodeid>
character*(*) name ! [output] full filename
\end{verbatim}
This routine prepends the common file prefix (specified on the {\tt
START}, {\tt RESTART}, or {\tt CONTINUE} directive) and directory (scratch or
permanent) and appends the process number for parallel files. For
example
\begin{verbatim}
call util_file_name('movecs', .false., .false., name)
\end{verbatim}
might result in \verb+name+ being set to
\verb+/msrc/home/d3g681/c60.movecs+ (i.e., having the name of the
permanent directory and the file prefix prepended onto the stub).
Another example,
\begin{verbatim}
call util_file_name('khalf', .true., .true., name)
\end{verbatim}
might yield \verb+/scratch/h2o.khalf.99+ (i.e., having the name
of the scratch directory and the file prefix prepended and the process
number appended).
\subsubsection{{\tt util\_file\_prefix}}
\begin{verbatim}
subroutine util_file_prefix(name, fullname)
character*(*) name [input]
character*(*) fullname [output]
\end{verbatim}
{\em This routine is superceded for most purposes by}\
\verb+util_file_name()+.
By default all filenames should be prefixed
with the \verb+file_prefix+ which is the argument presented to the
\verb+START+, \verb+RESTART+, or \verb+CONTINUE+ directive in the input. This is most
simply accomplished by calling this routine which returns in
\verb+fullname+ the value of \verb+file_prefix+ followed (with no
intervening characters) by the contents of \verb+name+.
\subsubsection{{\tt util\_pname}}
\begin{verbatim}
subroutine util_pname(name, pname)
character*(*) name [input]
character*(*) pname [output]
\end{verbatim}
{\em This routine is superceded for most purposes by}\
\verb+util_file_name()+.
Construct a unique parallel name by appending the process number after
the stub name. E.g., \verb+fred.0001+, \verb+fred.0002+, \ldots. The
number of leading zeroes are adjusted so that there are none in front
of the highest numbered processor. This is useful for generating
names for files, but is probably superseded by the exclusive access
files in CHEMIO (see Section \ref{sec:ChemIO}.)
\subsection{Sequential Fortran Files}
\subsubsection{{\tt util\_flush}}
\begin{verbatim}
subroutine util_flush(unit)
integer unit [input]
\end{verbatim}
If possible, flush the Fortran output buffers associated with the
specified unit. Note that this is generally required in order for
output to be visible during the course of a calculation and thus
should be called after most write operations to standard output.
Also, on some machines it is a fatal error to flush a unit on which no
output has been performed thus care must be taken to ensure that
writes and flushes are paired --- e.g., it is wrong to have all
processes flush unit six when only process zero has written output.
\subsubsection{{\tt sread} and {\tt swrite}}
\begin{verbatim}
subroutine sread(unit, a, n)
integer unit [input]
double precision a(n) [output]
integer n [input]
subroutine swrite(unit, a, n)
integer unit [input]
double precision a(n) [input]
integer n [input]
\end{verbatim}
Read/write an array of {\tt double} {\tt precision} words from the given Fortran
unit (variable record length, binary file). These routines are
valuable to avoid inefficient implied {\tt DO} loops and also to
circumvent system limitations on record lengths (e.g., some Cray
systems). The I/O operations are internally chopped into 0.25~Mbyte
chunks.
\subsection{Parallel file operations}
\subsubsection{{\tt begin\_seq\_output}, {\tt write\_seq}, and {\tt end\_seq\_output}}
\begin{verbatim}
subroutine begin_seq_output()
subroutine write_seq(unit, text)
integer unit [input]
character*(*) text [input]
subroutine end_seq_output()
\end{verbatim}
These routines support sequential (i.e., ordered) formatted output
from all parallel processes. A call to \verb+begin_seq_output+
indicates the start of a section of sequentialized output. This can
be followed by any number of calls to \verb+write_seq+, which {\em
must} be followed by calling \verb+end_seq_output+. All output will
be sent to node 0 and written there in order of increasing node
number.
{\em All nodes must participate in all calls of a sequential output section}.
Because we have to declare a fixed length string, it is possible for
some transmissions to be truncated. In practice, however, we choose
something rather longer than typical line lengths and it should not be
a serious problem.
Observe that the specified unit is the Fortran unit on node zero, not
that of the invoking node!
\subsection{Data packing and unpacking}
\begin{verbatim}
subroutine util_pack_16(nunpacked, packed, unpacked)
integer nunpacked [input]
integer packed(*) [output]
integer unpacked(nunpacked) [input]
subroutine util_unpack_16(nunpacked, packed, unpacked)
integer nunpacked [input]
integer packed(*) [input]
integer unpacked(nunpacked) [output]
subroutine util_pack_8(nunpacked, packed, unpacked)
integer nunpacked [input]
integer packed(*) [output]
integer unpacked(nunpacked) [input]
subroutine util_unpack_8(nunpacked, packed, unpacked)
integer nunpacked [input]
integer packed(*) [input]
integer unpacked(nunpacked) [output]
\end{verbatim}
These routines pack/unpack unsigned eight bit (0--255) or sixteen bit
(0--65535) integers to/from standard Fortran integers. The number of
unpacked numbers {\em must} be a multiple of the number of values that
fit into a single Fortran integer. On 32 bit machines this is four
eight-bit values and two sixteen-bit values. On 64 bit machines these
numbers are eight and four respectively. The number of values that
can be packed per integer can be computed in a machine
independent fashion using MA
\begin{verbatim}
npacked_per_int = ma_sizeof(mt_int, 1, mt_byte) /
n_bytes_per_value
\end{verbatim}
under the assumption that the word length is an exact multiple of the
value length.
\subsection{Checksums}
Checksums are useful for rapid comparison and validation of data, such
as digital signatures for verification of important messages, or, more
relevant to us, to determine if input and disk resident restart data
are still consistent. The checksum routines provided here are
wrappers around the RSA implementation of the RSA Data Security, Inc.
MD5 Message-Digest Algorithm. It is the reference implementation for
internet RFC 1321, The MD5 Message-Digest Algorithm, and as such has
been extensively tested and there are no restrictions placed upon its
distribution or export. License is granted by RSA to make and use
derivative works provided that such works are identified as "derived
from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all
material mentioning or referencing the derived work. Consider this
done. The unmodified network posting is included in md5.txt for
reference.
\begin{quote}
MD5 is probably the strongest checksum algorithm most people will need
for common use. It is conjectured that the difficulty of coming up
with two messages having the same message digest is on the order of
$2^{64}$ operations, and that the difficulty of coming up with any
message having a given message digest is on the order of $2^{128}$
operations.
\end{quote}
The checksums are returned (through the NWChem interface) as character
strings containing a 32 character hexadecimal representation of the
128 bit binary checksum. This form loses no information, may be
readily compared with single statements of standard C/F77, is easily
printed, and does not suffer from byte ordering problems. The
checksum depends on both the value and order of data, and thus
differing numerical representations, floating-point rounding
behaviour, and byte ordering, make the checksum of all but simple text
data usually machine dependent unless great care is taken when moving
data between machines. The Fortran test program merely tests the
Fortran interface. For a more definitive test of MD5 make
\verb+mddriver+ and execute it with the \verb+-x+ option, comparing
output with that in \verb+md5.txt+.
\subsubsection{Checksum C and Fortran interface}
C routines should include \verb+checksum.h+ for prototypes.
There is no Fortran header file since there are no functions.
The checksum of a contiguous block of data may be generated with
\begin{verbatim}
call checksum_simple(len, data, sum)
\end{verbatim}
--- to get more sophisticated see below and have a look at \verb+ftest.F+.
\begin{verbatim}
C: void checksum_init(void);
F77: subroutine checksum_init()
\end{verbatim}
Initialize the internal checksum. \verb+checksum_update()+ may then
be called repeatedly. The result does NOT depend on the number
of calls to \verb+checksum_update()+ - e.g., the checksum of an array
element-by-element is the same as the checksum of all elements
(in the same order) at once.
\begin{verbatim}
C: void checksum_update(int len, const void *buf)
F77: subroutine checksum_update(len, buf)
integer len ! [input] length in bytes
<anything but character> buf(*) ! [input] data to sum
\end{verbatim}
Update the internal checksum with \verb+len+ bytes of data from the
location pointed to by buf. Fortran may use the MA routines
for portable conversion of lengths into bytes.
\begin{verbatim}
F77: subroutine checksum_char_update(buf)
character*(*) buf ! [input] data to sum
\end{verbatim}
Same as \verb+checksum_update()+ but only for Fortran character strings
(trailing blanks are included).
\begin{verbatim}
C: void checksum_final(char sum[33])
F77: subroutine checksum_final(sum)
character*32 sum ! [output] checksum
\end{verbatim}
Finish generating the checksum and return the checksum value
as a C (null terminated) or Fortran character string.
\begin{verbatim}
C: void checksum_simple(int len, const void *buf, char sum[33]);
F77: subroutine checksum_simple(len, buf, sum)
integer len ! [input] length in bytes
<anything but character> buf(*) ! [input] data to sum
character*32 sum ! [output] checksum
\end{verbatim}
Convenience routine when checksumming a single piece of data.
Same as:
\begin{verbatim}
call checksum_init()
call checksum_update(len, buf)
call checksum_final(sum)
\end{verbatim}
\begin{verbatim}
F77: subroutine checksum_char_simple(buf, sum)
character*(*) buf ! [input] data to sum
character*32 sum ! [output] checksum
\end{verbatim}
Same as \verb+checksum_simple()+ but only for Fortran character strings
(trailing blanks are included).
\subsection{Source version information}
\subsubsection{{\tt util\_version}}
\begin{verbatim}
subroutine util_version
\end{verbatim}
By default this routine does nothing since it is expensive to
construct. If you execute the command {\tt make version} in the
{\tt util} directory then all configured source files will be
processed to generate a copy \verb+util_version+ which when called
will printout the name and version information of all source files,
organized by module. Of course, you'll also have to relink.
\subsection{Times and dates}
\subsubsection{{\tt util\_cpusec}}
\begin{verbatim}
double precision function util_cpusec()
\end{verbatim}
This function returns the cputime in seconds from the start of the
process. On some systems this number will be the same as the wall
time. The resolution and call overhead will also vary. This routine
should provide the most accurate cputime. On nearly all systems the
clocks are not synchronized between processes.
\subsubsection{{\tt util\_wallsec}}
\begin{verbatim}
double precision function util_wallsec()
\end{verbatim}
Routine to return wall clock seconds since the start of execution. On
nearly all systems the clocks are not synchronized between processes.
Resolution will also vary.
\subsubsection{{\tt util\_date}}
\begin{verbatim}
subroutine util_date(date)
character*(*) date [output]
\end{verbatim}
Routine to return to Fortran the current date in the same format as the
standard C routine {\tt ctime()}. Note that there are 26 characters
in this format and a fatal error will result if the argument {\tt
date} is too small.
\subsection{System operations and information}
\subsubsection{{\tt util\_hostname}}
\begin{verbatim}
subroutine util_hostname(name)
character*(*) name [output]
\end{verbatim}
Returns in {\tt name} the hostname of the machine. A fatal error
results if {\tt name} is too small to hold the result --- 256
characters should suffice.
\subsubsection{{\tt util\_file\_unlink}}
\begin{verbatim}
subroutine util_file_unlink(filename)
character*(*) filename [input]
\end{verbatim}
The calling process executes the \verb+unlink()+ system call to delete
the file. If the file does not exist then it quietly returns. If the
file exists and the unlink fails then it aborts calling
\verb+ga_error()+.
\subsubsection{{\tt util\_file\_copy}}
\begin{verbatim}
subroutine util_file_copy(input, output)
character*(*) input [input]
character*(*) output [input]
\end{verbatim}
The calling process copies the named input file to the named output
file. All errors are fatal.
\subsubsection{{\tt util\_system}}
\begin{verbatim}
integer function util_system(command)
character*(*) command [input]
\end{verbatim}
The calling processes execute the UNIX system call \verb+system()+
with \verb+command+ as an argument. This executes \verb+command+
inside the Bourne shell. Returned is the completion code of the
command (typically 0 on success). If this functionality is not
supported on a given machine then a non-zero value (1) is returned.
\subsection{C to Fortran interface}
\subsubsection{{\tt string\_to\_fortchar} and {\tt
fortchar\_to\_string}}
\begin{verbatim}
#ifdef CRAY
#include "fortran.h"
int string_to_fortchar(_fcd f, int flen, char *buf);
int fortchar_to_string(_fcd f, int flen, char *buf,
const int buflen);
#else
int string_to_fortchar(char *f, int flen, char *buf);
int fortchar_to_string(const char *f, int flen, char *buf,
const int buflen);
#endif
\end{verbatim}
These C callable routines automate the tricky conversion of C
null-terminated character strings to Fortran character strings
(\verb+string_to_fortchar+) and vice versa
(\verb+fortchar_to_string+). The Cray interface is
complicated by their use of character descriptors. We describe the
non-Cray interface.
\begin{itemize}
\item {\tt f} --- a pointer to the Fortran character string
\item {\tt flen} --- the length of the Fortran string (i.e., number of
storage locations in bytes)
\item {\tt buf} --- pointer to the C character string
\item {\tt buflen} --- the size of buf (i.e., number of bytes in the
buffer).
\end{itemize}
In converting to C format, strings are stripped of trailing blanks and
terminated with a null-character. In converting to Fortran format, the
null character is removed and the Fortran string padded on the right
with blanks.
\subsection{Debugging aids}
\subsubsection{{\tt ieeetrap}}
\subsection{Miscellaneous BLAS-like operations}
dabsmax.F --- to be removed
dabssum.F --- to be removed
rsg.f --- Eispack diagonalization routine --- should use Lapack
equivalent instead
\subsubsection{Initializing arrays --- {\tt dfill} and {\tt ifill}}
\begin{verbatim}
subroutine dfill(n, s, x, ix)
integer n ! [input] No. of elements to initialize
double precision s ! [input] Value to set each element to
double precision x(*) ! [output] Array to initialize
integer ix ! [input] Stride between elements
subroutine ifill(n, i, m, im)
integer n ! [input] No. of elements to initialize
integer i ! [input] Value to set each element to
integer m(*) ! [output] Array to initialize
integer im ! [input] Stride between elements
\end{verbatim}
Initialize \verb+n+ elements of the array \verb+x(*)+ to the value
\verb+s+. The stride between elements is specified by \verb+ix+ which
should be specified as one for contiguous data. Routine
\verb+ifill()+ should be used for integer data.