Skip to content

Developer Documentation

TOFarmer edited this page Apr 29, 2019 · 13 revisions

Developer Documentation

Please read this documentation before modifying the MDMC code base. Any pull requests that are not consistent with this documentation will not be merged.

Coding Standards

Follow standards described in PEP 8, except where it differs from standards already adopted in surrounding code.

snake_case

snake_case is used for all variables names, except when the variable contains an abbreviation. So a variable related to a molecular dynamics (MD) engine is MD_engine, rather than md_engine. The same applies for physical symbols, e.g. Q for momentum transfer and E for energy should both be upper case.

Mathematical Operands

With regards mathematical operands, favour a space separating both sides of an operand:

E = h_bar * 1e18 * np.pi * np.arange(n) / (n * dt)

instead of:

E = h_bar*1e18*np.pi*np.arange(n)/(n*dt)

If an expression runs over two lines, prefer brackets to backslash, and align expressions in the same manner as for mathematical formula (i.e. new line should start with operand):

E = (h_bar * 1e18 * np.pi
     * np.arange(n) / (n * dt))

instead of:

E = h_bar * 1e18 * np.pi\
    * np.arange(n) / (n * dt)

or:

E = (h_bar * 1e18 * np.pi *
     np.arange(n) / (n * dt))

Imports

Imports should be grouped in the following order:

  1. stdlib
  2. third party libraries
  3. local modules

Each group should be sorted alphabetically and should be separated by a newline.

Units

All physical quantities within MDMC should possess units.

Everything related to units in MDMC is defined in MDMC.common.units. This includes:

  • the system of units (in the SYSTEM dictionary)
  • A Unit class, which derives from str to add additional mul, div, and pow methods so that strings representing units (e.g. 'Ang', 's') can be combined by these operations: Unit('Ang') * Unit('s') == Unit('Ang s')
  • UnitFloat and UnitArray classes, which derive from float and numpy.ndArray to add additional a Unit object to the representation, by means of a unit attribute.

So all physical quantities must be a UnitFloat or a UnitArray, and have the correct Unit object as an attribute. This can be achieved by having the unit as a property, rather than an attribute, and using one of the following decorators (in MDMC.common.decorators):

  • unit_decorator. This should typically be the decorator that is used as it sets the property to be either a UnitFloat or UnitArray. It should be added to the property setter:
@property
def velocity(self):

    return self._velocity

@velocity.setter
@unit_decorator(unit=units.LENGTH / units.TIME)
def velocity(self, velocity):

    self._velocity = velocity
  • unit_decorator_getter. This only be used either where the property has no setter method or where the getter method performs a calculation before setting the value (which may result in the UnitFloat/UnitArray being cast to a float/ndArray). It should only be used in these cases as it is more expensive than unit_decorator, as it initialises a UnitFloat/UnitArray object every time the getter is called. It should be added to the property getter:
@property
@unit_decorator_getter(unit=units.LENGTH)
def dims(self):

    return self._dims

In both of the above examples the unit passed to the decorator is a constant from the SYSTEM of units defined in the units module; however it would be equally valid to define a unit in this argument:

from MDMC.common.units import Unit
@property
@unit_decorator_getter(unit=Unit('nm'))
def dims(self):

    return self._dims

It is then obviously important that all functions and methods that use these properties have the correct factors to ensure the unit conversions are correct.

Documentation

MDMC follows the NumPy documentation style, which is consistent with PEP 257.

Code Checker/Linter

Use a code checker or linter such as pylint or flake8, to ensure PEP 8 coding standards are adopted.

Clone this wiki locally