CARP example simulations are created using the carputils framework in a
standardised way that seeks to promote conciseness and familiarity to
developers. Writers of new examples are therefore advised to first look over
existing examples. Look in the directory hierarchy of the devtests or
benchmarks repositories - examples are the python source files conventionally
named run.py
in directories whose name describes the main purpose of the
example.
Note
For a complete working example simulation, please look at the ‘simple bidomain’ example in the devtests repository (devtests/bidomain/simple), which can be copied and adapted to create new examples.
The carputils framework can be used by any python script on a machine where it
is installed - scripts do not need to be placed inside the devtests or
benchmarks repositories. The reasons to place them there is to share them
conveniently with others and for inclusion in the automatic testing system
carptests
.
A CARP run script will contain at a minimum:
from carputils import tools
@tools.carpexample()
def run(args, job):
# Generate CARP command line and run example
pass # Placeholder
if __name__ == '__main__':
run()
The script defines a run
function which takes as its arguments a namespace
object containing the command line parameters (generated by the standard
library argparse module) and a Job
object. The run
function should use the carputils.tools.carpexample()
function decorator,
as shown, which generates the above arguments and completes some important pre-
and post-processing steps.
Many of the tasks of run scripts are common between examples, for example for
setting up the correct CARP command line options for a particular solver.
carputils
therefore performs many of these common tasks automatically or by
providing convenience functions. Below is a more complete example:
"""
Description of the example.
"""
EXAMPLE_DESCRIPTIVE_NAME = 'Example of Feature X'
EXAMPLE_AUTHOR = 'Joe Bloggs <joe.bloggs@example.com>'
from datetime import date
from carputils import tools
def parser():
# Generate the standard command line parser
parser = tools.standard_parser()
group = parser.add_argument_group('experiment specific options')
# Add an extra argument
group.add_argument('--experiment',
default='bidomain',
choices=['bidomain', 'monodomain'])
return parser
def jobID(args):
today = date.today()
ID = '{}_{}_{}_np{}'.format(today.isoformat(), args.experiment,
args.flv, args.np)
return ID
@tools.carpexample(parser, jobID)
def run(args, job):
# Generate general command line
cmd = tools.carp_cmd('example.par')
# Set output directory
cmd += ['-simID', job.ID]
# Add some example-specific command line options
cmd += ['-bidomain', int(args.experiment == 'bidomain'),
'-meshname', '/path/to/mesh']
# Run example
job.carp(cmd)
if __name__ == '__main__':
run()
Below the various parts of the above example are explained.
carputils.tools.standard_parser()
returns an ArgumentParser
object
from the argparse
module of the python standard library. You can then add
your own example-specific options in the manner shown. See
the argparse documentation
for information on how to add different types of command line option.
To make it easier to identify experiment specific options, an argument group
is created and
arguments added directly to it.
This is optional but increases clarity.
def parser():
# Generate the standard command line parser
parser = tools.standard_parser()
group = parser.add_argument_group('experiment specific options')
# Add an extra argument
group.add_argument('--experiment',
default='bidomain',
choices=['bidomain', 'monodomain'])
return parser
The jobID
function generates an ID for the example when run. The ID is used
to name both the example output directory and the submitted job on batch
systems. The function takes the namespace object returned by the parser as an
argument and should return a string, ideally containing a timestamp as shown:
def jobID(args):
today = date.today()
ID = '{}_{}_{}_np{}'.format(today.isoformat(), args.experiment,
args.flv, args.np)
return ID
The carputils.tools.carpexample()
decorator takes the above parser and
jobID functions as arguments. It takes care of some important pre- and
post-processing steps and ensures the correct arguments are passed to the run
function at runtime:
@tools.carpexample(parser, jobID)
def run(args, job):
carputils.tools.carp_cmd()
generates the initial command line for the
CARP executable, including the correct solver options for the current run
configuration the standard command line parser generated above. If you are
using a CARP parameter file, pass the name as an optional argument to
carp_cmd()
, otherwise just call with no argument:
# Generate general command line
cmd = tools.carp_cmd('example.par')
The CARP command must always have a -simID
argument set. When your example
runs CARP only once, this will be the ID
attribute of the job
object
passed to run, otherwise it should be a subdirectory:
# Set output directory
cmd += ['-simID', job.ID]
Your example should then add any additional command line arguments to the command list:
# Add some example-specific command line options
cmd += ['-bidomain', int(args.experiment == 'bidomain'),
'-meshname', '/path/to/mesh']
Finally, use the carp
method of the job
object to execute the
simulation. The reason for this, rather than executing the command directly,
is that the job
object takes care of additional preprocessing steps and
automatically generates batch scripts on HPC systems. To run shell commands
other than CARP, see the carputils.job.Job
documentation.
# Run example
job.carp(cmd)
At the very end of your run script, add the below statements. This executes the run function when the file is executed directly:
if __name__ == '__main__':
run()
Examples should be well commented, but should also start with a descriptive python docstring to serve as a starting point for new users. This should include:
The docstring must be at the top of the file, before any module imports but
after the script interpreter line, and is essentially a comment block started
and ended by triple quotes """
:
#!/usr/bin/env python
"""
An example testing the ...
"""
EXAMPLE_DESCRIPTIVE_NAME = 'Example of Feature X'
EXAMPLE_AUTHOR = 'Joe Bloggs <joe.bloggs@example.com>'
The docstring should be followed by two variables as above.
EXAMPLE_DESCRIPTIVE_NAME
should be a short descriptive name of the test to
be used as a title in the documentation, e.g. ‘Activation Time Computation’ or
‘Mechanical Unloading’. EXAMPLE_AUTHOR
should be the name and email address
of the primary author(s) of the test in the format seen above. Multiple authors
are specified like:
EXAMPLE_AUTHOR = ('Joe Bloggs <joe.bloggs@example.com>,'
'Jane Bloggs <jane.bloggs@example.com> and'
'Max Mustermann <max.mustermann@beispiel.at>')
The docstring is used to build the example documentation at https://carpentry.medunigraz.at/carputils/examples/, and can include reStructuredText formatting. Some key features are summarised below, but for a more comprehensive summary of the format please see the Sphinx webstie. It is important to bear in mind that indentation and blank lines have significance in rst format.
Headings are defined by underlining them with = , - , + ,
~ , with the order in which they are used indicating the nesting
level: |
Heading 1
=========
Heading 1.1
-----------
Heading 1.1.1
+++++++++++++
Heading 1.2
-----------
|
Python code highlighting is done by ending a paragraph with a double
colon :: followed by an indented block: |
Here is an example of a run function::
def run(argv, outdir=None):
for list in argv:
print argv
|
Highlighting of other languages is done with a code-block
directive: |
.. code-block:: bash
echo "some message" > file.txt
|
LaTeX-formatted maths may be inserted with the math environment
(info): |
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
|
or inline: | I really like the equation :math:`a^2 + b^2 = c^2`.
|
Images may be included, but must be stored in the doc/images
directory of carputils. The path used in the image directive must
then begin with /images to work correctly. |
.. image:: /images/ring_rigid_bc.png
|