metaprogramming patterns for physics simulation...

201
Metaprogramming Patterns for Physics Simulation and Verification Roy H. Stogner The University of Texas at Austin April 16, 2012 Roy H. Stogner Metaprogramming April 16, 2012 1 / 52

Upload: hadieu

Post on 28-Jun-2018

219 views

Category:

Documents


2 download

TRANSCRIPT

Metaprogramming Patterns for Physics Simulationand Verification

Roy H. Stogner

The University of Texas at Austin

April 16, 2012

Roy H. Stogner Metaprogramming April 16, 2012 1 / 52

Computational Modeling and Verification

PECOS ResearchVerification, Validation, Uncertainty Quantification• Atmospheric entry vehicle, two key quantities of interest:

I Rate of recession of TPS (throughout peak heating regime)I Local peak heat flux to after-body

• Validation and uncertainty quantification for these QoI

Roy H. Stogner Metaprogramming April 16, 2012 2 / 52

Computational Modeling and Verification

PECOS Development

Experimental Data

QUESO

FIN-SlibMeshBoost

Turbulence

SHOCKINGMUTATION

GSL

Chemistry/Shocktube

Plug FlowABLATION1D

GSL

Ablation

Calibration/Validation

FIN-S

Inve

rsio

n

Forw

ard

QUESO/Dakota

Multiphysics Analysis

MASA

QoI

GRVYExternal Libraries

LDVFlow

Measurements

NASA EAST Shocktube

Measurements

Molecular Beam (O2)Heated Flow Titration (N2)

New Codes

• New subphysicsmodels

• New developers

• New QoIpostprocessing

• New numerics

• New bugs

Roy H. Stogner Metaprogramming April 16, 2012 3 / 52

Computational Modeling and Verification

PECOS Development

Experimental Data

QUESO

FIN-SlibMeshBoost

Turbulence

SHOCKINGMUTATION

GSL

Chemistry/Shocktube

Plug FlowABLATION1D

GSL

Ablation

Calibration/Validation

FIN-S

Inve

rsio

n

Forw

ard

QUESO/Dakota

Multiphysics Analysis

MASA

QoI

GRVYExternal Libraries

LDVFlow

Measurements

NASA EAST Shocktube

Measurements

Molecular Beam (O2)Heated Flow Titration (N2)

New Codes• New subphysics

models

• New developers

• New QoIpostprocessing

• New numerics

• New bugs

Roy H. Stogner Metaprogramming April 16, 2012 3 / 52

Computational Modeling and Verification

PECOS Development

Experimental Data

QUESO

FIN-SlibMeshBoost

Turbulence

SHOCKINGMUTATION

GSL

Chemistry/Shocktube

Plug FlowABLATION1D

GSL

Ablation

Calibration/Validation

FIN-S

Inve

rsio

n

Forw

ard

QUESO/Dakota

Multiphysics Analysis

MASA

QoI

GRVYExternal Libraries

LDVFlow

Measurements

NASA EAST Shocktube

Measurements

Molecular Beam (O2)Heated Flow Titration (N2)

New Codes• New subphysics

models

• New developers

• New QoIpostprocessing

• New numerics

• New bugs

Roy H. Stogner Metaprogramming April 16, 2012 3 / 52

Computational Modeling and Verification

PECOS Development

Experimental Data

QUESO

FIN-SlibMeshBoost

Turbulence

SHOCKINGMUTATION

GSL

Chemistry/Shocktube

Plug FlowABLATION1D

GSL

Ablation

Calibration/Validation

FIN-S

Inve

rsio

n

Forw

ard

QUESO/Dakota

Multiphysics Analysis

MASA

QoI

GRVYExternal Libraries

LDVFlow

Measurements

NASA EAST Shocktube

Measurements

Molecular Beam (O2)Heated Flow Titration (N2)

New Codes• New subphysics

models

• New developers

• New QoIpostprocessing

• New numerics

• New bugs

Roy H. Stogner Metaprogramming April 16, 2012 3 / 52

Computational Modeling and Verification

PECOS Development

Experimental Data

QUESO

FIN-SlibMeshBoost

Turbulence

SHOCKINGMUTATION

GSL

Chemistry/Shocktube

Plug FlowABLATION1D

GSL

Ablation

Calibration/Validation

FIN-S

Inve

rsio

n

Forw

ard

QUESO/Dakota

Multiphysics Analysis

MASA

QoI

GRVYExternal Libraries

LDVFlow

Measurements

NASA EAST Shocktube

Measurements

Molecular Beam (O2)Heated Flow Titration (N2)

New Codes• New subphysics

models

• New developers

• New QoIpostprocessing

• New numerics

• New bugs

Roy H. Stogner Metaprogramming April 16, 2012 3 / 52

Computational Modeling and Verification

PECOS Development

Experimental Data

QUESO

FIN-SlibMeshBoost

Turbulence

SHOCKINGMUTATION

GSL

Chemistry/Shocktube

Plug FlowABLATION1D

GSL

Ablation

Calibration/Validation

FIN-S

Inve

rsio

n

Forw

ard

QUESO/Dakota

Multiphysics Analysis

MASA

QoI

GRVYExternal Libraries

LDVFlow

Measurements

NASA EAST Shocktube

Measurements

Molecular Beam (O2)Heated Flow Titration (N2)

New Codes• New subphysics

models

• New developers

• New QoIpostprocessing

• New numerics

• New bugs

Roy H. Stogner Metaprogramming April 16, 2012 3 / 52

Computational Modeling and Verification

Method of Manufactured Solutions

Verification Process• “Manufacture” a closed form exact solution u, e.g. parameterized trig

functions:(Roy, 2002)

u(x, y, z, t) = u0 + ux fs

(auxπxL

)+ uy fs

(auyπyL

)+

+ uz fs

(auzπzL

)+ ut fs

(autπt

L

)• Insert u into model equation system F , evaluate source terms

• Use simulation code to solve modified physics F (u) ≡ F (u)− F (u)• Verify that solution uh → u at expected rate

Roy H. Stogner Metaprogramming April 16, 2012 4 / 52

Computational Modeling and Verification

Maple MMS: 3D Navier-Stokes Energy Term

Qe =−apxπpx

L

γ

γ − 1sin

�apxπx

L

� �u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��+

+apyπpy

L

γ

γ − 1cos

�apyπy

L

� �v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

��+

−apzπpz

L

γ

γ − 1sin

�apzπz

L

� �w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

��+

+aρxπρx2L

cos�aρxπx

L

� �u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

����u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��2+

+�w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

��2+

�v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

��2�

+

−aρyπρy2L

sin�aρyπy

L

� �v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

����u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��2+

+�w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

��2+

�v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

��2�

+

+aρzπρz2L

cos�aρzπz

L

� �w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

����u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��2+

+�w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

��2+�v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

��2�

+

+auxπux

2Lcos

�auxπx

L

����w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

��2+

�v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

��2+

+3�u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��2��

ρ0 + ρx sin�aρxπx

L

�+ ρy cos

�aρyπy

L

�+ ρz sin

�aρzπz

L

��+

+�p0 + px cos

�apxπx

L

�+ py sin

�apyπy

L

�+ pz cos

�apzπz

L

�� 2γ

(γ − 1)

+

−auyπuy

Lsin

�auyπy

L

� �v0 + vx cos

�avxπx

L

�+ vy sin

�avyπy

L

�+ vz sin

�avzπz

L

�� �ρ0 + ρx sin

�aρxπx

L

�+ ρy cos

�aρyπy

L

�+ ρz sin

�aρzπz

L

��·

·�u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��+

−auzπuz

Lsin

�auzπz

L

� �w0 + wx sin

�awxπx

L

�+ wy sin

�awyπy

L

�+ wz cos

�awzπz

L

�� �ρ0 + ρx sin

�aρxπx

L

�+ ρy cos

�aρyπy

L

�+ ρz sin

�aρzπz

L

��·

·�u0 + ux sin

�auxπx

L

�+ uy cos

�auyπy

L

�+ uz cos

�auzπz

L

��+

Roy H. Stogner Metaprogramming April 16, 2012 5 / 52

Computational Modeling and Verification

And more 3D Navier-Stokes Energy Term

Roy H. Stogner Metaprogramming April 16, 2012 6 / 52

Computational Modeling and Verification

Combinatorial Explosion

Explosion in source term size• Exponential complexity increase with more sophisticated models

I Basic Sutherland viscosity starts at a million characters

• Large CAS RAM requirements (128 GB insufficient for Sutherland)

• segfaults, incorrect output

Hierarchic MMS?• Manual simplification of sub-terms, one-by-one

• Recombination into final forcing function

• Still labor-intensive

Automatic Differentiation?• Adding complex dependencies to MASA?

Roy H. Stogner Metaprogramming April 16, 2012 7 / 52

Computational Modeling and Verification

Combinatorial Explosion

Explosion in source term size• Exponential complexity increase with more sophisticated models

I Basic Sutherland viscosity starts at a million characters

• Large CAS RAM requirements (128 GB insufficient for Sutherland)

• segfaults, incorrect output

Hierarchic MMS?• Manual simplification of sub-terms, one-by-one

• Recombination into final forcing function

• Still labor-intensive

Automatic Differentiation?• Adding complex dependencies to MASA?

Roy H. Stogner Metaprogramming April 16, 2012 7 / 52

Computational Modeling and Verification

Combinatorial Explosion

Explosion in source term size• Exponential complexity increase with more sophisticated models

I Basic Sutherland viscosity starts at a million characters

• Large CAS RAM requirements (128 GB insufficient for Sutherland)

• segfaults, incorrect output

Hierarchic MMS?• Manual simplification of sub-terms, one-by-one

• Recombination into final forcing function

• Still labor-intensive

Automatic Differentiation?• Adding complex dependencies to MASA?

Roy H. Stogner Metaprogramming April 16, 2012 7 / 52

Computational Modeling and Verification Generic Programming

Generic Programming

• Or more informally, “Duck Typing”: templating around unspecifieddata types that expected to be overloaded to act like mathematicalobjects, creating new code and new data types at compile time.

• We do this all the time for float/double/long double.

• So we can duct tape our templated typename to any class thatbehaves like we expect math to behave

Roy H. Stogner Metaprogramming April 16, 2012 8 / 52

Computational Modeling and Verification Generic Programming

Duck Typing

If it walks like a duck, quacks likea duck, looks like a duck, it mustbe a duck.

Unless it’s a dragon doing a duckimpression...

We ran into a couple of those.

Roy H. Stogner Metaprogramming April 16, 2012 9 / 52

Computational Modeling and Verification Generic Programming

Duck Typing

