Level 1 MESA++
This page describes Level 1 MESA++, which extends the Level 0
interface with exceptions and more C++-friendly argument lists.
What is Level 1 MESA++?
Some wrinkles
Namespaces
What is Level 1 MESA++?
Level 1 MESA++ is a straightforward extension of Level 0 MESA++
that makes use of exceptions and of more C++-friendly argument lists
while retaining a procedural interface.
Let's take those points in reverse order. C++ support
object-oriented programming, but it is not a pure object-oriented
language, like Eiffel or Java, where all
data is in the form of
objects and all procedures
are methods of object classes. You can write the kinds of
procedure-oriented programs you are familiar with from Fortran in C++
and you can even achieve near-Fortran efficiency if you write them
carefully. C++ is, after all, based on C, which in turn was designed to
closely match the assembly instruction set of a typical computer of its
day. Level 1 MESA++ supports procedural programming by providing a
library of procedures that make little use of class objects.
Note that we said "little use", not "no use." The C++ standard
library provides a number of container types, such as string and vector, which are classes but at
a fairly low level. We make use of these simple standard classes in
Mesa++ Level 1 wherever they make sense. However, there are some
limitations on where they can sensibly be used, as described in the
next section.
Finally, MESA makes extensive use of an error flag argument
(typically spelled ierr) in
its argument lists. C++
provides a somewhat more elegant method of handling errors, namely,
exceptions. An exception is "thrown" when an error condition is
detected, and "caught" at some higher level of the code that is
prepared to deal with the exception. Intermediate layers of code simply
propagate the exception upwards, automatically perfoming some cleanup
along the way. This model avoids the need to check the error flag at
every level of the code to see if that level should stop and return the
error flag to the next higher level of code.
The C++ library provides a number of standard exception types, but
we have chosen to provide our own Mesa_Exception
class to represent MESA++ exceptions. This class stores the location of
the exception (as a string)
and the ierr value (as an int).
Some wrinkles
We intend for Level 1 MESA++ to retain as much of the computational efficiency of the underlying Fotran as possible. This puts some restrictions on how we write this level of MESA++.Exceptions are supposed to be "pay to play." In other words, the use of exceptions in a program is not supposed to incur significant memory or runtime cost until an exception is actually thrown. This ideal is nearly realized on modern C++ compilers, and we use exceptions freely.
Standard library classes are another matter. We use string fairly freely, because of the enormous convenience of having the string contents and length readily available in a single package and because of the extensive string manipulation functionality provided by the methods of the string class. We reason that character strings are not often used at the lowest levels of a calculation (this certainly seems true of MESA and MESA++) so their overhead is almost always acceptable.
vector is a beautiful class in many ways. It provides automatic memory management and, like string, it wraps data and size information in one place. We can even extract the data pointer from a vector and wrap it in a Shape to be passed into a Fortran routine that expects a deferred array argument.
The fly in the ointment is that we cannot do the reverse. When a Fortran procedure does the allocating of a Shape, we have no way to move it into a vector short of copying all the data. That's an expensive operation we'd like to avoid anywhere it could create a computational bottleneck. Hence, there is presently (and likely always will be) a lot of procedures at Level 1 that use Shape in preference to vector.
Of course, we could write our own class that combines Shape and vector and has the machinery to decide which is wanted in various contexts. We might even be able to make this reasonably efficient. However, it's something that is only experimental at the moment, and not yet part of MESA++ Level 1. It may make more sense to more fully flesh out Shape instead and use it in preference to vector.
Name spaces
Many functions in MESA++ Level 0 do not return an ierr flag and already have perfectly serviceable argument lists. We incorporate these into MESA++ Level 1 via a using declaration, so that they appear in the Level 1 name spaces as if they were defined in those name spaces. This should be completely transparent to the average developer, who should rarely if ever have occasion to explicitly use the Level 0 name spaces.
All Level 1 and Level 2 MESA++ functions and objects based on a module in MESA will be found in a corresponding namespace Mesa_module. The Level 0 functions and objects are found in Mesa_module_L0. The reason for separating out the Level 0 functions is that they are usually implemented as direct references to the underlying MESA Fortran functions, and references (unlike actual functions) cannot be overloaded. To provide a function in Level 1 that has an improved interface (perhaps with a potential thrown exception) to a MESA function accessed via reference in level 0, it is necessary to place that function in a separate namespace so the names don't collide.
website
design
by
Andreas Viklund