1
2/** \page develop Developing Code Using SC
3
4In addition to the executables, the Scientific Computing toolkit libraries
5and include files can be installed on your machine.  This is described in
6the \ref compile section of this manual.
7
8The <tt>sc-config</tt> program can be use to obtain the compilers, compiler
9options, and libraries needed to use the SC toolkit from your program.
10This utility is discussed below, along with how the SC toolkit must be
11initialized in your <tt>main</tt> subroutine.
12
13<ul>
14  <li> \ref scconfig
15  <li> \ref scinit
16  <li> \ref devsamp
17  <li> \ref scexcept
18  <li> \ref devcheck
19</ul>
20
21\section scconfig The sc-config Program
22
23The sc-config program returns information about how SC was compiled
24and installed.  See \ref sc-config for more information.
25
26\section scinit Initializing SC
27
28First the execution environment must be initialized using
29the ExEnv init member.
30
31<pre>
32  ExEnv::init(argc, argv);
33</pre>
34
35By default, all output will go to the console stream, cout.  To change
36this, use the following code:
37
38<pre>
39  ostream *outstream = new ofstream(outputfilename);
40  ExEnv::set_out(outstream);
41</pre>
42
43MPI is allowed wait until MPI_Init is called to fill in argc and argv, so
44you may have to call MPI_Init before you even know that we ready to
45construct MPIMessageGrp.  So if an MPIMessageGrp is needed, it is up to the
46developer to call MPI_Init to get the argument list for certain MPI
47implementations.
48
49<pre>
50  MPI_Init(&argc, &argv);
51</pre>
52
53When files are read and written, an extension is added to a
54basename to construct the file name.  The default is "SC".
55To use another basename, make the following call, where
56<tt>basename</tt> is a <tt>const char *</tt>:
57
58<pre>
59  SCFormIO::set_default_basename(basename);
60</pre>
61
62If your job might run in parallel, then make the following
63call or the nodes will print redundant information.  The
64<tt>myproc</tt> argument is the rank of the called node.
65
66<pre>
67  SCFormIO::init_mp(myproc);
68</pre>
69
70This segment of code sets up an object to provide multi-threading:
71
72<pre>
73  RefThreadGrp thread = ThreadGrp::initial_threadgrp(argc, argv);
74  ThreadGrp::set_default_threadgrp(thread);
75  if (thread.nonnull())
76    ThreadGrp::set_default_threadgrp(thread);
77  else
78    thread = ThreadGrp::get_default_threadgrp();
79</pre>
80
81This segment of code sets up the message passing object:
82
83<pre>
84  RefMessageGrp grp = MessageGrp::initial_messagegrp(argc, argv);
85  if (grp.nonnull())
86    MessageGrp::set_default_messagegrp(grp);
87  else
88    grp = MessageGrp::get_default_messagegrp();
89</pre>
90
91\section devsamp MP2 Implementation Example
92
93This section illustrates how to add a new method a new method to MPQC.
94
95\subsection devsampsrc MP2 Implementation Example: Source
96
97This example code illustrates a complete MP2 energy
98implementation using the SC Toolkit.  First an MP2 class is
99declared and the necesary base class member functions are
100provided.  Next a ClassDesc is defined.  Finally, the member
101functions are defined.
102
103Note that no main routine is provided.  This is because this file
104is designed to be used to extend the functionality of the mpqc
105executable.  To generate a new mpqc executable with the new class
106available for use, see the \ref devsampmak section.
107
108\include mp2.cc
109
110\subsection devsampmak MP2 Implementation Example: Makefile
111
112This example Makefile demonstrates how to link in a new class to
113form a new mpqc executable, here named mp2.  The code is given in
114the \ref devsampsrc section.  The \ref scconfig "sc-config command"
115is used to obtain information about how the SC toolkit
116was compiled and installed.  The library specified with -lmpqc
117provides the main routine from mpqc.
118
119\include Makefile
120
121\subsection devsampinp MP2 Implementation Example: Input
122
123This input file can be used with the program illustrated in
124the \ref devsampsrc section.  It will compute the MP2 energy
125using the new MP2 class.  Note that only the
126\ref mpqcoo "object-oriented input format" can be used with
127user provided classes.
128
129\include mp2.in
130
131\section scexcept Exception Handling in SC
132
133The development of SC began before exception handling was available in C++.
134A retrofit of the code to use exceptions is in progress.  It is difficult
135to retrofit a code, especially a parallel code, to do exception handling.
136There will be some limitations: exception handling will not work well for
137parallel jobs, objects whose members throw might be left in a questionable
138state, etc.  However, it is intended that SC objects will be usable in an
139interactive environment.  It is also planned that exceptions be used
140internally to facilitate recover from certain problems.
141
142All new code should use exceptions instead of exit or abort and allocate
143resources in such a way that, if an exception occurs, all resources such as
144memory or locks are released.  A hierarchy of exception classes has been
145created that maps better to scientific computing than the standard
146exceptions.  More information is below, as well as in the documentation for
147the SCException class and its derivatives.
148
149<ul>
150  <li> \ref scexceptmem
151  <li> \ref scexceptlocks
152  <li> \ref scexcepttimer
153  <li> \ref scexceptexample
154  <li> \ref scexceptdebug
155</ul>
156
157\subsection scexceptmem Exceptions and Memory Allocation
158
159Consider the following code fragment:
160
161<pre>
162Object *obj = new Object;
163double *array = new double[n];
164
165f(obj, array, mol);
166
167delete obj;
168delete[] array;
169</pre>
170
171If an exception is thrown in the function f(), then storage for array and
172obj will not be released.  The standard C++ library provides a class,
173auto_ptr, to deal with obj, and the SC toolkit provides a class, auto_vec,
174to deal with array.
175
176The include files for these two classes are:
177
178<pre>
179#include \<memory\>
180#include \<util/misc/autovec.h\>
181</pre>
182
183the code would be modified as follows:
184
185<pre>
186std::auto_ptr<Object> obj(new Object);
187sc::auto_vec<double> array(new double[n]);
188
189f(obj.get(), array.get());
190
191obj.release();  // or just let the destructor release it
192array.release();  // or just let the destructor release it
193</pre>
194
195Note that when sc::Ref is used to store pointers, the storage will
196automatically be released when necessary.  No special treatment is needed
197to deal with exceptions.
198
199\subsection scexceptlocks Exceptions and Locks
200
201Consider the following code fragment:
202
203<pre>
204g(const sc::Ref<sc::ThreadLock> &lock)
205{
206  lock->lock();
207  f();
208  lock->unlock();
209}
210</pre>
211
212If f() throws, then the lock is never released.  The ThreadLock
213lock() and unlock() members should not be used anymore.  Now
214do the following:
215
216<pre>
217g(const sc::Ref<sc::ThreadLock> &lock)
218{
219  sc::ThreadLockHolder lockholder(lock);
220  f();
221  lockholder->unlock(); // or let the destructor unlock it
222}
223</pre>
224
225\subsection scexcepttimer Exceptions and Region Timers
226
227Consider the following code fragment:
228
229<pre>
230g(const sc::Ref<sc::RegionTimer> &regtim)
231{
232  regtim->enter("f()");
233  f();
234  regtim->exit();
235}
236</pre>
237
238If f() throws, then the "f()" timing region is never exited.
239Instead use the following:
240
241<pre>
242g(const sc::Ref<sc::RegionTimer> &regtim)
243{
244  sc::Timer timer(regtim, "f()");
245  f();
246  timer.reset(); // or let the destructor exit the region
247}
248</pre>
249
250\subsection scexceptexample Using the SC Exception Classes
251
252The SC exceptions provide information that can be used into two
253ways. First, text information is provided so that if the exception is not
254caught at a lower level, then the mpqc executable will catch it and write
255information about the problem to the terminal or an output file.  Second,
256information about the nature of the problem is provided, to permit
257developers to catch the exception and deal with it in some way.  The
258documentation for sc::SCException and all of its derivatives gives more
259information about the exceptions that are available.  As an example,
260consider the following loop, where a maximum number of iterations is
261permitted:
262
263<pre>
264XYZ::update()
265{
266  for (int i=0; i<maxiter; i++) {
267    // ... compute xyz update ...
268    if (residual < threshold) return;
269  }
270  throw MaxIterExceeded("too many iterations xyz computation",
271                        __FILE__, __LINE__, maxiter, class_desc());
272}
273</pre>
274
275The first argument to the exception class is a brief description of the
276error.  Additional information can be provided,
277see SCException::elaborate() description below.
278The next two arguments are
279the filename and line number.  The C preprocessor provides these for you
280with the __FILE__ and __LINE__ macros.  The next argument is specific to
281the MaxIterExceeded exception; it is the maximum number of iterations.
282Finally, a ClassDesc* can be given, which will be used to print out the
283class name of the object that failed.  All of these arguments are optional;
284however, the first three should always be given.
285
286It is possible to provide additional information using the
287SCException::elaborate() member.  This will return a ostream, and the
288additional information can be written to this stream.  However, if for some
289reason it is not possible to write to this stream (say, there wasn't enough
290memory to allocate it), then an exception will be thrown.  For this reason,
291the string description given as the first argument should be informative
292since the additional information might not be available, and attempts to
293use elaborate() should be in a try block.  So, for example, the elaborate()
294member could be used in the above example as follows:
295
296<pre>
297XYZ::update()
298{
299  for (int i=0; i<maxiter; i++) {
300    // ... compute xyz update ...
301    if (residual < threshold) return;
302  }
303  MaxIterExceeded ex("too many iterations in xyz computation",
304                     __FILE__, __LINE__, maxiter, class_desc());
305  try {
306    ex.elaborate() << "this can happen when the stepsize is too small"
307                   << std::endl
308                   << "the stepsize is " << stepsize
309                   << std::endl;
310  }
311  catch (...) {}
312  throw ex;
313}
314</pre>
315
316Note that writing to stream returned by elaborate() won't necessarily cause
317anything to get written to the terminal or an output file.  The information
318will be available when the what() member is called, if writing to the
319stream succeeds.  If the exception is caught by the mpqc main routine, then
320it will be printed for the user to see.  If the program catches the
321exception and determines that it is possible to proceed in a different way,
322then the user will never see the text.
323
324\subsection scexceptdebug Debugging Code with Exceptions
325
326Usually, exceptions are not the desired behaviour in a program, and it is
327necessary to debug a program that throws an exception.  This was easy when
328abort was called, because abort would raise a signal that was caught by the
329debugger and the code is stopped at the appropriate place.  With exceptions
330the matter is more complex, because the stack is unwound when an exception
331is thrown and most debugging information is lost.  To work around this
332problem, a breakpoint can be set in code that will be reached only in an
333exception, and will be run before the stack unwind begins.  A useful place
334to do this when GCC is used as the compiler is in the routine
335__cxa_allocate_exception().  So, in gdb, the following could be done:
336
337<pre>
338$ gdb ./scextest
339(gdb) b main
340(gdb) run
341Breakpoint 1, main () at /home/cljanss/src/SC/src/lib/util/misc/scextest.cc:172
342172           f();
343(gdb) b __cxa_allocate_exception
344(gdb) cont
345Breakpoint 2, 0x40582d46 in __cxa_allocate_exception ()
346   from /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.5/libstdc++.so.5
347(gdb) where
348#0  0x40582d46 in __cxa_allocate_exception ()
349   from /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.5/libstdc++.so.5
350#1  0x0804b3f7 in f () at /home/cljanss/src/SC/src/lib/util/misc/scextest.cc:60
351#2  0x0804b9e9 in main ()
352    at /home/cljanss/src/SC/src/lib/util/misc/scextest.cc:172
353</pre>
354
355Giving gdb "b main" followed by "run" was required before gdb could find the
356__cxa_allocate_exception symbol.
357
358\section devcheck Adding Test Cases to the Verification Suite
359
360There are two ways to test an MPQC build.  The <tt>testbuild</tt> and
361<tt>testrun</tt> make targets can be used to run test programs in
362various library directories, and the <tt>check</tt> and related make
363targets can be used to run MPQC on sets of input files.  See
364\ref mpqcval for more information about how to run the tests.
365
366Test programs can be added to the library directories by providing a source
367file with a main routine.  The set of test programs that is to be built and
368run by <tt>testbuild</tt> and <tt>testrun</tt>, respectively, is given by
369the <tt>TESTPROGS</tt> variable in the library's <tt>Makefile</tt>.  It may
370be necessary for an explicit rule to be given for building the test program
371to ensure that necessary libraries are linked in.  If a file named after
372the test program with a <tt>.out</tt> suffix is found in the source
373directory, then <tt>testrun</tt> fail if the command's output differs from
374that file.  Care must be taken to ensure that the output is architecture
375independent in this case.  Otherwise, <tt>testrun</tt> will fail only if
376running the command results in a nonzero return code.
377
378Additional MPQC test inputs can be added in the
379<tt>src/bin/mpqc/validate</tt> directory.  These inputs can be provided in
380one of two ways.  An input which is used to automatically generate multiple
381test cases can be written (with a <tt>.qci</tt> suffix), or a subdirectory
382with each input can be made.  See <tt>Makefile</tt>, <tt>basis1.qci</tt>,
383and <tt>input</tt> in the <tt>src/bin/mpqc/validate</tt> directory for
384examples.
385
386After you have added new inputs and modified the Makefile, change into the
387<tt>src/bin/mpqc/validate</tt> subdirectory of your object directory (where
388you compiled MPQC) and type <tt>make inputs</tt>.  This will create a
389<tt>input</tt> subdirectory containing MPQC input files with a
390<tt>.in</tt> suffix.  Files ending with a <tt>.qci</tt> suffix will also be
391placed in the <tt>input</tt> directory.  These contain a description of the
392calculation that is used by the utility program that checks the results of
393the validation suite.  Both the <tt>.in</tt> and <tt>.qci</tt> files for the
394new test cases must be copied into the <tt>ref</tt> directory in the source
395tree.  Note that inputs that are not useful in your build environment are
396not created by <tt>make inputs</tt>.
397
398*/
399