If it walks like a duck, quacks likea duck, looks like a duck, it mustbe a duck.

Unless it’s a dragon doing a duckimpression...

We ran into a couple of those.

Roy H. Stogner Metaprogramming April 16, 2012 9 / 52

Computational Modeling and Verification Generic Programming

Duck Typing

If it walks like a duck, quacks likea duck, looks like a duck, it mustbe a duck.

Unless it’s a dragon doing a duckimpression...

We ran into a couple of those.

Roy H. Stogner Metaprogramming April 16, 2012 9 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Multi-precision

Example

template <typename T, typename S>

struct ShadowNumber {.........T _val;

S _shadow;

};

• Simultaneous calculation with multiple floating point representations,to estimate rounding error:

ExampleShadowNumber<float, double> shadowed_float;

ShadowNumber<double, long double> shadowed_double;

Roy H. Stogner Metaprogramming April 16, 2012 10 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

template <unsigned int size, typename T>

struct NumberArray {.........

template <typename T2>

NumberArray<size,T>& operator+= (const NumberArray<size,T2>& a) {

for (unsigned int i = 0; i != size; ++i)

_data[i] += a[i]; return *this;

}.........T _data[size];

};

• Compile-time fixed array sizes - no heap memory

• Fixed length loops can unroll with no branching

• Mixed data subtypes

Roy H. Stogner Metaprogramming April 16, 2012 11 / 52

Computational Modeling and Verification Example Data Types

Overloaded Functions, Operators

Example

#define NumberArray_std_unary(funcname) \

template <unsigned int size, typename T> \

inline \

NumberArray<size, T> \

funcname (const NumberArray<size, T>& a) \

{ \

NumberArray<size, T> returnval; \

\

for (unsigned int i = 0; i != size; ++i) \

returnval[i] = funcname(a[i]); \

\

return returnval; \

}

NumberArray_std_unary(exp)

NumberArray_std_unary(sin)

NumberArray_std_unary(cos)

• Templates shouldreplace writing NTNf

repetitive codes usingunsafe macros

• Templated function andstruct names can’t betemplate arguments.

• We still need macros toavoid Nf repetitivetemplate functions.

• This gives usmultidimensional nth

derivatives in 300 linesof C++

Roy H. Stogner Metaprogramming April 16, 2012 12 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f);

// Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v);

// Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f);

// Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Example Data Types

Operator-Overloaded Vectors

Example

NumericArray<3,double> v;

v[1] = 2;

NumericArray<3,float> f;

f[2] = 1;

v += sin(f); // Great!

f += sin(v); // Tolerable!

v = v + sin(f); // Undefined?

What is the return type supposed to be for

template <unsigned int size, typename T1, typename T2>

operator+(const NumberArray<size,T1>& a,

const NumberArray<size,T2>& b)

std:: problem too - complex<float> + double won’t compile

Roy H. Stogner Metaprogramming April 16, 2012 13 / 52

Computational Modeling and Verification Computing new Data Types

Return Type Selection, Template Specialization

Let’s give it a template:

template <typename S, typename T>

struct CompareTypes {

// typedef something supertype;

};

And then we can specialize

Exampletemplate <>

struct CompareTypes<float,double> {

typedef double

supertype;

};

Roy H. Stogner Metaprogramming April 16, 2012 14 / 52

Computational Modeling and Verification Computing new Data Types

Return Type Selection, Template Specialization

Let’s give it a template:

template <typename S, typename T>

struct CompareTypes {

// typedef something supertype;

};

Or, for templated classes, partially specialize

Exampletemplate <unsigned int size, typename T, typename T2>

struct CompareTypes<NumberArray<size,T>,T2> {

typedef NumberArray<size,typename CompareTypes<T,T2>::supertype>

supertype;

};

Roy H. Stogner Metaprogramming April 16, 2012 14 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Here Be Dragons

A NumberArray of something, combined with anything else we haven’tseen before

Example

template <unsigned int size, typename T, typename T2>

struct CompareTypes<NumberArray<size,T>,T2> {

typedef NumberArray<size,

typename CompareTypes<T,T2>::supertype>

supertype;

};

if(typeid(CompareTypes<

NumberArray<3,float>,double

>::supertype) ==

typeid(NumberArray<3,double>))

how_much_we_rock = 10;

Roy H. Stogner Metaprogramming April 16, 2012 15 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Here Be Dragons

A NumberArray of something, combined with anything else we haven’tseen before

Example

template <unsigned int size, typename T, typename T2>

struct CompareTypes<NumberArray<size,T>,T2> {

typedef NumberArray<size,

typename CompareTypes<T,T2>::supertype>

supertype;

};

if(typeid(CompareTypes<

NumberArray<3,NumberArray<float> >,double

>::supertype) ==

typeid(NumberArray<3,NumberArray<double> >))

how_much_we_rock = 11; // That extra push over the cliff

Roy H. Stogner Metaprogramming April 16, 2012 15 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Here Be Dragons

A ShadowNumber of something, combined with anything else we haven’tseen before

Example

template <typename T, typename S, typename T2>

struct CompareTypes<ShadowNumber<T,S>,T2> {

typedef ShadowNumber<typename CompareTypes<T,T2>::supertype,

typename CompareTypes<S,T2>::supertype>

supertype;

};

if(typeid(CompareTypes<

ShadowNumber<float,double>,double

>::supertype) ==

typeid(ShadowNumber<double,double>))

how_much_we_rock = 7; // C is still a passing grade

Roy H. Stogner Metaprogramming April 16, 2012 15 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Here Be Dragons

A ShadowNumber of something, combined with a NumberArray

Example

template <typename T, typename S, typename T2>

struct CompareTypes<ShadowNumber<T,S>,T2> {

typedef ShadowNumber<typename CompareTypes<T,T2>::supertype,

typename CompareTypes<S,T2>::supertype>

supertype;

};

if(typeid(CompareTypes<

NumberArray<3,float>,ShadowNumber<float,double>

>::supertype) ==

typeid(NumberArray<3,ShadowNumber<float,double> >))

how_much_we_rock = -1; // This didn’t even compile

Roy H. Stogner Metaprogramming April 16, 2012 15 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Here Be Dragons

A ShadowNumber of something, combined with a NumberArray

Example

template <typename T, typename S, typename T2>

struct CompareTypes<ShadowNumber<T,S>,T2> {

typedef ShadowNumber<typename CompareTypes<T,T2>::supertype,

typename CompareTypes<S,T2>::supertype>

supertype;

};

if(typeid(CompareTypes<

NumberArray<3,float>,ShadowNumber<float,double>

>::supertype) ==

typeid(ShadowNumber<NumberArray<3,float>,NumberArray<3,double> >))

how_much_we_rock = -1; // This didn’t even compile

Roy H. Stogner Metaprogramming April 16, 2012 15 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Killing Dragons• Mathematically, these are isomorphic:

I (V ⊗W )n

I V n ⊗Wn

• Your compiler doesn’t understandisomorphisms:

I {float, double}[size]I {float[size]}, {double[size]}

• Need partial template specialization,SFINAE to disambiguate

Example

template <unsigned int size, typename T, typename T2, typename S2>

struct CompareTypes<NumberArray<size,T>,ShadowNumber<T2,S2> > {

typedef NumberArray<size,

typename CompareTypes<T,ShadowNumber<T2,S2> >::supertype>

supertype;

};

Roy H. Stogner Metaprogramming April 16, 2012 16 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Killing Dragons• Mathematically, these are isomorphic:

I (V ⊗W )n

I V n ⊗Wn

• Your compiler doesn’t understandisomorphisms:

I {float, double}[size]I {float[size]}, {double[size]}

• Need partial template specialization,SFINAE to disambiguate

Example

template <unsigned int size, typename T, typename T2, typename S2>

struct CompareTypes<NumberArray<size,T>,ShadowNumber<T2,S2> > {

typedef NumberArray<size,

typename CompareTypes<T,ShadowNumber<T2,S2> >::supertype>

supertype;

};

Roy H. Stogner Metaprogramming April 16, 2012 16 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Killing Dragons• Mathematically, these are isomorphic:

I (V ⊗W )n

I V n ⊗Wn

• Your compiler doesn’t understandisomorphisms:

I {float, double}[size]I {float[size]}, {double[size]}

• Need partial template specialization,SFINAE to disambiguate

Example

template <unsigned int size, typename T, typename T2, typename S2>

struct CompareTypes<NumberArray<size,T>,ShadowNumber<T2,S2> > {

typedef NumberArray<size,

typename CompareTypes<T,ShadowNumber<T2,S2> >::supertype>

supertype;

};

Roy H. Stogner Metaprogramming April 16, 2012 16 / 52

Computational Modeling and Verification Computing new Data Types

Return Types: Killing Dragons• Mathematically, these are isomorphic:

I (V ⊗W )n

I V n ⊗Wn

• Your compiler doesn’t understandisomorphisms:

I {float, double}[size]I {float[size]}, {double[size]}

• Need partial template specialization,SFINAE to disambiguate

Example

template <unsigned int size, typename T, typename T2, typename S2>

struct CompareTypes<NumberArray<size,T>,ShadowNumber<T2,S2> > {

typedef NumberArray<size,

typename CompareTypes<T,ShadowNumber<T2,S2> >::supertype>

supertype;

};

Roy H. Stogner Metaprogramming April 16, 2012 16 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡ − 1

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡ − 1 ...no, wait, that’s C

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡ 0D[R] ≡ {a+ bε : a, b ∈ R}

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡ 0D[R] ≡ {a+ bε : a, b ∈ R}

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡ 0D[R] ≡ {a+ bε : a, b ∈ R}

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

“Dual Numbers” - [Clifford 1873],[Study 1903]

• Add a new element ε to R, close the field:{m∑i=0

aiεi : ai ∈ R,m <∞

}

• Take the quotient with ε2 ≡ 0D[R] ≡ {a+ bε : a, b ∈ R}

• (a+ bε)× (c+ dε) = (ac) + adε+ bcε+ bdε2 = ((ac) + (ad+ bc)ε)

• Extending to division, algebraic functions, transcendental functions,etc gives: for any function f(x),

f(a+ bε) = f(a) + bf ′(a)ε

• This time the isomorphism practically codes itself!

Roy H. Stogner Metaprogramming April 16, 2012 17 / 52

Computational Modeling and Verification Automatic Differentiation

Operator-Overloaded Forward Differentiation

Example

typedef double RawType

// typedef ShadowNumber<double, long double> RawType;

typedef DualNumber<RawType,RawType> FirstDerivType;

const FirstDerivType x(pi/6,1); // Initializing independent var

const FirstDerivType sinx = sin(x); // Caching just like normal

