Sundance is a moderately large and rather complex package. The good news for you is that only a small fraction of the classes and an even smaller fraction of the methods are needed for user-level code. In fact, for many "user-level" classes the only method you ever call will be the contructor.
One of the main goals of this document is to distinguish those user-level classes and methods from developer-level classes and methods. The class reference manual has separate pages for user-level classes and for low-level classes. Furthermore, in the method listing for each user-level class, there are subgroups for user-level and developer-only methods.
Please read the following sections on
Understanding handle classes and how they are used in Sundance is important for reading and writing Sundance code and browsing the source and class documentation. Handle classes are used in Sundance to simplify user-level polymorphism and provide transparent memory management.
Polymorphism is a buzzword meaning the representation of different but related object types (derived classes, or subclasses) through a common interface (the base class). In C++, you can't use a base-class object to represent a derived class; you have to use a pointer to the base class object to represent a pointer to the derived class. That leads to a rather awkward syntax and also requires attention to memory management. To simplify the interface and make memory management automatic, all user-level polymorphism is done with handle classes. A handle class is simply a class that contains a pointer to a base class, along with an interface providing user-callable methods, and a (presumably) intelligent scheme for memory management.
So if you want to work with a family of Sundance objects, for instance the different flavors of symbolic objects, you need only use:
For example, Sundance symbolic objects are represented with a handle class called Expr. The different symbolic types derive from ExprBase, but they are never used directly after construction; they are used only through the Expr handle class. The code fragment below shows some Exprs being constructed through subclass constructors and then being used in Expr operations.
Expr x = new CoordExpr(0, "x"); Expr f = x + 3.0*sin(x); Expr dx = new Derivative(0); Expr df = dx*f;
Notice that a pointer to a subclass object is created using the new operator, and then given to the handle. The handle object assumes responsibility for that pointer: it does all memory management, any copying that might occur, and will eventually delete it. You, the user, should never delete a pointer that has been passed to a handle. Memory management is the responsibility of the handle. (Code like this will seem familiar to Java programmers, who call new but never delete).
Some important user-level handle classes in Sundance are
Sundance has been designed so that memory management is transparent to the user; that is, the user should never have to worry about deleting memory that has been allocated. With the exception of new pointers that are immediately passed to handles, user-level code is entirely free of pointers.
When writing Sundance code, you can assume that
Memory management of symbolic expressions is designed so that the contents of an expression can be modified after the fact. This lets you use the same expression with different data at all steps in an iterative procedure, for instance. Please see the section on Assignment and copying of expressions for more information.
Sundance can both assemble and solve linear systems in parallel.
Parallel Sundance uses the SPMD paradigm, in which the same code is run on all processors. Communication is done using the CSMR MPIComm class, which is essentially an object wrapper for selected MPI features. To use Sundance's parallel capabilities, the CPPUtilities package supporting Sundance has to be built with MPI enabled, and you must use a parallel solver such as Trilinos. See the installation documentation for help in installing parallel Sundance.
One of the design goals was to make parallel solves look to the user as much as possible like serial solves. In particular, the symbolic description of an equation set and boundary conditions is completely unchanged from serial to parallel runs. To run a problem in parallel, you simply need to
Sundance is a high-level system, in which a finite-element problem is described with expressions, function spaces, and domains instead of low-level concepts such as matrix entries, elements, and nodes. If you find yourself asking things such as "how can I modify the entries in row k" instead of "how can I modify my symbolic equation set," you're probably thinking about the problem the wrong way. Of course, you can write Sundance code using it's low-level features directly, but such code will be harder to read and almost always less efficient. So please stick to the higher-level objects and operations. Matlab programmers who have learned to write their problems as high-level vector and matrix operations instead of low-level loops will find this way of thinking natural.