# Rust, For Science!

Rustfest Rome

\sum_{n=1}^{\infty} n= -\frac{1}{12}
$\sum_{n=1}^{\infty} n= -\frac{1}{12}$
\frac{\partial L}{\partial f} - \frac{d}{dt} \frac{\partial L}{\partial f'} = 0
$\frac{\partial L}{\partial f} - \frac{d}{dt} \frac{\partial L}{\partial f'} = 0$
\psi (x) = -i \hbar \frac{\partial}{\partial x}(-i \hbar \frac{\partial \psi}{\partial x})
$\psi (x) = -i \hbar \frac{\partial}{\partial x}(-i \hbar \frac{\partial \psi}{\partial x})$
P(A \lvert B ) = \frac{P(B \lvert A) P(A)}{P(B)}
$P(A \lvert B ) = \frac{P(B \lvert A) P(A)}{P(B)}$
\sigma = \sqrt{\frac{\sum (x - \bar{x})^2}{n - 1}}
$\sigma = \sqrt{\frac{\sum (x - \bar{x})^2}{n - 1}}$
\nabla \times G = J + \frac{\partial D}{\partial t}
$\nabla \times G = J + \frac{\partial D}{\partial t}$
\rho (\frac{\partial V}{\partial t} + V\cdot \nabla V) = \nabla P + \rho g + \mu \nabla^2 V
$\rho (\frac{\partial V}{\partial t} + V\cdot \nabla V) = \nabla P + \rho g + \mu \nabla^2 V$
\hat{f}(\zeta) = \int_{-\infty}^{\infty} f(x) e^{-e \pi i x \zeta} dx
$\hat{f}(\zeta) = \int_{-\infty}^{\infty} f(x) e^{-e \pi i x \zeta} dx$
F_g = \frac{G m_1 m_2}{r^2}
$F_g = \frac{G m_1 m_2}{r^2}$
f(x) = \frac{1}{1 + e^{-x}}
$f(x) = \frac{1}{1 + e^{-x}}$
J(\theta_j) \leftarrow 0_j \pm \eta \cdot \frac{\sum (\hat{y} - y)^2 \cdot x}{2n}
$J(\theta_j) \leftarrow 0_j \pm \eta \cdot \frac{\sum (\hat{y} - y)^2 \cdot x}{2n}$
\frac{d}{{dx}}f\left( x \right) = \mathop {\lim }\limits_{\Delta \to 0} \frac{{f\left( {x + \Delta } \right) - f\left( x \right)}}{\Delta }
$\frac{d}{{dx}}f\left( x \right) = \mathop {\lim }\limits_{\Delta \to 0} \frac{{f\left( {x + \Delta } \right) - f\left( x \right)}}{\Delta }$

# What is Scientific Computing?

High-Performance Computing

Data Science

Numerical Analysis & Simulation

# Rust?

## What's Going On Here?

• Simulating a Double Pendulum
• Just plain Rust
• Uses a struct for state
• Displaying The Simulation
• Using GGEZ
• Takes values from the struct

## Enter WebAssembly

pub struct DoublePendulumLagrangian {
/// Gravitational Constant.
pub g: f64,
/// Mass of the first bob.
pub m1: f64,
/// Mass of the second bob.
pub m2: f64,
/// Initial angle of the first bob.
pub t1: f64,
/// Initial angle of the second bob.
pub t2: f64,
/// Angular velocity of the first bob.
pub dt1: f64,
/// Angular velocity of the second bob.
pub dt2: f64,
/// Length of the rod for the first bob.
pub l1: f64,
/// Length of the rod for the second bob.
pub l2: f64,
}

impl DoublePendulumLagrangian {
// ...

## Enter WebAssembly

const { DoublePendulumLagrangian } = wasm_bindgen;

wasm_bindgen('../out/main_bg.wasm')
.then(runApp)
.catch(console.error)

function runApp() {
const elem = document.getElementById('container')
const two = new Two({ fullscreen: true })
.appendTo(elem)

const g = 9.8
const m1 = 2.0
const m2 = 2.0
const t1 = 2.0
const t2 = 1.5
const l1 = 100
const l2 = 100

const pendulum = DoublePendulumLagrangian.new(
g, m1, m2,
t1, t2, l1, l2
)
drawBobs(two, pendulum)
// ...

# Fearless Concurrency Makes Multithreading Easy

• Rayon
• OpenCL
• ArrayFire

## Example: Numerical Integration

fn integrate<F>(f: F, a: f64, b: f64, n: u32) -> f64
where
F: Fn(f64) -> f64,
{
let h = (b - a) / n as f64;
let mut result = 0.5 * f(a) + 0.5 * f(b);

for i in 1..n {
result += f(a + i as f64 * h);
}
result * h
}

## Example: Numerical Integration

extern crate rayon;

use rayon::prelude::*;


## Example: Numerical Integration

fn integrate_threaded<F>(f: F, a: f64, b: f64, n: u32) -> f64
where
F: Fn(f64) -> f64 + Sync,
{
let h = (b - a) / n as f64;
let result: f64 = (1..n)
.into_par_iter()
.map(|i| f(a + i as f64 * h))
.sum();

h * result
}

# Integrating With Standard Tools

## Example 1: MPI

#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
// Initialize the MPI environment
MPI_Init(NULL, NULL);

// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);

// Get the processes rank
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);

// Print off a hello world message
printf("Processor %s, rank %d\n", processor_name, world_rank);

// Finalize the MPI environment
MPI_Finalize();
}

## Add The Dependency

[dependencies]
mpi = "0.5"

## Write in Rust

extern crate mpi;

use mpi::traits::*;

fn main() {
// Initialize the MPI environment
let universe = mpi::initialize().unwrap();
let world = universe.world();

// Get the number of processes
let size = world.size();

// Get the processes rank
let rank = world.rank();

// Get the processor name
let processor_name = mpi::environment::processor_name().unwrap();

// Print off a hello world message
println!("Processor {}, rank {}", processor_name, rank);
}

## Other Tools

• PyO3
• RGSL
• Rust Specific (nalgebra, alga, nphysics, timely-dataflow, ...)

# What about in Rust?

## EXCVR

• Evaluation Context
• Jupyter Kernel
• REPL

# So What's The Problem?

## Resources

github.com/rustwasm

github.com/rust-unofficial/awesome-rust