If you would like to help contribute to BOUT++ then there are many things you can do which will make a difference. There are projects large and small which a student or researcher could use to get started with BOUT++ and get more familiar with the code. You don’t need to be particularly familar with BOUT++ or C++ to work on many of these. You can see a current list of outstanding bugs and feature requests on the GitHub issue page.
BOUT++ consists of about 60,000 lines of C/C++, along with 18,500 lines of IDL and 12,000 of Python. Of this, about 40,000 lines is the core BOUT++ code, and the remainder a mix of pre- and post-processors, and physics modules. As production codes go, this is not particularly huge, but it is definitely large enough that keeping the code ‘clean’ and understandable is necessary. This is vital if many people are going to work on the code, and also greatly helps code debugging and verification. There are therefore a few house rules to keep in mind when modifying the BOUT++ code.
When modifying the core BOUT++ code, please keep in mind that this portion of the code is intended to be general (i.e. independent of any particular physical system of equations), and to be used by a wide range of users. Making code clear is also more important in this section than the physics model since the number of developers is potentially much greater.
Here are some rules for editing the core BOUT++ code:
The workflow we use is essentially “gitflow”.
All work should be done in feature branches, branched off next. When complete, a pull request can be submitted.
At irregular intervals, we will create a release branch. No new features go into the release branch - only bug fixes and documentation.
First get a copy of the BOUT-dev repository (or git pull to update an existing copy):
git clone git@github.com:boutproject/BOUT-dev.git
cd BOUT-dev
Create a new branch myfeature, branching from next. Choose a descriptive name for myfeature, anything except “master” or “next”.
git checkout next
git pull
git checkout -b myfeature # Switched to a new branch "myfeature"
Create a fork on Github following the instructions here.
If you want to push your branch to BOUT-dev to share with other developers, run:
git push -u yourfork myfeature
This command pushes myfeature to your fork (named yourfork) of the BOUT-dev repository, and the -u flag adds it as a remote tracking branch. After setting up the tracking branch, you can call “git push” without any parameters to push updates to myfeature.
If another developer wants to try out this branch, they will first need to add your repository as a new remote:
git remote add yourfork https://github.com/YourUsername/BOUT-dev.git
then they will be able to checkout your branch:
git checkout -b myfeature yourfork/myfeature
Note: If you have write access to the central BOUT-dev repository, you can push your branches there.
Now you would make changes, commit changes and push as usual:
... make changes ...
git add <files>
git commit
git push # Pushes to origin/myfeature
You can switch between branches using checkout:
git checkout master # Switch to "master"
git checkout myfeature # Switch to "myfeature"
Once your feature is complete, ask other developers to have a look by creating a Pull Request on the BOUT-dev page. One of the maintainers will review your code and merge it into next. They may give you comments to improve the code. You can make additional changes and push them to the same feature branch and they will be automatically added to the pull request.
Code is read an order of magnitude more times than it is written. It’s also written for people and not for the computer! For these reasons, it’s important that we stick to some form of coding standards. The following coding style guidelines broadly follow the LLVM Coding Standards. The LLVM Coding Standards go into more depth, and explain the reasoning behind the guidelines more thoroughly than here. If you just follow the guidelines below, you won’t go far wrong though.
These guidelines are intended to make code easier to read and therefore easier to understand. Being consistent in coding style also helps comprehension by reducing cognitive load.
Comments in the code are vital to helping understanding. Comments that are embedded in the code should explain why something is done, rather than how.
For documenting what functions and classes do, we use Doxygen.
//
over C style /* */
///
./// Foo the bar
///
/// Apply the standard foo method to @p bar
///
/// Typical usage:
///
/// foo(bar, "simple", result);
///
///
/// @param[in] quux Number of times to foo
/// @param[out] result filled with quux fooed bars
///
/// @returns true on success
bool applyFoo(BoutReal bar, int quux, std::vector<int> &result);
Naming things correctly is super important! It is also one of the trickiest parts of coding.
Names should be descriptive. Code is read an order of magnitude more often than it is written, so it is vital that it is easy to comprehend.
There are some conventions you should follow when naming things:
Prefer a longer descriptive name over a shorter abbreviated one:
inner_boundary_flags
rather than inbndflgs
, generator
rather than
gen
. It’s much easier to read and comprehend than the abbreviated form.
Spaces after if
, for
, etc.
Wrong:
if(expr){
doSomething();
}else{
doOtherThing();
}
Right:
if (expr) {
doSomething();
} else {
doOtherThing();
}
This especially helps readability, making conditional statements stand out over function calls.
Braces on same line as statement:
Wrong:
void doFoo(bool expr)
{
if (expr)
{
doSomething();
}
else
{
doOtherThing();
}
}
Right:
void doFoo(bool expr) {
if (expr) {
doSomething();
} else {
doOtherThing();
}
}
This one is more style than readability - it’s the style that the majority of BOUT++ already uses.