~ubuntu-branches/ubuntu/karmic/psicode/karmic

« back to all changes in this revision

Viewing changes to doc/progman/psi_module.tex

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck, Michael Banck, Daniel Leidert
  • Date: 2009-02-23 00:12:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090223001202-rutldoy3dimfpesc
Tags: 3.4.0-1
* New upstream release.

[ Michael Banck ]
* debian/patches/01_DESTDIR.dpatch: Refreshed.
* debian/patches/02_FHS.dpatch: Removed, applied upstream.
* debian/patches/03_debian_docdir: Likewise.
* debian/patches/04_man.dpatch: Likewise.
* debian/patches/06_466828_fix_gcc_43_ftbfs.dpatch: Likewise.
* debian/patches/07_464867_move_executables: Fixed and refreshed.
* debian/patches/00list: Adjusted.
* debian/control: Improved description.
* debian/patches-held: Removed.
* debian/rules (install/psi3): Do not ship the ruby bindings for now.

[ Daniel Leidert ]
* debian/rules: Fix txtdir via DEB_MAKE_INSTALL_TARGET.
* debian/patches/01_DESTDIR.dpatch: Refreshed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%
 
2
% PSI Programmer's Manual
 
3
%
 
4
% Essentials of a PSI Module
 
5
%
 
6
% David Sherrill, 31 January 1996
 
7
% Updates by TDC, 2002.
 
8
% Updates by CDS for C++, January 2008
 
9
%
 
10
 
 
11
To function as part of the PSI package, a program must incorporate
 
12
certain required elements.  This section will discuss the header files,
 
13
global variables, and functions required to integrate a new C++ module
 
14
into \PSIthree.  Here is a minimal \PSIthree\ program, whose elements
 
15
are described below.  Note that we are using C++ namespaces to avoid
 
16
conflicting names between modules, as we are moving toward a
 
17
single-executable design.  However, for legacy reasons certain globals and
 
18
the \celem{gprgid()} function need to have C-linkage.
 
19
 
 
20
\begin{verbatim}
 
21
            #include <cstdio>
 
22
            #include <cstdlib>
 
23
            #include <libipv1/ip_lib.h>
 
24
            #include <psifiles.h>
 
25
            #include <libqt/qt.h>
 
26
            #include <libciomr/libciomr.h>
 
27
            #include <libchkpt/chkpt.h>
 
28
            #include <libpsio/psio.h>
 
29
 
 
30
            extern "C" {
 
31
              FILE *infile, *outfile;
 
32
              char *psi_file_prefix;
 
33
            }
 
34
 
 
35
            // begin module-specific namespace
 
36
            namespace psi { namespace MODULE_NAME {
 
37
 
 
38
              // global variables, function declarations, and
 
39
              // #define statements here
 
40
 
 
41
            }} // close namespace psi::MODULE_NAME
 
42
 
 
43
            // main needs to be in the global namespace
 
44
            // but give it access to the psi::MODULE_NAME namespace
 
45
 
 
46
            using namespace psi::MODULE_NAME
 
47
 
 
48
            int main(int argc, char *argv[])
 
49
            {
 
50
 
 
51
              psi_start(&infile, &outfile, &psi_file_prefix, 
 
52
                argc-1, argv+1, 0);
 
53
              ip_cwk_add(":MODULE_NAME"); // MODULE_NAME all caps here
 
54
              psio_init(); psio_ipv1_config();
 
55
 
 
56
              /* to start timing, tstart(outfile); */
 
57
                
 
58
              /* Insert code here */
 
59
 
 
60
              /* to end timing, tstop(outfile); */
 
61
 
 
62
              psio_done();
 
63
              psi_stop(infile, outfile, psi_file_prefix);
 
64
            }
 
65
 
 
66
            // this needs to be global namespace also
 
67
            extern "C" {
 
68
              char *gprgid(void)
 
69
              {
 
70
                 char *prgid = "MODULE_NAME";
 
71
                 return(prgid);
 
72
              }               
 
73
            }
 