const FirstDerivType y = sinx*sinx; // Smart pow would work too

const double raw_y = raw_value(y); // No implicit down-conversions

double deriv = raw_value(y.derivatives());

assert(deriv == 2*sin(pi/6)*cos(pi/6)); // FP ops match hand-code

Roy H. Stogner Metaprogramming April 16, 2012 18 / 52

Computational Modeling and Verification Automatic Differentiation

Operator-Overloaded Forward Differentiation

Example

typedef double RawType

// typedef ShadowNumber<double, long double> RawType;

typedef DualNumber<RawType,RawType> FirstDerivType;

const FirstDerivType x(pi/6,1); // Initializing independent var

const FirstDerivType sinx = sin(x); // Caching just like normal

const FirstDerivType y = sinx*sinx; // Smart pow would work too

const double raw_y = raw_value(y); // No implicit down-conversions

double deriv = raw_value(y.derivatives());

assert(deriv == 2*sin(pi/6)*cos(pi/6)); // FP ops match hand-code

Roy H. Stogner Metaprogramming April 16, 2012 18 / 52

Computational Modeling and Verification Automatic Differentiation

Operator-Overloaded Forward Differentiation

Example

typedef double RawType

// typedef ShadowNumber<double, long double> RawType;

typedef DualNumber<RawType,RawType> FirstDerivType;

const FirstDerivType x(pi/6,1); // Initializing independent var

const FirstDerivType sinx = sin(x); // Caching just like normal

const FirstDerivType y = sinx*sinx; // Smart pow would work too

const double raw_y = raw_value(y); // No implicit down-conversions

double deriv = raw_value(y.derivatives());

assert(deriv == 2*sin(pi/6)*cos(pi/6)); // FP ops match hand-code

Roy H. Stogner Metaprogramming April 16, 2012 18 / 52

Computational Modeling and Verification Automatic Differentiation

Operator-Overloaded Forward Differentiation

Example

typedef double RawType

// typedef ShadowNumber<double, long double> RawType;

typedef DualNumber<RawType,RawType> FirstDerivType;

const FirstDerivType x(pi/6,1); // Initializing independent var

const FirstDerivType sinx = sin(x); // Caching just like normal

const FirstDerivType y = sinx*sinx; // Smart pow would work too

const double raw_y = raw_value(y); // No implicit down-conversions

double deriv = raw_value(y.derivatives());

assert(deriv == 2*sin(pi/6)*cos(pi/6)); // FP ops match hand-code

Roy H. Stogner Metaprogramming April 16, 2012 18 / 52

Computational Modeling and Verification Automatic Differentiation

Operator-Overloaded Forward Differentiation

Example

typedef double RawType

// typedef ShadowNumber<double, long double> RawType;

typedef DualNumber<RawType,RawType> FirstDerivType;

const FirstDerivType x(pi/6,1); // Initializing independent var

const FirstDerivType sinx = sin(x); // Caching just like normal

const FirstDerivType y = sinx*sinx; // Smart pow would work too

const double raw_y = raw_value(y); // No implicit down-conversions

double deriv = raw_value(y.derivatives());

assert(deriv == 2*sin(pi/6)*cos(pi/6)); // FP ops match hand-code

Roy H. Stogner Metaprogramming April 16, 2012 18 / 52

Computational Modeling and Verification Automatic Differentiation

“Hyper-dual Numbers” - [Fike 2009]

• Add two new elements ε1, ε2 to R• Take the quotient with ε21 ≡ ε22 ≡ 0

H[R] ≡ {a+ bε1 + cε2 + dε1ε2 : a, b, c, d ∈ R}

• (a+ bε1 + cε2 + dε1ε2)× (e+ fε1 + gε2 + hε1ε2) =(ae) + (af + be)ε1 + (ag + ce)ε2 + (ah+ de+ bg + cf)ε1ε2

• Extending gives: for any function f(x),f(a+bε1+bε2+cε1ε2) = f(a)+bf ′(a)(ε1+ε2)+(b2f ′′(a)+cf ′(a))ε1ε2

• adding εiεj = 0 to quotient would give vector gradients instead...

Roy H. Stogner Metaprogramming April 16, 2012 19 / 52

Computational Modeling and Verification Automatic Differentiation

Hyper-dual Numbers via Recursive Mathematics

• RecallI D[X] ≡ {a+ bε : a, b ∈ X}I f(a+ bε) = f(a) + bf ′(a)ε

• Applied directly to R we get first derivatives• Applied recursively:

I D[D[R]] ≡ {a+ cε2 : a, c ∈ D[R]}I D[D[R]] ≡ {(a+ bε1) + (c+ dε1)ε2 : a, b, c, d ∈ R}I f((a+ bε1) + (c+ dε1)ε2) = f(a+ bε1) + (c+ dε1)f

′(a+ bε1)ε2I = f(a) + bf ′(a)ε1 + (c+ dε1)(f

′(a) + bf ′′(a)ε1)ε2I = f(a) + bf ′(a)ε1 + cf ′(a)ε2 + (cbf ′′(a) + df ′(a))ε1ε2

• In other words, D[D[R]] ≡ H[R]• This isomorphism works in software, too!

Roy H. Stogner Metaprogramming April 16, 2012 20 / 52

Computational Modeling and Verification Automatic Differentiation

Hessian Differentiation via Recursive Templates

Example

typedef DualNumber<RawType,NumberArray<3,RawType> > FAD1;

typedef DualNumber<FAD1,NumberArray<3,FAD1> > FAD2;

NumberArray<3, FAD2> xyz;

xyz[0] =

FAD2(x,NumberArrayUnitVector<3,0,RawType>::value());

xyz[1] =

FAD2(y,NumberArrayUnitVector<3,1,RawType>::value());

xyz[2] =

FAD2(z,NumberArrayUnitVector<3,2,RawType>::value());

const FAD2 u = some_function(xyz);

RawType laplacian_u = 0;

for (unsigned int i=0; i != 3; ++i)

laplacian_u += u.derivatives()[i].derivatives()[i];

Roy H. Stogner Metaprogramming April 16, 2012 21 / 52

Computational Modeling and Verification Automatic Differentiation

Hessian Differentiation via Recursive Templates

Example

typedef DualNumber<RawType,NumberArray<3,RawType> > FAD1;

typedef DualNumber<FAD1,NumberArray<3,FAD1> > FAD2;

NumberArray<3, FAD2> xyz;

xyz[0] =

FAD2(x,NumberArrayUnitVector<3,0,RawType>::value());

xyz[1] =

FAD2(y,NumberArrayUnitVector<3,1,RawType>::value());

xyz[2] =

FAD2(z,NumberArrayUnitVector<3,2,RawType>::value());

const FAD2 u = some_function(xyz);

RawType laplacian_u = 0;

for (unsigned int i=0; i != 3; ++i)

laplacian_u += u.derivatives()[i].derivatives()[i];

Roy H. Stogner Metaprogramming April 16, 2012 21 / 52

Computational Modeling and Verification Automatic Differentiation

Hessian Differentiation via Recursive Templates

Example

typedef DualNumber<RawType,NumberArray<3,RawType> > FAD1;

typedef DualNumber<FAD1,NumberArray<3,FAD1> > FAD2;

NumberArray<3, FAD2> xyz;

xyz[0] =

FAD2(x,NumberArrayUnitVector<3,0,RawType>::value());

xyz[1] =

FAD2(y,NumberArrayUnitVector<3,1,RawType>::value());

xyz[2] =

FAD2(z,NumberArrayUnitVector<3,2,RawType>::value());

const FAD2 u = some_function(xyz);

RawType laplacian_u = 0;

for (unsigned int i=0; i != 3; ++i)

laplacian_u += u.derivatives()[i].derivatives()[i];

Roy H. Stogner Metaprogramming April 16, 2012 21 / 52

Computational Modeling and Verification Automatic Differentiation

MASA PDE Examples

Manufactured Solution

// Arbitrary manufactured solution

U.template get<0>() = u_0 + u_x * sin(a_ux * PI * x / L) +

u_y * cos(a_uy * PI * y / L);

// Why not U[0] and U[1]? Explanation to come...

U.template get<1>() = v_0 + v_x * cos(a_vx * PI * x / L) +

v_y * sin(a_vy * PI * y / L);

ADScalar RHO = rho_0 + rho_x * sin(a_rhox * PI * x / L) +

rho_y * cos(a_rhoy * PI * y / L);

ADScalar P = p_0 + p_x * cos(a_px * PI * x / L) +

p_y * sin(a_py * PI * y / L);

// Constitutive laws

Tensor GradU = gradient(U);

Tensor Tau = mu * (GradU + transpose(GradU) -

2./3. * divergence(U) * RawArray::identity());

FullArray q = -k * T.derivatives();

Roy H. Stogner Metaprogramming April 16, 2012 22 / 52

Computational Modeling and Verification Automatic Differentiation

MASA PDE Examples

Euler

// Gas state

ADScalar T = P / RHO / R;

ADScalar E = 1. / (Gamma-1.) * P / RHO;

ADScalar ET = E + .5 * U.dot(U);

// Constitutive laws

Tensor GradU = gradient(U);

Tensor Tau = mu * (GradU + transpose(GradU) -

2./3. * divergence(U) * RawArray::identity());

FullArray q = -k * T.derivatives();

// Conservation equation residuals

Scalar Q_rho = raw_value(divergence(RHO*U));

RawArray Q_rho_u = raw_value(divergence(RHO*U.outerproduct(U)) +

P.derivatives());

Scalar Q_rho_e = raw_value(divergence((RHO*ET+P)*U));

Roy H. Stogner Metaprogramming April 16, 2012 22 / 52

Computational Modeling and Verification Automatic Differentiation

MASA PDE Examples

Navier-Stokes

// Gas state

ADScalar T = P / RHO / R;

ADScalar E = 1. / (Gamma-1.) * P / RHO;

ADScalar ET = E + .5 * U.dot(U);

// Constitutive laws

Tensor GradU = gradient(U);

Tensor Tau = mu * (GradU + transpose(GradU) -

2./3. * divergence(U) * RawArray::identity());

FullArray q = -k * T.derivatives();

// Conservation equation residuals

Scalar Q_rho = raw_value(divergence(RHO*U));

RawArray Q_rho_u = raw_value(divergence(RHO*U.outerproduct(U) - Tau) +

P.derivatives());

Scalar Q_rho_e = raw_value(divergence((RHO*ET+P)*U + q - Tau.dot(U)));

Roy H. Stogner Metaprogramming April 16, 2012 22 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Automatic upconversion is dangerous!

Example

