User Tools

Site Tools


dev:codingconventions

This is an old revision of the document!


Coding Conventions

Stick to the standard

  • Code enabled by default should be standard Fortran 2008 [-std=f2008]
  • OpenMP code should follow version 3.X of the standard
  • MPI should should follow version 3 of the standard
  • Extended functionality should match POSIX and LSB.

Write explicit code

  • Every USE-statement should have an ONLY:-clause, which lists the imported symbols [-Wuse-without-only].
  • Every OMP PARALLEL-region should declare default(none).
  • Every static variable should be marked with the SAVE attribute.
  • Every Fortran module should contain the line IMPLICIT NONE [-fimplicit-none].
  • Every conversion that might change value should be explicit [-Wconversion]. Rationale:
    • INTEGER i=4.9999, i.e. i=INT(4.9999) implies i==4. Use NINT(4.9999) as appropriate.
    • natom*natom, nrow_global*ncol_global overflows INT(KIND=4) for large simulations.
    • always use REAL() with KIND parameter, i.e. r = REAL(i, KIND=dp).
    • avoid FLOAT() in favour of REAL(, KIND=dp).
    • the global number of grid points (pw_grid_type%ngpts,ngpts_cut) overflows INT(KIND=4) for large simulations.

Don't use poorly designed language features

  • Do not use the GOTO-statement. See also http://xkcd.com/292/ and 10.1145/362929.362947
  • Do not use left-hand-side (lhs) reallocations of allocatables [-Wrealloc-lhs-all]. Why?
  • Do not use FORALL constructs. Why?
  • Do not use OMP THREADPRIVATE variables.
  • Do not query the STAT from a DEALLOCATE, the Fortran runtime takes care.
  • Do not use RANDOM_NUMBER(), it's not consistent across different compilers.

Fight spaghetti code

There are two measure of defense against spaghetti code:

  1. Decoupling on the module and package level:
    • Every module should depend on as few other modules as possible.
    • Every package should depend on as few other packages as possible.
  2. Information hiding, also known as encapsulation.
    • External libraries should be wrapped within a single module or package.
    • Every module should hide its content by containing the line PRIVATE and only few public symbols.
    • Every package should hide its content by providing only a small public API through a single module.

Use existing infrastructure

For many common operations there exist wrappers in CP2K to prevent usage errors and to allow for central redirections, i.e. avoid to use direct calls to external libraries in CP2K

  • Use the routines from cp_files.F instead of calling OPEN and CLOSE directly.
  • Use the routines from the full-matrix fm-package instead of calling BLAS or Scalapack directly.
  • Use the routines from message_passing.F instead of calling MPI directly.
  • Use the routines from fft_lib.F instead of calling FFT (any library) directly.
  • Use the routines from machine.F to access architecture depended things like e.g. the working directory.
  • Don't use UNIT=* in WRITE or PRINT statements. Instead request a unit from the logger: iw=cp_logger_get_default_unit_nr() and write only if you actually received a unit: IF(iw>0) WRITE (UNIT=iw, ,,,).
  • Use CP2K's error-handling, instead of the STOP statement.

Remove dead code

  • Every line of code has to be compiled and maintained. Hence, unused variables and code poses an unnecessary burden and should be removed [-Wunused-variable -Wunused-but-set-variable -Wunused-dummy-argument].
  • Sometimes it is beneficial to keep debugging code around nevertheless. Such code should be put into a IF(debug_this_module)-block, with a parameter set to .FALSE.. This way the code will stay up-to-date and easily callable.

Format and document code

  • Each files should start with the official CP2K header.
  • Each .F file should contain either a PROGRAM or a single MODULE, whose name matches the filename.
  • Each module and routine should be annotated with Doxygen documentation.
  • Each preprocessor flag should start with two underscores and be documented in the INSTALL-file and added to the cp2k_flags function (cp2k_info.F).
  • The code should be formatted with the prettify tool by running make -j pretty.

Write tests

Doxygen documentation

  • Every FUNCTION and SUBROUTINE should be preceded by a valid doxygen block.
  • The following keywords are required: \brief, \param (for each parameter), \retval (for functions)
  • The following keywords are optional: \note, \par, \date, \author
  • Please run make doxify to format your doxygen comments, or generate templates where none exist
  • See our doxygen pages for the result
dev/codingconventions.1545220875.txt.gz · Last modified: 2020/08/21 10:14 (external edit)