Coding Guidelines

This section presents an incomplete list of coding guidelines currently used to develop AMR-Wind code. As is the case with rules, it might not apply to all circumstances. Please use your best judgement when trying to comply with the rules and break them if necessary, but be ready to convince the rest of the team.

Use modern C++

Traditionally, AMReX based solvers have used C++ for managing data structures but Fortran for computational kernels. However, AMR-Wind is purely written in C++. One of the primary drivers for this choice is our desire to target next-generation Exascale systems that require targeting GPUs through CUDA, HIP, and other offloading paradigms. Support for languages other than C/C++ is not very mature for these architectures.

Consult ISO C++ Core Guidelines for best practices when coding in C++.

Write code targeting heterogeneous architectures

All code must be written in a way such that it can run on GPUs without errors. Please consult the GPU section in AMReX documentation to learn the correct data structures and looping paradigms to use when targeting heterogeneous architectures.

Unit and regression tests

Code modifications must not break existing unit tests or regression tests. If a change is known to break current behavior, e.g., a bug fix or an enhancement, the tests must be updated to account for this change and any necessary updates to documentation must be made to document this.

New features must be accompanied with the necessary suite of unit and regression tests as appropriate. There should be at least one test that exercises the feature to catch issue early on. New features must also be documented in the user and theory manual.

Pull-request based workflow

All updates must be submitted as pull-requests on the public GitHub repository. Pull requests will be reviewed by core developers and must also pass all Continuous Integration checks before it is merged into mainline source tree.

If a pull-requests fails during nightly tests after it is merged with the mainline code base, it will be reverted and a new pull request should be submitted with appropriate fixes.

Style Guide/Recommendations

This section documents the preferred style for formatting source code within AMR-Wind. While the guidelines presented in the previous section are based on technical and quality assurance reasons, the formatting style is largely a matter of individual taste and there is no hard and fast rule. However, to ensure consistency in a codebase used by a large team, we provide some guidelines here.

AMR-Wind comes with a .clang-format definition that can be used with Clang format to automatically reformat source code to be consistent with the rest of the codebase. Many source code editors come with Clang format integration that allows you to reformat code from within your text editor. Please consult the Clang format documentation, or your editor’s documentation to setup clang-format integration. However, please be careful that you only use Clang format on code you’ve written modified and not on code that has not been written by you.

Other AMR-Wind specific conventions:

  1. All AMR-Wind specific code must be within amr_wind namespace. Code for unit tests must be in amr_wind_tests namespace.

  2. Following AMReX convention, header files will use a .H extension and C++ source files will use a .cpp extension.

  3. Use snake_case almost everywhere, i.e., for variables, namespaces, function and method names. Exceptions include when overriding AMReX class methods in inherited classes.

  4. Use CamelCase for class names. Capitalize the first letter of the first word in the compound name also.

  5. Use m_ prefix for class instance variables. No prefix for class methods.

  6. Keep logic in functions short. Always use descriptive names for function names and variables that provide the reader with clues as to what the function does.

Sample C++ code

 1#ifndef CFDSIM_H
 2#define CFDSIM_H
 3
 4#include "AMReX_AmrCore.H"
 5#include "SimTime.H"
 6#include "FieldRepo.H"
 7#include "PDEBase.H"
 8#include "Physics.H"
 9
10namespace amr_wind {
11
12// Forward declaration if necessary
13namespace turbulence {
14class TurbulenceModel;
15}
16
17/** Data structures for a CFD simulation
18 *
19 *  CFDSim is a thin wrapper that holds all the necessary objects for a CFD
20 *  simulation. The key data members within this object are:
21 *
22 *  - mesh (amrex::AmrCore) The AMR mesh hierarchy data structure
23 *  - time (SimTime)        The time object
24 *  - repo (FieldRepo)      The field repository
25 *  - pde_manager (PDEMgr)  PDE manager interface
26 *  - physics_manager       List of physics active in this simulation
27 *  - turbulence_model      Reference to the turbulence model
28 */
29class CFDSim
30{
31public:
32    CFDSim(amrex::AmrCore& mesh);
33
34    ~CFDSim();
35
36    //! Return the AMR mesh hierarchy
37    amrex::AmrCore& mesh() { return m_mesh; }
38    const amrex::AmrCore& mesh() const { return m_mesh; }
39
40    //! Return simulation time control
41    SimTime& time() { return m_time; }
42    const SimTime& time() const { return m_time; }
43
44    //! Return the field repository
45    FieldRepo& repo() { return m_repo; }
46    const FieldRepo& repo() const { return m_repo; }
47
48    //! Return the PDE manager instance
49    pde::PDEMgr& pde_manager() { return m_pde_mgr; }
50    const pde::PDEMgr& pde_manager() const { return m_pde_mgr; }
51
52    //! Return the physics manager instance
53    PhysicsMgr& physics_manager() { return m_physics_mgr; }
54    const PhysicsMgr& physics_manager() const { return m_physics_mgr; }
55
56    //! Return a vector of physics instances active in this simulation
57    PhysicsMgr::TypeVector& physics() { return m_physics_mgr.objects(); }
58    const PhysicsMgr::TypeVector& physics() const { return m_physics_mgr.objects(); }
59
60    //! Return the turbulence model instance used in this simulation
61    turbulence::TurbulenceModel& turbulence_model() { return *m_turbulence; }
62    const turbulence::TurbulenceModel& turbulence_model() const
63    { return *m_turbulence; }
64
65    //! Initialize the turbulence model after reading necessary inputs
66    void create_turbulence_model();
67
68    //! Initialize the different physics models based on user inputs
69    void init_physics();
70
71private:
72    amrex::AmrCore& m_mesh;
73
74    SimTime m_time;
75
76    FieldRepo m_repo;
77
78    pde::PDEMgr m_pde_mgr;
79
80    PhysicsMgr m_physics_mgr;
81
82    std::unique_ptr<turbulence::TurbulenceModel> m_turbulence;
83};
84
85} // namespace amr_wind
86
87#endif /* CFDSIM_H */