Autodoc and Autotest

Alamo includes a self-contained automatic documentation (autodoc) and automatic test (autotest) system. The purpose of the custom autodoc and autotest systems is to:

  1. Make it easy for developers to add documentation and regression tests

  2. Keep documentation and tests accessible and up-to-date

  3. Prevent old or out-of-date documentation.

Autodoc system

The autodoc system parses the source files stored in ./src/ to generate the content of the Inputs portion of this documentation. There are two ways to create compliant documentation: via parser comments, and via header file comments.

Parser comments

The IO::ParmParse class (inherited from the AMReX ParmParse class) is used to read all input paramters from the input file, usually though lines like this:

pp.query("lame",lambda);
pp.query("shear",mu);

To generate the autodocumentation, simply add a standard C++ comment following the query line:

pp.query("lame",lambda); // Lame parameter
pp.query("shear",mu);    // Shear modulus

or immediately preceeding the query line:

// Lame parameter
pp.query("lame",lambda);
// Shear modulus
pp.query("shear",mu);

Note that the parser object must be called pp for the autodoc system to locate the query. As long as the convention is followed, the content of the comments will be automatically scraped and included in the Inputs section of the documentation. (For instance: Model::Solid::Linear::Isotropic)

Header comments

General comments to document a class, or collection of methods, goes at the top of the associated header file. Use standard C++ comments (//). These comments will get scraped by the autodoc system, and will be formatted along with the rest of the inputs.

For example, consider the documentation for the linear isotropic material model class. The following leading comment is formatted at Model::Solid::Linear::Isotropic

//
// This model implements an isotropic linear elastic material.
// See `this link <https://en.wikipedia.org/wiki/Linear_elasticity#(An)isotropic_(in)homogeneous_media>`_
// for more information about the theory.
//
// Free energy for a linear material is defined as
// 
// .. math::
//
//     W(\nabla\mathbf{u}) = 
//     \frac{1}{2}\nabla\mathbf{u}\cdot\mathbb{C}\,\nabla\mathbf{u}
//
// For an isotropic material, stress and strain are related through
// 
// .. math::
// 
//     \mathbb{C}_{ijkl} = \lambda \delta_{ij}\varepsilon_{kk} + 2\mu\varepsilon_{ij}
// 
// where :math:`\lambda` and :math:`\mu` are the Lame constant and shear modulus, respectively.
// Users can specify these either through (:code:`lame` and :code:`shear`)
// OR (:code:`lambda` and :code:`mu`) OR (:code:`E` and :code:`nu`).
//
// Class methods:
// 
// #. :code:`Isotropic()`: 
//    Basic constructor. Does nothing, and leaves all values initiated as NAN.
// #. :code:`Isotropic(Solid<Set::Sym::Isotropic> base)`
//    Basic constructor. Does nothing gut allows for inheritance.
// #. :code:`Isotropic(Set::Scalar a_mu, Set::Scalar a_lambda)`
//    BAD old-fashioned constructor. Do not use!
// #. :code:`~Isotropic()`
//    Simple destructor. Don't need to change it.
// #. :code:`void Define(Set::Scalar a_mu, Set::Scalar a_lambda)`
//    BAD old-fashioned way of doing things. Use :code:`Parse` instead.
// #. :code:`Set::Scalar W(const Set::Matrix & gradu) const override`
//    Returns elastic free energy density
// #. :code:`Set::Matrix DW(const Set::Matrix & gradu) const override`
//    Returns first derivative of free energy, the stress tensor
// #. :code:`Set::Matrix4<...> DDW(const Set::Matrix & ) const override`
//    Returns second derivative of free energy, the modulus tensor
// #. :code:`virtual void Print(std::ostream &out) const override`
//    Prints the modulus tensor object to output stream (usually the terminal)
// #. :code:`static Isotropic Random()`
//    Static method that generates a random yet acceptable model.
// #. :code:`static Isotropic Zero()`
//    Static method that generates a "zero" element (so that there is no effect under addition)
// #. :code:`static void Parse(Isotropic & value, IO::ParmParse & pp)`
//    Parser where all the IO occurs
//
//

ReStructuredText

All comments are formatted using restructuredtext markup. You can make use of this is if you like, but it is not required for good documentation.

Documentation generation

To generate this documentation, complete with the scraped markup, run

make docs

in the alamo root directory. The file alamo/docs/requirements.txt contains a list of the necessary packages. You can install them using pip. Once the documenation generation is complete, you can view it by

google-chrome docs/build/html/index.html

Autotest system

Alamo contains a complete regression testing system to ensure that established capabilities do not get lost during subsequent development. Regression tests are run automatically by github, and must all pass prior to merge into the development or master branches. For information on how to run the regression tests, see Testing.

Test requirements

Remember that your test will be run automatically on GitHub and by other users, so avoid creating long, memory-intensive tests. Instead, design your tests so that they run long enough to identify errors, but short enough so that they can be performed tractable. Make sure that your tests are not redundant with existing tests as well.

Creating a test

  1. Create a subdirectory in the ./tests with your test name, e.g. “MyTest” [./tests/MyTest]

  2. Place your test input file in this directory and name it input [./tests/input].

  3. At the top of the test input file, add

    #@ [sectionname]
    

    where sectionname can be any unique handle name. The #@ directive is ignored by alamo, but all comments beginning with it will be parsed by the autotest system.

  4. Test your test by running

    ./scripts/runtests ./tests/MyTest
    

    If alamo has been compiled in 3D, this should cause your test to run. The output of your test will be stored in

    ./tests/MyTest/output_YYYY-MM-DD_HH.MM.SS_hostname_sectionname
    

Once you have done this, your test will be executed along with all other regression tests by GitHub. If your test fails to complete - for instance, it segfaults or aborts abnormally - this will trigger a “failed test”

Input file directives

There are several directives that you can use for your inputs. These are written using the #@ comments at the top of the input file.

#@  [2D-serial-5levels]        | each [...] specifies a run of the test
#@  dim    = 2                 | specify two dimensions
#@  nprocs = 1                 | specify running in serial (the default)
#@  check  = false             | for this test we do not want to run the verification
#@
#@  [3D-parallel-4levels]      | another test
#@  dim    = 3                 | specify running in 3D (the default)
#@  nprocs = 4                 | specify run in parallel with 4 processors
#@  args   = amr.max_level=4   | specify an additional argument to be added to input file
#@  benchmark-beaker = 16.10   | timing test: benchmark-id record current average time to
#@  benchmark-statler = 11.36  |     run on platform "id". The autotest system will let you
#@  benchmark-github = 22.75   |     know if future changes slow the test down.
#@  ignore = myargument        | tell alamo to ignore certain arguments

For additional examples, see the Tests section.

Test verification

Successfully running a test does not tell you much unless you know that the correct answer was produced. To automatically verify your test, add an executable file called test to the test directory:

./tests/MyTest/test

The test script must be executable, and can be written in a language of your choice, as long as you have the appropriate shebang at the top. There are two requirements on the test script:

  1. It must take a single argument, the test directory name.

  2. It produces a zero error code if the test passes, and a nonzero error code if the test fails.

It is up to you to make sure that the test accurately assesses the output. You can store reference data inside the test directory; e.g.

./tests/MyTest/reference/stress_xx.dat
./tests/MyTest/reference/stress_xy.dat
....

as long as the data files are reasonably small in size and, of course, are text-based. For example tests, see the existing tests in the repository.