QMG logo

Notes on the QMG source code

Much of the QMG package is written in C++. The purpose of this page is to give a brief overview of the source code in case the user wishes to modify it. This page assumes familiarity with C++. The source code is in subdirectories of $QMG_ROOT/src. The subdirectories are as follows: Some commands span several directories and files. The most complicated example is the mesh generator. Invoking gmmeshgen first executes gmmeshgen.m or gmmeshgen.tcl depending on the scripting language. These in turn invoke invoke gm_meshgen, a C++ routine whose source file is in $QMG_ROOT/src/meshgen. In turn, this front end invokes meshgen, a C++ routine in file meshgen.cpp the same directory. That routine is the main driver for mesh generation.

The file meshgen.cpp refers to both breps and simplicial complexes. These are defined in .h and .cpp files in either the tcl or matlab subdirectory, depending on which scripting language you use. The two versions of qbrep.h and qsimpcomp.h have been written so as to provide largely the same public interface. This means that most of the mesh generator works the same way regardless which .h file is included when you compile the mesh generator. The .cpp files contain quite different implementations. The Matlab implementation of breps stores the entire brep in a matlab data structure (a nested zba cell-array). The Tcl implementation of breps stores the brep in a C-language data structure, and then wraps it with the C++ class for manipulation by the mesh generator. The data structure is opaque to Tcl, but routines are provided to convert it to string format (this is required by Tcl for any object) and also to list format.

Thus, the choice of formats for breps and simplicial complexes is determined by which version of qbrep.h and qsimpcomp.h is included when the mesh-generator is compiled. The Makefile paths control this inclusion. QMG could have been written so that the choice of format of the brep is been postponed until run-time by using C++ abstract base classes and inheritance. But there did not seem to be any advantage to postponing this choice since QMG is compiled for either Matlab or Tcl but not both.

Another complicated feature in the mesh generator is the GUI panel that tracks the progress of the mesh generator. This gui is controlled by a class called Meshgen_gui. That class is defined by a header file qmg_gui.h in the meshgen directory. But there are two C++ implementations of the class, one in the tcl directory and one in the matlab directory. The two files qmg_gui.cpp call either matlab routine gm_mggui.m or tcl routine gm_mggui.m.

General naming conventions used in the source code are as follows. There are C-language routines defined in the XDR subdirectory and CLAPACK subdirectory. There are also C-language routines for defining the internal Tcl data structures for breps and meshes (as mentioned above). All the rest of the code is in C++. All of the C++ global names are wrapped in namespace QMG. This namespace in turn has some nested namespaces. Names used mainly within the mesh generator are wrapped in namespace QMG::MG. Names used to interface with the front end (matlab or tcl) are in namespace QMG::FrontEnd. There are a few other smaller namespaces with QMG used in the code.

Macros are not used extensively in the code. As is common practice, .h files are guarded with #ifdef/#define/#endif against double-inclusion. There are some macros used to handle incompatibilities between various C++ compilers. For instance, the NEED_TYPENAME_KEYWD macro is set if the compiler requires the C++ keyword typename in the situations mandated by the C++ standard.

The C++ source files that are invoked directly by the scripting language (Matlab or Tcl/Tk) all begin with the letters "gm" and are all in the meshgen and model subdirectories. These are C++ programs that can be linked to either Matlab or Tcl. These files all follow a standard format. There is a routine called worker in an anonymous namespace (i.e., not visible outside that file). The worker routine checks the arguments and then either does the work, or else calls some other routine that does the work. At the end of the file, the source code gm_entrypoint.cpp is included. This file is pulled from either the matlab or tcl source directory and is the actual entrypoint for the routine. This entrypoint follows the standard conventions for either matlab or tcl callable functions, and eventually invokes worker.

Perhaps the most important C++ class in the package is QMG::Brep, which is the class for breps. It defines a read-only data structure with many accessor functions, such as routines to retrieve control points, etc. It also defines many specialized iterator member classes. For example, if you want to loop over all the faces of a brep named b1, you can say

for (QMG::Brep::Face_Spec_Loop_Over_Faces fspec(b1);

The class for creating breps is QMG::Brep_Under_Construction, which is derived from QMG::Brep. This class is located in qbrep_constr.h. This class lets the caller insert new topological faces, control points, etc. There are no routines for modifying a brep after it is created. The only way to carry out modification is to copy the brep over.

Similarly, meshes are QMG::SimpComp (in qsimpcomp.h) and are read-only. To create a mesh, there is a second class QMG::SimpComp_Under_Construction in the same file.

There are many low-level classes important to QMG. For instance, QMG::Face_Spec is a pair of integers (dimension, index) used to index faces of a brep and is quite ubiquitous. QMG uses many STL classes, in particular string, maps and vectors.

A key data structure in mesh generation is QMG::MG::ActiveBoxVec. This data structure holds active boxes in the quadtree. There are several ActiveBoxVec's floating around, and boxes get transferred from one to another as the mesh generator runs. Another data structure is ActiveBox. This is not really a standalone data structure; instead, it is a pointer to a particular entry (an active box) in an ActiveBoxVec.

Some other conventions used in the source code are as follows. Variable di often stands for the embedded dimension, and gdim for the intrinsic dimension. Variables called fspec, new_fspec, subfspec, etc are usually face-specs, that is, ordered pairs of integers (facedim, faceind) that index a face of a brep. Variable tol is always the current absolute tolerance ("absolute" means that the tolerance lies between 0 and 1), scfac is usually the scale factor of the brep under consideration, and scaled_tol is the product of tol and scfac and is the tolerance relative to the size of the current brep.

The routine throw_error is called when there is an error. This routine is implemented in qerr.cpp in either the matlab or tcl subdirectory. The tcl version of throw_error will throw an exception that eventually returns control to the outer wrapper (in gm_entrypoint.cpp). The matlab version calls mexErrMsgTxt, which transfers control back to Matlab. Depending on compiler flags, the matlab version of throw_error will either throw an exception that eventually leads back to the wrapper, which then calls mexErrMsgTxt, or else it directly calls mexErrMsgTxt. The former is preferable since the stack unwinding process will free up allocated memory and close files, but the latter may be necessary on platforms where C++ exceptions and Matlab are not compatible.

There are four makefiles shipped with QMG. They are for Unix Tcl, Unix Matlab, Windows Tcl and Windows Matlab. These are all in subdirectories of $QMG_ROOT/build. The makefiles include a file called custom which needs to be customized. The makefiles themselves do not need customization. These makefiles also include pieces from the various src subdirectories. For instance, in the src/meshgen subdirectory, there are two files called meshgen_defs and meshgen_targets. The file meshgen_defs contains macro definitions that spell out which targets must be made in src/meshgen.

This documentation is written by Stephen A. Vavasis and is copyright ©1999 by Cornell University. Permission to reproduce this documentation is granted provided this notice remains attached. There is no warranty of any kind on this software or its documentation. See the accompanying file 'copyright' for a full statement of the copyright.

Stephen A. Vavasis, Computer Science Department, Cornell University, Ithaca, NY 14853, vavasis@cs.cornell.edu