---
# System prepended metadata

title: PHAS0100 - week 5
tags: [teaching, class, phas0100]

---

# PHAS0100 - week 5

### 2pm-5pm Friday, 11th February 2022

:::info
## :tada: Welcome to the 5th live-class!

#### Reminder: both groups are now merged into this Friday class

### Today

Today we will ...

- Review what you have learnt about libraries
- Choose a library for our next project
- Install a library using different methods
:::

### Group working
 - We will be working in groups of 3-5 people in the hands-on exercises.
 - You will populate this collaborative document with the relevant findings based upon discussions in your group

### Timetable for this afternoon
    
| Start | End | Topic  | Room |
| -------- | -------- | -------- | ----- |
| 14:00     | 14:15     | Intro + [Quiz](#Quiz)    | Main | 
| 14:15 | 14:35 | [Group exercise on choosing a library](#Choosing-an-external-library) | Breakout-1 |
| 14:35 | 14:55 | Write each group's inferences about the libraries on this HackMD collaborative doc | Breakout-1 |
|14:55 | 15:05 | Break | ---|
|15:05 | 15:10 | [Intro to using a library](#Using-an-external-library) | Main |
|15:10 | 15:50 | Install a [library from the Ubuntu repos](#Installing-yaml-cpp-from-Ubuntu-20.04-LTS-repositories) and then [directly from developers](#Install-an-updated-version-directly-from-the-project-repository) | Breakout-2|
|15:50 | 15:55 | Review | Main |
|15:55 | 16:05 | Break | ---|
|16:05 | 16:20 | [Adapt to use the library with CMake](#Adapt-to-use-the-library-with-CMake)| Breakout-3|
|16:20 | 16:45 | [Using Eigen](#Using-Eigen) | Breakout-4|
|16:45 | 16:55 | Summary of libraries, and intro to package managers | Main |



## Quiz
:::success
Access [menti.com](https://menti.com) and enter the code: **2184 3701**
:::
    
## Breakout session 1 

### Class Exercise 25 
### Choosing an external library
### Goal
:::success
:dart: Choose a units library for your next project.
:::
:::info
:information_source:  For our project, we won't need something too complicated, only some speed conversions (m/s, km/h, mph, feet/s,...) and all the libraries mentioned below are able to do so. Therefore, don't focus as much in the technical capabilities of each. However, do consider the [points mentioned on our lesson about choosing a library][lesson-choose].

Each group will, together, analyse one of the following libraries. You have ~35-40 minutes in total. After perusing the library, you may discuss it internally within your group to evaluate it. Afterwards, write an itemised list of your important findings for public visibility in this collaborative document under the library heading that your group considered.
:::

Breakout groups and libraries to consider:

Group 1. [Units & measures][units-codeproject]
Group 2. [Unit Conversion and Dimensional Analysis Library][units-nholthaus]
Group 3. [mp-units][units-mp]
Group 4. [Lawrence Livermore National Security **The Units** library][units-llns]
Group 5. [Boost's units][units-boost]

### Itemised summary of each group's findings
#### Group 1. [Units & measures][units-codeproject]
 - Header only
 - Code Project Open License (CPOL), very permissive, non-copyleft license
 - Well documented
 - Modular and intuitive design
 - Outdated (2017), multiple communication channels, but auther last responded to comments in 2017
 - One person developer who is an enthusiast
 - Not implemented on GitHub
 - Not many downloads (~800)
 - Only 21 revisions (last 2017) 
#### Group 2. [Unit Conversion and Dimensional Analysis Library][units-nholthaus]
 - header only
 - 380 commits on the Github
 - built on c++14 with no dependencies
 - A compile-time, dimensional analysis library.
 - Have fixed compilation error when iostream was disabled.
 - Continuous Integration did not pass.
 - Unit tags and containers are split into separate namespaces to avoid conflicting
 - consists of a single header units.h, and can be included into your project without being built.
 - The library consists of a single file plus unit tests. To incorporate the library into your project, simply copy the header into a location in your include path or add the included CMake project into your build.
 - Only one communication channel, should give us more.
 - Why it takes so long to open it in container??? Over 10 mins passed, still not. That's True.
#### Group 3. [mp-units][units-mp] 
 ##### Library condition
 - 1. [x] The codes are readable. And efficiency.
 - 2. [x] Latest updates: 3 days ago
 - 3. [x] Connection with the contributor: Email, issues page on Github. reachable
 - 4. [x] Licence: MIT
 - 5. Commits: 1583
 - 6. stars: 535
 - 7. COntributors: 24
 - 8. Issues: 54
 - code tested? -> extensive tests in test directory
 - tutorial | ease of use : external page https://mpusz.github.io/units/introduction.html
 - - dependencies -> high number of dependencies scattered, not all included in the requirements.txt file
 ##### Basic functions
 - 1. Simple numeric operations
    ```cpp
    static_assert(10 * km / 2 == 5 * km);
    ```
 - 2. Unit conversions
    ```cpp
    static_assert(1 * h == 3600 * s);
    ```
 - 3. Dimension conversions
    ```cpp
    static_assert(1000 / (1 * s) == 1 * kHz);
    ```
#### Group 4. [Lawrence Livermore National Security **The Units** library][units-llns]

##### Strengths 
 - supports a header only mode and a compiled mode
 - neat and organised documentation
 - option of static or shared library, installed like typical package
 - license, can redistribute in source and binary forms if you put the copy right
 - the warranties and fitness of purpose is displayed
 - license name bsd3
 - provides low level documentation
 - incude 17 unit tests and several CI systems
 - the conversion also supports mathematical operations
 - very active testing on Github, most recent 11 days ago, more than 20 testing histories in recent 3 months
 - a lot of tests, 98% passing
##### Flaws
 - some of the test links are broken
 - "work in progress" so function names can change
 - string processing available in the compiled mode (to use full functionality need compiled)
 - cannot use name of copy right holder to endorse products
 - Azure Pipelines : Never Built
 - need at least Cpp 11, recommended Cpp 14 though

#### Group 5. [Boost's units][units-boost]
 - Boost is a quasi-standard library, equivalent to the continuation and expansion of STL
 - No runtime execution cost is introduced
 - Open Source
 - Last updated March 2010


 
### Online groups
 
#### Group 1. [Units & measures][units-codeproject]
 - 
 - 
 -
#### Group 2. [Unit Conversion and Dimensional Analysis Library][units-nholthaus]
 - 
 -
#### Group 3. [mp-units][units-mp] 
 -
 -
#### Group 4. [Lawrence Livermore National Security **The Units** library][units-llns]
 - header only (only 3 headers)
 - two commits on GH
 - last commit 2020
 - Could be complete? - nope, there are two unresolved issues on GH
 - Detailed README
 - Has continuous integration with Github Actions
 - Has BSD3 license
 - some links in the readme are incorrect
 - high quality-seeming projects that are using the library: scipp and GridDyn
 - no compile-time checking of units
 - 3 contributors that seem very well qualified (SWEs)
 - tests look extensive (there's lots in test folders)
 - good code coverage
#### Group 5. [Boost's units][units-boost]
 -
 -

### Solution (thoughts on various units libraries)
1. [Code Project][units-codeproject]:
   - It has a weird license, with a clause that you can't use it on immoral activities
   - Also not clear if any VCS is used
   - Not clear about the extent of involvement of the developer community and the uptake among users
2. [Nic Holthaus's][units-nholthaus]:
   - MIT license
   - Single file, header only C++14 library
   - Partly active (last commit to `master` in Oct 2020), but not a very large community
   - Clear documentation (but a single page). Likely to be up-to-date with code since it is autogenerated by Doxygen
   - Large coverage
   - Tested on older compiler versions, rather than an entire suite of compilers (to catch compiler regression bugs). Especially old clang had poor compile times.
3. [Mateusz Pusz's][units-mp]:
   - MIT license
   - active repository
   - subject to inclusion in the standard library as part of C++23/C++26 standardisation
   - active community
   - header only library, available via conan and CMake examples
   - Tested on a few modern compilers, but unknown coverage
   - Requires a very modern C++ compiler (uses a few C++20 features like `concepts`) which may not be installed on all user's machines (or might not be installable e.g. if they lack `sudo` rights which is the case for a typical HPC system)
   - has dependencies for now (`fmt` and `gsl-lite`)
   - Good documentation
4. [LLNLS's][units-llns]:
   - BSD license
   - Not ultra modern, but is at least C++11, which is reasonable
   - active repository
   - header only mode and a compiled mode (which can be confusing to beginners)
   - well tested
   - coding standards enforced through linters and formatters
   - Good documentation
     -  comparison with others
     -  online web page to try unit conversions
5. [Boost's][units-boost]
   - Boost license
   - Header only
   - is a template-heavy library. could lead to long compile times
   - Last release from 2010! (?)
     - though it follows boost clear release cycle
   - tested on older compilers 
   - [repo](https://github.com/boostorg/units) no that easy to find (from the docs)!
   - some community interaction but not much as the others
     - but mailing list and IRC


### Optional extra material to consider outside class:
_Relevant conference talk from CppCon2021 (optional material to watch outside of class hours)_: [Units Libraries and Autonomous Vehicles: Lessons from the Trenches](https://www.youtube.com/watch?v=QEBlaaht5cA). Dr Hogg, who has a Physics background, presented an overview of various technical and human factors to consider in developing and using a units library.

[units-codeproject]: https://www.codeproject.com/Articles/1088293/Units-and-measures-for-Cplusplus
[units-nholthaus]: https://github.com/nholthaus/units
[units-mp]: https://github.com/mpusz/units
[units-llns]: https://units.readthedocs.io/en/latest/
[units-boost]: https://www.boost.org/doc/libs/1_78_0/doc/html/boost_units.html
[lesson-choose]: https://rits.github-pages.ucl.ac.uk/research-computing-with-cpp/05libraries/sec01ChoosingLibraries.html

## Breakout session 2 

### Class Exercise 26

### Using an external library

### Goal 
:::success
:dart: Use [`yaml-cpp`][yaml-cpp] to read the [given yaml file][yaml-code] for some simulation.
1. Using the yaml-cpp version provided by ubuntu (`apt`)
2. Using a newer release from the yaml-cpp developers
:::

[yaml-cpp]: https://github.com/jbeder/yaml-cpp
[yaml-code]: https://gist.github.com/krishnakumarg1984/011f259554ecb8f0a96ed735c1ac634b
[lesson-library]: https://rits.github-pages.ucl.ac.uk/research-computing-with-cpp/05libraries/sec02LibraryBasics.html

### Setup

:::info
:information_source: 15-20 minutes to complete. Tutors can assist with install-related issues.
:::

Create a new directory on your desktop
```bash
mkdir week05
cd week05
git clone --recurse-submodules https://github.com/UCL/CMakeHelloWorld yaml-ex

# In the command below, the trailing slash is important!
ln -s yaml-ex/.devcontainer/

# Open the current folder on VSCode, via terminal or through VSCode itself
code .

# In the pop-up menu within VSCode, choose to "Reopen in container"
```

### Installing yaml-cpp from Ubuntu 20.04 LTS repositories

1. Open a terminal window within the VSCode container instance. You should see
   ```bash
   vscode ➜ /workspaces/week05 (master ✗) $ 
   ```
1. Fetch the latest package update definitions from the Ubuntu repos using the package manager (`apt`). This can take a while.
   ```bash
   $ sudo apt update
   ```
      Optionally (but not required for this exercise), you may want to upgrade any upgradable packages with:
   ```bash
   $ sudo apt upgrade -y
   # The optional 'y' (yes) flag in the above command serves to instruct Ubuntu to upgrade the packages without asking for a confirmation dialog.
   ```
1. Install `apt-file` to know what files each package we install contains.
   ```bash
   $  sudo apt install apt-file
   ```
   and update their list too:
   ```bash
   $ sudo apt-file update
   ```
1. Search for `yaml-cpp`:
   ```bash
   $ apt search yaml-cpp
   ```
   :::info
   There are two choices ... which one do we need? Use
   ```bash
   $ apt-file show <package_name> | less
   ```
   to make the decision. Press `q` to quit `less`.
   :::
   :::danger
   The `dev` version contains also the header files that we require.
   :::
1. Install the relevant `yaml-cpp` package as follows
   ```bash
   $ sudo apt install <package_name>
   ```
   :::danger
   the package name is: `libyaml-cpp-dev`
   :::
1. Download/copy the [provided files][yaml-code] (cpp and yaml) to the `yaml-ex` folder and try to build it using `g++` command. From your lesson notes, do you [remember the procedure][lesson-library]?
   ```bash
   cd yaml-ex
   
   # Download the `config.yaml` and `useyaml.cpp` files in this folder before proceeding with the compilation step given below
   g++ useyaml.cpp -o useyaml -l yaml-cpp
   ```

1. Run the code!
   ```bash
   ./useyaml
   ```
   Open the generated output file (`result.yaml`) in the `yaml-ex` directory and inspect the value of metallicity. In particular, note its precision (number of significant digits) in the output file vs the result printed on the console.
   
### Install an updated version directly from the  project repository

You may have noticed that the metallicity result in the output file does has a lower precision than that reported on the console. This was a [bug][yaml-cpp-bug] that was reported to the developers which was fixed in [a newer release](https://github.com/jbeder/yaml-cpp/pull/649). Let's install the latest release then.

1. Make sure your version (from the Ubuntu repos) is indeed older than the latest one [in GitHub][yaml-cpp].
   ```bash
   $ apt show <package_name>
   ```
   The version of the library in Ubuntu 20.04.3 LTS repos is `0.6.2`.
2. Download the latest release of the library to the project folder (`week0`5`):
   ```bash
   $ cd /workspaces/week05
   ```
   :::spoiler with git tags
   ```bash
   $ git clone https://github.com/jbeder/yaml-cpp
   $ cd yaml-cpp
   $ git checkout -b 0.7.0 tags/yaml-cpp-0.7.0
   ```
   :::
   :::spoiler with curl
   You can get the tar or zip file from the GitHub [releases page][yaml-release]
   ```bash
   $ curl -LO https://github.com/jbeder/yaml-cpp/archive/yaml-cpp-0.7.0.tar.gz
   $ tar zxf yaml-cpp-0.7.0.tar.gz --transform s/yaml-cpp-yaml-cpp-0.7.0/yaml-cpp/
   $ cd yaml-cpp
   ```   
   :::
   [yaml-release]: https://github.com/jbeder/yaml-cpp/releases
   
3. Build the library as a shared library
   ```bash
   $ mkdir build; cd build
   $ cmake .. -DYAML_BUILD_SHARED_LIBS=ON
   
   # In the below step, just using `make` by itself, will build a lot of targets, including the tests, some of which are likely to fail due to various dependency issues and due to warnings being treated as errors in the compile configuration 
   $ make yaml-cpp
   ```
4. Go to your code and build it now using the newer yaml-cpp.
   ```bash
   $ cd ../../yaml-ex # or: cd /workspaces/week05/yaml-ex
   $ g++ useyaml.cpp -o useyaml -I ../yaml-cpp/include -L ../yaml-cpp/build/ -l yaml-cpp
   ```
5. Run it
   ```bash
   $ ./useyaml
   ```
6. __Does it work__ if you try to run it?


Hint: Use the `ldd` command to verify the exact path to the shared libraries your executable uses. 

   :::spoiler Tell your program where to look for the shared library.   
   There is a variable that your OS looks for when looking for libraries: `LD_LIBRARY_PATH`
   ```bash
   $ export LD_LIBRARY_PATH="/workspaces/week05/yaml-cpp/build:${LD_LIBRARY_PATH}"
   $ ./useyaml
   ```
   :::
   
   
7. Does the updated library result in an improved precision for metallicity in the generated output file?


[yaml-cpp-bug]: https://github.com/jbeder/yaml-cpp/issues/469

## Breakout session 3 

### Class Exercise 27
### Adapt to use the library with CMake

:::success
:dart: Use [`yaml-cpp`][yaml-cpp] to read the [given yaml file][yaml-code] for some simulation.
Using the new version of yaml-cpp with CMake
:::

:::info
:watch:  20 minutes
:::
1. Change the `CMakeLists.txt` to include the library. How would you do it? Check that you get the same results as the manual compilation result on the command line.

### Solution to Class Exercise 27 
#### Using a CMake-based build for a project that uses the latest version of yaml-cpp

We structure our project folder as per follows:

1. Create a new directory for this exercise. We call it `cmake-based-yaml-ex`. Within this folder, arrange the files as follows:
```
/workspaces/week05/cmake-based-yaml-ex
├── CMakeLists.txt
├── yaml-cpp
└── yaml-ex
```

2. The root `CMakeLists.txt` has the following content (there are detailed explanations as comments for the relevant lines)

```cmake=
# The 'yaml-cpp' library itself only requires a minimum version of 3.4 for cmake. 
# We choose a higher version (perhaps in the future, we may wish to add other libraries
# to our application i.e. 'useyaml' that may require a higher version of cmake)
cmake_minimum_required(VERSION 3.16)  


project(cmake_based_useyaml LANGUAGES CXX)


# cmake usually mirrors the entire directory structure of the source files.
# So, by default, it builds the binary executable in the corresponding subdirectory 
# of the build folder. This may be bit too deeply nested for our liking. 
# We can direct cmake to build the executable in the root of the 'build' folder as follows:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")

# defines targets and sources
add_subdirectory(yaml-ex)

# The 'yaml-cpp' folder contains the CMakeLists.txt provided by the 'yaml-cpp' library developer
# We will simply build the library as part of our application (useyaml).
add_subdirectory(yaml-cpp)

# Now, we link our application (useyaml) to the external 'yaml-cpp' library
# Notice that the 'CMakeLists.txt' provided by the library developer contains the line 
# `add_library(yaml-cpp ....)` i.e. 'yaml-cpp' is the name of the library we wish to link to
target_link_libraries(useyaml PRIVATE yaml-cpp)

# At run-time, our application depends on an input file 'config.yaml'. So, we use the `configure_file` 
# facility provided by cmake to copy the required source file to the run-time directory.
configure_file(yaml-ex/config.yaml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/config.yaml @ONLY)
```

3. The `CMakeLists.txt` within our `yaml-ex` source folder contains the following one-liner:

```
add_executable(useyaml useyaml.cpp)
```

4. Build and run. i.e. at the root of the directory `/week05/cmake-based-yaml-ex`

```
$ mkdir build && cd build
$ cmake ..
$ make
$ ./useyaml
```

The `result.yaml` file should contain the metallicity with the higher precision digits. To convince yourself that the `useyaml` executable indeed uses the latest downloaded version of the library (and not the one we installed earlier from the Ubuntu repos), we may run the following command

```
$ ldd ./useyaml
```


[yaml-cpp]: https://github.com/jbeder/yaml-cpp
[yaml-release]: https://github.com/jbeder/yaml-cpp/releases
[yaml-code]: https://gist.github.com/dpshelio/259f84836a4ee2759a7edd2ab6d90ee6
[lesson-library]: https://rits.github-pages.ucl.ac.uk/research-computing-with-cpp/05libraries/sec02LibraryBasics.html
[yaml-cpp-bug]: https://github.com/jbeder/yaml-cpp/issues/469
[conan-guide]: https://docs.conan.io/en/latest/getting_started.html
[hunter-guide]:https://hunter.readthedocs.io/en/latest/quick-start/boost-components.html 
[hunter-yaml]: https://hunter.readthedocs.io/en/latest/packages/pkg/yaml-cpp.html
[cpm-guide]: https://github.com/cpm-cmake/CPM.cmake#adding-cpm

## Breakout session 4 

### Class Exercise 28

### Using Eigen

:::info
:information_source: [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page) is a C++ template library for linear algebra (matrices, vectors, numerical solvers, etc.)
:::

:::success
:dart: Add the example provided below that uses Eigen to your project and any other required dependency.
:::

1. Add Eigen to your CMake project using any of the following methods
   - There is a `FindEigen.cmake` module available if you want to use that. Alternatively, you may use CMake's `find_package` functionality to integrate Eigen into your project as described in the documentation given [here](https://eigen.tuxfamily.org/dox/TopicCMakeGuide.html).
   - Have a look at the [CMakeCatch2 template repo][cmakecatch2] and see whether you understand how it's included in that project
  
2. Use this short example which employs `Eigen`
   :::spoiler Example code using matrix operations
   ```cpp
   #include <iostream>
   #include <Eigen/Dense>
    
   int main()
   {
     Eigen::Matrix2d m(2,2);
     m(0,0) = 3;
     m(1,0) = 2.5;
     m(0,1) = -1;
     m(1,1) = m(1,0) + m(0,1);
     std::cout << "m(2,2) \n" << m << std::endl;
   
     Eigen::Vector3d vr(3);
     vr << 1, 0, 1;
     Eigen::Matrix3d corners(3, 3);
     corners << vr * vr.transpose();
     std::cout << "corners matrix:\n"
               << corners << std::endl;
   
   
     Eigen::MatrixXd X = Eigen::MatrixXd::Random(5,5);
     std::cout << "A random matrix X: \n" << X
               << "\n Its inversed X^-1: \n" << X.inverse()
               << "\nis X * X^-1 == I? "
               << std::boolalpha 
               << (X * X.inverse()).isApprox(Eigen::MatrixXd::Identity(5, 5)) 
               << std::endl;
   }
   ```
   :::
3. Include the above code in your project, build and run.

[cmakecatch2]: https://github.com/UCL/CMakeCatch2

### Introduction to C++ Package Managers

- [Conan](https://docs.conan.io/en/latest/getting_started.html)
- [Hunter](https://hunter.readthedocs.io/en/latest/)
- [CMake Package Manager (CPM)](https://github.com/cpm-cmake/CPM.cmake)
- [vcpkg](https://vcpkg.io/en/index.html)

## Homework exercise 29

### Using the Conan package manage

:dart: Include [`yaml-cpp`][yaml-cpp] to read the [given yaml file][yaml-code] into your project.

1. Install conan and find the yaml-cpp library
    ```bash
    $ sudo apt install python3-pip
    $ pip3 install conan
    $ conan search yaml-cpp --remote=conan-center
    $ conan profile new default --detect
    $ conan profile update settings.compiler.libcxx=libstdc++11 default
    ```
1. Follow the [conan guide][conan-guide] to do the following steps:
    1. Create the [`conanfile.txt`][conan-guide]
    2. Run the conan install
    3. Modify cmake to include the new created files
    4. Build and run



## Homework exercise 30

### Using a json library

- Convert the [yaml-code] example to use a json library, for example [nlohmann's json][json-nlohmann].
- Include this JSON library (using one of the many ways i.e. manually, using CMake modules or using a package manager) to your project. Use this [json file][json-data].

[json-nlohmann]: https://json.nlohmann.me/
[json-data]: https://gist.github.com/krishnakumarg1984/f62c9a1df4ac6db3fdc6fab2d69ed1f6
[boost-solarsystem]: https://www.boost.org/doc/libs/1_78_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/tutorial/solar_system.html


# Questions

Here you can post any question you have while we are going through this document. A summary of the questions and the answers will be posted in moodle after each session. Please, use a new bullet point for each question and sub-bullet points for their answers.

For example writing like this:
```
- Example question
  - [name=student_a] Example answer
  - [name=TA_1] Example answer
```
produces the following result:
- Example question
  - [name=student_a] Example answer
  - [name=TA_1] Example answer

Write new questions below :point_down: 

  - [name=]
  - [name=TA_1] Example answer


###### tags: `phas0100` `teaching` `class`