Some notes about the art of programing on ARTS: 1. Never use float or double explicitly, use the type Numeric instead. This is set in arts.h (to double by defaults). Thus, it is possible to compile the program for float by simply changing the typedef in arts.h. 1.a. Use VECTOR and MATRIX for mathematical vectors and matrices (with elements of type Numeric). Use ARRAY for example to create an array of strings (and likewise for any other type). This should work for everything except bool (dunno why not for bool, strange things happen). ARRAYs can be used just like VECTORs. In particular, you can use round braces to get 1-based indexing, and they do range checks. 2. Terminology: Calculations are carried out in the so called workspace (WS), on workspace variables (WSVs). A WSV is for example the variable containing the absorption coefficients. The WSVs are manipulated by workspace methods (WSMs). The WSMs to use are specified in the contollfile in the same order in which they will be executed. 3. This one is intentionally left blank. 4. This one as well. 5. Global variables: Are not visible by default. To use them you have to declare them like this: extern const Numeric PI; which will make the global constant PI=3.14... available. Other important globals: full_name: The full name of the program, including version number. parameters: All command line parameters. basename: Used to construct report file and output file names. out_path: Output path. messages: Controls the verbosity level. wsv_data: WSV lookup data. wsv_group_names: Lookup table for the names of *types* of WSVs. md_data: WSM lookup data. The only exception from this rule are the output streams out0 to out3, which are visible by default. 6. Files: Always use the open_output_file and open_input_file functions to open files. This switches on exceptions, so that any error occuring later on with this file will result in an exception. (Currently not really implemented in the GNU compiler, but please use it anyway.) 7.a How to add a workspace variable: a) Create a record entry in file workspace.cc. (One of the wsv_data.push_back blocks.) Take the already existing entries as templates. At the moment the type of the variable can be only vector or string, but more types can be very easily added. However, I think the concept works best if WSVs are only of a rather limited number of different types, so that generic WSMs can be used extensively, for example for IO. The name must be *exactly* like you use it in the source code, because this is used to generate interface functions. b) Add the variable to the workspace in workspace.h c) That's it! 7.b How to add a workspace variable group: a) Add a `your_type_' handle to the enum WsvGroup in workspace.h b) Add a function virtual operator your_type_*() { safety(); return NULL; }; to class WsvP in workspace.h c) Add a wsv_group_names.push_back("your_type") function to the function define_wsv_data() in workspace.cc. The name must be *exactly* like you use it in the source code, because this is used to generate interface functions. d) That's it! (But as stated above, use this feature wisely) 7.c How to add a workspace method: a) Create an entry in md_data in file methods.cc. (Make a copy of an existing entry (one of the md_data.push_back(...) blocks) and edit it to fit your new method.) Don't forget the dokumentation string! It should contain line breaks and even double line breaks (= blank lines) in apropriate places. In the future there should also be example values for keyword parameters here, but this is not yet implemented. Also maybe an ´author' field would be nice. (FIXME: Update this.) b) Run: $ make. c) Look in md.h. There is a new function prototype void (...) Check that everything looks nice. If necessary, change the documentation string. d) Add your function to one of the .cc files which contain method functions. Such files must have names starting with "m_". (See separate HowTo if you want to create a new source file.) The header of your function must be compatible with the prototype in md.h. e) Thats it! 8. How to add a source code file: a) Create your file. Files containing workspace methods should start with `m_'. b) You have to register your file in the file `src/Makefile.am'. This file states which source files are needed for arts. Should be self-explanatory where you have to add your file. The above goes for source (.cc) and header (.h) files likewise. c) Go to the top level arts directory and run: $ reconf d) In the same directory, run: $ configure This will create new Makefiles which take your new file into account. e) Go to src and run: $ cvs add to make your file known to CVS. ---------------------------------------------------------------------- CVS stuff: 1. How to check out arts: a) Go to a temporary directory b) run cvs co arts 2. How to update (if you already have a copy): a) Go to the top arts directory (called simply `arts') b) run cvs update IMPORTANT!! Always update, before you start to make changes to the program, especially after a longer pause. If you edit an outdated copy, it will be a lot more work to bring your changes into the current copy of the program. 3. How to commit your changes: a) You should make sure that the program compiles and runs without obvious errors before you commit. a1) If you have created a new source file, make it known to CVS by running: $ cvs add in the directory where the file resides. In general, when you run cvs update, it will warn you about any files it doesn't know by marking them with a `?'. Files that are created during the compilation process, but should not be part of the package are listed in the .cvsignore files in each directory. b) Have you added the documentation for your new features? :-) c) Increase the subversion number in file src/version.cc. d) Open the file ChangeLog in the top level Arts directory with your favorite editor. With Emacs, you can very easily add an entry by typing either M-x add-change-log-entry or C-x 4 a. Specify the new version number and describe your changes. e) Make sure that you have saved all your files. Go to the top level arts directory and run: $ cvs commit f) This will pop up an editor. Use the mouse to cut and paste the ChangeLog message also to this editor window. Safe the file and exit the editor. If you made changes in different directories, another editor will pop up, already containing your message. Save again and exit. Do this until no more editors come up. (Note: This works well if you set $ export EDITOR=xedit With smarter editors there might be problems, because they might refuse to safe your file if you haven't made changes to it. So you would have to add a blank to the message each time a new directory is commited.) g) You have to give your version of the program a symbolic name, so that it can be retrieved later on if necessary. Do this by saying: cvs tag arts-x-y-z where x,y,z must be replace by the version numbers. You have to use dashes to separate the numbers, a point (`.') will not work. h) Tell the other developers about it. (Guess we should set up a mailing list) 4. How to move your arts working directory: !!!! Never try to move CVS directories !!!! Insted: a) Commit your changes. b) Go *above* the top level arts directory. c) Run: $ cvs release -d arts This will ask for confirmation, and if you say `y' delete your working copy of arts. d) Go to the directory where you want to have your arts copy in the future. e) Check out a new copy (See Howto 1) ---------------------------------------------------------------------- Build stuff: 1. Interesting ./configure options: --disable-warnings: Compile with -Wall on g++ compilers (by default warnings are on). THIS DOES NOT WORK (REQUIRES AUTO-TOOLS): --disable-assert: Include #define NDEBUG 1 in config.h. This is (will be FIXME: Implement this) the central switch to turn off all debugging features (index range checking for vectors, the trace facility, assertions,...) 2. Version numbers: Package version number is set in configure.in. Always increase this when you make a new distribution. The minor version number is set in src/version.cc. Always increase this before you do a CVS commit, even for small changes. 3. This is from Eleftherios Gkioulekas Assert: The idea behind assert is simple. Suppose that at a certain point in your code, you expect two variables to be equal. If this expectation is a precondition that must be satisfied in order for the subsequent code to execute correctly, you must assert it with a statement like this: assert(var1 == var2); In general assert takes as argument a boolean expression. If the boolean expression is true, execution continues. Otherwise the `abort' system call is invoked and the program execution is stopped. If a bug prevents the precondition from being true, then you can trace the bug at the point where the precondition breaks down instead of further down in execution or not at all. The `assert' call is implemented as a C preprocessor macro, so it can be enabled or disabled at will. One way to enable assertions is to include `assert.h'. #include Then it's possible to disable them by defining the `NDEBUG' macro. During debugging and testing it is a good idea to leave assertions enabled. However, for production runs it's best to disable them. If your program crashes at an assertion, then the first thing you should do is to find out where the error happens. To do this, run the program under the `gdb' debugger. First invoke the debugger: % gdb ...copyright notice... Then load the executable and set a breakpoint at the `abort' system call: (gdb) file arts (gdb) break exit (or break __assert_fail) Now run the program: (gdb) run Instead of crashing, under the debugger the program will be paused when the `abort' system call is invoked, and you will get back the debugger prompt. Now type: (gdb) where to see where the crash happened. You can use the `print' command to look at the contents of variables and you can use the `up' and `down' commands to navigate the stack. For more information, see the GDB documentation or type `help' at the prompt of gdb. 4. Assertion failures may occur in the ARRAY and VECTOR functions. Sometimes it helps to temporarily add the following cody immediately in front of the failed assertion: cout << "i = " << i << endl; cout << "dim() = " << dim() << endl; cout << "typeid = " << typeid(v_[0]).name() << endl; assert(i