Skip to content

Commit

Permalink
Update coding guidelines in file CONTRIBUTING.md
Browse files Browse the repository at this point in the history
  • Loading branch information
sunqm committed Sep 21, 2017
1 parent 87ccb10 commit d56e4f5
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 262 deletions.
160 changes: 152 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,157 @@
# Contributing to PySCF

The following is a set of guidelines for contributing to
[PySCF](https://github.com/sunqm/pyscf) package. These are just guidelines,
not rules. Feel free to propose changes.
The development guideline of [PySCF](https://github.com/sunqm/pyscf) program is
to provide an environment which is convenient for method developing, quick
testing and calculations for systems of moderate size. We emphasize first the
simplicity, next the generality, finally the efficiency. We favor the
implementations which have clear structure with optimization at Python level.
When Python performance becomes a big bottleneck, C code can be implemented to
improve efficiency. Following we specify the standard for C/Python interface
and other coding rules in the PySCF program. The following is a set of
guidelines for contributing to package. These are just guidelines, not rules.
Feel free to propose changes.

* New features are first placed in dev branch.

* Code at least should work with python-2.7, gcc-4.8.
- Writing python code compatibile with Python 2.6, 2.7, 3.2 - 3.6.
- Except complex value and variable length array, following C89 standard for C code.
Code standard
=============

* Using ctypes to bridge C/python functions.
* Code at least should work under python-2.7, gcc-4.8.

* 90/10 functional/OOP, unless performance critical, functions are pure.

* 90/10 Python/C, only computational hot spots were written in C.

* To extend python function with C/Fortran:

* Following C99 standard for C code.

* Following Fortran 95 standard (http://j3-fortran.org/doc/standing/archive/007/97-007r2/pdf/97-007r2.pdf)
for Fortran code.

* Using ctypes to interface C/python functions

* Do **not** use other program languages (to keep the package light-weight).

* External C/Fortran libraries.
These are libraries to be compiled and linked in the PySCF C libraries. Their
compiling/linking flags are resolved in the cmake config system.
- BLAS, FFTW: Yes.
- LAPACK, Scalapack, ARPACK: Yes but not recommended. These libraries can be
used in the PySCF C level library. But we recommend to restructure your code
and move the relevant linear algebra and sparse matrix operations to Python
code.
- MPI and other parallel libraries: No. MPI is the only library that can be
used in the code. The MPI communications should be implemented at python
level through MPI4py library.

* Minimal requirements on 3rd party programs or libraries.
- For 3rd party Python library, implementing either back up plan or
error/exception handler to avoid breaking the import chain
- 3rd party C library should not be compiled by default. A cmake option in
CMakeLists.txt can be provided to enable these C libraries

* Not enforced but recommended
- Compatible with Python 2.6, 2.7, 3.2-3.*.
To write code that works for both Python 2 and Python 3, you have to choose
the common set of Python 2 and Python 3. Please watch out the following
Python language features which may be regularly used in the program but
behave different in Python 2 and 3:
+ Avoiding relative import.
+ Use the % format for print function or "from future import print_function".
+ Distinguish / and // in python 2.
+ map, zip and filter functions return generator in python 3. Changing the
return value of map, zip and filter to list, eg list(zip(a,b)), to make
them work in the same way in python 2 and 3.
+ Always import "from functools import reduce" before using reduce function.
+ Avoid dict.items() method.
+ Avoid xrange function.
+ String should contain only ASCII character

- Python coding style. Whenever possible, follow PEP-8
https://www.python.org/dev/peps/pep-0008/

- New features are first placed in dev branch.


Name convention
===============

* The prefix or suffix underscore in the function names have special meanings.
- functions with prefix-underscore like ``_fn`` are private functions. They
are typically not documented, and not recommended to be used outside the
file where it is defined.
- functions with suffix-underscore like ``fn_`` means that they have side
effects. The side effects include the change of the input argument, the
runtime modification of the class definitions (attributes or members), or
module definitions (global variables or functions) etc.
- regular (pure) functions do not have underscore in the prefix or suffix.

API convention
==============

* :class:`gto.Mole` and :class:`pbc.gto.Cell` holds all global parameters, like
the log level, the largest memory allowed etc. They are used as the default
value for all other classes.

* Method class.

- Most QC method classes (like HF, CASSCF, FCI, ...) directly take three
attributes ``verbose``, ``stdout`` and ``max_memory`` from
:class:`gto.Mole`. Overwriting them only affects the behavior of the local
instance for that method class. In the following example, ``mf.verbose``
mutes the output produced by :class:`RHF` method, and the output of
:class:`MP2` is written in the log file ``example.log``::

>>> from pyscf import gto, scf, mp
>>> mol = gto.M(atom='H 0 0 0; H 0 0 1', verbose=5)
>>> mf = scf.RHF(mol)
>>> mf.verbose = 0
>>> mf.kernel()
>>> mp2 = mp.MP2(mf)
>>> mp2.stdout = open('example.log', 'w')
>>> mp2.kernel()
- Method class are only to hold the options or environments (like convergence
threshold, max iterations, ...) to control the behavior/convergence of the
method. The intermediate status are **not** supposed to be saved in the
method class (during the computation). However, the final results or
solutions are kept in the method object for convenience. Once the results
are generated in the method instance, they are assumed to be read only. To
simplify the function input arguments, class member functions can take the
results as the default arguments if the caller did not provide enough
arguments.

- In __init__ function, initialize/define the problem size. The problem size
(like num orbitals etc) can be considered as environment parameter. The
environment parameters are not supposed to be changed by other functions.
It is recommended to inherit the class from the :class:`pyscf.lib.StreamObj`,
and initialize attribute ._keys in the __init__ function. Attribute ._keys
is used for sanity check.

- Kernel functions
It is recommended to provide an entrance method called ``kernel`` for the
method class. The kernel function should be able to guide the program flow
to the right driver function.

- Return value.
Create return value for all functions whenever possible. For methods
defined in class, return self instead of None if the method does not have
particular return values.


Unit Tests and Example Scripts
==============================

* Examples to run modules should be placed in the appropriate directory within
the /examples directory. While the examples should be easy enough to run on a
modest personal computer; however, should not be trivial and instead showcase
the functionality of the module. The format for naming examples is::

/examples/name_of_module/XX-function_name.py

where XX is a two-digit numeric string.

* Test cases are placed in the /test/name_of_module directory and performed with
nosetest (https://nose.readthedocs.io/en/latest/). These tests are to ensure
the robustness of both simple functions and more complex drivers between
version changes.
Loading

0 comments on commit d56e4f5

Please sign in to comment.