\title{Tendon Robot Statics}
\author{John Till}
\date{}

\documentclass[12pt]{article}

\usepackage[a4paper, margin=0.75in]{geometry}
\usepackage[colorlinks=true,urlcolor=blue]{hyperref}
\usepackage{amsmath,amssymb}
\usepackage{graphicx}

\usepackage{xcolor}
\definecolor{OffWhite}{rgb}{0.93,0.93,0.93}
\definecolor{QtCommentColor}{rgb}{0,0.5,0}
\definecolor{QtKeywordColor}{rgb}{0.5,0.5,0}
\definecolor{QtPurpleColor}{rgb}{0.5,0,0.5}
\definecolor{QtGlobal}{rgb}{0.808,0.361,0}
\definecolor{QtFunctionColor}{rgb}{0,0.404,0.486}
\definecolor{BlenderPythonString}{rgb}{0.392,0,0}
\definecolor{BlenderPythonKeyword}{rgb}{0.502,0,0.314}
\definecolor{BlenderPythonGold}{rgb}{0.373,0.373,0}
\definecolor{BlenderPythonLiteral}{rgb}{0,0,0.784}
\definecolor{BlenderPythonBackground}{rgb}{0.6,0.6,0.6}

\usepackage[T1]{fontenc} %for upquotes in listings
\usepackage{textcomp} %for upquotes in listings
\usepackage{listings}
\lstset{
		language=C++,
		escapeinside={!-}{-!},
		upquote=true,
		%
		otherkeywords={Vector3d, DiagonalMatrix, VectorXd, Matrix3d, Map, MatrixXd, Vector6d, Vector4d,
		              Matrix6d, Eigen, Upper, std, fstream, Matrix3Xd,
									UnitX, pow, inverse, transpose, segment, data, UnitZ, cross, hat_squared,
									hat_postmultiply, hat_premultiply,
									Zero, Identity, UnitY, cosseratTendonRobotOde, ode4, cols, row, main, shootingFunction,
									block, rotation_error, solveLevenbergMarquardt, toDenseMatrix,
									selfadjointView, llt, close, kirchhoffTendonRobotOde, cwiseProduct, cwiseMin,
									cwiseMax, getRouting, normalized},
    morekeywords=[2]{Vector3d, DiagonalMatrix, VectorXd, Matrix3d, Map, MatrixXd, Vector6d, Vector4d,
		                 Matrix6d, Eigen, Upper, std, fstream, Matrix3Xd},
		morekeywords=[3]{UnitX, UnitZ, pow, inverse, transpose, segment, data, cross, hat_squared,
		                 hat_postmultiply, hat_premultiply,
		                 Zero, Identity, UnitY, cosseratTendonRobotOde, ode4, cols, row, main, shootingFunction,
										 block, rotation_error, solveLevenbergMarquardt, toDenseMatrix,
										 selfadjointView, llt, close, kirchhoffTendonRobotOde, cwiseProduct, cwiseMin,
										 cwiseMax, getRouting, normalized},
    %
		frame = single,
		rulecolor=\color{black},
    tabsize=4, % tab space width
    showstringspaces=false, % don't mark spaces in strings
		%
		basicstyle=\footnotesize,%\color{QtIdentifier},
		backgroundcolor=\color{OffWhite},
    commentstyle=\color{QtCommentColor}, % comment color
    keywordstyle=\color{QtKeywordColor}, % keyword color
		keywordstyle=[2]{\color{QtPurpleColor}},
		keywordstyle=[3]{\color{QtFunctionColor}},
    stringstyle=\color{QtCommentColor} % string color
}

\begin{document}

\makeatletter
\renewcommand{\@maketitle}{
\newpage
\null
\vskip 2em
\begin{center}
{\LARGE \@title \par}
\end{center}
\par
} \makeatother

\maketitle

\section{Tendon Robot Model in C++}

