NOX Developer's Coding Guidelines
Adapted largely from
Programming in
C++, Rules and Recommendations, by Mats Henricson and Erik
Nyquist.
Structure of the Files
Naming Conventions
- C++ header files end in
.H
and source files end in
.C
- The name of the files should correspond to the name of the class
they define, with double-colons replaced by underscores. For example,
the definition of the class
NOX::Abstract::Group
is in
the file NOX_Abstract_Group.H
.
General File Structure
- Each file should begin as follows:
//@HEADER
// ************************************************************************
//
// NOX: An Object-Oriented Nonlinear Solver Package
// Copyright (2002) Sandia Corporation
//
// LOCA: Library of Continuation Algorithms Package
// Copyright (2005) Sandia Corporation
//
// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
// license for use of this work by or on behalf of the U.S. Government.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
// Questions? Contact Roger Pawlowski (rppawlo@sandia.gov) or
// Eric Phipps (etphipp@sandia.gov), Sandia National Laboratories.
// ************************************************************************
// CVS Information
// $Source: /space/CVS/Trilinos/packages/nox/src/NOX_Description.H,v $
// $Author: rppawlo $
// $Date: 2007/08/28 22:07:55 $
// $Revision: 1.69 $
// ************************************************************************
//@HEADER
Once the file is committed to the CVS repository, the CVS Information lines
will look something like the following:
// $Source: /space/CVS/Trilinos/packages/nox/src/NOX_Description.H,v $
// $Author: rppawlo $
// $Date: 2007/08/28 22:07:55 $
// $Revision: 1.69 $
The header information is automatically filled in between the two
//@HEADER
keys when we run the nox/maintenance/update_nox_headers.sh
command.
Include File Structure
Naming Conventions
- Everything must be declared within the
NOX
namespace. No exceptions!
- Furthermore, each class should be within the appropriate
sub-namespace. The choices are:
Abstract
Parameter
Solver
StatusTest
LineSearch
Direction
Epetra
- Class names should begin with an uppercase letter. Variable and
function names should begin with a lowercase letter.
- In names (function, class, variable, etc)
which consist of more than one word, the words are
written together and each word that follows the first is begun
with an uppercase letter. (e.g.,
NOX::Linesearch::MoreThuente
).
- Do not use identifiers which begin
with one or two underscores (`
_
' or `__
').
- Names should not include abbreviations that are not generally
accepted.
- Choose variable names that suggest the usage.
Style
Classes
- The public, protected, and private sections of a class are to be
declared in that order (the public section is declared before the
protected section which is declared before the private section).
- No inline functions, except the empty
{}
function. The reason for this is that if the function does not inline
correctly, it can actually lead to slower code rather than faster
code.
Functions
Variable declarations
Loops and conditionals: if
, for
,
while
, etc.
- User parens to make code readable.
if (a == b && c < d || e == f) // No!
{
/* Stuff */
}
if (((a == b) && (c < d)) || (e == f)) // Yes
{
/* Stuff */
}
- The block of any
if
statement should always follow on
a separate line.
if ( /*Something*/ ) i++; // No!!
if ( /*Something*/ ) // Yes!
i++;
- Braces ("{}") which enclose a block should be aligned as follows:
if ( /*Something*/ ) // Yes!
{
i++;
j++;
}
if ( /*Something*/ ) { // Okay
i++;
j++;
}
if ( /*Something*/ ) // No!
{
i++;
j++;
}
Adding the following line to your \c .emacs file will help:
(c-set-offset 'substatement-open 0)
Miscellaneous
- Always provide a space on both sides of
=
signs and all logical
operators.
- Each statement shall always be in a separate line, however small it may appear.
- Do not use spaces around
`
.
' or `->
', nor between unary operators
and operands.
- Use the c++ mode in GNU Emacs to
format code.
Coding Rules
- A public member function must never return a non-const reference
or pointer to member data.
- Constants are to be defined using
const
or
enum
; never using #define
.
- A switch statement must always contain a default branch which
handles unexpected cases.
Output
The
NOX::Utils
class has utility functions related
to printing. To use it, include
NOX_Utils.H
.
- For any non-error print statement, call the
NOX::Utils::out
or NOX::Utils::pout
functions with the appropriate
MsgType flag. The flags are:
NOX::Utils::Error
NOX::Utils::Warning
NOX::Utils::OuterIteration
NOX::Utils::InnerIteration
NOX::Utils::Parameters
NOX::Utils::Details
NOX::Utils::OuterIterationStatusTest
NOX::Utils::LinearSolverDetails
NOX::Utils::TestDetails
NOX::Utils::StepperIteration
NOX::Utils::StepperDetails
NOX::Utils::StepperParameters
NOX::Utils::Debug
Error Handling
Comments
We use Doxygen for the comments. To generate the documentation. Instructions can be found in the README file in the top-level nox directory.
- Document each class, function, and enum in the header
files.
- The one exception is that functions in derived objects do not
need to be documented if the documentation is inherited from
the base class. This should be tested in Doxygen to be sure that it
works correctly.
- Here's an example of documented a class. Note the formatting of
the comments. It's a C-style comment. The open comment marker
(
/*
) is followed by an exclamation mark to indicate that
it's a Doxygen comment. The open and close comment markers are on
lines by themselves, and the text of the comment is indented two
spaces. Always include a \brief
description. The long
description follows. Observe the use of the formatting tags
\c
and \e
. The \note
tag is
used for any special notes. The \author
tag is
recommended.
/*!
\brief Arbitrary combination of status tests.
In the \c AND (see NOX::Status::Combo::ComboType) combination, the
result is \c Unconverged (see NOX::Status::StatusType) if \e any of
the tests is \c Unconverged. Otherwise, the result is equal to the
result of the \e first test in the list that is either \c Converged
or \c Failed. It is not recommended to mix \c Converged and \c
Failed tests in an \c AND combination.
In the \c OR combination, the result is \c Unconverged if \e all of
the tests are \c Unconverged. Otherwise, it is the result of the \e
first test in the list that is either \c Converged or \c
Failed. Therefore, it will generally make sense to put the \c Failed
-type tests at the end of the \c OR list.
\note We always runs through all tests, even if we don't need
to. This is useful so that the user knows which tests have and have
not be satisfied.
\author Tammy Kolda (SNL 8950)
*/
class Combo : public Test {
...
}; // class Combo
- Any parameters that are used within the class must be
documented in the class description and in the file NOX_Description.H on the parameters "page".
Note that the name, a brief description, and the default value for
each parameter is listed.
/*!
\brief %Newton-like solver with a line search.
The following parameters are valid for this solver:
- "Line Search" - Sublist of the line search parameters, passed to
the NOX::Linesearch::Factory. Defaults to an empty list.
- "Linear Solver" - Sublist of the linear solver parameters, passed
to Abstract::Group::computeNewton(). Furthermore, the "Tolerance"
within this list may be modified by the
resetForcingTerm(). Defaults to an empty list.
- "Forcing Term Method" - Method to compute the forcing term, i.e.,
the tolerance for the linear solver. Defaults to ""
(nothing). Choices are "Type 1" and "Type 2".
- "Forcing Term Minimum Tolerance" - Minimum acceptable linear
solver tolerance. Defaults to 1.0e-6.
- "Forcing Term Maximum Tolerance" = Maximum acceptable linear
solver tolerance. Default to 0.01.
- "Forcing Term Alpha" - Used for the "Type 2" forcing term
calculation. Defaults to 1.5.
- "Forcing Term Gamma" - Used for the "Type 2" forcing term
calculation. Defaults to 0.9.
\author Tammy Kolda (SNL 8950), Roger Pawlowski (SNL 9233)
*/
Here's a more complicated example to produce a two-tiered list.
/*!
The parameters must specify the type of line search as well as all
the corresponding parameters for that line search.
<ul>
<li> "Method" - Name of the line search. Valid choices are
<ul>
<li> "Full Step" (NOX::Linesearch::FullStep)
<li> "Interval %Halving" (NOX::Linesearch::Halving)
<li> "Polynomial" (NOX::Linesearch::Polynomial)
<li> "More'-Thuente" (NOX::Linesearch::MoreThuente)
</ul>
</ul>
*/
- Constants and enums can generally be described with simple
\brief
comments. Those can be formatted in either of two
ways, as follows.
/*!
\brief The test can be either the AND of all the component
tests, or the OR of all the component tests.
*/
enum ComboType {AND, OR};
//! Constructor
Combo(ComboType t = OR);
- Doxygen does automatically cross-linking, which is very
convenient. However, sometimes it cross-links when you don't intend
for it to. For example, the following line would automatically
generate a link from the word
Newton
to the
NOX::Solver::Newton class.
//! Newton-like solver with a line search.
To prevent that automatic link, insert a percent sign (%
)
immediately before the word that is causing the link. For example,
//! %Newton-like solver with a line search.