(Teaching) Coding is Fun¶

Matthias Möller (Numerical Analysis)

DIAM Research Day - November 7th, 2024

The situation¶

  • Teaching a course on object-oriented scientific programming with C++ to 150-200 bachelor and master students from all faculties
  • Static slides hinder interaction with students (i.e. "What happens if you change i++ to ++i in a while loop?")
  • Switching between editor/terminal and slides disturbs the flow of lecturing
  • Wanting to have a printable version of the static slides

Whatever solution is used, it should be available to all students independent of the operating system and without the need to install extra tools!

A solution¶

Jupyter logo

+

Xeus cling logo

+

Binder logo

Jupyter notebooks is an open-source, interactive web application that allows you to create and share documents that contain live code, equations, visualizations, and text. Together with the RISE extension you can turn your Jupyter notebooks into live reveal.js-based presentations.

Xeus Cling is a Jupyter kernel that allows you to run C++ code in Jupyter notebooks. It is based on the interactive C++ interpreter developed by CERN.

Binder is a free-of-charge online service for running customized computing environments.

Example¶

Slide formatting with markdown, e.g., boldface, italics, including equations $a^2+b^2=c^2$

# Example

Slide formatting with `markdown`: **boldface**, _italics_, including equations $a^2+b^2=c^2$

or HTML

<p>or <code>HTML</code></p>

The style of the slides can be further adjusted via the rise.css file.

Example of a slide with embedded C++ code¶

The following code snippet illustrates the use of a while loop

In [1]:
#include <iostream>

int i = 0;
while (i++ < 10) {
    std::cout << i << " ";
}
1 2 3 4 5 6 7 8 9 10 

Quiz question: What happens if you change i++ to ++i?

An advanced example¶

The following code snippet illustrates how to include the Eigen library

In [2]:
#include <iostream>
#include </home/jovyan/eigen/Eigen/Dense>

Eigen::Matrix2d A;  A << 1.0, 2.0, 3.0, 4.0;
Eigen::Vector2d x(5,6);

std::cout << A * x << std::endl;
17
39

The magic behind the scenes¶

Demo repository: https://github.com/mmoelle1/DIAM-RD2024

GitHub repository

Branches explained¶

2024 (default)

  • contains the notebooks (and GitHub actions) and other content such as plots
  • duplicate this branch and make it the default for next years edition

binder

  • contains the configuration to run the notebooks on https://mybinder.org

gh-pages

  • contains the auto-generated static slides (don't touch it!)

Workflow¶

  1. Each time you push a change to the default branch, the GitHub actions generate the static slides in the gh-pages branch. That's why you need to change the default branch each time you create the next year's edition.

  2. The links in the README.md file refer to the binder branch. The first time you launch a binder image (or when you did not do so for a longer time) will take some time since the binder image needs to be (re-)created. Binder images will be cached, so all further launches will be much faster.

Customizing the binder image¶

The binder branch contains the two configuration files:

environment.yml postBuild
name: xeus-cling channels: - conda-forge dependencies - xeus-cling - xeus-python - matplotlib-base - notebook < 7.0 - pip: - rise - nbgitpuller - jupyter-contrib-nbextensions #!/bin/bash # Enable splitcell jupyter contrib nbextension install --user jupyter nbextension enable splitcell/splitcell # Download and unpack the Eigen library curl -s https://gitlab.com/libeigen/eigen/-/archive/ 3.4.0/eigen-3.4.0.tar.bz2 | tar -xjf - -C $HOME/ mv $HOME/eigen-3.4.0 $HOME/eigen

Similar to the Eigen library you can download and install other libraries. Each time you update a file in the binder branch the binder image is recreated.

Summary¶

  • Presented a workflow for creating and deploying dynamically changeable slides with embedded executable C++ code blocks
  • Successfully tested in the course TW3720TU/WI4771TU in Q2 2023/24
  • Workflow can be easily adapted to your own needs (e.g., use Python or Julia kernel)
In [ ]:
#include <iostream>
int msg[] = {10, 9, 9, 9, 9, 84, 104, 97, 110, 107, 32, 121, 111, 117, 33};
std::cout << std::string(msg, msg + 120) << std::endl;