{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "I recently discovered [cling](https://root.cern.ch/drupal/content/cling) after I saw this Tweet\n", "\n", "

I made a C++ kernel for Jupyter for some reason: https://t.co/7ApuZyeR0r

— Min RK (@minrk) May 19, 2015
\n", "\n", "\n", "From the cling website, \"Cling is an interactive C++ interpreter, built on the top of LLVM and Clang libraries. Its advantages over the standard interpreters are that it has command line prompt and uses just-in-time (JIT) compiler for compilation.\" As I write (or mostly teach through dual-coding with students) quite a bit of C++ and have already been utilizing the [IPython](http://ipython.org/)/[Jupyter](https://jupyter.org/) notebook as a teaching tool for sometime, I was immediately interested in using [MinRK](https://github.com/minrk)'s [clingkernel](https://github.com/minrk/clingkernel) for this purpose as well as exploring and testing out my own ideas. As I learned more about cling, I found most of the examples to be very trivial and those that inluded the calling/loading of external functions typically only utilized the functions from the standard library. I was eager to give it try on something a little more complex, and because most of the code we write in my group is heavily dependent on [Trilinos](http://trilinos.org/), I thought I would attempt to solve a simple linear algebra system of the form\n", "\n", "$$\n", "A \\vec{x} = \\vec{b}\n", "$$\n", "\n", "using [AztecOO](http://trilinos.org/packages/epetra/) solvers with [Epetra](http://trilinos.org/packages/aztecoo/) datastructures from Trilinos (at least AztecOO and Epetra). This is an adaptation of the example code provided in Figure 1 of the [AztecOO User's guide](http://trilinos.org/oldsite/packages/aztecoo/AztecOOUserGuide.pdf).\n", "\n", "Of course, to reproduce the code below, you will need to [install cling](https://github.com/vgvassilev/cling) and Trilinos. Additionally, if you want to use MinRK's [clingkernel](https://github.com/minrk/clingkernel) you need to install the [Jupyter notebook](https://github.com/jupyter/notebook#jupyter-notebook) from the `master` branch, and install the kernel. With that, you should be able to download this notebook and execute it with few modifications." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cling provides a few metaprocessing commands to perform actions that you would normal provide as arguments to the build system, such as providing locations for include files, loading shared libraries, etc. The documentation for the metaprocessing commands are\n", "\n", "````\n", ".x test.cpp – load a file (if the file defines void test() it will be executed)\n", ".L libname – load a libary or file\n", ".x filename.cxx – loads filename and calls void filename() if defined\n", ".I path – adds an include path\n", ".printAST – shows the abstract syntax tree after each processed entity\n", ".q – exit cling\n", ".help – display a brief description\n", "````\n", "\n", "We'll start by loading the location of the installed header files in my Trilinos build (here I only built AztecOO and Epetra in serial to keep it simple). Cling utilizes the Clang compiler which is pretty picky, so I had to edit the header files in a few locations where `#include` statments where provided with angle brackets `< >` for local includes, where the compiler wanted double quotes. In other words, I had to change\n", "\n", "````\n", "#include \n", "````\n", "\n", "to \n", "\n", "````\n", "#include \"foo.h\"\n", "````\n", "\n", "in a few of the Trilinos headers. So the metaprocessing command to tell the system where the header files are:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [] } ], "source": [ ".I /usr/local/trilinos-serial/include/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now we provide the include statememts." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [] } ], "source": [ "#include \"AztecOO.h\"" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [] } ], "source": [ "#include \"AztecOO_Version.h\"\n", "#include \"Epetra_SerialComm.h\"\n", "#include \"Epetra_Map.h\"\n", "#include \"Epetra_Vector.h\"\n", "#include \"Epetra_CrsMatrix.h\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now the metaprocessing to load the shared libraries. Since I'm on a Mac, I had to define the environment variable \n", "\n", "````bash\n", "export DYLD_LIBRARY_PATH=/usr/local/trilinos-serial/lib:$DYLD_LIBRARY_PATH\n", "````\n", "\n", "before launching the notebook/cling so the system knows where to find the libraries at runtime. On a Linux machine, this variable would be `LD_LIBRARY_PATH`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [] } ], "source": [ ".L libepetra\n", ".L libaztecOO" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we start in with the actual Epetra/AztecOO code. Since it's not apparent to me whether it's possible for `cling` to support [MPI](http://www.open-mpi.org/) processes, we'll just provide a serial implementation. We start with some code that instantiates the Epetra serial communicator and provides some information about the version of Trilinos we are using." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r\n", "AztecOO in Trilinos 12.1 (Dev)\r\n", "\r\n", "\r\n", "Epetra::Comm::Processor 0 of 1 total processors.\r\n" ] } ], "source": [ "Epetra_SerialComm Comm;\n", " \n", "int NumMyElements = 1000;\n", "\n", "if (Comm.MyPID()==0)\n", " std::cout << AztecOO_Version() << std::endl << std::endl;\n", "\n", " std::cout << Comm <