double problem(FirstDerivType x, SecondDerivType y) {

// This is desirable:

x *= 2.0;

// But now the compiler doesn’t see a problem with this!

return (x+y).derivatives().derivatives();

}

• Code with 2nd and higher derivatives still requires care

• For safe code: automatic upconversion only for built-in types,automatic downconversion for DualNumber, even to “HypodualNumber”

Roy H. Stogner Metaprogramming April 16, 2012 23 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Automatic upconversion is dangerous!

Example

double problem(FirstDerivType x, SecondDerivType y) {

// This is desirable:

x *= 2.0;

// But now the compiler doesn’t see a problem with this!

return (x+y).derivatives().derivatives();

}

• Code with 2nd and higher derivatives still requires care

• For safe code: automatic upconversion only for built-in types,automatic downconversion for DualNumber, even to “HypodualNumber”

Roy H. Stogner Metaprogramming April 16, 2012 23 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Automatic upconversion is dangerous!

Example

double problem(FirstDerivType x, SecondDerivType y) {

// This is desirable:

x *= 2.0;

// But now the compiler doesn’t see a problem with this!

return (x+y).derivatives().derivatives();

}

• Code with 2nd and higher derivatives still requires care

• For safe code: automatic upconversion only for built-in types,automatic downconversion for DualNumber, even to “HypodualNumber”

Roy H. Stogner Metaprogramming April 16, 2012 23 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Automatic upconversion is dangerous!

Example

double problem(FirstDerivType x, SecondDerivType y) {

// This is desirable:

x *= 2.0;

// But now the compiler doesn’t see a problem with this!

return (x+y).derivatives().derivatives();

}

• Code with 2nd and higher derivatives still requires care

• For safe code: automatic upconversion only for built-in types,automatic downconversion for DualNumber, even to “HypodualNumber”

Roy H. Stogner Metaprogramming April 16, 2012 23 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Automatic upconversion is dangerous!

Example

double problem(FirstDerivType x, SecondDerivType y) {

// This is desirable:

x *= 2.0;

// But now the compiler doesn’t see a problem with this!

return (x+y).derivatives().derivatives();

}

• Code with 2nd and higher derivatives still requires care

• For safe code: automatic upconversion only for built-in types,automatic downconversion for DualNumber, even to “HypodualNumber”

Roy H. Stogner Metaprogramming April 16, 2012 23 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!

I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:

I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)

I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:

I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:

I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:

I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:

I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:I Sparse vector data types

I Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizations

I Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Computational Modeling and Verification Automatic Differentiation

Lessons Learned

• Hyperduals are inefficient!I (1 +m)n data for n derivatives in m dimensions (e.g. (1 + 3)2 = 16)I Should require less than (e.g. 10)

n∑i=0

(m+ i− 1)!

(m− 1)!i!

• For efficient higher derivatives: partial specialization of recursiveDualNumber

• For efficient higher dimensions:I Sparse vector data typesI Functional metaprogramming for efficient compile-time optimizationsI Functional-to-imperative APIs for run-time operations

Roy H. Stogner Metaprogramming April 16, 2012 24 / 52

Numeric Functional Metaprogramming Functional Data Structures

Data Structures with Templates: Type ContainerExample

template <typename HeadType,

typename TailContainer=NullContainer,

typename Comparison=ValueLessThan>

struct Container

{

typedef HeadType head_type; // car and cdr would scare

typedef TailContainer tail_set; // off the Fortran folks

typedef Comparison comparison;

// These may be empty types or may have data

HeadType head;

TailContainer tail;.........};

struct NullContainer

{.........};

Roy H. Stogner Metaprogramming April 16, 2012 25 / 52

Numeric Functional Metaprogramming Functional Data Structures

Data Structures with Templates: Type Container

Example

Container<IntType<1> > no_data_one_static_int;

Container<IntType<1>,

Container<IntType<4> > no_data_two_static_ints;

Container<IntType<1,float>,

Container<IntType<4,float> > float_data_two_static_ints;

Container<IntType<1,double>,

Container<IntType<4>,NumberArray<3,double> > heterogenous_data;

Roy H. Stogner Metaprogramming April 16, 2012 26 / 52

Numeric Functional Metaprogramming Functional Data Structures

Data Structures with Templates: Type Container

Example

Container<IntType<1> > no_data_one_static_int;

Container<IntType<1>,

Container<IntType<4> > no_data_two_static_ints;

Container<IntType<1,float>,

Container<IntType<4,float> > float_data_two_static_ints;

Container<IntType<1,double>,

Container<IntType<4>,NumberArray<3,double> > heterogenous_data;

Roy H. Stogner Metaprogramming April 16, 2012 26 / 52

Numeric Functional Metaprogramming Functional Data Structures

Data Structures with Templates: Type Container

Example

Container<IntType<1> > no_data_one_static_int;

Container<IntType<1>,

Container<IntType<4> > no_data_two_static_ints;

Container<IntType<1,float>,

Container<IntType<4,float> > float_data_two_static_ints;

Container<IntType<1,double>,

Container<IntType<4>,NumberArray<3,double> > heterogenous_data;

Roy H. Stogner Metaprogramming April 16, 2012 26 / 52

Numeric Functional Metaprogramming Functional Data Structures

Data Structures with Templates: Type Container

Example

Container<IntType<1> > no_data_one_static_int;

Container<IntType<1>,

Container<IntType<4> > no_data_two_static_ints;

Container<IntType<1,float>,

Container<IntType<4,float> > float_data_two_static_ints;

Container<IntType<1,double>,

Container<IntType<4>,NumberArray<3,double> > heterogenous_data;

Roy H. Stogner Metaprogramming April 16, 2012 26 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting into a NullContainer is easy:

• If we’re inserting null, we’re still left with a NullContainer

• If not, we have a one-element container with the inserted element.

Examplestruct NullContainer

{.........template <typename ValueType, typename NewComparison>

struct Insert

{

typedef

typename IfElse<

(TypesEqual<ValueType,NullContainer>::value),

NullContainer,

Container<ValueType, NullContainer, NewComparison>

>::type type;

};.........};

C++ template syntax: karmic retribution for engineering majors whomocked CS majors’ Lisp syntax?

Roy H. Stogner Metaprogramming April 16, 2012 27 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting into a NullContainer is easy:

• If we’re inserting null, we’re still left with a NullContainer

• If not, we have a one-element container with the inserted element.

Examplestruct NullContainer

{.........template <typename ValueType, typename NewComparison>

struct Insert

{

typedef

typename IfElse<

(TypesEqual<ValueType,NullContainer>::value),

NullContainer,

Container<ValueType, NullContainer, NewComparison>

>::type type;

};.........};

C++ template syntax: karmic retribution for engineering majors whomocked CS majors’ Lisp syntax?

Roy H. Stogner Metaprogramming April 16, 2012 27 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting into a NullContainer is easy:

• If we’re inserting null, we’re still left with a NullContainer

• If not, we have a one-element container with the inserted element.

Examplestruct NullContainer

{.........template <typename ValueType, typename NewComparison>

struct Insert

{

typedef

typename IfElse<

(TypesEqual<ValueType,NullContainer>::value),

NullContainer,

Container<ValueType, NullContainer, NewComparison>

>::type type;

};.........};

C++ template syntax: karmic retribution for engineering majors whomocked CS majors’ Lisp syntax?

Roy H. Stogner Metaprogramming April 16, 2012 27 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting into a NullContainer is easy:

• If we’re inserting null, we’re still left with a NullContainer

• If not, we have a one-element container with the inserted element.

Examplestruct NullContainer

{.........template <typename ValueType, typename NewComparison>

struct Insert

{

typedef

typename IfElse<

(TypesEqual<ValueType,NullContainer>::value),

NullContainer,

Container<ValueType, NullContainer, NewComparison>

>::type type;

};.........};

C++ template syntax: karmic retribution for engineering majors whomocked CS majors’ Lisp syntax?

Roy H. Stogner Metaprogramming April 16, 2012 27 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting into a NullContainer is easy:

• If we’re inserting null, we’re still left with a NullContainer

• If not, we have a one-element container with the inserted element.

Examplestruct NullContainer

{.........template <typename ValueType, typename NewComparison>

struct Insert

{

typedef

typename IfElse<

(TypesEqual<ValueType,NullContainer>::value),

NullContainer,

Container<ValueType, NullContainer, NewComparison>

>::type type;

};.........};

C++ template syntax: karmic retribution for engineering majors whomocked CS majors’ Lisp syntax?

Roy H. Stogner Metaprogramming April 16, 2012 27 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting in nonempty sorted sets is trickier:

• If we’re inserting null, we return our same set

• If we’re inserting a type smaller than our set head, then it becomesthe new head and our set becomes the new tail

• If we’re inserting a type larger than our set head, then the head staysunchanged and we insert into the tail

• If we’re inserting something equivalent to our set head, then the headmay get “upgraded”

• Templating around a comparison type to define “smaller”, “larger” and“equivalent” can give us set-like, multiset-like, or vector-like behavior

Roy H. Stogner Metaprogramming April 16, 2012 28 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting in nonempty sorted sets is trickier:

• If we’re inserting null, we return our same set

• If we’re inserting a type smaller than our set head, then it becomesthe new head and our set becomes the new tail

• If we’re inserting a type larger than our set head, then the head staysunchanged and we insert into the tail

• If we’re inserting something equivalent to our set head, then the headmay get “upgraded”

• Templating around a comparison type to define “smaller”, “larger” and“equivalent” can give us set-like, multiset-like, or vector-like behavior

Roy H. Stogner Metaprogramming April 16, 2012 28 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting in nonempty sorted sets is trickier:

• If we’re inserting null, we return our same set

• If we’re inserting a type smaller than our set head, then it becomesthe new head and our set becomes the new tail

• If we’re inserting a type larger than our set head, then the head staysunchanged and we insert into the tail

• If we’re inserting something equivalent to our set head, then the headmay get “upgraded”

• Templating around a comparison type to define “smaller”, “larger” and“equivalent” can give us set-like, multiset-like, or vector-like behavior

Roy H. Stogner Metaprogramming April 16, 2012 28 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting in nonempty sorted sets is trickier:

• If we’re inserting null, we return our same set

• If we’re inserting a type smaller than our set head, then it becomesthe new head and our set becomes the new tail

• If we’re inserting a type larger than our set head, then the head staysunchanged and we insert into the tail

• If we’re inserting something equivalent to our set head, then the headmay get “upgraded”

• Templating around a comparison type to define “smaller”, “larger” and“equivalent” can give us set-like, multiset-like, or vector-like behavior