This example shows how to implement the tendon robot model from the paper \href{https://ieeexplore.ieee.org/document/5957337}{``Statics and Dynamics of Continuum Robots With General Tendon Routing and External Loading''}, which is also described in Chapter 4 of the dissertation \href{https://etd.library.vanderbilt.edu//available/etd-10042011-115347/}{``The Mechanics of Continuum Robots: Model-based Sensing and Control''}.

At the top of the C++ script, we start with the simple independent parameters:
\begin{lstlisting}
//Independent Parameters
const double E = 200e9;
const double G = 80e9;
const double rad = 0.001;
const double rho = 8000;
const Vector3d g = 9.81*Vector3d::UnitX();
const double L = 0.5;
const int num_tendons = 4;
\end{lstlisting}
These are straightforward. However, the independent parameters also include the tendon routing paths. The journal paper considers general routing paths with offsets given by the functions $\boldsymbol{r}_i(s)$ for $1 \leq i \leq$ num\_tendons, as well as derivatives $\dot{\boldsymbol{r}}_i(s)$ and $\ddot{\boldsymbol{r}}_i(s)$. Tendons are often routed parallel to the backbone, and simulations involving functions as design parameters tend to be a bit complicated, so for now we'll assume there is no dependence on $s$ so that $\boldsymbol{r}_i$ is constant. We implement this in C++ for four tendons spaced $90^\circ$ apart:
\begin{lstlisting}
const double tendon_offset = 0.01506;
#define R(theta) (tendon_offset*Vector3d(!-\textcolor{QtFunctionColor}{cos}-!(theta), !-\textcolor{QtFunctionColor}{sin}-!(theta), 0))
const Vector3d r[num_tendons] = {R(0), R(pi/2), R(pi), R(pi*3/2)};
#undef R
\end{lstlisting}
We define a macro function ``R'' which makes it easier to initialize the array ``r'' with vectors spaced $90^\circ$ apart. We immediately undefine the macro so that we can use the symbol ``R'' in the future without accidently invoking the macro. Now there is just one more independent parameter; the input to the forward kinematics problem is the tension in each tendon:
\begin{lstlisting}
const VectorXd tau = Vector4d(15,0,0,0);
\end{lstlisting}
We set $\tau_1 = 15$N and $\tau_2 = \tau_3 = \tau_4 = 0$N.
With the independent parameters set, there are several dependent parameter calculations:
\begin{lstlisting}
//Dependent parameter calculations
const double area = pi*pow(rad,2);
const double I = pi*pow(rad,4)/4;
const double J = 2*I;
const DiagonalMatrix<double, 3> Kse (G*area,G*area,E*area);
const DiagonalMatrix<double, 3> Kbt (E*I,E*I,G*J);
const Matrix3d Kse_dense = Kse.toDenseMatrix();
const Matrix3d Kbt_dense = Kbt.toDenseMatrix();
\end{lstlisting}
There is some redundancy in the stiffness matrices; we have both dense and diagonal data structures so that we can use either representation without making a conversion.

The core of the model is the ODE function. The state variables are $\boldsymbol{p}$, $\boldsymbol{R}$, $\boldsymbol{v}$, and $\boldsymbol{u}$. At the start of the ODE function we unpack the state vector:
\newpage
\begin{lstlisting}
void cosseratTendonRobotOde(VectorXd& y_s_out, VectorXd& y){
    //Unpack state vector
    Matrix3d R = Map<Matrix3d>(&y[3]);
    Vector3d v = Map<Vector3d>(&y[12]);
    Vector3d u = Map<Vector3d>(&y[15]);
\end{lstlisting}
The paper describes how one must solve a linear system to find $\dot{\boldsymbol{v}}$ and $\dot{\boldsymbol{u}}$. We declare the variables to setup this system:
\begin{lstlisting}
Vector3d a = Vector3d::Zero();
Vector3d b = Vector3d::Zero();
Matrix3d A_plus_Kse = Kse_dense; = Kse_dense;
Matrix3d G = Matrix3d::Zero();
Matrix3d H_plus_Kbt = Kbt_dense;
\end{lstlisting}
In Equation (16) of the paper, the left-hand side coefficient matrix is given by
\begin{align*}
\begin{bmatrix}
\boldsymbol{K}_{se} + \boldsymbol{A} & \boldsymbol{G} \\ \boldsymbol{G}^T & \boldsymbol{K}_{bt} + \boldsymbol{H}
\end{bmatrix}.
\end{align*}
For the program, it makes sense to roll $\boldsymbol{K}_{se} + \boldsymbol{A}$ into a single variable, and likewise for $\boldsymbol{K}_{bt} + \boldsymbol{H}$. Then we sum the variables as described just before Equation (15):
\begin{lstlisting}
for(int i = 0; i < num_tendons; i++){
    Vector3d pb_si = u.cross(r[i]) + v;
    double pb_s_norm = pb_si.!-\textcolor{QtFunctionColor}{norm}-!();
    Matrix3d A_i = -hat_squared(pb_si)*(tau(i)/pow(pb_s_norm,3));
    Matrix3d G_i = -hat_postmultiply(A_i,r[i]);
    Vector3d a_i = A_i*(u.cross(pb_si));

    a += a_i;
    b += r[i].cross(a_i);
    A_plus_Kse += A_i;
    G += G_i;
    H_plus_Kbt += hat_premultiply(r[i],G_i);
}
\end{lstlisting}
After the summation in this loop, the variables will have the correct values. The smaller components are combined to setup the linear system coefficient matrix:
\begin{lstlisting}
Matrix6d K;
K << A_plus_Kse, G, G.transpose(), H_plus_Kbt;
\end{lstlisting}
The right-hand side ``rhs'' is given just before Equation (16), and we construct the vector:
\begin{lstlisting}
Vector3d nb = Kse*(v - Vector3d::UnitZ());
Vector3d mb = Kbt*u;

Vector6d rhs;
rhs << -u.cross(nb) - !-\textcolor{QtFunctionColor}{transposeMultiply}-!(R,rho*area*g) - a,
       -u.cross(mb) - v.cross(nb) - b;
\end{lstlisting}
We solve for the body frame internal force and moment as intermediate variables before setting the right-hand side values. This is partially to recognize physically relevant terms, but also to avoid repeated calculations of ``nb''.

\newpage \noindent
With the linear system setup, we are positioned to complete the ODE function by solving for the derivatives:
\begin{lstlisting}
    //Pack state vector derivative
    Map<Vector3d> p_s(&y_s_out[0]);
    Map<Matrix3d> R_s(&y_s_out[3]);
    Map<Vector6d> vs_and_us(&y_s_out[12]);

    //ODEs
    p_s = R*v;
    R_s = hat_postmultiply(R,u);
    vs_and_us = K.selfadjointView<Eigen::Upper>().llt().!-\textcolor{QtFunctionColor}{solve}-!(rhs);
}
\end{lstlisting}
One of Eigen's linear solvers is used to solve the 6x6 linear system. The ``selfadjointView'' takes advantage of the symmetry of ``K''.

After the ODE function, we move on to the shooting method's objective function. At the top of the function we unpack the guess:
\begin{lstlisting}
static MatrixXd Y; //Declare Y global to save results
VectorXd shootingFunction(VectorXd guess){
    Vector3d n0 = guess.segment<3>(0);
    Vector3d v0 = Kse.inverse()*n0 + Vector3d::UnitZ();
    Vector3d u0 = guess.segment<3>(3);
\end{lstlisting}
One of the unknown state variables is $\boldsymbol{v}(0)$, but we guess $\boldsymbol{n}(0)$ and solve for $\boldsymbol{v}(0)$ since I suspect this will lead to better \emph{numerical conditioning} of the objective function. Next we integrate the tendon robot ODE:
\begin{lstlisting}
VectorXd y0(18);
y0 << p0, Map<VectorXd>(Matrix3d(R0).data(), 9), v0, u0;

//Numerically integrate the Cosserat rod equations
Y = ode4<cosseratTendonRobotOde>(y0, L);
\end{lstlisting}
Once the integration is done, we can find the violation of the static equilibrium equations. There are forces acting on the final disk from the backbone and tendon attachment points. We extract the internal force in the backbone:
\begin{lstlisting}
//Find the internal forces in the backbone prior to the final plate
Vector3d vL = Y.block<3,1>(12,Y.cols()-1);
Vector3d uL = Y.block<3,1>(15,Y.cols()-1);

Vector3d nb = Kse*(vL - Vector3d::UnitZ());
Vector3d mb = Kbt*uL;
\end{lstlisting}
Then we sum the forces and moments acting on the plate, starting with the backbone, then looping over the tendons:
\begin{lstlisting}
//Find the equilibrium error at the tip, considering tendon forces
Vector3d force_error = -nb;
Vector3d moment_error = -mb;
for(int i = 0; i < num_tendons; i++){
    Vector3d pb_si = uL.cross(r[i]) + vL;
    Vector3d Fb_i = -tau(i)*pb_si.normalized();
    force_error += Fb_i;
    moment_error += r[i].cross(Fb_i);
}
\end{lstlisting}
The tendon loading terms are given by Equations (18), (19), and (20). Finally we complete the objective function by returning a single error vector:
\begin{lstlisting}
    Vector6d distal_error;
    distal_error << force_error, moment_error;

    return distal_error;
}
\end{lstlisting}

With the objective function complete, we are finally ready to write the simulation driver. Over in the main function, the problem is solved in just a few lines:
\begin{lstlisting}
int main(int, char**){
    Vector6d init_guess = Vector6d::Zero(); //nb and u

    //Solve with shooting method
    VectorXd wrench_soln = solveLevenbergMarquardt<shootingFunction>
                               (init_guess, 1e-12, 500, 1e-2, 0.5, 1e-7, 1e-9);
\end{lstlisting}
The solver uses finite differences to build the Jacobian, and the default finite difference increments are too small. Thus we specify all the parameters for the ``solveLevenbergMarquardt'' function to use larger increments. With the problem solved, the results should be visualized. I think it can be difficult to understand tendon robot behavior from simple line plots, so we'll generate a render of the robot instead. The backbone curve, tendon curves, and full pose at nine points along the backbone are saved to text files:
\begin{lstlisting}
    //Save results for Blender visualization
    std::fstream file("centerline.dat", std::fstream::out);
    file << Y.block(0,0,3,Y.cols());
    file.close();

    MatrixXd tendonlines(3*num_tendons, Y.cols());
    for(int i = 0; i < Y.cols(); i++){
        Vector3d p = Y.block<3,1>(0,i);
        Matrix3d R = Map<Matrix3d>(&Y(3,i));
        for(int j = 0; j < num_tendons; j++)
            tendonlines.block<3,1>(3*j,i) = p + R*r[j];
    }
    file = std::fstream("tendonlines.dat", std::fstream::out);
    file << tendonlines;
    file.close();

    const int num_disks = 9;
    Matrix3Xd disks(3,4*num_disks);
    for(int i = 1; i <= num_disks; i++){
        int j = ((Y.cols()-1) * i) / num_disks;
        Vector3d p = Y.block<3,1>(0,j);
        Matrix3d R = Map<Matrix3d>(&Y(3,j));
        disks.block<3,3>(0,4*(i-1)) = R;
        disks.block<3,1>(0,4*(i-1)+3) = p;
    }
    file = std::fstream("disks.dat", std::fstream::out);
    file << disks;
    file.close();

    return 0;
}
\end{lstlisting}
Running the C++ script should produce three files ``centerline.dat'', ``tendonlines.dat'', and ``disk.dat''. These files will be located in the active directory the program is run from, which by default is a build folder when using Qt.

\section{Visualization with Blender}

One of the nice features of Blender is that in addition to using the user interface, you can also perform modeling tasks using Python scripts. This is perfect for generating 3d models from simulation results.

The output text files should be moved to the Blender subfolder. The Python script to render the tendon robot is contained in ``Tendon\_Robot\_Render.blend''. Upon opening the file with Blender, the Python scripting pane will be in the upper left. There is a ``Run Script'' button on the bottom right of the pane as shown below:
\begin{figure}[h]
	\centering
		\includegraphics[width=0.95\textwidth]{fig/ScriptingPane.jpg}
	\label{fig:Pane}
\end{figure}

\noindent
Running this script with the text files present will cause a render of the robot to be saved to the ``output'' subfolder:
\begin{figure}[h]
	\centering
		\includegraphics[width=0.8\textwidth]{fig/TendonRobotRender.jpg}
\end{figure}

\noindent Applying a tension on the first tendon has caused the backbone to bend, exactly as we would expect. Since the distributed weight of the backbone is not very large, the backbone curve nearly has a constant curvature.

\lstset{
		language=Python,
		escapeinside={!-}{-!},
		%
		deletekeywords={def, type, object, range, len, int},
		otherkeywords={def, True, False, type, object, range, len},
		morekeywords=[2]{def},
		morekeywords=[3]{True, False, type, object, range, len},
		%
		frame = single,
		rulecolor=\color{black},
    tabsize=4, % tab space width
    showstringspaces=false, % don't mark spaces in strings
		%
		basicstyle=\footnotesize,%\color{QtIdentifier},
		%backgroundcolor=\color{BlenderPythonBackground},
    %commentstyle=\color{QtCommentColor}, % comment color
    keywordstyle=\color{BlenderPythonKeyword}, % keyword color
		keywordstyle=[2]{\color{BlenderPythonGold}},
		keywordstyle=[3]{\color{BlenderPythonLiteral}},
    stringstyle=\color{BlenderPythonString}, % string color
		literate={0}{{\textcolor{BlenderPythonLiteral}{0}}}{1}%
             {1}{{\textcolor{BlenderPythonLiteral}{1}}}{1}%
             {2}{{\textcolor{BlenderPythonLiteral}{2}}}{1}%
             {3}{{\textcolor{BlenderPythonLiteral}{3}}}{1}%
             {4}{{\textcolor{BlenderPythonLiteral}{4}}}{1}%
             {5}{{\textcolor{BlenderPythonLiteral}{5}}}{1}%
             {6}{{\textcolor{BlenderPythonLiteral}{6}}}{1}%
             {7}{{\textcolor{BlenderPythonLiteral}{7}}}{1}%
             {8}{{\textcolor{BlenderPythonLiteral}{8}}}{1}%
             {9}{{\textcolor{BlenderPythonLiteral}{9}}}{1}%
             {.0}{{\textcolor{BlenderPythonLiteral}{.0}}}{2}% Following is to ensure that only periods
             {.1}{{\textcolor{BlenderPythonLiteral}{.1}}}{2}% followed by a digit are changed.
             {.2}{{\textcolor{BlenderPythonLiteral}{.2}}}{2}%
             {.3}{{\textcolor{BlenderPythonLiteral}{.3}}}{2}%
             {.4}{{\textcolor{BlenderPythonLiteral}{.4}}}{2}%
             {.5}{{\textcolor{BlenderPythonLiteral}{.5}}}{2}%
             {.6}{{\textcolor{BlenderPythonLiteral}{.6}}}{2}%
             {.7}{{\textcolor{BlenderPythonLiteral}{.7}}}{2}%
             {.8}{{\textcolor{BlenderPythonLiteral}{.8}}}{2}%
             {.9}{{\textcolor{BlenderPythonLiteral}{.9}}}{2}%
						 {type}{type}{4}%
						 {object}{object}{6}%
						 {range}{range}{5}%
						 {len}{len}{3}%
						 {int}{int}{3}%
						 {format}{format}{6}%
}

We won't get into the details of the different parts of the Blender Python script here. The script is given in whole below to close out the example:
\begin{lstlisting}
import bpy
from bpy import context
import numpy as np
import mathutils
from mathutils import Matrix, Vector
import os

def drawDisk(p,R):
    rotm = Matrix(R)
    (x_base, y_base, z_base) = Vector(p) + rotm * Vector((0, 0, -0.001/2))
    (x_top, y_top, z_top) = Vector(p) + rotm * Vector((0, 0, 0.001/2))

    #Curve settings
    curveData = bpy.data.curves.new('myCurve', type='CURVE')
    curveData.dimensions = '!-\textcolor{BlenderPythonString}{3D}-!'
    curveData.resolution_u = 2
    polyline = curveData.splines.new('POLY')
    polyline.points.add(1)
    polyline.points[0].co = (x_base, y_base, z_base, 1)
    polyline.points[1].co = (x_top, y_top, z_top, 1)

    cross_section = bpy.ops.curve.primitive_bezier_circle_add(radius=0.017)
    ob = bpy.context.object
    ob.name = 'cross_section_disk'

    curveOB = bpy.data.objects.new('myCurve', curveData)
    scn = bpy.context.scene
    scn.objects.link(curveOB)
    scn.objects.active = curveOB
    curveOB.select = True
    curveOB.data.bevel_object = bpy.data.objects['cross_section_disk']
    curveOB.data.use_fill_caps = True

    mat = bpy.data.materials.new("RGBA")
    mat.use_transparency = True;
    mat.diffuse_color = (79/255.0, 41/255.0, 132/255.0)
    mat.alpha = 1;
    curveOB.active_material = mat

def drawRod(p):
    (rows,cols) = p.shape

    #Curve settings
    curveData = bpy.data.curves.new('tCurve', type='CURVE')
    curveData.dimensions = '!-\textcolor{BlenderPythonString}{3D}-!'
    curveData.resolution_u = 2
    polyline = curveData.splines.new('POLY')
    polyline.points.add(cols-1)

    cross_section = bpy.ops.curve.primitive_bezier_circle_add(radius=0.001)
    ob = bpy.context.object
    ob.name = 'tcross_section'

    #Loop through spatial steps
    for i in range(0,cols):
    	x,y,z = p[0,i], p[1,i], p[2,i]
    	polyline.points[i].co = (x, y, z, 1)

    curveOB = bpy.data.objects.new('myCurve', curveData)
    scn = bpy.context.scene
    scn.objects.link(curveOB)
    scn.objects.active = curveOB
    curveOB.select = True
    curveOB.data.bevel_object = bpy.data.objects['tcross_section']
    curveOB.data.use_fill_caps = True

def drawTendon(p):
    (rows,cols) = p.shape

    #Curve settings
    curveData = bpy.data.curves.new('tCurve', type='CURVE')
    curveData.dimensions = '!-\textcolor{BlenderPythonString}{3D}-!'
    curveData.resolution_u = 2
    polyline = curveData.splines.new('POLY')
    polyline.points.add(cols-1)

    cross_section = bpy.ops.curve.primitive_bezier_circle_add(radius=0.0003)
    ob = bpy.context.object
    ob.name = 'tcross_section_tendon'

    #Loop through spatial steps
    for i in range(0,cols):
    	x,y,z = p[0,i], p[1,i], p[2,i]
    	polyline.points[i].co = (x, y, z, 1)

    curveOB = bpy.data.objects.new('myCurve', curveData)
    scn = bpy.context.scene
    scn.objects.link(curveOB)
    scn.objects.active = curveOB
    curveOB.select = True
    curveOB.data.bevel_object = bpy.data.objects['tcross_section_tendon']
    curveOB.data.use_fill_caps = True

    mat = bpy.data.materials.new("RGBA")
    mat.use_transparency = True;
    mat.diffuse_color = (255/255.0, 221/255.0, 0)
    mat.alpha = 1;
    curveOB.active_material = mat

### MAIN ###
script_dir = os.getcwd() #<-- absolute path of dir the script is in
bpy.context.scene.world.horizon_color = (1,1,1) #white background
scene = bpy.data.scenes["Scene"]
scene.render.resolution_x = 1280*2
scene.render.resolution_y = 720*2

#Load data
centerline = np.loadtxt( os.path.join(script_dir, 'centerline.dat'))
tendonlines = np.loadtxt( os.path.join(script_dir, 'tendonlines.dat'))
disks = np.loadtxt( os.path.join(script_dir, 'disks.dat'))
num_disks = int(disks.shape[1]/4);
num_tendons = int(tendonlines.shape[0]/3);

#Delete objects already in the scene
for item in bpy.data.objects:
    if item.type == 'MESH' or item.type=='CURVE':
        item.select = True
        bpy.ops.object.delete()

#Create the render
drawRod(centerline)
for i in range(0,num_tendons):
    drawTendon(tendonlines[3*i:3*(i+1), 0:tendonlines.shape[1]])
for i in range(0,num_disks):
    drawDisk(disks[0:3,4*i+3], disks[0:3,4*i:4*i+3])

rel_path = 'output/TendonRobotRender.jpg'
abs_file_path = os.path.join(script_dir, rel_path)
bpy.data.scenes["Scene"].render.filepath = abs_file_path
bpy.ops.render.render( animation=False, write_still=True )
\end{lstlisting}

\end{document}


%
%
%  This file is inserted in the file Segmentation.tex
%
%

\subsection{Overview}
\label{sec:AboutWatersheds}
\index{Watersheds}
\index{Watersheds!Overview}
Watershed segmentation classifies pixels into regions using gradient descent on
image features and analysis of weak points along region boundaries.  Imagine
water raining onto a landscape topology and flowing with gravity to collect in
low basins.  The size of those basins will grow with increasing amounts of
precipitation until they spill into one another, causing small basins to merge
together into larger basins.  Regions (catchment basins) are formed by using
local geometric structure to associate points in the image domain with local
extrema in some feature measurement such as curvature or gradient magnitude.
This technique is less sensitive to user-defined thresholds than classic
region-growing methods, and may be better suited for fusing different types of
features from different data sets.  The watersheds technique is also more
flexible in that it does not produce a single image segmentation, but rather a
hierarchy of segmentations from which a single region or set of regions can be
extracted a-priori, using a threshold, or interactively, with the help of a
graphical user interface
\cite{Yoo1992,Yoo1991}.

The strategy of watershed segmentation is to treat an image $f$ as a height
function, i.e.,  the surface formed by graphing $f$ as a function of its
independent parameters, $\vec{x} \in U$.  The image $f$ is often not the
original input data, but is derived from that data through some filtering,
graded (or fuzzy) feature extraction, or fusion of feature maps from different
sources.  The assumption is that higher values of $f$ (or $-f$) indicate the
presence of boundaries in the original data.  Watersheds may therefore be
considered as a final or intermediate step in a hybrid segmentation method,
where the initial segmentation is the generation of the edge feature map.

Gradient descent associates regions with local minima of $f$ (clearly interior
points) using the watersheds of the graph of $f$, as in
Figure~\ref{fig:segment}.
\begin{figure}
\centering
\includegraphics[width=0.9\textwidth]{WatershedCatchmentBasins.eps}
\itkcaption[Watershed Catchment Basins]{A fuzzy-valued boundary map, from an image
  or set of images, is segmented using local minima and catchment basins.}
\protect\label{fig:segment}
\end{figure}
That is, a segment consists of all points in $U$ whose paths of steepest
descent on the graph of $f$ terminate at the same minimum in $f$.  Thus, there
are as many segments in an image as there are minima in $f$.  The segment
boundaries are ``ridges'' \cite{Koenderink1979,Koenderink1993,Eberly1996} in
the graph of $f$.  In the 1D case ($U \subset \Re$), the watershed boundaries
are the local maxima of $f$, and the results of the watershed segmentation is
trivial.  For higher-dimensional image domains, the watershed boundaries are
not simply local phenomena; they depend on the shape of the entire watershed.

The drawback of watershed segmentation is that it produces a region for each
local minimum---in practice too many regions---and an over segmentation
results.  To alleviate this, we can establish a minimum watershed depth.  The
watershed depth is the difference in height between the watershed minimum and
the lowest boundary point.  In other words, it is the maximum depth of water
a region could hold without flowing into any of its neighbors.  Thus, a
watershed segmentation algorithm can sequentially combine watersheds whose
depths fall below the minimum until all of the watersheds are of sufficient
depth.  This depth measurement can be combined with other saliency
measurements, such as size.  The result is a segmentation containing regions
whose boundaries and size are significant.  Because the merging process is
sequential, it produces a hierarchy of regions, as shown in
Figure~\ref{fig:watersheds}.
\begin{figure}
\centering
\includegraphics[width=0.9\textwidth]{WatershedsHierarchy.eps}
\itkcaption[Watersheds Hierarchy of Regions]{A watershed segmentation combined
with a saliency measure (watershed depth) produces a hierarchy of regions.
Structures can be derived from images by either thresholding the saliency
measure or combining subtrees within the hierarchy.}
\protect\label{fig:watersheds}
\end{figure}
Previous work has shown the benefit of a user-assisted approach that provides
a graphical interface to this hierarchy, so that a technician can quickly move
from the small regions that lie within an area of interest to the union of
regions that correspond to the anatomical structure \cite{Yoo1991}.

There are two different algorithms commonly used to implement watersheds:
top-down and bottom-up.  The top-down, gradient descent strategy was chosen for
ITK because we want to consider the output of multi-scale differential
operators, and the $f$ in question will therefore have floating point
values. The bottom-up strategy starts with seeds at the local minima in the
image and grows regions outward and upward at discrete intensity levels
(equivalent to a sequence of morphological operations and sometimes called {\em
morphological watersheds} \cite{Serra1982}.) This limits the accuracy by
enforcing a set of discrete gray levels on the image.

\begin{figure}
\centering
\includegraphics[width=0.9\textwidth]{WatershedImageFilter.eps}
\itkcaption[Watersheds filter composition]{The construction
of the Insight watersheds filter.}
\protect\label{fig:constructionWatersheds}
\end{figure}

Figure~\ref{fig:constructionWatersheds} shows how the ITK image-to-image
watersheds filter is constructed.  The filter is actually a collection of
smaller filters that modularize the several steps of the algorithm in a
mini-pipeline.  The segmenter object creates the initial segmentation via
steepest descent from each pixel to local minima. Shallow background regions
are removed (flattened) before segmentation using a simple minimum value
threshold (this helps to minimize oversegmentation of the image).  The
initial segmentation is passed to a second sub-filter that generates a
hierarchy of basins to a user-specified maximum watershed depth.  The
relabeler object at the end of the mini-pipeline uses the hierarchy and the
initial segmentation to produce an output image at any scale {\em below} the
user-specified maximum.  Data objects are cached in the mini-pipeline so that
changing watershed depths only requires a (fast) relabeling of the basic
segmentation.  The three parameters that control the filter are shown in
Figure~\ref{fig:constructionWatersheds} connected to their relevant
processing stages.

\subsection{Using the ITK Watershed Filter}
\label{sec:UsingWatersheds}
\index{Watersheds!ImageFilter}
\input{WatershedSegmentation.tex}

%\subsection{Interpreting the Results}
%\label{sec:VisualizingWatersheds}
%\index{Watersheds!Visualization}
%In order to interpret the output of the Insight watersheds algorithm, it is
%important to understand what the output represents and how it is formatted. The
%itk::WatershedImageFilter produces an image of unsigned long integers.  Each
%integer number is a label for a unique segmented region (catchment basin) from
%the original input.  The output is the same size and dimensionality of the
%input.

%Because the segmented image may have potentially many thousands of labels, some
%care must be taken when visualizing the data or information may be lost.  One
%effective way to visualize the output is to map the integer labels into
%distinct RGB colors.  Because labels close in value tend to also be close
%spatially in the image, it is helpful to spread sequential label values far
%apart in the RGB range.  A hashing scheme that puts more weight on the
%least-significant integer bits is a good way to accomplish this.
%Figure~\ref{fig:colorVisWatersheds} shows a slice taken from a segmentation of
%a section of abdomen from the Visible Female Cryosection data.  The unsigned
%long label values of the output have been hashed into RGB colors.

%\begin{figure}
%\centering
%\includegraphics[width=.95\textwidth]{WatershedAbdomenSegmentation.eps}
%\itkcaption[Watershed segmentation of visible woman data]{A slice from a
%segmentation of Visible Female cryosection data.
%The original is shown at the left and the segmented image is shown to the
%right. Colored regions in the segmented image correspond to structures in the
%original data. }
%\protect\label{fig:colorVisWatersheds}
%\end{figure}

%For volumetric data, it is often interesting to create a surface rendering of
%one or more regions in the output.  This can be done by thresholding the
%region(s) of interest from the output image and exporting the result to a
%visualization package capable of isosurface rendering.  Thresholding can be
%done either by explicit manipulation of the image values through an ITK image
%iterator, or using one of the several Insight image thresholding filters.

%Figure~\ref{fig:surfaceRenderingWatersheds} is a surface rendering of the right
%eye, the optic nerve and chiasm, the lens of the eye, and the right lateral
%rectus muscle.  A slice from the original Visible Female head and neck
%cryosection data from which the segmentations were created is shown at the
%left.  This image was created as described above by thresholding isovalues in a
%watershed segmentation output and then rendered using third-party visualization
%software.

%\begin{figure}
%\centering
%\includegraphics[width=0.95\textwidth]{WatershedRendering.eps}
%\itkcaption[Watershed segmenation visualization]{A surface rendering (right)
%of four anatomical structures in the Visible
%Female head and neck. A slice of the data from which the segmentation was
%created is shown at the left.  The right and left optic nerves and chiasm are
%shown in yellow.  The right eye is in transparent purple.  The lens is dark
%purple.  The structure in red is the lateral rectus muscle.}
%\protect\label{fig:surfaceRenderingWatersheds}
%\end{figure}


% ====================================================================
\chapter{Introduction}
\label{sec:Introduction}

% --------------------------------------------------------------------
\section{Purpose}
\label{sec:Purpose}

Describe the purpose for this algorithm.

% ====================================================================
\chapter{Algorithm Details}
\label{sec:AlgorithmDetails}

% --------------------------------------------------------------------
\section{Algorithm Overview}
\label{sec:AlgorithmOverview}

Include an overview of the algorithm from a black box level.
Describe how the algorithm is related to other algorithms.

% --------------------------------------------------------------------
\subsection{Algorithm Inputs}
\label{sec:AlgorithmInputs}

Describe any inputs that the algorithm uses to make
calculations from. Inputs are summarized in \autoref{tab:CCddd-input}.

\begin{table}
  \centering
  \caption{Input information for CCddd.}
  \label{tab:CCddd-input}
  \begin{CCInOutTable}
    % Five (5) columns
    % symbol & description & unit & range & notes \\
    $m$ % mathematical symbol
    & mass % short description
    & \si{\kilo\gram} % dimension of quantity
    & $\mathbb{R} \in (-\infty, \infty)$ % math-valid range
    & {}\footnote{Technically this is the \emph{intertial} mass as opposed to gravitational mass.}\footnote{Negative mass is allowed by the mathematics so it is not an error. However, since negative inertial mass often yields physical paradoxes it is worth a warning.} % notes
    \\%
    $\vec{a}$ % mathematical symbol
    & acceleration\footnote{One-dimensional vector, direction indicated by sign.} % short description
    & \si{\meter\per\second\squared} % dimension of quantity
    & $\mathbb{R} \in (-\infty, \infty)$ % math-valid range
    \\%
  \end{CCInOutTable}
\end{table}

% --------------------------------------------------------------------
\subsection{Algorithm Outputs}
\label{sec:AlgorithmOutputs}

Describe the outputs from the algorithm. Outputs are summarized in \autoref{tab:CCddd-output}.

\begin{table}
  \centering
  \caption{Output information for CCddd.}
  \label{tab:CCddd-output}
  \begin{CCInOutTable}
    % Five (5) columns
    % symbol & description & unit & range & notes \\
    $\vec{F}$ % mathematical symbol
    & force % short description
    & \si{\newton} % dimension of quantity
    & $\mathbb{R} \in (-\infty, \infty)$ % math-valid range
    & % notes
    \\%
  \end{CCInOutTable}
\end{table}

% --------------------------------------------------------------------
\section{Algorithm Description}
\label{sec:AlgorithmDescription}

Detailed description of the algorithm with sufficient fidelity
to allow independent implementation.

% --------------------------------------------------------------------
\subsection{Assumptions / Limitations}
\label{sec:AssumptionsLimitations}

Describe any known limitations or assumptions that went into
the design.

%-%% ====================================================================
%-%\chapter{Trade Studies}
%-%\label{sec:TradeStudies}
%-%
%-%Provide details and results of any trade studies used in the
%-%design of this algorithm.  Should include any optimization studies
%-%used to determine parameter values.  This may just be a summary with
%-%reference to other documents.

% ====================================================================
\chapter{Algorithm Verification}
\label{sec:AlgorithmVerification}

Provide test cases and associated metrics / tolerances to be
used to test that any implementation of the algorithm is correct. Refer to \autoref{tab:CCddd-verification} for a summary of tests.

\begin{table}
  \centering
  \caption{Verification test cases for CCddd.}
  \label{tab:CCddd-verification}
  % These lengths are necessary to avoid white space from the \{top,mid,bottom}rule lines
  \setlength{\aboverulesep}{0pt}
  \setlength{\belowrulesep}{0pt}
  \setlength{\extrarowheight}{.75ex}
  \begin{tabular}{lll>{\columncolor{green}}l}
    \toprule%
    \multicolumn{1}{c}{\bfseries ID}%
    &\multicolumn{1}{c}{\bfseries $m$}%
    &\multicolumn{1}{c}{\bfseries $\vec{a}$}%
    &\multicolumn{1}{>{\columncolor{green}}c}{\bfseries $\vec{F}$}%
    \\%
    \midrule%
    1 & 1 & 1 & 1%
    \\%
    2 & 3.300 & -9.800 & -32.34%
    \\%
    \bottomrule
  \end{tabular}
\end{table}


\documentclass[10pt,a4paper]{article}
\usepackage[textwidth=16cm,textheight=23cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
%\usepackage{url}
\usepackage{hyperref}
\usepackage{bm}

\newcommand{\Trans}{\mathcal{T}}
\newcommand{\filterationF}{\mathcal{F}}
\newcommand{\mkt}{\mathrm{mkt}}
\newcommand{\ytw}{\mathrm{ytw}}
\newcommand{\dd}{\mathrm{d}}
\newcommand{\CRdelta}{\mathrm{CR01}}

\newcommand{\inVaR}{{\mathrm{iv}}}
\newcommand{\notInVaR}{{\mathrm{niv}}}

\usepackage{tcolorbox}
\tcbuselibrary{theorems}

\newtcbtheorem[number within=section]{MyRemark}{Remark}%
{colback=green!5,colframe=green!35!black,fonttitle=\bfseries}{th}

\parindent=0pt
\parskip=1.5ex

\begin{document}

\title{Note on Deal Contingent Trades}
\author{Youngsuk Lee}
\date{26 July 2020}
\maketitle

\section{Structure}

The firm enters a derivative trade such as FX forwards or FX options with a counterparty where the trade is contingent on an agreed deal such as merger, regulatory approval, etc.

Consider such a deal-contingent trade (DCT) and its hedge trade, both of which are booked in the trading book. Figure
\ref{fig:dct-illustration} illustrates two situations:
\begin{itemize}
	\item Deal succeeds where DCT is well hedged throughout its life.
	\item Deal fails where there is a potential sudden P\&L due to (i) the mark-to-market is {\em released} from DCT and
	the PV changes from the {\em naked} hedge.
\end{itemize}

\begin{figure}[h!]
	\begin{center}
		\includegraphics[width=16cm]{figs/dct-illustration.png}
	\end{center}
	\caption{If we put them into the reg VaR and realise the P\&Ls.
%		left: The deal succeeds. right: The deal fails tomorrow. There are two sources of P\&Ls: (i) blue bar with '+': The mark-to-market of DCT drops to zero.
%		(ii) orange bar with '/': The mark-to-market of the hedge trade moves.
	}
	\label{fig:dct-illustration}
	\hrule
\end{figure}

\begin{figure}[h!]
	\begin{center}
		\includegraphics[width=16cm]{figs/dct-illustration-held.png}
	\end{center}
	\caption{
If we put them outside the reg VaR and hold the P\&Ls..
	}
	\label{fig:dct-illustration-held}
	\hrule
\end{figure}

\section{Risk-Not-In-VaR}

\subsection{Risk-Not-In-VaR P\&L}

For typical VaR models, it is not easy to incorporate the risk of deal failures.

To express the P\&L of this missing risk, let
\begin{itemize}
	\item $V$: mark-to-market of DCT
	\item $\bar{V}$: today's mark-to-market
	\item $\Delta V$: random variable to represent the total P\&L in $V$
	\item $\Delta V^\inVaR$: the part of $\Delta V$ included in VaR.

	For example, if DCT is a simple FX forward on the spot rate $z$,
	\begin{equation}
	\Delta V^\inVaR = \delta_z \cdot \Delta Z
	\label{eqn:pnl-in-var-example}
	\end{equation}
	where $\delta_z$ is the first-order sensitivity and $\Delta Z$ is the random variable representing the change in $z$.
	\item $\Delta V^\notInVaR$: the part of $\Delta V$ not included in VaR
	\item $F$ is the random variable indicating the deal failure:
	\begin{equation}
	F = \left\{
	\begin{array}{cl}
		1, & \textrm{if the deal has failed.}\\
		\\
		0, & \textrm{otherwise}
	\end{array}
	\right.
	\end{equation}
\end{itemize}
Then, we have
\begin{equation}
\Delta V = -\bar{V} \cdot F + \Delta V^\inVaR \cdot (1 - F)
\end{equation}
and
\begin{eqnarray}
\Delta V^\notInVaR &=& \Delta V - \Delta V^\inVaR\\
& = & -\bar{V} \cdot F - \Delta V^\inVaR  \cdot F
\end{eqnarray}

With multiple deals, each of which denoted by $i$,
\begin{equation}
\Delta V^\notInVaR = \sum_{i=1}^{I}\left[ - \bar{V}_i \cdot F_i
- \Delta V_i^\inVaR \cdot F_i \right]
\label{eqn:missing-pnl}
\end{equation}

\subsection{Model}

To move Eq (\ref{eqn:missing-pnl}), we use a simple multi-variate normal distribution.

\subsubsection{Failure Indicator}
To model $F_i$, we can use a standard framework used for credit default modelling.

Let $P_i$ be the probability of the deal failure. To simulate the deal failure events, let $X_i$ be an $N(0,1)$ random variable, indicating the deal quality and set
\begin{equation}
F_i := \left\{
\begin{array}{cl}
1, & \textrm{if}\quad \Phi(X_i) < P_i,\\
\\
0, & \textrm{otherwise}
\end{array}
\right.
\end{equation}

For joint simulations of $\{F_i\}_{i=1}^{I}$, the correlation should be specified:
\begin{equation}
\rho^F_{i,j} := \mathrm{corr}(F_i, F_j).
\end{equation}

\subsubsection{VaR P\&Ls}

To model $\Delta V_i^\inVaR$, without loss of generality, assume that it can be written as a function of $\Delta \bm{Z}$, the return distribution of a set of risk factors $\bm{z} = [z_1, \cdots, z_K]$ included in VaR:
\begin{equation}
\Delta V_i^\inVaR := \Delta V_i^\inVaR(\Delta \bm{Z})
\end{equation}
As an example, see Eq (\ref{eqn:pnl-in-var-example}).

\begin{MyRemark}{VaR P\&L functions}{}
$\Delta V_i^\inVaR$ is the same P\&L (approximation) function used in VaR.
\end{MyRemark}

We assume that $\Delta Z$ follows a multi-variate normal distribution with
\begin{equation}
\Delta Z_k \sim N(\mu_k, \sigma_k^2) \quad \textrm{and} \quad \mathrm{corr}(\Delta Z_k, \Delta Z_l) = \rho_{k,l}^{Z}.
\end{equation}

\subsubsection{Correlation: Deal Failures and Risk Factors}

Finally, the correlations among deal quality indices $X_i$'s and VaR risk factors $Z_k$'s should be specified:
\begin{equation}
\rho_{i,k}^{F,Z} = \mathrm{corr}(X_i, Z_k)
\end{equation}

\subsection{Model Parameter Estimations}

{\bf Postulations}: The following parameters are postulated by appropriate {\em experts}:
\begin{itemize}
	\item Failure Probability and Correlations: 	$\{P_i\}$ and $\{\rho^F_{i,j}\}$ where $i, j = 1, \cdots, I$
	\item Deal vs market correlations: $\{ \rho_{i,k}^{F,Z}\}$ for $i = 1, \cdots, I$ and $k = 1, \cdots, K$.

	Due to the nature of typical deal contingent trades, they would be set to zero.

\end{itemize}

{\bf Calibrations}: The following risk factor model parameters
\begin{center}
	$\{\mu_k\}$, $\{\sigma_k\}$ and $\{\rho_{k,l}^Z\}$ where $k, l = 1, \cdots, I$:
\end{center}
would be calibrated to simulated returns of the relevant historical VaR models.

\subsection{Quantification}

\begin{enumerate}
	\item Run standard Monte Carlo simulations on
	\begin{equation}
	\{X_i\}_{i=1}^{I}\quad\textrm{and}\quad\{Z_k\}_{k=1}^{K}.
	\end{equation}
	\item Generate scenarios of the risk-not-in-VaR P\&L $\Delta V^\notInVaR$ using Eq (\ref{eqn:missing-pnl}).
	\item Calculate the 99th tail measure.
\end{enumerate}

\end{document}


\documentclass[12pt]{article}
\usepackage{SteveStyle}

\begin{document}

\title{\texttt{Math 470 - Summary Report}}
\author{Stephen Fay 260844060, under Prof. Gantumur Tsogtgerel}
\date{May 1st to August 31st}
\maketitle

\begin{abstract}
In this project we explore geometric properties of numerical integrators applied to Hamiltonian ordinary differential equations; we study the n-body problem, chosen for it's wealth of symmetries and chaotic behavior. We combine symplectic numerical schemes \cite{Numerical} with projections onto invariant manifolds, which we obtain with well known symmetry methods for dimensionality reduction \cite{Symmetry-methods}. Using backward error analysis we show that the projections violate symplecticity; postulating that projection methods may give rise to an attractor - a subset of the preserved manifold, we investigate the Lyapunov spectrum of our modified equations but find evidence that for $n\geq 3$ the projection methods make the equations \textit{more} chaotic.
\end{abstract}

\section{Symmetry methods}
We look at lie groups, their algebras and their applications to differential equations. We study Noether's theorem at different levels of generality and abstraction; in the language of Lagrangian formalism invariant physical quantities such as energy and total angular momentum are found with Noether's theorem with respect to the kepler problem and the n-body problem.

We look at Pointcar\'e cuts of the Heinon-Heiles system, there appears to exist a first integral but at a critical energy bifurcation occurs and the conserved manifold becomes strange.

\section{Numerical Integration of Hamiltonian ODEs}
Some classical integration schemes are surveyed with an eye kept on applications to Hamiltonian systems: euler methods, midpoint rule, Str\"omer Verlet and Runge-Kutta symplectic methods. After a brief venture into symplectic geometry we discuss the advantages of using symplectic integrators, proving relevant theorems along the way.

Projections onto invariant manifolds are introduced, various algorithms (some of my own inventions) are discussed and compared first with computational experiments, and later analytically. Certain other methods for preserving first integrals which where not implemented, such as solving equations in local coordinates, are also presented.

We apply the methods of backward error analysis to numerical integration schemes and compare the modified vector fields with the exact vector fields / one-forms; we determine second and third order modified terms to add to the modified equations based off of the projections to see if they improve the accuracy of the numerical flows. It is clear from these equations that the projected flows are no longer symplectic, this prompts further investigation of the flows.

We suspect from the experiments that the numerical integrators with projection create an attractor in the two body problem; the experiments showed that if the orbit of the reduced mass starts off with small eccentricity, that the orbit would be attracted to circular motion. Also, numerical simulations of the two and many body problem showed that the projection methods tended to select for trajectories which maximized the angles between first integrals. From these two observations we postulate that the projection methods may give rise to an attractor. By taking the logarithm of the eigenvectors of the eigenvalues of the jacobian, we can estimate the lyapunov spectrum; apply this method to a symplectic integrator for which both the theory and the experiment yield pairs of Lyapunov exponents - each positive exponent has an equal in magnitude corresponding negative exponent (a theorem derived rigorously). If the hypothesis had been correct, we would have gotten that the sum of the spectrum of the projected equations would be negative, instead we found for three and four bodies, that the sum of the eigenvalues was positive, which is evidence for the opposite - that the introduction of projections makes the equations more chaotic rather than giving rise to an attractor.

\section{Conclusions}
Something I found particularly satisfying about working on this project is that the theory and computational experiments complemented each other: the theory was driving the experiments, and the experiments where confirming the theory and driving me in new directions; for instance I would never have (alas, wrongly) suspected the existence of an attractor had I not seen some suspicion in the graphical behavior of numerical solutions to the kepler problem.

Reading literature and diving into textbooks was a fascinating and informative experiance, this has prepared and motivated me to think more ambitiously and I feel I have gained some insight into how research in applied math is conducted.

I was drawn to the kepler problem because I have been wrestling with it's quantum analogue for the last 4 months (Hydrogen atom), and with Noether's theorem in quantum mechanics for the past 11 months.

Many thanks to Prof. Gantumur Tsogtgerel for supporting and inspiring me along the way; and to my peers Selim Amar and Noah Nicodemo for staying in tune with my project and asking pertinant questions.

\bibliographystyle{plain}
\bibliography{MyBibliography}

\end{document}


\chapter{Epilogue}
In this thesis, we have presented a detailed study of bendotaxis -- a new mechanism by which a droplet squeezes itself out of an elastic channel: the capillary pressure of the droplet bends the channel walls confining the droplet in such a way that causes the droplet to move spontaneously.  We have focussed on questions pertinent to the possible application of bendotaxis to self cleaning surfaces, which has motivated consideration of the time scale of motion, physical effects that might impede droplet transport, the influence of channel geometry, and the collaborative effects that arise between neighbouring channels. In this chapter we summarize our results and suggest some ideas for further work.

\section{Summary of the thesis}
We began in Chapter 1 with a discussion of the mechanism of bendotaxis: the Laplace pressure within a droplet induces a tapering of the confining channel that drives it towards the free end. By considering this mechanism, we predicted that the direction of motion is universal -- droplets should be transported to the free end, regardless of whether they wet the channel or not -- and verified this with a proof-of-concept experiment.

Having shown that the direction of bendotaxis is universal, we turned in Chapter~2 to develop a two-dimensional dynamic model of bendotaxis. The physical processes represented by our model were motivated by the proof of concept experiment of Chapter~1; in particular, we exploited the small aspect ratio of the droplet and the slenderness of the channel walls to reduce the dimensionality of the problem. The resulting spatially one-dimensional system of PDEs that describe this model were solved numerically; using these solutions, we verified that wettability independent droplet transport is a feature that is reproduced by our model and identified three key characteristic features of the dynamics of bendotaxis in two-dimensional channels: Firstly, motion occurs on two time scales: a short time scale on which the channel walls respond to a torque imbalance by bending rapidly (causing the droplet to spread), and a longer time scale on which droplets translate to the free end. Secondly, even in the absence of inertia, droplets accelerate along the channel, in contrast to bendo-capillary imbibition from a fixed bath of liquid, for which the leading meniscus decelerates throughout the motion. Finally,  when surface tension is sufficiently strong, the channel walls touch before the droplet reaches the free end. We made analytic progress in understanding the first two of these observations by assuming small channel wall deflections;  this asymptotic analysis suggested that the time scale of bendotaxis is inversely proportional to the product of the channel bendability $\nu$ and the droplet volume $V$, as a scaling argument valid for small droplets also suggested. The mathematical model provides some insight that could inform the design of superhydrophobic surfaces  that exploit bendotaxis for anti-fogging. In particular, we noted that more compliant channels will transport droplets faster (it would be desirable to remove droplets from such a surface as quickly as possible), but this faster transport must be balanced with the increased risk of trapping the droplets within the channel, thereby compromising the surface’s performance.

In Chapter 3, we presented an experimental study of bendotaxis. The experimental setup was similar to that in the proof of concept experiments of Chapter 1, except that the parameters of the system (specifically the channel geometry, droplet viscosity, and channel wall stiffness) were systematically varied to present a robust test of the mathematical model developed in Chapter 2. The experimental droplet trajectories have a similar shape and time scale of motion to those predicted by the analysis of our model (both from scaling, asymptotics, and numerics). Nevertheless, the experimentally observed motion was systematically slower than predicted -- a discrepancy that is consistent with the two-dimensional nature of our theory and the  associated overestimation of the relative droplet volume. To facilitate comparison of a much larger data set and reduce dependence on initial conditions, we introduced the time taken to traverse a section of the channel as a proxy for the full dynamics represented by the trajectories. Analysis of the experimental data showed that the small volume result of Chapter 2 describes the dynamics reasonably well, even when the droplet has finite volume. Moreover, this analysis showed that deviations from the small volume result -- the non-linearity associated with larger channel deflections, and the finite drop size effects predicted by the model -- are represented in the experimental data in a way that is consistent with the model predictions.

In Chapter 4, we considered two mechanisms by which droplets might become trapped in channels whilst undergoing bendotaxis. The first of these was geometric trapping, which describes the scenario first encountered in Chapter~2 in which the channel walls touch before the droplet reaches the free end. We built upon the ideas of Chapter~2, where we saw that the channel bendability for which droplet trapping occurs is reasonably insensitive to the droplet volume and initial position, provided that the droplet starts reasonably far from the free end of the channel. In particular, we extended our model of bendotaxis to describe the behaviour beyond the point of wall contact, and identified two post contact  scenarios -- channel walls touching at a single point, and channel walls making contact along a portion of their length, the latter occuring only when the channel bendability $\nu$ is very large. Numerical solutions of the model equations display complex dynamics that result from the strong squeezing at early times that is associated with large channel bendability, as well as from the competition between two diverging quantities (the meniscus pressure and viscous dissipation) as the droplet advances into a channel of vanishing thickness.
%If, on the one hand, the meniscus approaches the end of the channel while the walls are simply touching, it appears to reach the end in finite time with asymptotic behaviour faster than the corresponding rigid case. On the other hand, if the meniscus approaches the end of a channel whose walls are in contact along a portion of their length (making a cusp at the contact point), the meniscus appears to take an infinite amount of time to reach the cusp.

In the second half of Chapter 4, we considered when droplets may be trapped as a result of contact angle hysteresis. We extended the model to encode the idea of a non-unique contact angle at a stationary interface and supplemented this with the simplest possible contact angle dynamics.  In numerical solutions, we saw that droplets may be trapped (reach equilibria) part way along the channel, but this depends critically on whether the contact angle asymmetry across the droplet that is allowed by the given contact angle hysteresis is sufficient to permit an equilibrium. We mapped out the conditions under which such an equilibrium is possible and found, in particular, that for a given droplet, it may `escape' the channel provided that it starts close enough to the free end. Further, we found that droplets are more likely to be trapped in channels with higher contact angle hysteresis, confirming the need to minimize hysteresis in any superhydrophobic surface that seeks to exploit bendotaxis for anti-fogging. We also verified that the trapped states are indeed equilibria, that they are linearly stable, and that droplets will never translate to equilibrium -- heuristically, once droplets `get going' they will not be stopped.

In Chapter 5, we sought to understand the weaving instability that is observed in experiments of condensation of droplets into deformable microchannels~\citep{Seemann2011JPhysCondMat}. In doing so, we identified a novel bendo-capillary instability that is reminiscient of the Rayleigh-Plateau instability (in that it relies on a competition between the principal interfacial curvatures) and the instability described by~\cite{AlHousseiny2012NaturePhysics} (in that it is mediated by the channel that confines the liquid). Unlike the rigid (Al-Housseiny) case, however, the channel tapering in the bendo-capillary case is set by the liquid pressure meaning that both wetting and non-wetting liquids may, in theory, experience instability in the same channel. To study this bendo-capillary instability, we developed a mathematical model of a three-dimensional system and again exploited linear beam theory and lubrication theory to reduce its dimensionality. We focussed first on the no condensation case, where equilibria are possible. A linear stability analysis revealed that these equilibria are unstable to perturbations of a sufficiently small wavenumber and that the corresponding growth rates are highly sensitive to the amount of liquid in the channel, which is parametrized by the cross-sectional volume $V$. We then considered the effect of a non-zero condensation rate, which changed the picture in two important ways: (i) the cross-sectional volume $V$ becomes time-dependent, and (ii) condensation may drive dynamic effects in the (now time-dependent) base state. We saw that when the condensation rate is small, condensation enters only through the instantaneous value of $V$ and the instantaneous growth rate of a perturbation is given by the corresponding zero-condensation result; as a consequence of the sensitivity of the zero-condensation results to $V$, we saw how modes that grow slowly at first are able to catch up with, and overtake, those that grow faster initially. We speculated that these later modes reach the non-linear regime sooner. Numerical solutions of the linearized equations revealed that this mechanism is also present for condensation rates of any size, but interacts with the condensation driven dynamics. This tends to enhance the instantaneous growth rate and lengthen the band of unstable modes (compared to the quasistatic case) with longer wavelength modes being enhanced preferentially. Despite the simplicity of our model, its predictions agree in their order of magnitude with the condensation experiments of~\cite{Seemann2011JPhysCondMat}.

In Chapter 6, we sought to understand how multiple droplets in neighbouring channels might affect each other's bendotaxis -- a question relevant not only for self cleaning surfaces (which naturally have many channels) but also for the condensation experiments in which the weaving instability occurs simultaneously in neighbouring channels. We developed a mathematical model of this `multi-body’ bendotaxis in which, for simplicity, we assumed that the channel walls are rigid, and are tethered at their base by torsional elastic springs. As part of the model development, we identified the importance of a parameter $\Gamma$  that encodes the ability of the individual droplets to deform the channel that confines them, and is analogous to the bendability $\nu$ used throughout Chapters 2--5. Importantly, this torsional spring model is also able to describe wettability-independent droplet transport in a single channel. Modelling with torsional springs (rather than the potentially more realistic beam theory applied elsewhere in this thesis) simplifies the model equations to a system of ODEs which have an equilibrium corresponding to equal volume droplets in un-deformed channels. A linear stability analysis revealed that this equilibrium is always unstable and we do not, therefore, expect to see it in practice. Moreover, the linear stability analysis suggested that a pairwise mode is always the fastest growing. However, numerical solutions of the governing ODEs with an initial condition close to the equilibrium displayed a range of cluster sizes. For small $\Gamma$, the system almost always selects the pairwise mode (in accord with the linear stability analysis) because the angle of the channel walls (and thus direction of droplet motion) is set simply by the difference in position of droplets across them. We rationalized this result with an analysis that considers the governing ODEs in the case of small deflections that are associated with small $\Gamma$. For large $\Gamma$, however, a distribution of cluster sizes were observed, with a maximal size that scales with $\Gamma^{1/2}$. By using a discrete-to-continuum approximation of the ODEs, we suggested that this appears to be the result of the propagation of fronts through the system which `lock in' clusters of this set size; with a random initial condition, these fronts interact with one another to `smooth out' the cluster sizes between the pairwise mode preferred by the linear stability analysis and the maximal cluster size set by the front propagation. We also considered the implications of this model for self-cleaning surfaces exploiting bendotaxis; the key result is that for larger $\Gamma$, a greater proportion of droplets reach the free end, but they do so in channels that are almost closed at the free end, and thus potentially difficult for droplets to be removed from.

\section{Future work}
In this section, we provide a brief overview of how the work presented in this thesis might be extended.

We hypothesized in Chapter 3 that some of the discrepancies between experimental data and the predictions of the model of Chapter 2 are a result of  the two-dimensional nature of the model, which does not account for the fact that the length of the droplet (and interfacial curvature) vary in the third dimension in the experiments. It would be useful to quantify these effects and thereby assess the validity of this hypothesis. We anticipate that to do so, the mathematical model of Chapter 2 could be extended to describe variations of a finite extent in the third spatial direction (similar to the model of Chapter 5, although there the liquid had infinite extent in the third direction). With geometric extensions to the model of Chapter 2 in mind, one might also consider how the shape of the channel walls influences the dynamics of bendotaxis; in particular, one might take further inspiration from the setae of the water strider, which played an important role in the problem that provided our original motivation for studying bendotaxis. The setae are conically shaped, and they should, therefore, have a lower resistance to deformation at their tip than at their base; this should, in turn, exacerbate the relative `softness' of the free end of the channel, potentially increasing the speed of motion of droplet transport, but increasing the risk of trapping. A first step towards modelling this softening might be to consider the two-dimensional configuration of Chapter 2 with a variable bending stiffness $B = B(x)$. (Indeed, with a variable bending stiffness, many more possibilities open up, such as bendotaxis in tubes, which could be useful for micro-fluidic applications.)

In Chapter 4, we observed numerically that a droplet approaching the end of a channel whose walls are in contact at a single point appear to be able to reach this contact point in finite time (approaching with power law behaviour), but a droplet approaching the end of a channel whose walls are in contact over a portion of their length appear to take an infinite time to do so. It would be good to confirm and rationalize this behaviour, perhaps using an asymptotic approximation of the solution as the droplet approaches the contact point.

We focussed in Chapter 4 on identifying when droplets are trapped with a view to preventing this from happening, but, in other situations, this behaviour could perhaps be turned to our advantage. Indeed,  the trapping of droplets in tapered channels that results from contact angle hysteresis is believed to be part of a wider `capillary ratchet' mechanism that is exploited by feeding shorebirds~\citep{Prakash2008Science}. Furthermore, with modifications to the channel set-up, additional possibilities for droplet control might open up; for example, by controlling tapering angle of the channel walls at the clamped end, we can imagine a scenario in which only droplets with a sufficiently large surface tension are transported to the free end, whilst others are trapped, and others still (of the same wettability) are transported to the clamped end of the channel.

The natural extension to our study of the bendo-capillary instability in Chapter 5 is to solve the corresponding non-linear equations numerically. This would allow us to assess how the linearly unstable modes interact with one another as well as to predict which mode will ultimately be observed at late times, once the linearized analysis is no longer valid. We stress, however, that this is not a simple task for myriad reasons. For example, care is required in discretizing the biharmonic operator in the beam equation on a moving domain, fluid and solid deformations must be solved for simultaneously (leading to a large number of degrees of freedom), and the free surface must be appropriately parametrized.

It would also be interesting to study how the mobility of the liquid affects the bendo-capillary instability; we assumed for simplicity that the liquid is sat at the base of the channel but a similar instability should occur if there is a second meniscus closer to the clamped end (a scenario that would be more appropriate for bendotaxis). In that case, there are potentially two modes of instability, depending on whether the protrusions of the perturbation to the leading meniscus are in phase or out of phase with those at the trailing meniscus (sinusoidal or varicose modes).

There are several ways in which the study of multi-body bendotaxis in Chapter 6 could be extended. Most pressingly, we assumed that the droplets have a constant volume, and focussed primarily on the case when each droplet has the same volume. This is often not the case in experiments of bendo-capillary clustering (for example, in the condensation experiments which provide motivation). In addition, a recent study by~\cite{Hadjittofis2016JFM} identified how mass changes in a similar system can exert a strong influence on the dynamic behaviour, both suppressing or enhancing clustering depending on how quickly it occurs. One might extend this work further to imagine a scenario in which droplets nearer to the free end are evaporated preferentially; this may exert a stabilizing control on our system, which is always unstable when droplet volumes are constant.

With respect to self cleaning surfaces that could exploit bendotaxis, it would be useful to consider boundary conditions other than periodic in the $y$ direction because, after all, a real surface would have finite extent. Beyond the channel geometry considered here, one might extend our model to include two dimensional arrays of pillars; key difficulties with this would be that surface tension forces require a more careful calculation (because of the three-dimensional menisci), and resistive forces from the lubricating flow might be reduced because the liquid can flow in two directions.

Finally, we note that in the second part of this thesis, we took much inspiration from the condensation experiments of~\cite{Seemann2011JPhysCondMat}, but made progress towards understanding the observations by decoupling the behaviour into the weaving instability in a single channel and the interaction between bendotaxis in neighbouring two-dimensional channels. For a model that is more faithful to the experiments, one would have to couple these two together (i.e. Chapters 5 and 6), as well as account for droplets and contact angle hysteresis (Chapter 4), all of which would pose a significant modelling challenge.


\section{The \texttt{VMask} class}

The \verb+VMask+ class is an abstraction over the VIPS \verb+DOUBLEMASK+ and
\verb+INTMASK+ types which gives convenient and safe representation of
matricies.

\verb+VMask+ has two sub-classes, \verb+VIMask+ and \verb+VDMask+. These
represent matricies of integers and doubles respectively.

\subsection{Constructors}

There are four constructors for \verb+VIMask+ and \verb+VDMask+:

\begin{verbatim}
VIMask( int xsize, int ysize );
VIMask( int xsize, int ysize,
  int scale, int offset, ... );
VIMask( int xsize, int ysize,
  int scale, int offset,
  std::vector<int> coeff );
VIMask( const char *name );
VIMask();
VDMask( int xsize, int ysize );
VDMask( int xsize, int ysize,
  double scale, double offset, ... );
VDMask( int xsize, int ysize,
  double scale, double offset,
  std::vector<double> coeff );
VDMask( const char *name );
VDMask();
\end{verbatim}

The first form creates an empty matrix, with the specified dimensions;
the second form initialises a matrix from a varargs list; the third form
sets the matrix from a vector of coefficients; the fourth from the named file.
The final form makes a mask object with no contents yet.

The varargs constructors are not wrapped in Python --- use the vector
constructor instead. For example:

\begin{verbatim}
m = VMask.VIMask (3, 3, 1, 0,
		  [-1, -1, -1,
		   -1,  8, -1,
		   -1, -1, -1])
\end{verbatim}

\subsection{Projection functions}

A set of member functions of \verb+VIMask+ provide access to the fields in
the matrix:

\begin{verbatim}
int xsize() const;
int ysize() const;
int scale() const;
int offset() const;
const char *filename() const;
\end{verbatim}

\verb+VDMask+ is the same, except that the \verb+scale()+ and \verb+offset()+
members return \verb+double+. \verb+VMask+ allows all operations that are
common to \verb+VIMask+ and \verb+VDMask+.

\subsection{Assignment}

\verb+VMask+ defines copy and assignment with pointer-style
semantics. You can write stuff like:

\begin{verbatim}
VIMask fred( "mask" );
VMask jim;

jim = fred;
\end{verbatim}

This reads the file \verb+mask+, noting a pointer to the mask in \verb+fred+.
It then makes \verb+jim+ also point to it, so \verb+jim+ and \verb+fred+ are
sharing the same underlying matrix values.

Internally, a \verb+VMask+ object is just a pointer to a reference-counting
block, which in turn holds a pointer to the underlying VIPS \verb+MASK+ type.
You can therefore efficiently pass \verb+VMask+ objects to functions by
value, and return \verb+VMask+ objects as function results.

\subsection{Computing with \texttt{VMask}}

You can use \verb+[]+ to get at matrix elements, numbered left-to-right,
top-to-bottom. Alternatively, use \verb+()+ to address elements by $x,y$
position. For example:

\begin{verbatim}
VIMask fred( "mask" );

for( int i = 0; i < fred.xsize(); i++ )
    fred[i] = 12;
\end{verbatim}

\noindent
will set the first line of the matrix to 12, and:

\begin{verbatim}
VDMask fred( "mask" );

for( int x = 0; x < fred.xsize(); x++ )
    fred(x, x) = 12.0;
\end{verbatim}

\noindent
will set the leading diagonal to 12.

See the member functions below for other operations on \verb+VMask+.

\subsection{\texttt{VIMask} operations}

The following operations are defined for \verb+VIMask+:

\begin{verbatim}
// Cast to VDMask and VImage
operator VDMask();
operator VImage();

// Build gaussian and log masks
static VIMask gauss( double, double );
static VIMask log( double, double );

// Rotate
VIMask rotate45();
VIMask rotate90();

// Transpose, invert, join and multiply
VDMask trn() ;
VDMask inv();
VDMask cat( VDMask );
VDMask mul( VDMask );
\end{verbatim}

\subsection{\texttt{VDMask} operations}

The following operations are defined for \verb+VDMask+:

\begin{verbatim}
// Cast to VIMask and VImage
operator VIMask();
operator VImage();

// Build gauss and log masks
static VDMask gauss( double, double );
static VDMask log( double, double );

// Rotate
VDMask rotate45();
VDMask rotate90();

// Scale to intmask
VIMask scalei();

// Transpose, invert, join and multiply
VDMask trn();
VDMask inv();
VDMask cat( VDMask );
VDMask mul( VDMask );
\end{verbatim}

\subsection{Output of masks}

You can output masks with the usual \verb+<<+ operator.