Keep the style consistent !
This rule should be observed above all others. The coding style in code_saturne has evolved over the years, but unless you are ready to update a whole file to a more current style (in which case the other guidelines should be followed), try to remain consistent with the style in the current file.
For new files, use recently updated or reference examples, such as src/base/cs_field.c and src/base/cs_field.h for C, src/base/cs_array.cpp, and src/base/cs_array.h for C++.
If you consider your preferred coding style is better than the one used is superior in some manner to the one used, suggestions are welcome, and may lead to evolutions in the current style if the arguments are convincing, but remember that an inconsistent style is more time-consuming and difficult to read and understand.
Developers trying to follow a consistent style should expect help and counseling when they have questions, but those whose time is too precious to observe the existing code before providing their own or requesting assistance should understand that this is also true of those whom they expect to read their code.
The following general rules are strongly recommended:
For new developments, prefer C++ to C, as the code base will be progressively migrated to C++ (though C++ features will only be introduced by small increments)..
Except when adding additional white space to align similar definitions or arguments on several lines, standard English punctuation rules should be followed:
The code_saturne coding style inherits from common conventions, with a few specific additions.
The following presentation rules should be followed:
The following coding rules are strongly recommended:
Try to be consistent regarding line spacing. Use 1 separation line to highlight code blocks, but no more (i.e. avoid 2 successive blank lines). Make the code symmetric also: when a blank line follows an opening brace {, a similar line should precede the matching closing brace }. When no such line is used after an opening brace, none should be used either before the closing brace.
A .clang-format configuration file is available in the top-level source directory, so the clang-format tool may be used to obtain an acceptable presentation. Automated formatting does not exactly follow the above recommendations, but is as close as possible using the available parameters, so can provide a good starting point, though it is not activated automatically to allow for manual fine-tuning.
ANSI C11 or above is required, so C11-specific constructs are allowed. C99 variable-length arrays should be avoided, as it is not always clear whether they are allocated on the stack or heap, and are an optional feature only (though we could expect that support for those constructs will remain available on general-purpose architectures, and removed only in the embedded space).
For C++, at least C++14 is assumed.
Assertions are conditions which must always be verified. Several expanded macro libraries may be available, but a standard C language assertion has the following properties:
Assertions are thus very useful to ensure that conditions which are always expected (and not dependent on program input) are met. They also make code more readable, in the sense that it is made clear that conditions checked by an assertion are always expected, and that not handling other cases is not an programming error or omission.
If a condition may not be met for some program inputs, and not just in case of programmer error, a more complete test and call to an error handler (such as bft_error) is preferred.
The following rules should be followed:
The following form is preferred for enumerations:
Macros and enumerations related to myclass structures are prefixed by CS_MYCLASS_.
Public functions implementing methods are named cs_*class_method*, while private functions are simply named: class_method and are declared static.
Files containing these functions are named class.c.
Several integer types are found in code_saturne:
In the code_saturne kernel, it is preferable to use base functions provided by the BFT subsystem to the usual C functions, as those logging, exit and error-handling functions will work correctly when running in parallel, and the memory management macros ensure return value checking and allow additional logging.
The array below summarizes the replacements for usual functions:
Standard C function | code_saturne macro or function | Header |
---|---|---|
exit | cs_exit | cs_base.h |
exit on error | bft_error | bft_error.h |
printf | bft_printf | bft_printf.h |
printf (to standard logs) | cs_log_printf | cs_log.h |
malloc | BFT_MALLOC | bft_mem.h |
CS_MALLOC_HD | cs_base_accel.h | |
realloc | BFT_REALLOC | bft_mem.h |
CS_REALLOC_HD | cs_base_accel.h | |
free | BFT_FREE | bft_mem.h |
CS_FREE_HD | cs_base_accel.h |
Messages for the user should always be defined in US English in the source code (which avoids using extended characters and the accompanying text encoding issues in source code).
To make future internationalization using a mechanism such as gettext() possible, translatable strings should be encased in a _( ) macro (actually an abbreviation for a call to gettext() if available, which reverts to an empty (identity) macro is internationalization is unavailable or disabled). Strings assigned to variables must be encased in a N_( ) macro (which is an `‘empty’' macro, used by the gettext toolchain to determine that those strings should appear in the translation dictionary), and the variable to which such a string is assigned should be encased in the _( ) macro where used.
Note that with UTF-8 type character strings, accented or otherwise extended characters are represented on multiple bytes. The strlen C function will return the string's real size, which may be greater than the number of output columns it uses. The cs_log_strlen function may be used to compute the printable width of a character string, while and cs_log_strpad and cs_log_strpadl may be use to pad a string.
Most rules applicable to C apply here also. Note that standard C++ stream output (using std::cout ) may be practical for temporary debugging code, but should not be used instead of bft_printf or cs_log for production code.
It is imperative that new code be written in C or C++ rather than in Fortran. Fortran continues to be one of the best supported languages in HPC (with C++ and C), and has some interesting features such as Co-Array Fortran (starting with in Fortran 2008), but...
The core python scripts use a coding style similar to PEP-8 PEP-8. PEP-257 (docstring conventions) is also recommended.
Other parts of the code tend to use a camelCase naming, but should otherwise adhere to the same standards. Moving the to PEP-8 style would be ideal, though to avoid confusion, this should be done in an atomic step for each module.
Documentation of the main code is based on the Doxygen tool, whose documentation may be found on its web site.
Additional pages for the documentation may be found in the source tree, under docs/doxygen. Files containing mostly examples may use the .h or .dox extension (with .dox preferred for easier identification), and pages which describe general aspects instead of code are preferably written in Doxygen Markdown (.md extension), as this allows better readability and interoperation with some editors (such as preview, syntax highlighting, ...).
When building the code, remember to often use make html and check the docs/doxygen/doxygen_warn.log file in the build directory for errors and warnings.
When modifying arguments to a function or modifying structures, make sure the special Doxygen comments are kept up to date. Using Doxygen comments in the C code and simplified comments in the headers (see cs_medcoupling_postprocess.cxx and cs_medcoupling_postprocess.h for example) is recommended, but as this adds to the coding effort, duplicating the headers from the reference C code to the headers is not recommended since recent versions of Doxygen complain about this, so avoiding duplicates is the preferred way. For inlined functions or structures the documentation should be available in the .h files since that is where the function or structure are defined.
For functions the following structure is advised (example extracted from cs_medcoupling_postprocess.cxx):
Private functions or structures should not appear in the documentation (though their arguments should be documented in the source code), so in most source files,
is used to mark the beginning of a section which should be ignored by Doxygen, and
used to mark the end of that section. In most cases, this includes private structures and functions in C code, but could be extended to public function definitions if the .h file header already contains the same Doxygen-formated comments.