Roy H. Stogner Metaprogramming April 16, 2012 28 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting in nonempty sorted sets is trickier:

• If we’re inserting null, we return our same set

• If we’re inserting a type smaller than our set head, then it becomesthe new head and our set becomes the new tail

• If we’re inserting a type larger than our set head, then the head staysunchanged and we insert into the tail

• If we’re inserting something equivalent to our set head, then the headmay get “upgraded”

• Templating around a comparison type to define “smaller”, “larger” and“equivalent” can give us set-like, multiset-like, or vector-like behavior

Roy H. Stogner Metaprogramming April 16, 2012 28 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations: Insert

Inserting in nonempty sorted sets is trickier:

• If we’re inserting null, we return our same set

• If we’re inserting a type smaller than our set head, then it becomesthe new head and our set becomes the new tail

• If we’re inserting a type larger than our set head, then the head staysunchanged and we insert into the tail

• If we’re inserting something equivalent to our set head, then the headmay get “upgraded”

• Templating around a comparison type to define “smaller”, “larger” and“equivalent” can give us set-like, multiset-like, or vector-like behavior

Roy H. Stogner Metaprogramming April 16, 2012 28 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations

• Union, Intersection, Difference with an empty container is trivial.

• With non-empty containers, Insert and Contains methods makerecursive definitions easy:

Example

template <typename Set2>

struct Union {

typedef typename

tail_set::Sorted::template Union<

typename Set2::Sorted::template Insert<

head_type

>::type

>::type type;

};

Roy H. Stogner Metaprogramming April 16, 2012 29 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations

• Union, Intersection, Difference with an empty container is trivial.

• With non-empty containers, Insert and Contains methods makerecursive definitions easy:

Example

template <typename Set2>

struct Union {

typedef typename

tail_set::Sorted::template Union<

typename Set2::Sorted::template Insert<

head_type

>::type

>::type type;

};

Roy H. Stogner Metaprogramming April 16, 2012 29 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations

• Union, Intersection, Difference with an empty container is trivial.

• With non-empty containers, Insert and Contains methods makerecursive definitions easy:

Example

template <typename Set2>

struct Union {

typedef typename

tail_set::Sorted::template Union<

typename Set2::Sorted::template Insert<

head_type

>::type

>::type type;

};

Roy H. Stogner Metaprogramming April 16, 2012 29 / 52

Numeric Functional Metaprogramming Functional Data Structures

Set Operations

• Union, Intersection, Difference with an empty container is trivial.

• With non-empty containers, Insert and Contains methods makerecursive definitions easy:

Example

template <typename Set2>

struct Union {

typedef typename

tail_set::Sorted::template Union<

typename Set2::Sorted::template Insert<

head_type

>::type

>::type type;

};

Roy H. Stogner Metaprogramming April 16, 2012 29 / 52

Numeric Functional Metaprogramming Functional Data Structures

Runtime Indexed ForEach

• Applying a standard functor to every set element

• Recursive compile-time metaprogram unrolls into a simple linearrun-time program

• f receives a non-compile-time-const v

Example

struct RuntimeForEach

{

template <typename Functor>

void operator()(const Functor &f) {

// f might want a reference, so we pass in a non-static copy

const typename head_type::value_type v = head_type::value;

f(v);

typename tail_set::RuntimeForEach()(f);

}

};

Roy H. Stogner Metaprogramming April 16, 2012 30 / 52

Numeric Functional Metaprogramming Functional Data Structures

Compile-time Indexed ForEach

• Applying a “template functor” to every set element

• Recursive compile-time metaprogram unrolls into a simple linearrun-time program

• f receives a compile-time-const HeadType

Example

struct ForEach

{

template <typename Functor>

void operator()(const Functor &f) {

f.operator()<HeadType>(v);

typename tail_set::ForEach()(f);

}

};

Roy H. Stogner Metaprogramming April 16, 2012 31 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors• An IndexSet lists sparse indices with potentially non-zero data• e.g. the vector [0 0 1 0 2 0] will have {3, 5} or a superset as index set

• Const-index O (1) access via template arguments

Example

template <typename T, typename IndexSet>

class SparseNumberArray {

public:

typedef IndexSet index_set;

static const unsigned int size = IndexSet::size;.........

T& raw_at(unsigned int i)

{ return _data[i]; }

.........private:

T _data[size];

};

Roy H. Stogner Metaprogramming April 16, 2012 32 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors• An IndexSet lists sparse indices with potentially non-zero data• Variable-index component access via runtime search through indices

• Const-index O (1) access via template arguments

Example

template <typename T, typename IndexSet>

class SparseNumberArray {

public:

typedef IndexSet index_set;

static const unsigned int size = IndexSet::size;.........

T& operator[](index_value_type i)

{ return _data[IndexSet::runtime_index_of(i)]; }

.........private:

T _data[size];

};

Roy H. Stogner Metaprogramming April 16, 2012 32 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors• An IndexSet lists sparse indices with potentially non-zero data• Variable-index component access via runtime search through indices• Const-index O (1) access via template arguments

Example

template <typename T, typename IndexSet>

class SparseNumberArray {

public:

typedef IndexSet index_set;

static const unsigned int size = IndexSet::size;.........template <unsigned int i>

typename entry_type<i>::type& get() {

return _data[IndexSet::template IndexOf<i>::index];

}.........private:

T _data[size];

};

Roy H. Stogner Metaprogramming April 16, 2012 32 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vector OperationsSome operations are easily defined, no index set operations needed:

• Multiplication by a constant: for loop over all data, multiply datum

Other operations require simple set operations:

• Element-wise addition takes a Union of index sets

• Element-wise multiplication takes an Intersection of index sets

• Element-wise division takes the numerator’s index set, but asserts(compile-time!) that the divisor’s is a superset.

Others require repeated set operations:

• Consider a typical binary function, max(a,b) , applied element-wise totwo sparse vectors:

• For each element in the intersection of the index sets, we apply thefunction to the corresponding pair of vector data.

• For each element in each asymmetric difference of the index sets, weapply the function to a pair of the present vector datum and 0.

Roy H. Stogner Metaprogramming April 16, 2012 33 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·]

