Code Contribution Guidelines¶
DINO is a high-performance scientific simulation code written primarily in Fortran90 and designed to run efficiently on massively parallel HPC systems. Contributions should therefore maintain high standards of readability, maintainability, numerical robustness, and parallel scalability. All contributors are expected to follow the guidelines below.
General Principles¶
Contributed code must satisfy the following principles:
- Correctness first: numerical algorithms must be verified and validated where applicable.
- Performance awareness: the code runs on large HPC systems; avoid unnecessary memory allocations, synchronization points, or communication overhead.
- Readability and maintainability: code should be understandable by other developers.
- Consistency: follow the coding style already used in DINO.
- Reproducibility: numerical results should remain reproducible across platforms whenever possible.
Modular Code Structure¶
DINO follows a modular software design to improve readability, maintainability, and extensibility. New contributions should preserve this philosophy by implementing functionality in small, well-defined modules rather than adding code to existing routines whenever possible.
Design Principles¶
Each module should have a single, clearly defined responsibility. A developer should be able to understand the purpose of a module from its name and a brief description.
Examples of well-defined responsibilities include
- grid generation,
- boundary conditions,
- chemistry integration,
- time integration,
- I/O routines,
- turbulence statistics.
Avoid combining unrelated functionality into a single module.
Keep Interfaces Small¶
Expose only the procedures that are intended to be used by other parts of the code.
Declare helper procedures and internal variables as private whenever possible, and explicitly list the public interface.
module chemistry_solver
implicit none
private
public :: initialize_chemistry
public :: advance_chemistry
contains
...
end module chemistry_solver
A small public interface makes modules easier to understand and reduces unintended dependencies between different parts of the code.
One Task per Procedure¶
Each subroutine or function should perform a single logical task.
For example, a routine responsible for computing diffusive fluxes should not also
- read input files,
- allocate memory,
- write output,
- or modify unrelated variables.
If a procedure grows to several hundred lines or contains multiple distinct tasks, consider splitting it into smaller routines with descriptive names.
Minimize Dependencies¶
Modules should depend only on the functionality they actually require.
Avoid importing an entire module if only one or two procedures are needed.
instead of
Reducing dependencies improves compilation times, limits namespace pollution, and makes the code easier to understand.
Reuse Existing Functionality¶
Before implementing a new routine, search the existing code base for similar functionality.
Duplicating algorithms often leads to inconsistent implementations and increases long-term maintenance effort. If existing functionality is sufficiently general, extend it rather than creating a second implementation.
Separate Physics from Infrastructure¶
Whenever possible, keep numerical algorithms and physical models independent of infrastructure code such as
- file I/O,
- MPI communication,
- logging,
- timers,
- and user input.
This separation makes the scientific implementation easier to understand, test, and reuse.
Write for Future Developers¶
A module should be understandable without requiring knowledge of the entire code base. Developers should be able to identify
- the purpose of the module,
- its inputs and outputs,
- and its interactions with other components
by reading only the module itself and its documentation.
Well-designed modules are easier to test, review, and extend, and they significantly reduce the effort required to maintain DINO over many years.
Code Formatting¶
Consistent code formatting is essential for maintaining readability and reducing the effort required for code reviews and future developments. The goal is not to enforce a specific visual style for its own sake, but to ensure that every developer can quickly understand and modify the code.
All contributions to DINO should follow the formatting conventions described below.
General Formatting Rules¶
Code should be written in a clear and structured way.
Avoid overly compact code that reduces readability. In scientific software, clarity is more important than minimizing the number of lines.
Prefer:
over:
Shorter code is not necessarily better code if it becomes harder to read.
Indentation¶
Use consistent indentation throughout the code.
Nested structures should be visually distinguishable by increasing the indentation level.
Example:
do k = k_start, k_end
do j = j_start, j_end
do i = i_start, i_end
field(i,j,k) = 0.0_mytype
enddo
enddo
enddo
Avoid inconsistent indentation, as it makes the logical structure of the code difficult to follow.
Line Length¶
Avoid excessively long lines.
Lines should generally not exceed approximately 100–120 characters. Long expressions should be split into multiple lines using the Fortran continuation character.
Prefer:
over:
when expressions become difficult to read.
Spacing¶
Use whitespace to improve readability.
Operators should be surrounded by spaces:
Avoid:
Use blank lines to separate logical sections of a routine.
For example:
! Compute velocity gradients
call compute_gradients(velocity, gradients)
! Compute viscous stresses
call compute_stress(gradients, stress)
Naming and Alignment¶
Use descriptive and consistent naming, following the table below:
| Element | Convention | Example |
|---|---|---|
| Modules | dino_<name> |
dino_transport_mod |
| Subroutines | verb-based | dino_compute_flux |
| Functions | descriptive | enthalpy_from_temperature |
| Variables | lowercase with _ |
cell_volume |
| Constants | uppercase | GAMMA_AIR |
| logical variables | lowercase with _ |
'is_periodic' |
Avoid single-letter variables except for loop indices (i, j, k).
unless the abbreviation is a well-established term in the code or scientific field.
Align related declarations when it improves readability.
Example:
Comments¶
Comments should explain why something is done, not simply repeat the code.
Avoid:
Prefer:
! Apply density correction to enforce mass conservation after the projection step.
density = density + correction
Important numerical methods, physical assumptions, approximations, or non-obvious implementation choices should always be documented.
Temporary and Debug Code¶
Temporary debugging statements should not be committed.
Remove
- commented-out code,
- unused variables,
- debugging
printstatements, - obsolete routines,
before creating a merge request.
If code is intentionally disabled but may be required later, explain the reason in a comment or track it using the issue management system.
Fortran-Specific Guidelines¶
All Fortran source files should follow these rules:
- Always use
implicit none. - Always specify
intent(in),intent(out), orintent(inout)for procedure arguments. - Use explicit interfaces through modules.
- Avoid deprecated language features.
- Avoid unnecessary global variables.
- Use named constants instead of hard-coded numerical values.
Example:
Avoid:
Prefer:
Formatting Before Submission¶
Before submitting a contribution:
- ensure that the code follows the formatting conventions,
- remove unnecessary whitespace changes,
- verify that only relevant files are modified,
- compile the code successfully.
Clean formatting makes code reviews easier and prevents unnecessary merge conflicts between developers.
A consistent style allows developers to focus on the scientific content of a contribution rather than spending time interpreting formatting differences.