Kariba
|
There are three kind of uses of the Kariba library:
These three scenarios are detailed below
In this case, build and install the library first, as described in the installation section. Note in which directory you installed the library, or perhaps you left it where it was build. Both options are fine.
For your model, create directory outside of the Kariba repository. This should probably become a Git repository of its own, to manage changes to your own model (including, for example, experimental versions on Git branches).
So you'd have two or optionally three directories: one with the Kariba repository, one with your model repository, and an optional one where you may have the Kariba library installed. For me, that would be something like
Once you've written the start of your model, add the necessary Kariba include files to your sources, e.g.
Note the use of angular brackets and the kariba/ directory prefix.
When you compile your code, you will need the -I
option to point the compiler to the Kariba header files.
If you didn't install Kariba in a separate directory, these should point to the directory where the Kariba library was compiled and which has the header files in the 'kariba' subdirectory. Also, find path of the 'libkariba.a' static library, which is probably in the same directory. Then, set -I
to have this directory included, and include the full path to the 'libkariba.a' library with your compilation. In the above example, the relevant directory is $HOME/code/kariba/src
, so something like the following compilation command works (mymodel.cpp
and utils.cpp
being local project files):
Note there is no -L
flag before the 'libkariba.a' path.
Add an -fopenmp
flag if needed, and replace -O3
with e.g. -Ofast
if wanted (and deemed safe).
If you installed the library (and its header files) in a separate directory, it's very similar. With the above example, it now becomes
The above two variants compile your code with a static variant of the Kariba library. If you'd like, you can use the dynamic library instead. The compilation variants then look as follows (using the -L
option this time):
(not installed; directly from the source repository)
and
With this variant, you'll need to set your LD_LIBRARY_PATH
(on Linux) or DYLD_LIBRARY_PATH
(on macOS) environment variables to point to the Kariba shared library. That would be (bash, zsh):
for a Linux installed variant, and similar for not-installed versions and macOS, replacing the path and/or environment variable accordingly.
The static library is easier to use. The advantage of a shared library can be that, if that library changes (e.g., because there was a bug fix of a specific function) and the library is updated (you re-installed the Kariba library), then your model follows that fix. With a static library, you would have to recompile your model as well. But it is likely that that is very quick, so you can probably still use the static library variant without hassle, even in the rare cases of updates to the Kariba library.
Essentially, you work the same way as above: create a repository for your model separately and independently from the Kariba library, and compile as suggested above.
For parts where you want to extend functionality, there may be a few ways to go about:
If you want to add or change the behaviour of a function of a particular Kariba class, you can do that fairly easily: use the C++ inheritance abilities to create a new class, inheriting from an existing Kariba class you'd like to extend, then add the new function, or override an existing function.
As an example, let's say we want to change the set_p()
member function of the kariba::Thermal
class. The minimum and maximum energy are not what we'd like (first lines of the original function):
So create a new header file (or add to an existing one), and include the following:
and in a source file, define the class and implement the overriddend function:
where you will need to write the rest of the function in the place of the ellipses, of course (so copy-paste the old function, change Thermal
to Thermal2
, make the actual changes for emin
and max
, and you're good).
Note that we don't need to override the constructor, or any of the other functions. As long as these stay the same, and there are no new member variables that need to be initialized in the constructor, there is no need for this.
When inheriting, be aware of the access priviliges:
public
. That way, member variables are still protected in derived (child) classes, so that every grandchildren can access their grandparents' member variables. While it can be argued this is not (always) good, in cases like the above, this is a major and important convenience (otherwise, you'd need to add a lot of setters and getters to the base class).public
.using Thermal::Thermal
tells the compiler that Thermal2
should use the matching constructor from Thermal
to initialize the class and its member variables (matching here means, by arguments; if there's only one constructor, which is the case in all Kariba classes, this doesn't matter).Logically, perhaps, the lower and upper boundary factors should be arguments in set_p()
, perhaps with default settings of 1/100 and
In this case, you'll work directly in the Kariba repository. However, do this on a new branch.
These changes should be for long-term changes; if you have something that is for a specific or temporary case, use the workflow in the section above.
First, check that you actually have and use a (GitHub) fork of the library. On GitHub, fork the repository. Then, copy the URL for the SSH-variant of the cod of your fork.
Now, back in the terminal on your local machine, check the remotes of the Kariba library:
If you see an 'upstream' and 'origin' remote, check that 'upstream' URL points to the original repository, not your fork. The 'origin' URL should point to your fork, with the URL starting with git@github.com:
(this indicates SSH is used).
If you only see an 'origin' remote, it likely points to the original repository, not your fork. Change that:
(the URL is the one you copied from GitHub; obviously <username>
is your user name.)
Now add the URL to the original Kariba repository as an upstream:
Check git remote -v
again to see that the URLs and names now match as mentioned above.
Create a separate branch, from the main branch, and add your changes there.
When finished, test that the library still builds, and that the unit tests and examples still build and run. If there was a fix that changes the outcome of a function, update the unit test accordingly (just be sure that your change is correct). If you added a function, add one or a few unit tests that specifically test this function.
Once everything is commit (you can easily make multipe small commits if it makes sense), first check that you are still up to date with the upstream repository. Pull in any changes and rebase upstream/main:
Then push the branch to your fork:
Now, on GitHub, create a pull request from that branch to the original repository. There is likely a big green button on the GitHub page: click it to prepare the pull request.
Fill out the necessary details, check again if everything looks good, then create the pull request (PR).
You are automatically already on the origina repository site, on the details for your PR. If everything went correctly, the continuous integration (CI) tests will be run. Wait to see if these all pass.
Now you'll hae to wait until a maintainer merges your PR. Or they may have some further questions or suggestions to improve your PR.
If you yourself are the maintainer, I'd suggest to wait a few days before merging. Sometimes, you later realise you have forgotten something, and you can then still easily add it to the PR.
Note: please avoid pushing directly to the original repository in you are a maintainer (or even directly to the main branch): using a personal fork makes following the flow of updates much easier. The PR, and changes that came with, is nicely laid out on GitHub (also when closed), and because merging a PR creates a merge commit, there are clear points where a consistent set of changes was added to the library.
Sometimes you want to update a pending pull request: you've forgotten to commit a file, accidentally commited a file that shouldn't be there[*], or made a typo while changing things.
For that, go to the correct branch in your local repository, make the changes as needed, then force-push the branch to your fork:
You may not need the --force
flag, if you only added commits. If you changed commits (with --amend
, or an interactive rebase, to keep the PRs history cleaner), then --force
is needed.
Once updated, the CI for the PR should run again, so check that your updates didn't make the tests fail.
[*] If you accidentally pushed a private key, a password, or some other secret onto GitHub, then changing things and force-pushing the update won't help. Even if you overwrite the Git history (an interactive rebase can do that), bots scrape GitHub all the time, and the secret may already have been comprised. Do get rid of the secret in the code, but also change the relevant secret as soon as possible.