= [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Vectors

Consider recursion with dual numbers, for automatic differentiation

• x is only non-constant w.r.t. x; y is only non-constant w.r.t. y

• DualNumber x and y are given unit vector gradients

• Their sums, products, etc. then all have optimally sparse gradients.

We now have excellent sparse vectors-of-T!

[0 0 0 0 2 0] + [0 0 1 0 0 0] = [0 0 1 0 2 0]

[· · · · 2 ·] + [· · 1 · · ·] = [· · 1 · 2 ·]

• From 6 FLOPs down to 0

• But not good enough yet

Roy H. Stogner Metaprogramming April 16, 2012 34 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse StructuresConsider recursion with arrays, for matrices, hessians

0 0 0 00 0 2 00 0 0 00 0 0 0

+

0 0 0 00 0 0 00 0 0 01 0 0 0

=

0 0 0 00 0 2 00 0 0 01 0 0 0

· · · ·· · 2 ·· · · ·· · · ·

+

· · · ·· · · ·· · · ·1 · · ·

=

· · · ·0 · 2 ·· · · ·1 · 0 ·

• A SparseNumberArray-of-SparseNumberArray is sparse...• But only with a tensor-product sparsity structure.

I Triangular matrices become full?I Diagonal matrices become full??

Roy H. Stogner Metaprogramming April 16, 2012 35 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse StructuresConsider recursion with arrays, for matrices, hessians

0 0 0 00 0 2 00 0 0 00 0 0 0

+

0 0 0 00 0 0 00 0 0 01 0 0 0

=

0 0 0 00 0 2 00 0 0 01 0 0 0

· · · ·· · 2 ·· · · ·· · · ·

+

· · · ·· · · ·· · · ·1 · · ·

=

· · · ·0 · 2 ·· · · ·1 · 0 ·

• A SparseNumberArray-of-SparseNumberArray is sparse...• But only with a tensor-product sparsity structure.

I Triangular matrices become full?I Diagonal matrices become full??

Roy H. Stogner Metaprogramming April 16, 2012 35 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse StructuresConsider recursion with arrays, for matrices, hessians

0 0 0 00 0 2 00 0 0 00 0 0 0

+

0 0 0 00 0 0 00 0 0 01 0 0 0

=

0 0 0 00 0 2 00 0 0 01 0 0 0

· · · ·· · 2 ·· · · ·· · · ·

+

· · · ·· · · ·· · · ·1 · · ·

=

· · · ·0 · 2 ·· · · ·1 · 0 ·

• A SparseNumberArray-of-SparseNumberArray is sparse...• But only with a tensor-product sparsity structure.

I Triangular matrices become full?I Diagonal matrices become full??

Roy H. Stogner Metaprogramming April 16, 2012 35 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse StructuresConsider recursion with arrays, for matrices, hessians

0 0 0 00 0 2 00 0 0 00 0 0 0

+

0 0 0 00 0 0 00 0 0 01 0 0 0

=

0 0 0 00 0 2 00 0 0 01 0 0 0

· · · ·· · 2 ·· · · ·· · · ·

+

· · · ·· · · ·· · · ·1 · · ·

=

· · · ·0 · 2 ·· · · ·1 · 0 ·

• A SparseNumberArray-of-SparseNumberArray is sparse...• But only with a tensor-product sparsity structure.

I Triangular matrices become full?I Diagonal matrices become full??

Roy H. Stogner Metaprogramming April 16, 2012 35 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse StructuresConsider recursion with arrays, for matrices, hessians

0 0 0 00 0 2 00 0 0 00 0 0 0

+

0 0 0 00 0 0 00 0 0 01 0 0 0

=

0 0 0 00 0 2 00 0 0 01 0 0 0

· · · ·· · 2 ·· · · ·· · · ·

+

· · · ·· · · ·· · · ·1 · · ·

=

· · · ·0 · 2 ·· · · ·1 · 0 ·

• A SparseNumberArray-of-SparseNumberArray is sparse...• But only with a tensor-product sparsity structure.

I Triangular matrices become full?I Diagonal matrices become full??

Roy H. Stogner Metaprogramming April 16, 2012 35 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structures• An IndexSet now stores data, not just static indices

• Index-dependent data type makes variable-index component accessimpossible!

Example

template <typename IndexSet>

class SparseNumberStruct {

public:

typedef IndexSet index_set;

static const unsigned int size = IndexSet::size;

template <unsigned int i>

typename entry_type<i>::type& get() {

return _data.template data<UnsignedIntType<i> >(); }.........private:

IndexSet _data;

};

Roy H. Stogner Metaprogramming April 16, 2012 36 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structures• An IndexSet now stores data, not just static indices• Index-dependent data type makes variable-index component access

impossible!

Example

template <typename IndexSet>

class SparseNumberStruct {

public:

typedef IndexSet index_set;

static const unsigned int size = IndexSet::size;

template <unsigned int i>

typename entry_type<i>::type& get() {

return _data.template data<UnsignedIntType<i> >(); }.........private:

IndexSet _data;

};

Roy H. Stogner Metaprogramming April 16, 2012 36 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structure Operations

No operations are easily defined.

• C for loops don’t work over heterogenous structures.

• Templated functors must be defined for every operation.

Multiplication by a constant, using a functor and subfunctor:

Exampletemplate <typename T2, typename IndexSet>

inline

typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype

operator * (const SparseNumberStruct<IndexSet>& a, const T2& b)

{

typedef typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype type;

typename CompareTypes<SparseNumberStruct<IndexSet>,T2>::supertype

returnval;

typename IndexSet::ForEach()

(BinaryFunctor<MultipliesSubfunctor, IndexSet, ConstantDataSet<T2>, typename type::index_set>

(MultipliesSubfunctor(), a.raw_data(), ConstantDataSet<T2>(b), returnval.raw_data()));

return returnval;

}

Roy H. Stogner Metaprogramming April 16, 2012 37 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structure Operations

No operations are easily defined.

• C for loops don’t work over heterogenous structures.

• Templated functors must be defined for every operation.

Multiplication by a constant, using a functor and subfunctor:

Exampletemplate <typename T2, typename IndexSet>

inline

typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype

operator * (const SparseNumberStruct<IndexSet>& a, const T2& b)

{

typedef typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype type;

typename CompareTypes<SparseNumberStruct<IndexSet>,T2>::supertype

returnval;

typename IndexSet::ForEach()

(BinaryFunctor<MultipliesSubfunctor, IndexSet, ConstantDataSet<T2>, typename type::index_set>

(MultipliesSubfunctor(), a.raw_data(), ConstantDataSet<T2>(b), returnval.raw_data()));

return returnval;

}

Roy H. Stogner Metaprogramming April 16, 2012 37 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structure Operations

No operations are easily defined.

• C for loops don’t work over heterogenous structures.

• Templated functors must be defined for every operation.

Multiplication by a constant, using a functor and subfunctor:

Exampletemplate <typename T2, typename IndexSet>

inline

typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype

operator * (const SparseNumberStruct<IndexSet>& a, const T2& b)

{

typedef typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype type;

typename CompareTypes<SparseNumberStruct<IndexSet>,T2>::supertype

returnval;

typename IndexSet::ForEach()

(BinaryFunctor<MultipliesSubfunctor, IndexSet, ConstantDataSet<T2>, typename type::index_set>

(MultipliesSubfunctor(), a.raw_data(), ConstantDataSet<T2>(b), returnval.raw_data()));

return returnval;

}

Roy H. Stogner Metaprogramming April 16, 2012 37 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structure Operations

No operations are easily defined.

• C for loops don’t work over heterogenous structures.

• Templated functors must be defined for every operation.

Multiplication by a constant, using a functor and subfunctor:

Exampletemplate <typename T2, typename IndexSet>

inline

typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype

operator * (const SparseNumberStruct<IndexSet>& a, const T2& b)

{

typedef typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype type;

typename CompareTypes<SparseNumberStruct<IndexSet>,T2>::supertype

returnval;

typename IndexSet::ForEach()

(BinaryFunctor<MultipliesSubfunctor, IndexSet, ConstantDataSet<T2>, typename type::index_set>

(MultipliesSubfunctor(), a.raw_data(), ConstantDataSet<T2>(b), returnval.raw_data()));

return returnval;

}

Roy H. Stogner Metaprogramming April 16, 2012 37 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structure Operations

No operations are easily defined.

• C for loops don’t work over heterogenous structures.

• Templated functors must be defined for every operation.

Multiplication by a constant, using a functor and subfunctor:

Exampletemplate <typename T2, typename IndexSet>

inline

typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype

operator * (const SparseNumberStruct<IndexSet>& a, const T2& b)

{

typedef typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype type;

typename CompareTypes<SparseNumberStruct<IndexSet>,T2>::supertype

returnval;

typename IndexSet::ForEach()

(BinaryFunctor<MultipliesSubfunctor, IndexSet, ConstantDataSet<T2>, typename type::index_set>

(MultipliesSubfunctor(), a.raw_data(), ConstantDataSet<T2>(b), returnval.raw_data()));

return returnval;

}

Roy H. Stogner Metaprogramming April 16, 2012 37 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Operator-Overloaded Sparse Structure Operations

No operations are easily defined.

• C for loops don’t work over heterogenous structures.

• Templated functors must be defined for every operation.

Multiplication by a constant, using a functor and subfunctor:

Exampletemplate <typename T2, typename IndexSet>

inline

typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype

operator * (const SparseNumberStruct<IndexSet>& a, const T2& b)

{

typedef typename MultipliesType<SparseNumberStruct<IndexSet>,T2>::supertype type;

typename CompareTypes<SparseNumberStruct<IndexSet>,T2>::supertype

returnval;

typename IndexSet::ForEach()

(BinaryFunctor<MultipliesSubfunctor, IndexSet, ConstantDataSet<T2>, typename type::index_set>

(MultipliesSubfunctor(), a.raw_data(), ConstantDataSet<T2>(b), returnval.raw_data()));

return returnval;

}

Roy H. Stogner Metaprogramming April 16, 2012 37 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Templated Functors• A subfunctor class represents a single operation

• Template overloading of operator() accepts arbitrary input types• CompareTypes or similar classes (or C++11 decltype) provides

proper return types

Example

struct MultipliesSubfunctor {

template <typename T1, typename T2>

struct Return {

typedef typename

SymmetricMultipliesType<T1,T2>::supertype type;

};

template <typename T1, typename T2>

typename Return<T1,T2>::type

operator()(const T1& x, const T2& y) const { return x * y; }

};

Roy H. Stogner Metaprogramming April 16, 2012 38 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Templated Functors• A subfunctor class represents a single operation• Template overloading of operator() accepts arbitrary input types

• CompareTypes or similar classes (or C++11 decltype) providesproper return types

Example

struct MultipliesSubfunctor {

template <typename T1, typename T2>

struct Return {

typedef typename

SymmetricMultipliesType<T1,T2>::supertype type;

};

template <typename T1, typename T2>

typename Return<T1,T2>::type

operator()(const T1& x, const T2& y) const { return x * y; }

};

Roy H. Stogner Metaprogramming April 16, 2012 38 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Templated Functors• A subfunctor class represents a single operation• Template overloading of operator() accepts arbitrary input types• CompareTypes or similar classes (or C++11 decltype) provides

proper return types

Example

struct MultipliesSubfunctor {

template <typename T1, typename T2>

struct Return {

typedef typename

SymmetricMultipliesType<T1,T2>::supertype type;

};

template <typename T1, typename T2>

typename Return<T1,T2>::type

operator()(const T1& x, const T2& y) const { return x * y; }

};

Roy H. Stogner Metaprogramming April 16, 2012 38 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Templated Functors• A subfunctor class represents a single operation• Template overloading of operator() accepts arbitrary input types• CompareTypes or similar classes (or C++11 decltype) provides

proper return types

Example

struct MultipliesSubfunctor {

template <typename T1, typename T2>

struct Return {

typedef typename

SymmetricMultipliesType<T1,T2>::supertype type;

};

template <typename T1, typename T2>

typename Return<T1,T2>::type

operator()(const T1& x, const T2& y) const { return x * y; }

};

Roy H. Stogner Metaprogramming April 16, 2012 38 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Templated Functors• A subfunctor class represents a single operation• Template overloading of operator() accepts arbitrary input types• CompareTypes or similar classes (or C++11 decltype) provides

proper return types

Example

struct MultipliesSubfunctor {

template <typename T1, typename T2>

struct Return {

typedef typename

SymmetricMultipliesType<T1,T2>::supertype type;

};

template <typename T1, typename T2>

typename Return<T1,T2>::type

operator()(const T1& x, const T2& y) const { return x * y; }

};

Roy H. Stogner Metaprogramming April 16, 2012 38 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]

{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]

Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Sparse Data Structures

Sparse Matrix Operations

Example

A ≡[a bT

c D

]{L,U} ≡ {LUL(A), LUU (A)}

L =

[a 0T

c LUL(D− ca−1bT)

]U =

[1 a−1bT

0 LUU (D− ca−1bT)

]Then apply to sparse arrays of arrays:

• One compile-time pass to allocate output structure

• One run-time pass to do calculations

• Asymptotic complexity drops beautifully

• But now we have asymptotic code generation to worry about!

Roy H. Stogner Metaprogramming April 16, 2012 39 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equations• A templated functor is almost a full physics equation!

I Define which physical quantities are inputs and outputs• Enumerated types are metaprogramming compatible

I Equations can be split into minimal chunks for modularityI Equations must be split into minimal chunks for Jacobian optimization?

Example

#define DeclareUnaryPhysics(physicsname, input1enum, outputenum, code) \

