#+TITLE: Introduction to C++ Part II
#+SUBTITLE: An IOP Student Organized Workshop
#+AUTHOR: Rohit Goswami MInstP
# I need the footnotes to be inlined
#+STARTUP: fninline
#+EXCLUDE_TAGS: noexport
#+BEGIN_SRC emacs-lisp :exports none :eval always
(require 'ox-extra)
(ox-extras-activate '(ignore-headlines))
#+END_SRC
* Configuration :ignoreheading:ignore:
:PROPERTIES:
:VISIBILITY: folded
:END:
# Kanged from https://gitlab.com/oer/oer-reveal/blob/master/org/config.org
# Also https://gitlab.com/oer/emacs-reveal-howto/-/blob/master/howto.org
** General Options :ignoreheading:ignore:
# No Table of contents, no section numbers
#+OPTIONS: toc:nil num:t
# Enable smart quotes
#+OPTIONS: ':t
** RevealJS Options :ignoreheading:ignore:
# Enable: browser history, slide numbers, fragment IDs in URLs, mouse wheel, links between presentations
#+OPTIONS: reveal_history:t reveal_slide_number:t reveal_fragmentinurl:t
#+OPTIONS: reveal_mousewheel:t reveal_inter_presentation_links:t
# Disable separate PDF pages for each fragment. Just use one per slide.
#+OPTIONS: reveal_pdfseparatefragments:nil
# Display notes on separate page for PDF export.
#+REVEAL_EXPORT_NOTES_TO_PDF: separate-page
# Transition styles: none/fade/slide/convex/concave/zoom/cube
#+REVEAL_TRANS: fade
# Set a base theme, then override
#+REVEAL_THEME: white
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.config/doom/revealExtras/robot-lung.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.config/doom/revealExtras/oerFragments.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.config/doom/revealExtras/rlExtras.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.config/doom/revealExtras/noImgBoxes.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.config/doom/revealExtras/moreCode.css
#+REVEAL_MARGIN: 0.2
#+REVEAL_PREAMBLE:
#+REVEAL_PLUGINS: (notes search zoom)
# The following variables are non-standard.
# Do not display TOC-progress on title slide.
#+REVEAL_TITLE_SLIDE_STATE: no-toc-progress
# Do not display TOC-progress on TOC slide.
#+REVEAL_TOC_SLIDE_STATE: no-toc-progress
# Do not include TOC slide in TOC-progress.
#+REVEAL_TOC_SLIDE_CLASS: no-toc-progress
# Use different heading for TOC.
#+REVEAL_TOC_SLIDE_TITLE: Agenda
** External Resources :ignoreheading:ignore:
# Note that doom-emacs sets this variable
# https://github.com/hlissner/doom-emacs/blob/develop/modules/lang/org/contrib/present.el
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.emacs.d/.local/straight/build-27.2/revealjs/plugin/accessibility/helper.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.emacs.d/.local/straight/build-27.2/revealjs/plugin/toc-progress/toc-progress.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.emacs.d/.local/straight/build-27.2/revealjs/dist/theme/toc-style.css
#+REVEAL_EXTRA_CSS: /Users/rohitgoswami/.emacs.d/.local/straight/build-27.2/revealjs/dist/theme/fonts/source-sans-pro/source-sans-pro.css
# Allow to selectively hide links.
#+REVEAL_EXTRA_SCRIPTS: ("/Users/rohitgoswami/.emacs.d/.local/straight/build-27.2/revealjs/dist/theme/hidelinks.js")
# The following creates an empty footer, for which the css style defines
# a height that agrees with the TOC-progress footer’s height.
# In this way, the footer’s height is taken into account by reveal.js’s
# size calculations.
#+REVEAL_SLIDE_FOOTER:
#+OPTIONS: reveal_toc_footer:t
** Macros :ignoreheading:ignore:
# Set a default bib file.
# Macros to display square brackets (in texts of hyperlinks).
# Based on: https://emacs.stackexchange.com/questions/7792/can-i-make-links-in-org-mode-that-contain-brackets-or
# Square Bracket Open [
#+MACRO: BO @@latex:\char91{}@@@@html:[@@
# Square Bracket Close ]
#+MACRO: BC @@latex:\char93{}@@@@html:]@@
# Macro for forced line break, e.g., in titles.
#+MACRO: BR @@latex:\\@@@@html:
@@
# Macro to generate abbr element in HTML. If a second argument is given, it
# defines the title attribute. For LaTeX, output first attribute as is and
# ignore second one.
#+MACRO: abbr (eval (concat "@@latex:" Introduction to C++ Part II "@@@@html:" Introduction to C++ Part II "@@"))
# Macros to display code in different colors.
#+MACRO: blackcode (eval (format "@@html:%s
@@ @@latex:\\verb|%s|@@" (org-html-encode-plain-text Introduction to C++ Part II) Introduction to C++ Part II))
#+MACRO: redcode (eval (format "@@html:%s
@@ @@latex:\\rverb|%s|@@" (org-html-encode-plain-text Introduction to C++ Part II) Introduction to C++ Part II))
#+MACRO: greencode (eval (format "@@html:%s
@@ @@latex:\\gverb|%s|@@" (org-html-encode-plain-text Introduction to C++ Part II) Introduction to C++ Part II))
#+MACRO: bluecode (eval (format "@@html:%s
@@ @@latex:\\bverb|%s|@@" (org-html-encode-plain-text Introduction to C++ Part II) Introduction to C++ Part II))
** LaTeX Options :ignoreheading:ignore:
# Setup for PDF generation via LaTeX export.
#+LATEX_CLASS_OPTIONS: [a4paper]
#+LATEX_HEADER: \usepackage[backend=biber,style=alphabetic]{biblatex}
#+LATEX_HEADER: \addbibresource{~/GDrive/zotLib.bib}
#+LATEX_HEADER: \newenvironment{notes}{\par\footnotesize}{\par}
#+LATEX_HEADER: \newenvironment{NOTES}{\par\footnotesize}{\par}
#+LATEX_HEADER: \newenvironment{leftcol}{\begin{minipage}{.49\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{rightcol}{\begin{minipage}{.49\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{leftcol30}{\begin{minipage}{.29\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{leftcol40}{\begin{minipage}{.39\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{leftcol60}{\begin{minipage}{.59\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{leftcol70}{\begin{minipage}{.69\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{rightcol30}{\begin{minipage}{.29\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{rightcol40}{\begin{minipage}{.39\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{rightcol60}{\begin{minipage}{.59\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \newenvironment{rightcol70}{\begin{minipage}{.69\textwidth}}{\end{minipage}}
#+LATEX_HEADER: \usepackage{newunicodechar}
#+LATEX_HEADER: \newunicodechar{≈}{$\approx$}
#+LATEX_HEADER: \newunicodechar{⋮}{\vdots}
#+LATEX_HEADER: \newunicodechar{ }{~}
#+LATEX_HEADER: \usepackage{xcolor}
#+LATEX_HEADER: \definecolor{darkred}{rgb}{0.3, 0.0, 0.0}
#+LATEX_HEADER: \definecolor{darkgreen}{rgb}{0.0, 0.3, 0.1}
#+LATEX_HEADER: \definecolor{darkblue}{rgb}{0.0, 0.1, 0.3}
#+LATEX_HEADER: \definecolor{darkorange}{rgb}{1.0, 0.55, 0.0}
#+LATEX_HEADER: \definecolor{sienna}{rgb}{0.53, 0.18, 0.09}
#+LATEX_HEADER: \hypersetup{colorlinks,linkcolor=darkblue,citecolor=darkblue,urlcolor=darkgreen}
#+LATEX_HEADER: \usepackage{newverbs}
#+LATEX_HEADER: \newverbcommand{\rverb}{\color{darkred}}{}
#+LATEX_HEADER: \newverbcommand{\gverb}{\color{darkgreen}}{}
#+LATEX_HEADER: \newverbcommand{\bverb}{\color{darkblue}}{}
* Start Here :ignoreheading:ignore:
* Brief Introduction
** Hello!
- Find me here: https://rgoswami.me
- Who?
+ *Rohit Goswami* MInstP
- Doctoral Researcher, University of Iceland, Faculty of Physical Sciences
#+begin_leftcol
[[file:images/physUoI.png]]
file:images/IOP-MasterLogo.png
#+end_leftcol
#+begin_rightcol
file:images/rannisLogo.png
#+DOWNLOADED: screenshot @ 2021-04-13 02:55:57
#+ATTR_HTML: :width 70% :height 70%
[[file:images/Hello!/2021-04-13_02-55-57_screenshot.png]]
#+end_rightcol
# ** What I Do
# #+begin_leftcol
# file:images/stuff/volcano.png
# #+end_leftcol
# #+begin_rightcol
# #+ATTR_REVEAL: :frag appear
# - A good place to work on Water!!
# file:images/collages/ice7.png
# #+end_rightcol
** Logistics
#+ATTR_REVEAL: :frag appear
- All contents are [[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2][hosted on GitHub]]
+ Slides are in ~docs/pres~
#+ATTR_REVEAL: :frag appear
- Slides have shortned commit IDs
+ These lead to specific points in the ~git log~
#+ATTR_REVEAL: :frag appear
- Questions are welcome after / during the lecture
+ [[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/discussions/categories/q-a][GitHub Discussions]] have been set up for this
* Local Project Layouts
** Language Agnostic Beginnings
#+ATTR_REVEAL: :frag appear
#+BEGIN_leftcol
#+ATTR_REVEAL: :frag (appear)
- ~Readme.{md,org}~ :: Motivation, rationale, license, installation instructions
- ~LICENSE~ :: Plain text, and preferably an open license
- [[https://github.com/azu/license-generator][license-generator]] is pretty handy for this
- ~.gitignore~ :: Lists files which do not need to be committed; typically generated files
- [[https://github.com/simonwhitaker/gibo][gibo]] can be used to generate these
#+END_leftcol
#+BEGIN_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src bash
$ git init # Inside project
$ gibo macOS Windows Xcode Emacs \
Vim Python C++ \
CMake TeX > .gitignore
$ touch readme.md
$ license-generator MIT \
--author "Person"
$ tree -L 2
.
├── LICENSE
├── docs
│ └── pres
└── readme.org
2 directories, 2 files
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/9c294144a3d5518dfe03ad53912f2e768e6cc47e][9c29414]]
#+end_gcid
#+END_rightcol
** C++ Project Structure
#+ATTR_REVEAL: :frag appear
#+BEGIN_leftcol
#+ATTR_REVEAL: :frag (appear)
- ~src/~ :: Should be split into libraries and executables
- ~include/~ :: For headers, internal and external
- ~docs/~ :: Documentation of all kinds, typically including markdown files
- ~CMakeLists.txt~ :: The project build system
- ~ci/~ :: Scripts for continuous integration
#+END_leftcol
#+BEGIN_rightcol
#+DOWNLOADED: screenshot @ 2021-04-12 21:03:39
#+ATTR_REVEAL: :frag appear
[[file:images/C++_Project_Structure/2021-04-12_21-03-39_screenshot.png]]
[fn:: Cute graphic [[http://archive.makzan.net/images/introducing-web-design/preprocessing.png][from here]]]
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
// Along each -I and INCLUDE
#include
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
// Starts in the same directory
// Reverse order upward
// -I and INCLUDE
#include "path-spec"
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/a5a0a9ebac0340a5dc7c1c192e062f3a68d32cc4][a5a0a9e]]
#+end_gcid
#+END_rightcol
* Iterative Improvements - I
** Refactoring CMakefile - I
#+begin_leftcol
- Comments are imperative
- Segregation of build allows for easy cleanup
- ~rm -rf build~
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
# --- Variables
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release
endif()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src bash
$ # Should fail!!!
$ cmake .
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/8193ad90fe6755f6c39d66f175572556dbcad5ad][8193ad9]]
#+end_gcid
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
# ---- Project ----
project(
PenningTrapSimulationII
VERSION 1.0
LANGUAGES CXX
)
# ---- Include guards ----
if(PROJECT_SOURCE_DIR
STREQUAL PROJECT_BINARY_DIR)
message(
FATAL_ERROR
"In-source builds not allowed.
Please make a new directory
(called a build directory)
and run CMake from there."
)
endif()
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src bash
$ # Works
$ cmake -H. -Bbuild
$ cmake --build build
$ cd build
$ simulation.exe
#+end_src
#+end_rightcol
** Header Only Includes
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- These are meant for small classes
+ With inlined definitions
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
#ifndef IOP_VEC_H
#define IOP_VEC_H
...
#endif /* IOP_VEC_H */
#+end_src
#+ATTR_REVEAL: :frag appear
- Prevents multiple inclusion
- Modularity means more unit-tests
+ Better guarantees
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
# --- Library
set(headers
"${CMAKE_CURRENT_SOURCE_DIR}/include/math_types/iop_vec.hpp")
set(sources "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp")
# Build
add_executable(simulation.exe ${sources})
# Add to INCLUDE
target_include_directories(
simulation.exe PUBLIC
$
)
#+end_src
#+ATTR_REVEAL: :frag appear
- We prefer ~<>~ to ~""~ for includes
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
#include
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/9ca7f3a123b9891159a805fe78b549a6762744da][9ca7f3a]]
#+end_gcid
#+end_rightcol
** Namespaces
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- Further improves modularity
+ Fewer clashes
+ *Never* use ~using~
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
namespace iopdat {
// data_types/iop_particle.hpp
class Particle {
public:
Vector3 position;
...
} }
#+end_src
#+ATTR_REVEAL: :frag appear
- Same conceptual region, even across files
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
namespace iopdat {
// data_types/iop_vec.hpp
class Vector3 {
...
} }
#+end_src
#+end_leftcol
#+begin_rightcol
#+DOWNLOADED: screenshot @ 2021-04-12 23:21:01
#+ATTR_REVEAL: :frag appear
[[file:images/Iterative_Improvements_-_I/2021-04-12_23-21-01_screenshot.png]]
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
set(headers
"include/data_types/iop_vec.hpp"
"include/data_types/iop_particle.hpp"
)
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
#include
#include
#+end_src
#+ATTR_REVEAL: :frag appear
- Regrouped the ~data_types~
+ ~math_types~ wasn't primitive enough
+ Refactoring early *is normal*
- With _tests_
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/2f1b16115cd612f2a3efd767dff4683a4f4657a9][2f1b161]]
#+end_gcid
#+end_rightcol
** Compiled Libraries
#+begin_leftcol
*Before*
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
class TimeStepper {
private:
std::vector
physics_list;
iopdat::Particle p;
double dt;
public:
TimeStepper(double time_step_size,
double charge,
double mass)
: p(charge, mass) {
dt = time_step_size;
}
...
};
#+end_src
#+end_leftcol
#+begin_rightcol
*After*
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
class TimeStepper {
private:
std::vector physics_list;
iopdat::Particle p;
double dt;
public:
TimeStepper(double time_step_size,
double charge,
double mass);
void AddProcess(PhysicsProcess*
process);
void Setup(iopdat::Vector3 position,
iopdat::Vector3 Velocity);
void Step();
void Print();
};
#+end_src
#+end_rightcol
*** Why?
#+begin_leftcol
*Header Only*
#+ATTR_REVEAL: :frag appear
- Easier to install
#+ATTR_REVEAL: :frag appear
- Can be dropped in and versioned
#+ATTR_REVEAL: :frag appear
- Slow, especially installed
+ They are expanded
*Compiled*
#+ATTR_REVEAL: :frag appear
- Compiled code is faster
#+ATTR_REVEAL: :frag appear
- Adds complexity though
+ Needs a build system
#+ATTR_REVEAL: :frag appear
- Can easier to read
+ More modular
+ Easier to document
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src bash
$ tree -L .
.
├── CMakeLists.txt
├── LICENSE
├── docs
│ └── pres
├── include
│ ├── data_types
│ └── phys_procs.hpp
├── libsrc
│ └── phys_procs.cpp
├── readme.org
└── src
├── CMakeLists.txt
└── main.cpp
6 directories, 7 files
#+end_src
#+end_rightcol
*** How? - I Code Separation
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- *declared* in ~.hpp~
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
/**
* @brief Takes a step
* @returns None.
*/
void Step();
#+end_src
#+ATTR_REVEAL: :frag appear
- The build system takes on most of the debt
+ Compiles the code as a library
- "header-only" libraries can also be built
- Ensures it can be linked at runtime
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
- *defined* in ~.cpp~
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
/**
* @detail The algorithm is a direct interpretation
* of standard mechanics
*/
void physproc::TimeStepper::Step() {
iopdat::Vector3 F(0, 0, 0);
for (int i = 0;
i < physics_list.size(); i++) {
F += physics_list.at(i)->Force(p);
}
iopdat::Vector3 dv(dt * F.x / p.mass,
dt * F.y / p.mass,
dt * F.z / p.mass);
p.velocity += dv;
p.position +=
iopdat::Vector3(p.velocity.x * dt,
p.velocity.y * dt,
p.velocity.z * dt);
}
#+end_src
#+end_rightcol
*** How? - II Building and Linking
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- For *header-only* libraries
+ PUBLIC -> INTERFACE
- target:
+ ~add_library(ioplib INTERFACE)~
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
// main.cpp
...
#include
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/e6d048e88c103df18e9bde45416299d0801aa427][e6d048e]]
#+end_gcid
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
# Build order
add_dependencies(simulation.exe ioplib)
# Libraries
target_link_libraries(simulation.exe
ioplib)
# Dependencies
add_library(
ioplib SHARED
"libsrc/phys_procs.cpp"
)
# Still need the older headers
target_include_directories(
ioplib PUBLIC
$
)
#+end_src
#+end_rightcol
*** When?
#+ATTR_REVEAL: :frag appear
- Larger projects refactor often
#+ATTR_REVEAL: :frag appear
- Modular components make it easy for new contributors
#+ATTR_REVEAL: :frag appear
- Reuse of code is easier this way
#+ATTR_REVEAL: :frag appear
- The speed benefits can be considerable
+ Speed here means compilation time
#+ATTR_REVEAL: :frag appear
- ~boost~ is a classic example of a mostly compiled library
#+ATTR_REVEAL: :frag appear
- ~Eigen3~ is famously header-only
#+ATTR_REVEAL: :frag appear
#+begin_quote
Let there be libraries!!
--- Rohit Goswami (2021)
#+end_quote
* Package Management
** Current Scenario
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
file:images/xkcd/python_xkcd.png
[fn:: Comic [[https://xkcd.com/353/][from here]]]
#+ATTR_REVEAL: :frag appear
- *Nix is the answer!!* (not here)
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
- ~Python~ :: ~poetry~, ~pipenv~, ~pyenv~
- ~C++~ :: ~conan~, ~vcpkg~, _~cpm~_
#+ATTR_REVEAL: :frag appear
file:images/collages/systemManagers.png
#+end_rightcol
** CPM and CMake
#+ATTR_REVEAL: :frag appear
#+begin_src bash
mkdir -p cmake
wget -O cmake/CPM.cmake "https://github.com/cpm-cmake/\
CPM.cmake/releases/latest/download/get_cpm.cmake"
# Can get slow otherwise, rebuilds constantly
export CPM_SOURCE_CACHE=$HOME/.cache/CPM
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
# --- Helpers
include(cmake/CPM.cmake)
CPMUsePackageLock(package-lock.cmake)
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src bash
# We like locks
cmake -H. -Bbuild
cmake --build build --target cpm-update-package-lock
#+end_src
* Testing and Continuous Integration
** Testing Frameworks
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- ~C++~ has great testing frameworks
+ _~Catch2~_, ~googletest~, ~doctest~, etc.
#+ATTR_REVEAL: :frag appear
- *Unit tests* are the first layer
+ Ensure each function outputs as expected
#+ATTR_REVEAL: :frag appear
- *Integration tests* are for workflows
+ Ensure each series of tasks connect correctly
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
# Catch2 CMakeLists.txt
include(CTest)
add_subdirectory(tests)
enable_testing()
#+end_src
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
# --- Externals ./tests/CMakeLists.txt
include(../cmake/CPM.cmake)
CPMAddPackage("gh:catchorg/Catch2@2.13.4")
add_executable(particle_tests
main.cpp
vector_particle-test.cpp
phys_processes-test.cpp
)
# Link everything
target_link_libraries(particle_tests
ioplib
Catch2)
target_compile_features(particle_tests PRIVATE cxx_std_17)
# Project Libraries
include_directories(
../src/include/data_types
${PROJECT_SOURCE_DIR}/src/include/)
# ---- Run tests ----
add_test(NAME particleIOP-unit-tests
COMMAND $)
#+end_src
#+end_rightcol
** Writing Tests
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
#define CATCH_CONFIG_MAIN
#define CATCH_CONFIG_RUNNER
#include
#+end_src
#+ATTR_REVEAL: :frag appear
- The macros must not be repeated
#+ATTR_REVEAL: :frag appear
- Many more test scenarios
+ d-SEAMS [[https://github.com/d-SEAMS/seams-core][has examples]]
+ [[https://github.com/catchorg/Catch2/blob/devel/docs/tutorial.md#scaling-up][Official docs are great]]
#+ATTR_REVEAL: :frag appear
- Try *fixing gravity* as _homework_!
+ Open a PR (pull request) when done
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
#include
#include
#include
#include
#include
TEST_CASE("Basic Vector class tests", "Vector3") {
iopdat::Vector3 a{1, 2, 3};
REQUIRE(sizeof(a) == 24);
REQUIRE(sizeof(a) / sizeof(1) == 6);
REQUIRE(sizeof(a) / sizeof(1.0) == 3);
iopdat::Vector3 b{4, 5, 6};
b += a;
REQUIRE(b.x == 5);
REQUIRE(b.y == 7);
REQUIRE(b.z == 9);
std::cout << b.x;
}
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/d9ded32c144fde02667dde19f70cf49a11bd5625][d9ded32]]
#+end_gcid
#+end_rightcol
** Continuous Integration
#+ATTR_REVEAL: :frag appear
- No one likes switching computers to test
+ MacOS, Windows (WSL often), Many Linux distributions
#+ATTR_REVEAL: :frag appear
- Some tests run for a long time
+ Less attractive locally
- ~nixpkgs~ can take over a day!
#+ATTR_REVEAL: :frag appear
- There are far too many options nowadays
+ Wercker, +Travis CI+, Shippable, GitLab CI, _Github Actions_
#+ATTR_REVEAL: :frag appear
- Mostly transient ~docker~ or ~nix~ based systems
+ Setup can be annoying without ~nix~
** Github Actions
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- [[https://github.com/nektos/act#installation][act allows]] local tests
#+ATTR_REVEAL: :frag appear
#+begin_src yaml
name: CMake
on: [push]
env:
BUILD_TYPE: Release
jobs:
build:
runs-on: ${{ matrix.OS }}
name: "${{ matrix.BUILD_TYPE }}"
strategy:
matrix:
include:
- BUILD_TYPE: Debug
OS: ubuntu-latest
- BUILD_TYPE: Debug
OS: macos-latest
- BUILD_TYPE: Debug
ARCH: x86_64
OS: windows-latest # broken
#+end_src
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src yaml
steps:
- uses: actions/checkout@v2
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -C $BUILD_TYPE
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/1293af3c860f29646d49339c1e50d37267a03f9b][1293af3]]
#+end_gcid
#+end_rightcol
* Embedding and Mixed Compilation
** Why Embed?
*** Visuals??
#+ATTR_REVEAL: :frag appear
- File I/O is sufficient
#+ATTR_REVEAL: :frag appear
#+begin_src bash
simulate.exe > someFile.txt
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import pandas as pd
df = pd.read_csv("someFile.txt", sep=" ")
# Do stuff now
#+end_src
#+ATTR_REVEAL: :frag appear
- Can be better for HPC systems
+ *Why embed / interpolate?*
** Better Examples
*** d-SEAMS
- Uses ~lua~ to expose a scripting engine
+ Computation is still ~C++~
- Reduces compilation requirements
+ Increases flexibility
fullcite:goswamiDSEAMSDeferredStructural2020
#+DOWNLOADED: screenshot @ 2021-04-13 03:36:06
[[file:images/Better_Examples/2021-04-13_03-36-06_screenshot.png]]
*** EON
- EON uses a server client architecture
- Is meant for distributed use
fullcite:henkelmanLongTimeScale2001
#+DOWNLOADED: screenshot @ 2021-04-13 03:39:23
#+ATTR_HTML: :width 80% :height 80%
[[file:images/Better_Examples/2021-04-13_03-39-23_screenshot.png]]
* PyBind11
** Embedding Python
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
- Example adapted [[https://github.com/tttapa/Pybind11-Matplotlib-Cpp][from here]]
#+ATTR_REVEAL: :frag appear
#+begin_src bash
pip install matplotlib
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src cmake
CPMAddPackage(
NAME pybind11
GITHUB_REPOSITORY pybind/pybind11
GIT_TAG v2.6.1
)
target_link_libraries(simulation.exe
ioplib pybind11::embed)
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
// py::scoped_interpreter
#include
#include
namespace py = pybind11;
int main() {
std::vector
signal(1024);
for (size_t i = 0; i < signal.size(); ++i)
signal[i] = std::exp(i / -256.0) * std::cos(2 * M_PI * 8 * i / 1024.0);
#+end_src
#+end_leftcol
#+begin_rightcol
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
py::scoped_interpreter guard{};
using namespace py::literals;
// Save the necessary local variables
// in a Python dict
py::dict locals = py::dict{
"signal"_a = signal,
};
// Execute Python code, using the variables
// saved in `locals`
py::exec(R"(
import matplotlib.pyplot as plt
plt.plot(signal)
plt.show()
)",
py::globals(), locals);
}
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/5c21716f31f1498ba9e67166ad6faba4cb9159af][5c21716]]
#+end_gcid
#+end_rightcol
*** Sample Run
#+DOWNLOADED: screenshot @ 2021-04-13 04:08:12
[[file:images/Embedding_Python/2021-04-13_04-08-12_screenshot.png]]
** Proton Stepper
#+begin_leftcol
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
// Getters
double physproc::TimeStepper::getX()
{ return p.position.x; }
#+end_src
#+ATTR_REVEAL: :frag appear
#+begin_src cpp
// Accumulators
std::vector x, y, z;
for (int i = 0; i < 1E3; i++) {
ProtonStepper.Step();
if (i % 7 == 0) {
x.push_back(ProtonStepper.getX());
...
}
}
py::scoped_interpreter guard{};
using namespace py::literals;
py::dict locals = py::dict{
"x"_a = x,
...
};
py::exec(R"(
)",
py::globals(), locals);
#+end_src
#+begin_gcid
[[https://github.com/HaoZeke/2021_April_IOP_IntroductionToCpp_Part2/commit/59555bce6a02ffe57bbd3e7ceefa5f8b271c4568][59555bc]]
#+end_gcid
#+end_leftcol
#+begin_rightcol
#+DOWNLOADED: screenshot @ 2021-04-13 04:37:30
#+ATTR_REVEAL: :frag appear
[[file:images/Proton_Stepper/2021-04-13_04-37-30_screenshot.png]]
#+ATTR_REVEAL: :frag appear
#+begin_src python
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, c='r', marker='o')
plt.show()
#+end_src
#+end_rightcol
* Conclusions
** Omitted Topics
#+ATTR_REVEAL: :frag appear
- Documentation :: Possibly the most underrated skill in compuational work
#+ATTR_REVEAL: :frag appear
- Package Management :: Managing OS's
#+ATTR_REVEAL: :frag appear
- HPC and Parallelism :: Efficient data usage and algorithms
#+ATTR_REVEAL: :frag appear
- Code Review Practices :: Scrum and teamwork
#+ATTR_REVEAL: :frag appear
- Inter process communication :: Across networks and process, including serialization
** Further Resources
- [[https://changkun.de/modern-cpp/en-us/00-preface/][Modern C++ Tutorial]] :: Community maintained, discusses features from C++11 onwards, spearheaded by Changkun Ou
- [[http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines][C++ Core Guidelines]] :: Maintained by Bjarne and Herb, great to get the pulse of the community
- [[https://docs.microsoft.com/en-us/cpp/cpp/welcome-back-to-cpp-modern-cpp?view=msvc-160][Microsoft Visual Studio]] :: Has a surprisingly good introduction and [[https://docs.microsoft.com/en-us/cpp/get-started/tutorial-console-cpp?view=msvc-160][even some projects]]
- [[https://rgoswami.me/posts/ccon-tut-nix/][A Tutorial Introduction to Nix]] :: Package management at the system level in a reproducible manner
- [[https://rgoswami.me/posts/symengine-gsod20/][SymEngine and the Season of Docs]] :: Describes the present SOTA for documentation practices in the context of a large multi-language project
- [[https://www.jetbrains.com/help/clion/unit-testing-tutorial.html][CLion]] :: Has a solid tutorial on tests and frameworks in general
* The End
** Bibliography
:PROPERTIES:
:CUSTOM_ID: bibliography
:END:
printbibliography:/Users/rohitgoswami/GDrive/zotLib.bib
** Thanks!
:PROPERTIES:
:reveal_background: #005ab6
:END:
# Local Variables:
# indent-tabs-mode: nil
# org-src-preserve-indentation: t
# End: