Walkthrough
A walkthrough of the directory structure and provided modules from SincLib
SincMethods Directory Structure
This section attempts to outline the directory structure of SincLib. As SincLib is still under development, it is possible for the layout to change in the future (and equally possible that this document will fall behind!)The following directory structure is for the SincLib source code; the binary tarball which is distributed has a different layout.
- SincMethods (top level directory)
- build - The python build directory. You may safely ignore and/or delete the contents. It is used as a temporary directory for the python-based install system.
- docs - Documentation for SincLib. We aim to keep two sets of documentation; the online, web-based version you are reading, and a TeX-based one which can be turned into a PDF and printed out.
- scripts - Driver scripts used to run the various classes of SincLib. When you are executing something from the command line, you are likely using something that came from this directory.
- src - Source code for SincLib's core.
- gplt - A small graphics library which interfaces with Gnuplot. This allows SincLib to have 3d graphing capabilities, if desired. The library is hosted here because the original author no long maintains it. It will be removed when a simple, straightforward 3D-plotting library for python is found.
- sinc - The top-level directory for the sinc modules. Its contents are outlined below.
- tests - Unit tests for SincLib. Unit testing is a way to automate the testing of all the features of your library. When new code is added, one can run the tests found in this directory to make sure it does not break any older code. Basically, the scripts in this directory makes sure SincLib works.
- logger.conf - Logging configurations for SincLib. As there are many parts to SincLib, you'll probably want to turn logging in a specific component on while keeping the other logging off. Refer to the section below.
- setup.py - The python file which invokes the python distutils system. This helps the end-user install SincLib to the system.
- setup.sh - This shell script configures the environment so a user can run a SincLib-based script from a user directory without root access.
Sinc modules
The following directories are submodules of the python module sinc. They can be found in the directory $SINCLIB/src/sinc:- __init__.py - Empty file (required to be present by Python).
- base - The base files for SincLib.
- DelayedMath.py - Implements a DelayedMatrix class; its subclasses contain many optimizations based upon the matrix structure.
- QuadratureLib.py - Implements definite integration through the Quadrature class.
- QuadratureNLib.py - Implements N-dimensional definite integration through the QuadratureN class
- SincBaseLib.py - Contains the base class, SincBase, from which all other 1D classes derive.
- SincBaseNLib.py - Contains the base class, SincBaseN, from which all other N-dimensional classes derive.
- sinclib.py - Various sinc helper routines.
- cSincFuncs.c - Implementation of the conformal mappings in C.
- cSincLib.c - Select routines from sinclib.py implemented in C.
- derivative - Automatic differentiation routines. Experimental.
- SincDerivativeLib.py - Automatic differentiation implementation.
- examples - Examples covering most of the different parts of SincLib.
- There are very many different example problem files in this directory. Most of them correspond to problems out of Lund and Bower's book. Explore them on your own.
- ode - ODE solvers.
- DiffEqIcLib.py - 2nd order ODE with mixed BCs. Augments sinc methods to solve at boundary points.
- DiffEqLib.py - 2nd order ODE with Dirichlet BCs. Uses pure sinc methods.
- FirstOrderIcLib.py - 1st order ODE with one endpoint nonzero.
- FirstOrderLib.py - 1st order ODE with both endpoints zero.
- SturmLiouvilleLib.py - Sturm-Liouville problem solver.
- ode_system - System of first-order ODE-IVP solver.
- DiffEqIvpData.py - Constants needed for the IVP solver.
- DiffEqOptLib.py - Quasi-linear first order ODE solver.
- DiffEqSystemv2Lib.py - Solver for a system of quasi-linear first order ODEs.
- parallel - Parallel implementations of various portions of SincLib. Experimental.
- DelayedMath.py - Parallel implementation of the DelayedMath library.
- DiffEqOptParallelLib.py - Parallel implementation of the DiffEqOpt.
- DiffEqParallelLib.py - Parallel implementation of the DiffEq class.
- pQuadratureLib.py - Parallel implementation of quadrature.
- pSincBaseLib.py - Parallel SincBase class.
- psinclib.py - Parallel version of sinclib.py.
- pde - PDE solvers.
- BurgersLib.py - Solves the nonlinear Burger's equation.
- HeatIcLib.py - Heat equation with an initial condition.
- HeatLib.py - Solves the heat equation.
- PdeLib.py - Base class for all PDEs
- PoissonLib.py - N-dimension Poission's equation solver.
- SchrodingerLib.py - Simple Schrodinger's equation solver. Available in N-dimensions.
- SincMolLib.py - Method of Lines implementation using purely sinc methods.
- solvers - This module will eventually hold all the different solvers which SincLib can use. Currently, only holds an experimental multigrid routine.
- multigrid.py - Implements the V-cycle and a FMG solver, along with some simple 1D and 2D restriction/interpolation operators.
SincLib Logging, Explained
Logging often contains a frustrating paradox - as a developer, I want a high-level of debugging output to spot bugs in my problems. However, as a user, I want a minimum amount of logging - I only need to know any errors that occurred during the computation and the final output.SincLib attempts to solve this problem by using the python logging infrastructure. The logging module is covered in the online python documents, http://docs.python.org/lib/module-logging.html. Each module gets its own logging object, based on the module name. For example, the logger for the DiffEqLib module is called "SincMethods.DiffEq". This logger is considered a child of the logger "SincMethods", which is again a child of the logger "root".
There are 5 different levels of logging verbosity, CRITICAL, ERROR, WARNING, INFO, and DEBUG. CRITICAL statements are reserved for very bad circumstances. ERROR corresponds to an error which is not CRITICAL, but causes program execution to halt. WARNING is for errors or exceptions which the user might want to know about, but are not fatal. INFO should be normal running info the user might want to look at. Finally, DEBUG is reserved for debug statements put in by the developers to determine what the program is doing at a fine-grained level. The logger object has a method for each level of verbosity. If you want to say "Hello world!" in the debug level and the object is called log, then you would use log.debug("Hello world!").
The logger object will only record statements set at its current level or higher. If the logger is set to DEBUG, all statements will be recorded. If the logger is set to WARNING, only CRITICAL, ERROR, and WARNING statements will be recorded.
If a statement is to be recorded, the logger object formats it, then passes it on to a handler. Each logger may have multiple handlers. The handler's job is to save the log data. For example, there is a StreamHandler, which can output the log data to the console's output. The FileHandler writes information to a log file. If there is a system logging/monitoring services, such as SMTP, syslog, or NT event service, those too have handlers which can be used. SincLib, by default, only uses the StreamHandler to print the statements out on the console.
The formatter object's job is to format the statement which is going to be logged. Common formats include adding the date the event occurred or the line of code where the event occurred.
Each logging object may be the child of a different object. If so, it passes any statements it records to the parent. Suppose we have the logging object "SincMethods.DiffEq" which records the statement "Hello World" at level INFO. If the the "SincMethods.DiffEq" object is set to INFO or DEBUG, then it will log the event. In addition, it will pass the event up to its parent, "SincMethods". If "SincMethods" is set to INFO or DEBUG, it will also record the event. This way, you can control the overall level of messages from the whole SincLib library, or just increase logging in a specific module.
A single file, logger.conf, controls the logging output for each component of SincLib. In the default logger.conf, there is roughly one logger per module. Most are children of the logger "SincMethods". The child handlers are all set to the handler blank, which specifies that there is no logging output. Instead, whenever they record a statement, it gets passed up to the parent, "SincMethods". There, the statement gets printed out to the console.
In order to add your own logger, you need to do two things. Suppose that you call your logger "foo" with qualified name "SincMethods.bar"
- Add your logger foo to the list of loggers in the section [loggers] of the file logger.conf.
- Make a section at the bottom of logger.conf for your own logger. It should look something like this:
[logger_foo]
level=INFO
qualname=SincMethods.bar
handlers=blank
Now, in your module, make sure you import everything from the SincBaseLib module. This will make sure that the loggers get loaded. Then, you want to retrieve the logger for your module. The two statements together should look like this and appear at the top of your module:
from sinc.base.SincBaseLib import *Then, anywhere in your code, you may log statements using the object log. Go ahead and try logging: log.debug("Hello World!").
log = logging.getLogger("SincMethods.bar")
SincLib's defaults system
Another great annoyance that SincLib has attempted to address is the challenges of having many input constants for sinc methods. Some constants, such as alpha or beta, probably aren't going to be changed after the problem has been written down. Other constants, like M, will probably be tweaked for each run. There will be some constants, like d, which users are afraid to touch, and will want to use the defaults specified by the implementations.To handle this, we have an option parsing system that pulls in information from the following places. In order of precedence,
- The command line parameters.
- User-defaults written in the problem file.
- Defaults for the solver class.
The defaults for a class are defined in the defaults method. It must be a static method, and return a python dictionary containing the defaults. Here's an example, taken from the current implementation of SincBase:
@staticmethodA couple of things to note:
def defaults():
""" Returns the default values and properties for the SincBase. """
option_defaults = \
{ 'M' : ['M','M','the number of nodes to use in the approximation', 16,'int'],
'beta': ['b','beta','The value for beta in the sinc approximation', 1.0],
'alpha':['a','alpha','The value for alpha in the sinc approximation',1.0],
'transform':['t','transform','The sinc transform to use.','eyelet'],
'd' : ['d','d','The value for "d" in the sinc transform',pi/2.0,'eval'],
}
return option_defaults
- The decorator @staticmethod before the definition of the function declares it to be a static method. Decorators require Python 2.4 or higher. This allows one to call the function without needing an instance of the class. So, if you want the defaults for the SincBase class, you may simply call SincBase.defaults().
- The returned value is a python dictionary. The keys for the dictionary is the variable name to set the defaults for, and the value is a list containing information about the default. The values in the list are covered below.
- The 'transform' key has a special meaning for the defaults system. Based on the value of this variable, the option parser will assign various functions to the class, corresponding to the conformal mapping used. So, with transform set to 'eyelet', the created instance, S, will have a method called 'phi' which is the appropriate conformal mapping. The conformal mappings are covered here.
The most confusing part of the defaults system is the elements in the lists returned. They represent, in order:
- The one-letter short name for the option. May also be set to None.
- The long name for the option.
- The online help description of the option.
- The default value.
- The python type that the input value should be converted to.