74
 
 
75
            // all other stuff is in a special namespace
 
76
            namespace psi { namespace MODULE_NAME {
 
77
                
 
78
            // other stuff below
 
79
            double some_function(int x) {
 
80
              // code
 
81
            }
 
82
 
 
83
            }} // close namespace psi::MODULE_NAME
 
84
\end{verbatim}
 
85
 
 
86
In the above example, we have included the typical C++ and PSI
 
87
header files, although for your specific module you may not need
 
88
all of these, or perhaps you may need additional ones (such as
 
89
\celem{string.h} or \celem{math.h}).  The PSI include files used in this
 
90
example are \file{libipv1/ip\_lib.h} (the input parser, described
 
91
in section \ref{C_IP}), \file{psifiles.h} (definitions of all the
 
92
PSI file numbers for I/O), \file{libqt/qt.h} (the ``quantum
 
93
trio'' library, containing miscellaneous math and utility functions),
 
94
\file{libciomr/libciomr.h} (the old PSI I/O and math routines library
 
95
-- although it contains no I/O anymore), \file{libchkpt/chkpt.h} (a
 
96
library for accessing the checkpoint file to obtain quantities such
 
97
as the SCF or nuclear repulsion energy), and \file{libpsio/psio.h}
 
98
(the PSI I/O library, see section \ref{C_IO_New}).  These include files
 
99
contain function declarations for all of the functions contained in
 
100
those libraries.
 
101
 
 
102
Note that all PSI modules require three global variables with C
 
103
linkage (i.e., inside an \celem{extern C} statement): \celem{infile},
 
104
\celem{outfile}, and \celem{psi\_file\_prefix}.  Each PSI module must
 
105
also have a C-linkage function called \celem{gprgid()} defined as shown.
 
106
The \celem{main()} function must be in global scope, and other functions
 
107
should be inside a namespace with the name of the module (which is further
 
108
contained inside a \celem{psi} namespace).  Consult a C++ book if you are
 
109
unfamiliar with namespaces.
 
110
 
 
111
The integer function \celem{main()} must be able to handle
 
112
command-line arguments required by the \PSIthree\ libraries.  In
 
113
particular, all \PSIthree\ modules must be able to pass to the
 
114
function \celem{psi\_start()} arguments for the user's input and
 
115
output filenames, as well as a global file prefix to be used for
 
116
naming standard binary and text data files.  (NB: the default names
 
117
for user input and output are \inputdat\ and \outputdat, respectively,
 
118
though any name may be used.) The current standard for command-line
 
119
arguments is for all module-specific arguments ({\em e.g.},
 
120
\celem{--quiet}, used in \module{detci}) {\em before} the input,
 
121
output, and prefix values.  The \celem{psi\_start()} function expects
 
122
to find {\em only} these last three arguments at most, so the
 
123
programmer should pass as \celem{argv[]} the pointer to the first
 
124
non-module-specific argument.  The above example is appropriate for a
 
125
\PSIthree\ module that requires no command-line arguments apart from
 
126
the input/output/prefix globals.  See the \PSIthree\ modules
 
127
\module{input} and \module{detci} for more sophisticated examples.
 
128
The final argument to \celem{psi\_start()} is an integer whose value
 
129
indicates whether the output file should be overwitten (1) or appended
 
130
(0).  Most \PSIthree\ modules should choose to append.
 
131
 
 
132
The \celem{psi\_start()} function initializes the user's input and
 
133
output files and sets the global variables \celem{infile},
 
134
\celem{outfile}, and \celem{psi\_file\_prefix}, based on (in order of
 
135
priority) the above command-line arguments or the environmental
 
136
variables \celem{PSI\_INPUT}, \celem{PSI\_OUTPUT}, and
 
137
\celem{PSI\_PREFIX}.  The value of the global file prefix can also be
 
138
specified in the user's input file.  The \celem{psi\_start()} function
 
139
will also initialize the input parser and sets up a default keyword
 