struct physicsname { \

static const char* name() { return #physicsname; } \

typedef UIntSetConstructor<input1enum>::type inputset; \

typedef UIntSetConstructor<outputenum>::type outputset; \

\

template <typename inputtype> \

auto operator() (const inputtype& input1enum##_NAME) \

-> decltype(code) { \

return code; \

} \

}

Roy H. Stogner Metaprogramming April 16, 2012 40 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equations• A templated functor is almost a full physics equation!

I Define which physical quantities are inputs and outputs• Enumerated types are metaprogramming compatible

I Equations can be split into minimal chunks for modularityI Equations must be split into minimal chunks for Jacobian optimization?

Example

#define DeclareUnaryPhysics(physicsname, input1enum, outputenum, code) \

struct physicsname { \

static const char* name() { return #physicsname; } \

typedef UIntSetConstructor<input1enum>::type inputset; \

typedef UIntSetConstructor<outputenum>::type outputset; \

\

template <typename inputtype> \

auto operator() (const inputtype& input1enum##_NAME) \

-> decltype(code) { \

return code; \

} \

}

Roy H. Stogner Metaprogramming April 16, 2012 40 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equations

Example

DeclareUnaryPhysics(DensityFromSpeciesDensities,

DENSITIES_VAR, DENSITY_VAR,

rhoi.sum());

DeclareBinaryPhysics(MomentumFromVelocity,

DENSITY_VAR, VELOCITY_VAR, MOMENTUM_VAR,

U * rho);

DeclareBinaryPhysics(VelocityFromMomentum,

DENSITY_VAR, MOMENTUM_VAR, VELOCITY_VAR,

rhoU / rho);

DeclareBinaryPhysics(SpecificEnergyFromSpecificInternalEnergy,

SPECIFIC_INTERNAL_ENERGY_VAR, SPEED_SQUARED_VAR,

SPECIFIC_ENERGY_VAR,

e + UdotU / 2);

• Functors get reused in every Physics set, for all input argument types

• Minimizing how much code must be entrusted to physics people

Roy H. Stogner Metaprogramming April 16, 2012 41 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equations

Example

DeclareUnaryPhysics(DensityFromSpeciesDensities,

DENSITIES_VAR, DENSITY_VAR,

rhoi.sum());

DeclareBinaryPhysics(MomentumFromVelocity,

DENSITY_VAR, VELOCITY_VAR, MOMENTUM_VAR,

U * rho);

DeclareBinaryPhysics(VelocityFromMomentum,

DENSITY_VAR, MOMENTUM_VAR, VELOCITY_VAR,

rhoU / rho);

DeclareBinaryPhysics(SpecificEnergyFromSpecificInternalEnergy,

SPECIFIC_INTERNAL_ENERGY_VAR, SPEED_SQUARED_VAR,

SPECIFIC_ENERGY_VAR,

e + UdotU / 2);

• Functors get reused in every Physics set, for all input argument types

• Minimizing how much code must be entrusted to physics people

Roy H. Stogner Metaprogramming April 16, 2012 41 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equations

Example

DeclareUnaryPhysics(DensityFromSpeciesDensities,

DENSITIES_VAR, DENSITY_VAR,

rhoi.sum());

DeclareBinaryPhysics(MomentumFromVelocity,

DENSITY_VAR, VELOCITY_VAR, MOMENTUM_VAR,

U * rho);

DeclareBinaryPhysics(VelocityFromMomentum,

DENSITY_VAR, MOMENTUM_VAR, VELOCITY_VAR,

rhoU / rho);

DeclareBinaryPhysics(SpecificEnergyFromSpecificInternalEnergy,

SPECIFIC_INTERNAL_ENERGY_VAR, SPEED_SQUARED_VAR,

SPECIFIC_ENERGY_VAR,

e + UdotU / 2);

• Functors get reused in every Physics set, for all input argument types

• Minimizing how much code must be entrusted to physics people

Roy H. Stogner Metaprogramming April 16, 2012 41 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets

• Equations are now represented by data types

• Data types can be stuck into metaprogramming containers!

Example

typedef VectorConstructor<

DensityFromSpeciesDensities,

VelocityFromMomentum,

MomentumFromVelocity,

SpeedSquaredFromVelocity,

SpecificEnergyFromConserved,

SpecificInternalEnergyFromSpecificEnergy,

SpecificEnergyFromSpecificInternalEnergy,

LinearTranslationalRotationalEnergyFromTemperature,

SpecificInternalEnergyFromOnlyTransationalRotationalEnergy

>::type AllPhysics;

Roy H. Stogner Metaprogramming April 16, 2012 42 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets

• Equations are now represented by data types

• Data types can be stuck into metaprogramming containers!

Example

typedef VectorConstructor<

DensityFromSpeciesDensities,

VelocityFromMomentum,

MomentumFromVelocity,

SpeedSquaredFromVelocity,

SpecificEnergyFromConserved,

SpecificInternalEnergyFromSpecificEnergy,

SpecificEnergyFromSpecificInternalEnergy,

LinearTranslationalRotationalEnergyFromTemperature,

SpecificInternalEnergyFromOnlyTransationalRotationalEnergy

>::type AllPhysics;

Roy H. Stogner Metaprogramming April 16, 2012 42 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets

• Equations are now represented by data types

• Data types can be stuck into metaprogramming containers!

Example

typedef VectorConstructor<

DensityFromSpeciesDensities,

VelocityFromMomentum,

MomentumFromVelocity,

SpeedSquaredFromVelocity,

SpecificEnergyFromConserved,

SpecificInternalEnergyFromSpecificEnergy,

SpecificEnergyFromSpecificInternalEnergy,

LinearTranslationalRotationalEnergyFromTemperature,

SpecificInternalEnergyFromOnlyTransationalRotationalEnergy

>::type AllPhysics;

Roy H. Stogner Metaprogramming April 16, 2012 42 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets

• Equations are now represented by data types

• Data types can be stuck into metaprogramming containers!

Example

typedef VectorConstructor<

DensityFromSpeciesDensities,

VelocityFromMomentum,

MomentumFromVelocity,

SpeedSquaredFromVelocity,

SpecificEnergyFromConserved,

SpecificInternalEnergyFromSpecificEnergy,

SpecificEnergyFromSpecificInternalEnergy,

LinearTranslationalRotationalEnergyFromTemperature,

SpecificInternalEnergyFromOnlyTransationalRotationalEnergy

>::type AllPhysics;

Roy H. Stogner Metaprogramming April 16, 2012 42 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Variable Sets

• Variables are now represented by enumerated values

• Enums can be stuck into metaprogramming containers!

Example

typedef UIntSetConstructor<

DENSITIES_VAR,

VELOCITY_VAR,

TEMPERATURE_VAR

>::type PrimitiveVars;

typedef UIntSetConstructor<

DENSITIES_VAR,

MOMENTUM_VAR,

ENERGY_VAR

>::type ConservedVars;

Roy H. Stogner Metaprogramming April 16, 2012 43 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Variable Sets

• Variables are now represented by enumerated values

• Enums can be stuck into metaprogramming containers!

Example

typedef UIntSetConstructor<

DENSITIES_VAR,

VELOCITY_VAR,

TEMPERATURE_VAR

>::type PrimitiveVars;

typedef UIntSetConstructor<

DENSITIES_VAR,

MOMENTUM_VAR,

ENERGY_VAR

>::type ConservedVars;

Roy H. Stogner Metaprogramming April 16, 2012 43 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Variable Sets

• Variables are now represented by enumerated values

• Enums can be stuck into metaprogramming containers!

Example

typedef UIntSetConstructor<

DENSITIES_VAR,

VELOCITY_VAR,

TEMPERATURE_VAR

>::type PrimitiveVars;

typedef UIntSetConstructor<

DENSITIES_VAR,

MOMENTUM_VAR,

ENERGY_VAR

>::type ConservedVars;

Roy H. Stogner Metaprogramming April 16, 2012 43 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Variable Sets

• Variables are now represented by enumerated values

• Enums can be stuck into metaprogramming containers!

Example

typedef UIntSetConstructor<

DENSITIES_VAR,

VELOCITY_VAR,

TEMPERATURE_VAR

>::type PrimitiveVars;

typedef UIntSetConstructor<

DENSITIES_VAR,

MOMENTUM_VAR,

ENERGY_VAR

>::type ConservedVars;

Roy H. Stogner Metaprogramming April 16, 2012 43 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

• Consider each variable as a rednode

• Consider each equation as ablack node

I Each output is a directededge from equation to variable

I Each input is a directed edgefrom variable to equation

Then our physics now looks like agraph!

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

Roy H. Stogner Metaprogramming April 16, 2012 44 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

• Consider each variable as a rednode

• Consider each equation as ablack node

I Each output is a directededge from equation to variable

I Each input is a directed edgefrom variable to equation

Then our physics now looks like agraph!

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

Roy H. Stogner Metaprogramming April 16, 2012 44 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

• Consider each variable as a rednode

• Consider each equation as ablack node

I Each output is a directededge from equation to variable

I Each input is a directed edgefrom variable to equation

Then our physics now looks like agraph!

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

Roy H. Stogner Metaprogramming April 16, 2012 44 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

• Consider each variable as a rednode

• Consider each equation as ablack node

I Each output is a directededge from equation to variable

I Each input is a directed edgefrom variable to equation

Then our physics now looks like agraph!

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

Roy H. Stogner Metaprogramming April 16, 2012 44 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

• Consider each variable as a rednode

• Consider each equation as ablack node

I Each output is a directededge from equation to variable

I Each input is a directed edgefrom variable to equation

Then our physics now looks like agraph!

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

Roy H. Stogner Metaprogramming April 16, 2012 44 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

• Consider each variable as a rednode

• Consider each equation as ablack node

I Each output is a directededge from equation to variable

I Each input is a directed edgefrom variable to equation

Then our physics now looks like agraph!

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

Roy H. Stogner Metaprogramming April 16, 2012 44 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

We can use metaprogramming toanswer questions about the graph.

• Given a set of input variables:I Which non-input variables in

the graph are nowdetermined?

I What are the dependencies ofeach variable?

• And a set of output variables:I Which equations must be

solved to evaluate them?I In which order?

Roy H. Stogner Metaprogramming April 16, 2012 45 / 52

Numeric Functional Metaprogramming Physics as a Graph Problem

Equation Sets as Bicolored Graphs

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

We can use metaprogramming toanswer questions about the graph.

• Given a set of input variables:I Which non-input variables in

the graph are nowdetermined?

I What are the dependencies ofeach variable?

• And a set of output variables:I Which equations must be

solved to evaluate them?I In which order?

Roy H. Stogner Metaprogramming April 16, 2012 45 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

SolveList

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

45

6

12

3

7

Given input variables, outputvariables, and equation functor classtypes connecting them, we want aSolveList: an ordered set of whichequations to solve in what order.

1 Find all the dependencies ofyour output variables

I Unreachable output variablesbecome a compile-time error

I Unnecessary non-inputnon-output variables are leftout

2 Greedy search throughequations (in the same order asfor dependency finding!), addingsolveable equations to list

Roy H. Stogner Metaprogramming April 16, 2012 46 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

SolveList

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

45

6

12

3

7

Given input variables, outputvariables, and equation functor classtypes connecting them, we want aSolveList: an ordered set of whichequations to solve in what order.

1 Find all the dependencies ofyour output variables

I Unreachable output variablesbecome a compile-time error

I Unnecessary non-inputnon-output variables are leftout

2 Greedy search throughequations (in the same order asfor dependency finding!), addingsolveable equations to list

Roy H. Stogner Metaprogramming April 16, 2012 46 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

SolveList

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

45

6

12

3

7

Given input variables, outputvariables, and equation functor classtypes connecting them, we want aSolveList: an ordered set of whichequations to solve in what order.

1 Find all the dependencies ofyour output variables

I Unreachable output variablesbecome a compile-time error

I Unnecessary non-inputnon-output variables are leftout

2 Greedy search throughequations (in the same order asfor dependency finding!), addingsolveable equations to list

Roy H. Stogner Metaprogramming April 16, 2012 46 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

SolveList

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

45

6

12

3

7

Given input variables, outputvariables, and equation functor classtypes connecting them, we want aSolveList: an ordered set of whichequations to solve in what order.

1 Find all the dependencies ofyour output variables

I Unreachable output variablesbecome a compile-time error

I Unnecessary non-inputnon-output variables are leftout

2 Greedy search throughequations (in the same order asfor dependency finding!), addingsolveable equations to list

Roy H. Stogner Metaprogramming April 16, 2012 46 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

SolveList

T

ei

ρi

(ρe)i

ρe

ρ

~u

~u · ~u

ρ~u · ~u

ρE

45

6

12

3

7

Given input variables, outputvariables, and equation functor classtypes connecting them, we want aSolveList: an ordered set of whichequations to solve in what order.

1 Find all the dependencies ofyour output variables

I Unreachable output variablesbecome a compile-time error

I Unnecessary non-inputnon-output variables are leftout

2 Greedy search throughequations (in the same order asfor dependency finding!), addingsolveable equations to list

Roy H. Stogner Metaprogramming April 16, 2012 46 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables

3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types

2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equation

I Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Evaluations on the Graph

State Updating

With user-specified types on all variables, SolveList evaluation is easy:

1 Create a Container type holding the specified variable types

2 Instantiate this State state; set values on the user input variables3 Do a ForEach loop over the SolveList

I Pass input variables from state, assign output variables to state foreach equation

With user-specified types on input variables only, we first need ametaprogramming pass:

1 Create a Container type holding the specified input variable types2 Do a metaprogramming loop over the SolveList

I Pass input variable types to each equationI Insert output variable types into the State

3 Do a ForEach loop at runtime as before

Roy H. Stogner Metaprogramming April 16, 2012 47 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

Differentiation looks already solved!

1 Collect your Physics

2 Choose your input variables

3 Evaluate the SolveList

4 Use DualNumber input variable types

5 Take derivatives() of output variables

6 Cheer

Roy H. Stogner Metaprogramming April 16, 2012 48 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

Differentiation looks already solved!

1 Collect your Physics

2 Choose your input variables

3 Evaluate the SolveList

4 Use DualNumber input variable types

5 Take derivatives() of output variables

6 Cheer

Roy H. Stogner Metaprogramming April 16, 2012 48 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

Differentiation looks already solved!

1 Collect your Physics

2 Choose your input variables

3 Evaluate the SolveList

4 Use DualNumber input variable types

5 Take derivatives() of output variables

6 Cheer

Roy H. Stogner Metaprogramming April 16, 2012 48 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

Differentiation looks already solved!

1 Collect your Physics

2 Choose your input variables

3 Evaluate the SolveList

4 Use DualNumber input variable types

5 Take derivatives() of output variables

6 Cheer

Roy H. Stogner Metaprogramming April 16, 2012 48 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

Differentiation looks already solved!

1 Collect your Physics

2 Choose your input variables

3 Evaluate the SolveList

4 Use DualNumber input variable types

5 Take derivatives() of output variables

6 Cheer

Roy H. Stogner Metaprogramming April 16, 2012 48 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

Differentiation looks already solved!

1 Collect your Physics

2 Choose your input variables

3 Evaluate the SolveList

4 Use DualNumber input variable types

5 Take derivatives() of output variables

6 Cheer

Roy H. Stogner Metaprogramming April 16, 2012 48 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Equation Derivatives

But how well does that solve differentiation?• Forward differentiation issues:

1 Needlessly expensive for many-input-variable, few-output variablegraphs

• or subgraphs!

• Adjoint differentiation issues:1 Needlessly expensive for many-output-variable, few-input variable

graphs• or subgraphs!

2 Typically requires additional temporary data• particularly with operator overloading...

• Optimal Jacobian Accumulation issues:1 NP-complete!

• don’t want to stress-test compilers...

• Heuristic: “Eh, Good Enough” Jacobian Accumulation

Roy H. Stogner Metaprogramming April 16, 2012 49 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing one NodeEach equation node can be used to define local partial derivatives

• Ni inputs, No outputs gives Ni ·No partial derivatives

• Small equations are efficiently evaluated with sparse forward AD

• Equation nodes are out of the picture

• Partial derivatives are directed edges with weights D(Vi, Vj)connecting variables Vi and Vj

An intermediate variable M can be “condensed away”:

• For all outgoing edges to output variable O:

• For all incoming edges from input variable I:• D(I,O)+ = D(I,M) ·D(M,O)

I (starting from D(I,O) ≡ 0 when creating a new edge)

Keep condensing until all remaining edges are directly from user inputs touser outputs

Roy H. Stogner Metaprogramming April 16, 2012 50 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing one NodeEach equation node can be used to define local partial derivatives

• Ni inputs, No outputs gives Ni ·No partial derivatives

• Small equations are efficiently evaluated with sparse forward AD

• Equation nodes are out of the picture

• Partial derivatives are directed edges with weights D(Vi, Vj)connecting variables Vi and Vj

An intermediate variable M can be “condensed away”:

• For all outgoing edges to output variable O:

• For all incoming edges from input variable I:• D(I,O)+ = D(I,M) ·D(M,O)

I (starting from D(I,O) ≡ 0 when creating a new edge)

Keep condensing until all remaining edges are directly from user inputs touser outputs

Roy H. Stogner Metaprogramming April 16, 2012 50 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing one NodeEach equation node can be used to define local partial derivatives

• Ni inputs, No outputs gives Ni ·No partial derivatives

• Small equations are efficiently evaluated with sparse forward AD

• Equation nodes are out of the picture

• Partial derivatives are directed edges with weights D(Vi, Vj)connecting variables Vi and Vj

An intermediate variable M can be “condensed away”:

• For all outgoing edges to output variable O:

• For all incoming edges from input variable I:• D(I,O)+ = D(I,M) ·D(M,O)

I (starting from D(I,O) ≡ 0 when creating a new edge)

Keep condensing until all remaining edges are directly from user inputs touser outputs

Roy H. Stogner Metaprogramming April 16, 2012 50 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing one NodeEach equation node can be used to define local partial derivatives

• Ni inputs, No outputs gives Ni ·No partial derivatives

• Small equations are efficiently evaluated with sparse forward AD

• Equation nodes are out of the picture

• Partial derivatives are directed edges with weights D(Vi, Vj)connecting variables Vi and Vj

An intermediate variable M can be “condensed away”:

• For all outgoing edges to output variable O:

• For all incoming edges from input variable I:• D(I,O)+ = D(I,M) ·D(M,O)

I (starting from D(I,O) ≡ 0 when creating a new edge)

Keep condensing until all remaining edges are directly from user inputs touser outputs

Roy H. Stogner Metaprogramming April 16, 2012 50 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing one NodeEach equation node can be used to define local partial derivatives

• Ni inputs, No outputs gives Ni ·No partial derivatives

• Small equations are efficiently evaluated with sparse forward AD

• Equation nodes are out of the picture

• Partial derivatives are directed edges with weights D(Vi, Vj)connecting variables Vi and Vj

An intermediate variable M can be “condensed away”:

• For all outgoing edges to output variable O:

• For all incoming edges from input variable I:• D(I,O)+ = D(I,M) ·D(M,O)

I (starting from D(I,O) ≡ 0 when creating a new edge)

Keep condensing until all remaining edges are directly from user inputs touser outputs

Roy H. Stogner Metaprogramming April 16, 2012 50 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing the Graph

Ia

Ib

Ic

Ma

Mb

Mc Md

Me

Mf

Oa

Ob

Oc

A

B

C D

E

F

G

H

I

• In what order do we condense these equations?I N -factorial possibilitiesI Some possibilities are cheaper than othersI NP -complete optimization problem

Eh, good enough

Roy H. Stogner Metaprogramming April 16, 2012 51 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing the Graph

Ia

Ib

Ic

Ma

Mb

Mc Md

Me

Mf

Oa

Ob

Oc

A

B

C D

E

F

G

H

I

• Forward differentiation:I Evaluates equations inputs-to-outputsI Effectively does Ma,Mb,Mc,Md,Me,Mf

I 3 + 3 + 3 + 6 + 9 + 9 = 33 multiply+add operations

Eh, good enough

Roy H. Stogner Metaprogramming April 16, 2012 51 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing the Graph

Ia

Ib

Ic

Ma

Mb

Mc Md

Me

Mf

Oa

Ob

Oc

A

B

C D

E

F

G

H

I

• Reverse differentiation:I Evaluates equations outputs-to-inputsI Effectively does Mf ,Me,Md,Mc,Mb,Ma

I Still 3 + 3 + 3 + 6 + 9 + 9 = 33 multiply+add operations

Eh, good enough

Roy H. Stogner Metaprogramming April 16, 2012 51 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing the Graph

Ia

Ib

Ic

Ma

Mb

Mc Md

Me

Mf

Oa

Ob

Oc

A

B

C D

E

F

G

H

I

• Greedy (lazy?) differentiation:I Pick cheapest condensations firstI Does Mc,Ma,Mb,Me,Mf ,Md

I Still 2 + 3 + 3 + 3 + 3 + 9 = 23 multiply+add operations: 30% cheaper!

Eh, good enough

Roy H. Stogner Metaprogramming April 16, 2012 51 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Chain Rule Application: Condensing the Graph

Ia

Ib

Ic

Ma

Mb

Mc Md

Me

Mf

Oa

Ob

Oc

A

B

C D

E

F

G

H

I

• Greedy (lazy?) differentiation:I Pick cheapest condensations firstI Does Mc,Ma,Mb,Me,Mf ,Md

I Still 2 + 3 + 3 + 3 + 3 + 9 = 23 multiply+add operations: 30% cheaper!

Eh, good enough

Roy H. Stogner Metaprogramming April 16, 2012 51 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Any Questions?

Lots of My Questions:• How much code for non-MASA

apps can be replaced bystandard libraries?

I Boost MTLI SacadoI Phalanx

• Can physics functors bedecomposed automatically?

I Precompilation script?

• Can we “roll up” sparsestructure algorithms?

Roy H. Stogner Metaprogramming April 16, 2012 52 / 52

Numeric Functional Metaprogramming Differentiation on the Graph

Any Questions?

Lots of My Questions:• How much code for non-MASA

apps can be replaced bystandard libraries?

I Boost MTLI SacadoI Phalanx

• Can physics functors bedecomposed automatically?

I Precompilation script?

• Can we “roll up” sparsestructure algorithms?

Roy H. Stogner Metaprogramming April 16, 2012 52 / 52