| 1 |  | 
|---|
| 2 | /** \page develop Developing Code Using SC | 
|---|
| 3 |  | 
|---|
| 4 | In addition to the executables, the Scientific Computing toolkit libraries | 
|---|
| 5 | and include files can be installed on your machine.  This is described in | 
|---|
| 6 | the \ref compile section of this manual. | 
|---|
| 7 |  | 
|---|
| 8 | The <tt>sc-config</tt> program can be use to obtain the compilers, compiler | 
|---|
| 9 | options, and libraries needed to use the SC toolkit from your program. | 
|---|
| 10 | This utility is discussed below, along with how the SC toolkit must be | 
|---|
| 11 | initialized 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 |  | 
|---|
| 23 | The sc-config program returns information about how SC was compiled | 
|---|
| 24 | and installed.  See \ref sc-config for more information. | 
|---|
| 25 |  | 
|---|
| 26 | \section scinit Initializing SC | 
|---|
| 27 |  | 
|---|
| 28 | First the execution environment must be initialized using | 
|---|
| 29 | the ExEnv init member. | 
|---|
| 30 |  | 
|---|
| 31 | <pre> | 
|---|
| 32 | ExEnv::init(argc, argv); | 
|---|
| 33 | </pre> | 
|---|
| 34 |  | 
|---|
| 35 | By default, all output will go to the console stream, cout.  To change | 
|---|
| 36 | this, use the following code: | 
|---|
| 37 |  | 
|---|
| 38 | <pre> | 
|---|
| 39 | ostream *outstream = new ofstream(outputfilename); | 
|---|
| 40 | ExEnv::set_out(outstream); | 
|---|
| 41 | </pre> | 
|---|
| 42 |  | 
|---|
| 43 | MPI is allowed wait until MPI_Init is called to fill in argc and argv, so | 
|---|
| 44 | you may have to call MPI_Init before you even know that we ready to | 
|---|
| 45 | construct MPIMessageGrp.  So if an MPIMessageGrp is needed, it is up to the | 
|---|
| 46 | developer to call MPI_Init to get the argument list for certain MPI | 
|---|
| 47 | implementations. | 
|---|
| 48 |  | 
|---|
| 49 | <pre> | 
|---|
| 50 | MPI_Init(&argc, &argv); | 
|---|
| 51 | </pre> | 
|---|
| 52 |  | 
|---|
| 53 | When files are read and written, an extension is added to a | 
|---|
| 54 | basename to construct the file name.  The default is "SC". | 
|---|
| 55 | To 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 |  | 
|---|
| 62 | If your job might run in parallel, then make the following | 
|---|
| 63 | call 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 |  | 
|---|
| 70 | This 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 |  | 
|---|
| 81 | This 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 |  | 
|---|
| 93 | This section illustrates how to add a new method a new method to MPQC. | 
|---|
| 94 |  | 
|---|
| 95 | \subsection devsampsrc MP2 Implementation Example: Source | 
|---|
| 96 |  | 
|---|
| 97 | This example code illustrates a complete MP2 energy | 
|---|
| 98 | implementation using the SC Toolkit.  First an MP2 class is | 
|---|
| 99 | declared and the necesary base class member functions are | 
|---|
| 100 | provided.  Next a ClassDesc is defined.  Finally, the member | 
|---|
| 101 | functions are defined. | 
|---|
| 102 |  | 
|---|
| 103 | Note that no main routine is provided.  This is because this file | 
|---|
| 104 | is designed to be used to extend the functionality of the mpqc | 
|---|
| 105 | executable.  To generate a new mpqc executable with the new class | 
|---|
| 106 | available for use, see the \ref devsampmak section. | 
|---|
| 107 |  | 
|---|
| 108 | \include mp2.cc | 
|---|
| 109 |  | 
|---|
| 110 | \subsection devsampmak MP2 Implementation Example: Makefile | 
|---|
| 111 |  | 
|---|
| 112 | This example Makefile demonstrates how to link in a new class to | 
|---|
| 113 | form a new mpqc executable, here named mp2.  The code is given in | 
|---|
| 114 | the \ref devsampsrc section.  The \ref scconfig "sc-config command" | 
|---|
| 115 | is used to obtain information about how the SC toolkit | 
|---|
| 116 | was compiled and installed.  The library specified with -lmpqc | 
|---|
| 117 | provides the main routine from mpqc. | 
|---|
| 118 |  | 
|---|
| 119 | \include Makefile | 
|---|
| 120 |  | 
|---|
| 121 | \subsection devsampinp MP2 Implementation Example: Input | 
|---|
| 122 |  | 
|---|
| 123 | This input file can be used with the program illustrated in | 
|---|
| 124 | the \ref devsampsrc section.  It will compute the MP2 energy | 
|---|
| 125 | using the new MP2 class.  Note that only the | 
|---|
| 126 | \ref mpqcoo "object-oriented input format" can be used with | 
|---|
| 127 | user provided classes. | 
|---|
| 128 |  | 
|---|
| 129 | \include mp2.in | 
|---|
| 130 |  | 
|---|
| 131 | \section scexcept Exception Handling in SC | 
|---|
| 132 |  | 
|---|
| 133 | The development of SC began before exception handling was available in C++. | 
|---|
| 134 | A retrofit of the code to use exceptions is in progress.  It is difficult | 
|---|
| 135 | to retrofit a code, especially a parallel code, to do exception handling. | 
|---|
| 136 | There will be some limitations: exception handling will not work well for | 
|---|
| 137 | parallel jobs, objects whose members throw might be left in a questionable | 
|---|
| 138 | state, etc.  However, it is intended that SC objects will be usable in an | 
|---|
| 139 | interactive environment.  It is also planned that exceptions be used | 
|---|
| 140 | internally to facilitate recover from certain problems. | 
|---|
| 141 |  | 
|---|
| 142 | All new code should use exceptions instead of exit or abort and allocate | 
|---|
| 143 | resources in such a way that, if an exception occurs, all resources such as | 
|---|
| 144 | memory or locks are released.  A hierarchy of exception classes has been | 
|---|
| 145 | created that maps better to scientific computing than the standard | 
|---|
| 146 | exceptions.  More information is below, as well as in the documentation for | 
|---|
| 147 | the 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 |  | 
|---|
| 159 | Consider the following code fragment: | 
|---|
| 160 |  | 
|---|
| 161 | <pre> | 
|---|
| 162 | Object *obj = new Object; | 
|---|
| 163 | double *array = new double[n]; | 
|---|
| 164 |  | 
|---|
| 165 | f(obj, array, mol); | 
|---|
| 166 |  | 
|---|
| 167 | delete obj; | 
|---|
| 168 | delete[] array; | 
|---|
| 169 | </pre> | 
|---|
| 170 |  | 
|---|
| 171 | If an exception is thrown in the function f(), then storage for array and | 
|---|
| 172 | obj will not be released.  The standard C++ library provides a class, | 
|---|
| 173 | auto_ptr, to deal with obj, and the SC toolkit provides a class, auto_vec, | 
|---|
| 174 | to deal with array. | 
|---|
| 175 |  | 
|---|
| 176 | The include files for these two classes are: | 
|---|
| 177 |  | 
|---|
| 178 | <pre> | 
|---|
| 179 | #include \<memory\> | 
|---|
| 180 | #include \<util/misc/autovec.h\> | 
|---|
| 181 | </pre> | 
|---|
| 182 |  | 
|---|
| 183 | the code would be modified as follows: | 
|---|
| 184 |  | 
|---|
| 185 | <pre> | 
|---|
| 186 | std::auto_ptr<Object> obj(new Object); | 
|---|
| 187 | sc::auto_vec<double> array(new double[n]); | 
|---|
| 188 |  | 
|---|
| 189 | f(obj.get(), array.get()); | 
|---|
| 190 |  | 
|---|
| 191 | obj.release();  // or just let the destructor release it | 
|---|
| 192 | array.release();  // or just let the destructor release it | 
|---|
| 193 | </pre> | 
|---|
| 194 |  | 
|---|
| 195 | Note that when sc::Ref is used to store pointers, the storage will | 
|---|
| 196 | automatically be released when necessary.  No special treatment is needed | 
|---|
| 197 | to deal with exceptions. | 
|---|
| 198 |  | 
|---|
| 199 | \subsection scexceptlocks Exceptions and Locks | 
|---|
| 200 |  | 
|---|
| 201 | Consider the following code fragment: | 
|---|
| 202 |  | 
|---|
| 203 | <pre> | 
|---|
| 204 | g(const sc::Ref<sc::ThreadLock> &lock) | 
|---|
| 205 | { | 
|---|
| 206 | lock->lock(); | 
|---|
| 207 | f(); | 
|---|
| 208 | lock->unlock(); | 
|---|
| 209 | } | 
|---|
| 210 | </pre> | 
|---|
| 211 |  | 
|---|
| 212 | If f() throws, then the lock is never released.  The ThreadLock | 
|---|
| 213 | lock() and unlock() members should not be used anymore.  Now | 
|---|
| 214 | do the following: | 
|---|
| 215 |  | 
|---|
| 216 | <pre> | 
|---|
| 217 | g(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 |  | 
|---|
| 227 | Consider the following code fragment: | 
|---|
| 228 |  | 
|---|
| 229 | <pre> | 
|---|
| 230 | g(const sc::Ref<sc::RegionTimer> ®tim) | 
|---|
| 231 | { | 
|---|
| 232 | regtim->enter("f()"); | 
|---|
| 233 | f(); | 
|---|
| 234 | regtim->exit(); | 
|---|
| 235 | } | 
|---|
| 236 | </pre> | 
|---|
| 237 |  | 
|---|
| 238 | If f() throws, then the "f()" timing region is never exited. | 
|---|
| 239 | Instead use the following: | 
|---|
| 240 |  | 
|---|
| 241 | <pre> | 
|---|
| 242 | g(const sc::Ref<sc::RegionTimer> ®tim) | 
|---|
| 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 |  | 
|---|
| 252 | The SC exceptions provide information that can be used into two | 
|---|
| 253 | ways. First, text information is provided so that if the exception is not | 
|---|
| 254 | caught at a lower level, then the mpqc executable will catch it and write | 
|---|
| 255 | information about the problem to the terminal or an output file.  Second, | 
|---|
| 256 | information about the nature of the problem is provided, to permit | 
|---|
| 257 | developers to catch the exception and deal with it in some way.  The | 
|---|
| 258 | documentation for sc::SCException and all of its derivatives gives more | 
|---|
| 259 | information about the exceptions that are available.  As an example, | 
|---|
| 260 | consider the following loop, where a maximum number of iterations is | 
|---|
| 261 | permitted: | 
|---|
| 262 |  | 
|---|
| 263 | <pre> | 
|---|
| 264 | XYZ::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 |  | 
|---|
| 275 | The first argument to the exception class is a brief description of the | 
|---|
| 276 | error.  Additional information can be provided, | 
|---|
| 277 | see SCException::elaborate() description below. | 
|---|
| 278 | The next two arguments are | 
|---|
| 279 | the filename and line number.  The C preprocessor provides these for you | 
|---|
| 280 | with the __FILE__ and __LINE__ macros.  The next argument is specific to | 
|---|
| 281 | the MaxIterExceeded exception; it is the maximum number of iterations. | 
|---|
| 282 | Finally, a ClassDesc* can be given, which will be used to print out the | 
|---|
| 283 | class name of the object that failed.  All of these arguments are optional; | 
|---|
| 284 | however, the first three should always be given. | 
|---|
| 285 |  | 
|---|
| 286 | It is possible to provide additional information using the | 
|---|
| 287 | SCException::elaborate() member.  This will return a ostream, and the | 
|---|
| 288 | additional information can be written to this stream.  However, if for some | 
|---|
| 289 | reason it is not possible to write to this stream (say, there wasn't enough | 
|---|
| 290 | memory to allocate it), then an exception will be thrown.  For this reason, | 
|---|
| 291 | the string description given as the first argument should be informative | 
|---|
| 292 | since the additional information might not be available, and attempts to | 
|---|
| 293 | use elaborate() should be in a try block.  So, for example, the elaborate() | 
|---|
| 294 | member could be used in the above example as follows: | 
|---|
| 295 |  | 
|---|
| 296 | <pre> | 
|---|
| 297 | XYZ::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 |  | 
|---|
| 316 | Note that writing to stream returned by elaborate() won't necessarily cause | 
|---|
| 317 | anything to get written to the terminal or an output file.  The information | 
|---|
| 318 | will be available when the what() member is called, if writing to the | 
|---|
| 319 | stream succeeds.  If the exception is caught by the mpqc main routine, then | 
|---|
| 320 | it will be printed for the user to see.  If the program catches the | 
|---|
| 321 | exception and determines that it is possible to proceed in a different way, | 
|---|
| 322 | then the user will never see the text. | 
|---|
| 323 |  | 
|---|
| 324 | \subsection scexceptdebug Debugging Code with Exceptions | 
|---|
| 325 |  | 
|---|
| 326 | Usually, exceptions are not the desired behaviour in a program, and it is | 
|---|
| 327 | necessary to debug a program that throws an exception.  This was easy when | 
|---|
| 328 | abort was called, because abort would raise a signal that was caught by the | 
|---|
| 329 | debugger and the code is stopped at the appropriate place.  With exceptions | 
|---|
| 330 | the matter is more complex, because the stack is unwound when an exception | 
|---|
| 331 | is thrown and most debugging information is lost.  To work around this | 
|---|
| 332 | problem, a breakpoint can be set in code that will be reached only in an | 
|---|
| 333 | exception, and will be run before the stack unwind begins.  A useful place | 
|---|
| 334 | to 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 | 
|---|
| 341 | Breakpoint 1, main () at /home/cljanss/src/SC/src/lib/util/misc/scextest.cc:172 | 
|---|
| 342 | 172           f(); | 
|---|
| 343 | (gdb) b __cxa_allocate_exception | 
|---|
| 344 | (gdb) cont | 
|---|
| 345 | Breakpoint 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 |  | 
|---|
| 355 | Giving 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 |  | 
|---|
| 360 | There 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 | 
|---|
| 362 | various library directories, and the <tt>check</tt> and related make | 
|---|
| 363 | targets 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 |  | 
|---|
| 366 | Test programs can be added to the library directories by providing a source | 
|---|
| 367 | file with a main routine.  The set of test programs that is to be built and | 
|---|
| 368 | run by <tt>testbuild</tt> and <tt>testrun</tt>, respectively, is given by | 
|---|
| 369 | the <tt>TESTPROGS</tt> variable in the library's <tt>Makefile</tt>.  It may | 
|---|
| 370 | be necessary for an explicit rule to be given for building the test program | 
|---|
| 371 | to ensure that necessary libraries are linked in.  If a file named after | 
|---|
| 372 | the test program with a <tt>.out</tt> suffix is found in the source | 
|---|
| 373 | directory, then <tt>testrun</tt> fail if the command's output differs from | 
|---|
| 374 | that file.  Care must be taken to ensure that the output is architecture | 
|---|
| 375 | independent in this case.  Otherwise, <tt>testrun</tt> will fail only if | 
|---|
| 376 | running the command results in a nonzero return code. | 
|---|
| 377 |  | 
|---|
| 378 | Additional MPQC test inputs can be added in the | 
|---|
| 379 | <tt>src/bin/mpqc/validate</tt> directory.  These inputs can be provided in | 
|---|
| 380 | one of two ways.  An input which is used to automatically generate multiple | 
|---|
| 381 | test cases can be written (with a <tt>.qci</tt> suffix), or a subdirectory | 
|---|
| 382 | with each input can be made.  See <tt>Makefile</tt>, <tt>basis1.qci</tt>, | 
|---|
| 383 | and <tt>input</tt> in the <tt>src/bin/mpqc/validate</tt> directory for | 
|---|
| 384 | examples. | 
|---|
| 385 |  | 
|---|
| 386 | After 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 | 
|---|
| 388 | you 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 | 
|---|
| 391 | placed in the <tt>input</tt> directory.  These contain a description of the | 
|---|
| 392 | calculation that is used by the utility program that checks the results of | 
|---|
| 393 | the validation suite.  Both the <tt>.in</tt> and <tt>.qci</tt> files for the | 
|---|
| 394 | new test cases must be copied into the <tt>ref</tt> directory in the source | 
|---|
| 395 | tree.  Note that inputs that are not useful in your build environment are | 
|---|
| 396 | not created by <tt>make inputs</tt>. | 
|---|
| 397 |  | 
|---|
| 398 | */ | 
|---|