140
tree (described in detail in section \ref{C_IP}).  This step is
 
141
required even if the program will not do any input parsing, because
 
142
some of the functionality of the input parser is assumed by
 
143
\library{libciomr.a} and \library{libpsio.a}.  For instance, opening a
 
144
binary file via \celem{psio\_open()} (see section \ref{C_IO_New})
 
145
requires parsing the \keyword{files} section of the user's input so
 
146
that a unit number (e.g.~52) can be translated into a filename.
 
147
The \celem{psi\_stop()} function shuts down the input parser and closes
 
148
the user's input and output files.
 
149
 
 
150
Timing information (when the program starts and stops, and how much
 
151
user, system, and wall-clock time it requires) can be printed to the
 
152
output file by adding calls to \celem{tstart()} and \celem{tstop()}
 
153
(from \library{libciomr.a}).
 
154
 
 
155
The sole purpose of the simple function \celem{gprgid()} is to provide
 
156
the input parser a means to determine the name of the current program.
 
157
This allows the input parser to add the name of the program to the
 
158
input parsing keyword tree.  This function is used by
 
159
\library{libpsio.a}, though the functionality it provides is rarely
 
160
used.
 
161
 
 
162
In all but the most trivial of modules, you will probably need to split
 
163
your code into multiple files.  The \PSIthree\ convention is to put
 
164
the \celem{main()} function, \celem{gprgid()}, and the allocation of
 
165
\celem{infile}, \celem{outfile}, and \celem{psi\_file\_prefix} into a
 
166
file with the same name as that of the module (and a .cc extension).
 
167
Other C++ source files should have everything wrapped within the
 
168
\celem{psi::MODULE\_NAME} namespace.  Any module-specific header files
 
169
should look like this:
 
170
 
 
171
\begin{verbatim}
 
172
#ifndef _psi_src_bin_MODULE_NAME_h
 
173
#define _psi_src_bin_MODULE_NAME_h
 
174
 
 
175
// if you need infile, outfile, and psi_file_prefix in the header,
 
176
// include them like this:
 
177
extern "C" {
 
178
  extern FILE *infile, *outfile;
 
179
  extern char *psi_file_prefix;
 
180
}
 
181
 
 
182
namespace psi { namespace MODULE_NAME {
 
183
 
 
184
/* header stuff goes here */
 
185
 
 
186
}} // namespace psi::MODULE_NAME
 
187
 
 
188
#endif  // header guard 
 
189
\end{verbatim} 
 
190
 
 
191
If you add \celem{infile}, etc, to a header file, make sure they are
 
192
within an \celem{extern "C"} statement and in the global namespace.
 
193
Since these variables are defined in MODULE\_NAME.cc, you should also
 
194
precede these variables with \celem{extern} to tell the compiler they've
 
195
been allocated in another module (e.g., \celem{extern FILE *infile}).
 
196
However, that means you then wouldn't be able to include that header
 
197
file in MODULE\_NAME.cc, because then you'd be telling the compiler
 
198
both that \celem{infile}, etc, are allocated elsewhere (according
 
199
to \celem{extern FILE *infile} in the header file) and also that it's
 
200
allocated in the current file (\celem{FILE *infile} in MODULE\_NAME.cc),
 
201
an obvious contradition.  Most of the official \PSIthree\ modules
 
202
use a trick defining or undefining a variable called \celem{EXTERN}
 
203
to avoid this apparent paradox and allow the use of the same header
 
204
file containing global variables (often called \file{globals.h}) in
 
205
MODULE\_NAME.cc and all other C++ source files.
 
206
 
 
207
As always, you are encouraged to avoid use of global variables when at
 
208
all possible.  It is customary to wrap variables that would otherwise be
 
209
global into data structures such as MOInfo (for things like the number
 
210
of orbitals) and Params (for user-specified parameters).  In the next
 
211
stage of PSI development, these commonly-used data structures will be
 
212
standardized as new C++ objects for maximum code re-use and flexibility.
 
213