====== Coding Conventions ====== ===== Stick to the standard ===== * Code enabled by default should be standard Fortran 2008 [-std=f2008] and C99 [-std=c99] * OpenMP code should follow version 3.X of the standard * MPI should should follow version 3 of the standard * Extended functionality should match [[wp>POSIX]] and [[wp>Linux_Standard_Base|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 [[doi>10.1145/362929.362947]] * Do not use left-hand-side (lhs) reallocations of allocatables [-Wrealloc-lhs]. [[https://github.com/cp2k/cp2k/issues/726 | Why? ]] * Do not use ''FORALL'' constructs. [[https://gcc.gnu.org/ml/fortran/2012-04/msg00025.html | 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 [[wp>Spaghetti_code|spaghetti code]]: - 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. - [[wp>Information_hiding|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 ===== Always prefer [[https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gfortran/Intrinsic-Procedures.html|built-in (intrinsic) functions]] instead of hand-coded routines since they usually include extra numerical checks to avoid intermediate under- or overflow while still performing optimally. Examples: * ''NORM2(x)'' instead of ''%%SQRT(x(1)**2 + x(2)**2 + x(3)**2)%%'' * ''DOT_PRODUCT(x, x)'' instead of ''%%x(1)**2 + x(2)**2 + x(3)**2%%'' * ''DOT_PRODUCT(x, y)'' instead of ''%%x(1)*y(1) + x(2)*y(2) + x(3)*y(3)%%'' 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 [[error_handling|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 [[dev:codingconventions#Doxygen| 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 [[dev:formattingconventions| prettify tool]] by running ''make -j pretty''. ===== Write tests ===== * Every feature should be tested, with the goal of complete [[ http://www.cp2k.org/static/coverage/ | code coverage by regtesting ]]. ===== 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 [[ http://doxygen.cp2k.org/files.html | doxygen pages ]] for the result