\label{ch:gravity}

\section{Introduction}

\subsection{Integration Strategy}

\castro\ uses subcycling to integrate levels at different timesteps.
The gravity algorithm needs to respect this.  Self-gravity is computed
via multigrid.  At coarse-fine interfaces, the stencil used in the
Laplacian understands the coarse-fine interface and is different than
the stencil used in the interior.

There are two types of
solves that we discuss with AMR:
\begin{itemize}
\item {\em composite solve} : This is a multilevel solve, starting at
  a coarse level (usually level 0) and solving for the potential on
  all levels up to the finest level.

\item {\em level solve} : This solves for the potential only on
 a particular level.  Finer levels are ignored.  At coarse-fine
 interfaces, the data from the coarse levels acts as Dirichlet
 boundary conditions for the current-level-solve.
\end{itemize}

The overall integration strategy is unchanged from the discussion in
\cite{castro_I}.  Briefly:
\begin{itemize}
\item At the beginning of a simulation, we do a multilevel composite
  solve (if \runparam{gravity.no\_composite}{\tt = 0}).

  We also do a multilevel composite solve after each regrid.

\item The old-time gravity on the coarse level is defined based on
  this composite solve, but we also do a level solve on the coarse
  level, and use it to determine the difference between the composite
  solve and the level solve, and store that in a \multifab.

\item After the hydro advance on the coarse level, we do another level
  solve, and use the (level solve $-$ compositive solve) as a lagged
  predictor of how much we need to add back to that level solve to get
  an effective new-time value for phi on the coarse level, and that's
  what defines the phi used for the new-time gravity

\item Then we do the fine grid timestep(s), each using the same
  strategy

\item At an AMR synchronization step across levels (see Section \ref{sec:amr_synchronization}
  for a description of when these synchronizations occur), if we're choosing
  to synchronize the gravitational field across levels (\runparam{gravity.no\_sync}{\tt = 0})
  we then do a solve starting from
  the coarse grid that adjusts for the mismatch between the fine-grid
  phi and the coarse-grid phi, as well as the mismatch between the
  fine-grid density fluxes and the coarse-grid density fluxes, and add
  the resulting sync solve phi to both the coarse and the fine level

  Thus, to within the gravity error tolerance, you get the same final
  result as if you had done a full composite solve at the end of the
  timestep (assuming \runparam{gravity.no\_sync}{\tt = 0}).
\end{itemize}

If you do \runparam{gravity.no\_composite}{\tt = 1}, then you never do a full
multilevel solve, and the gravity on any level is defined only by the
solve on that level.  The only time this would be appropriate is if
the fine level(s) cover essentially all of the mass on the grid for
all time.

\subsection{Controls}
\castro\ can incorporate gravity as a constant, monopole approximation,
or a full Poisson solve.  To enable gravity in the code, set:
\begin{verbatim}
USE_GRAV = TRUE
\end{verbatim}
in the {\tt GNUmakefile}, and then turn it on in the {\tt inputs} file
via {\tt castro.do\_grav = 1}.  If you want to incorporate a point mass
(through {\tt castro.point\_mass}), you must have
\begin{verbatim}
USE_POINTMASS = TRUE
\end{verbatim}
in the {\tt GNUmakefile}.

There are currently four options for how gravity is calculated,
controlled by setting \runparam{gravity.gravity\_type}.  The options are
{\tt ConstantGrav, PoissonGrav, Monopole Grav} or {\tt
  PrescribedGrav}.  Again, these are only relevant if {\tt USE\_GRAV =
  TRUE} in the {\tt GNUmakefile} and {\tt castro.do\_grav = 1} in the
{\tt inputs} file.  If both of these are set then the user is required
to specify the gravity type in the inputs file or the program will
abort.

Some additional notes:
\begin{itemize}

\item For the full Poisson solver
  (\runparam{gravity.gravity\_type}{\tt = PoissonGrav}), the behavior
  of the full Poisson solve / multigrid solver is controlled by
  \runparam{gravity.no\_sync} and \runparam{gravity.no\_composite}.

\item For isolated boundary conditions, and when
  \runparam{gravity.gravity\_type}{\tt = PoissonGrav}, the parameters
           {\tt gravity.max\_multipole\_order} and
           \runparam{gravity.direct\_sum\_bcs} control the accuracy of
           the Dirichlet boundary conditions.  These are described in
           Section \ref{sec-poisson-3d-bcs}.

\item For {\tt MonopoleGrav}, in 1D we must have {\tt coord\_sys = 2}, and in
  2D we must have {\tt coord\_sys = 1}.
\end{itemize}

The following parameters apply to gravity
solves:
\begin{itemize}
\item \runparam{gravity.gravity\_type} : how should we calculate gravity?
  Can be {\tt ConstantGrav}, {\tt PoissonGrav}, {\tt MonopoleGrav}, or
  {\tt PrescribedGrav}

\item \runparam{gravity.const\_grav} : if {\tt gravity.gravity\_type =
  ConstantGrav}, set the value of constant gravity (default: 0.0)

\item \runparam{gravity.no\_sync} : {\tt gravity.gravity\_type =
  PoissonGrav}, do we perform the ``sync solve"? (0 or 1; default: 0)

\item \runparam{gravity.no\_composite} : if {\tt gravity.gravity\_type
  = PoissonGrav}, whether to perform a composite solve (0 or 1;
  default: 0)

\item \runparam{gravity.max\_solve\_level} : maximum level to solve
  for $\phi$ and $\mathbf{g}$; above this level, interpolate from
  below (default: ${\tt MAX\_LEV} - 1$)

\item \runparam{gravity.abs\_tol} : if {\tt gravity.gravity\_type =
  PoissonGrav}, this is the absolute tolerance for the Poisson
  solve. You can specify a single value for this tolerane (or do
  nothing, and get a reasonable default value), and then the absolute
  tolerance used by the multigrid solve is $\text{abs\_tol} \times
  4\pi G\, \rho_{\text{max}}$ where $\rho_{\text{max}}$ is the maximum
  value of the density on the domain.  On fine levels, this absolute
  tolerance is multiplied by $\text{ref\_ratio}^2$ to account for the
  change in the absolute scale of the Laplacian operator.  You can
  also specify an array of values for \text{abs\_tol}, one for each
  possible level in the simulation, and then the scaling by
  $\text{ref\_ratio}^2$ is not applied.

\item \runparam{\tt gravity.rel\_tol} : if {\tt gravity.gravity\_type
  = PoissonGrav}, this is the relative tolerance for the Poisson
  solve. By default it is zero. You can specify a single value for
  this tolerance and it will apply on every level, or you can specify
  an array of values for \text{rel\_tol}, one for each possible level
  in the simulation. This replaces the old parameter
  \runparam{gravity.ml\_tol}.

\item \runparam{gravity.max\_multipole\_order} : if {\tt
  gravity.gravity\_type = PoissonGrav}, this is the max $\ell$ value
  to use for multipole BCs (must be $\geq 0$; default: 0)

\item \runparam{gravity.direct\_sum\_bcs} : if {\tt
  gravity.gravity\_type = PoissonGrav}, evaluate BCs using exact sum
  (0 or 1; default: 0)

\item \runparam{gravity.drdxfac} : ratio of dr for monopole gravity
  binning to grid resolution
\end{itemize}

The follow parameters affect the coupling of hydro and gravity:
\begin{itemize}
\item \runparam{castro.do\_grav} : turn on/off gravity

\item \runparam{castro.moving\_center} : do we recompute the center
   used for the multipole gravity solver each step?

\item \runparam{castro.point\_mass} : point mass at the center of the star
  (must be $\geq 0$; default: 0.0)
\end{itemize}

Note that in the following, {\tt MAX\_LEV} is a hard-coded parameter
in {\tt Source/Gravity.cpp} which is currently set to {\tt 15}.  It
determines how many levels can be tracked by the {\tt Gravity} object.

\section{Types of Approximations}

\subsection{{\tt ConstantGrav}}

Gravity can be defined as constant in direction and magnitude,
defined in the inputs file by

\noindent {\tt gravity.const\_grav = -9.8}

for example, to set the gravity to have magnitude $9.8$ in the
negative $y$-direction if in 2D, negative $z$-direction if in 3-D.
The actual setting is done in {\tt Gravity.cpp} as:
\begin{lstlisting}
 grav.setVal(const_grav, BL_SPACEDIM-1, 1, ng);
\end{lstlisting}

Note that at present we do not fill the gravitational potential $\phi$ in
this mode; it will be set to zero.

Note: {\tt ConstantGrav} can only be used along a Cartesian direction
(vertical for 2D axisymmetric).

\subsection{{\tt MonopoleGrav}}
\label{sec-monopole-grav}

{\tt MonopoleGrav} integrates the mass distribution on the grid
in spherical shells, defining an {\tt enclosed mass} and uses this
to compute the gravitational potential and acceleration in a
spherically-symmetric fashion.

\begin{itemize}

\item In 1D spherical coordinates we compute
  \begin{equation}
    g(r) = -\frac{G M_{\rm enclosed}}{ r^2}
  \end{equation}
  where $M_{\rm enclosed}$ is calculated from the density at the time
  of the call.

  For levels above the coarsest level we define the extent of that
  level's radial arrays as ranging from the center of the star ($r=0$)
  to the cell at that level farthest away from the origin.  If there
  are gaps between fine grids in that range then we interpolate the
  density from a coarser level in order to construct a continuous
  density profile.  We note that the location of values in the density
  profile and in the gravitational field exactly match the location of
  data at that level so there is no need to interpolate between points
  when mapping the 1D radial profile of $g$ back onto the original
  grid.

\item In 2D or 3D we compute a 1D radial average of density and use
  this to compute gravity as a one-dimensional integral, then
  interpolate the gravity vector back onto the Cartesian grid
  cells. At the coarsest level we define the extent of the 1D arrays
  as ranging from the center of the star to the farthest possible
  point in the grid (plus a few extra cells so that we can fill ghost
  cell values of gravity).  At finer levels we first define a single
  box that contains all boxes on that fine level, then we interpolate
  density from coarser levels as needed to fill the value of density
  at every fine cell in that box.  The extent of the radial array is
  from the center of the star to the {\em nearest} cell on one of the
  faces of the single box.  This ensures that all cells at that
  maximum radius of the array are contained in this box.

We then average the density onto a 1D radial array.  We note that
there is a mapping from the Cartesian cells to the radial array and
back; unlike the 1D case this requires interpolation. We use quadratic
interpolation with limiting so that the interpolation does not create
new maxima or minima.

The default resolution of the radial arrays at a level is the grid
cell spacing at that level, i.e., $\Delta r = \Delta x$. O For
increased accuracy, one can define \runparam{gravity.drdxfac} as a number
greater than $1$ ($2$ or $4$ are recommended) and the spacing of the
radial array will then satisfy $\Delta x / \Delta r = $ {\tt drdxfac}.
Individual Cartesian grid cells are subdivided by {\tt drdxfac} in
each coordinate direction for the purposing of averaging the density,
and the integration that creates $g$ is done at the finer resolution
of the new $\Delta r$.

Note that the center of the star is defined in the subroutine {\tt PROBINIT}
and the radius is computed as the distance from that center.

\MarginPar{there is an additional correction at the corners in {\tt
    make\_radial\_grav} that accounts for the volume in a shell that
  is not part of the grid}

\end{itemize}

{\color{red} What about the potential in this case? when does {\tt
    make\_radial\_phi} come into play?}

\subsection{{\tt PoissonGrav}}

The most general case is a self-induced gravitational field,
\begin{equation}
\mathbf{g}(\mathbf{x},t) = \nabla \phi
\end{equation}
where $\phi$ is defined by solving
\begin{equation}
\mathbf{\Delta} \phi = 4 \pi G \rho .\label{eq:Self Gravity}
\end{equation}

We only allow {\tt PoissonGrav} in 2D or 3D because in 1D, computing
the monopole approximation in spherical coordinates is faster and more
accurate than solving the Poisson equation.

\subsubsection{Poisson Boundary Conditions: 2D}

In 2D, if boundary conditions are not periodic in both directions, we
use a monopole approximation at the coarsest level. This involves
computing an effective 1D radial density profile (on {\tt level =
  0} only), integrating it outwards from the center to get the
gravitational acceleration $\mathbf{g}$, and then integrating $g$
outwards from the center to get $\phi$ (using $\phi(0) = 0$ as a
boundary condition, since no mass is enclosed at $r = 0$). For more
details, see Section \ref{sec-monopole-grav}.

\subsubsection{Poisson Boundary Conditions: 3D}\label{sec-poisson-3d-bcs}

The following describes methods for doing isolated boundary
conditions.  The best reference for \castro's implementation of this
is \cite{katz:2016}.

\begin{itemize}
\item \textbf{Multipole Expansion}

In 3D, by default, we use a multipole expansion to estimate the value
of the boundary conditions. According to, for example, Jackson's
\textit{Classical Electrodynamics} (with the corresponding change to
Poisson's equation for electric charges and gravitational
''charges''), an expansion in spherical harmonics for $\phi$ is
\begin{equation}
  \phi(\mathbf{x}) = -G\sum_{l=0}^{\infty}\sum_{m=-l}^{l} \frac{4\pi}{2l + 1} q_{lm} \frac{Y_{lm}(\theta,\phi)}{r^{l+1}}, \label{spherical_harmonic_expansion}
\end{equation}
The origin of the coordinate system is taken to be the \texttt{center}
variable, that must be declared and stored in the \texttt{probdata}
module in your project directory. The validity of the expansion used
here is based on the assumption that a sphere centered on
\texttt{center}, of radius approximately equal to the size of half the
domain, would enclose all of the mass. Furthermore, the lowest order
terms in the expansion capture further and further departures from
spherical symmetry. Therefore, it is crucial that \texttt{center} be
near the center of mass of the system, for this approach to achieve
good results.

The multipole moments $q_{lm}$ can be calculated by expanding the
Green's function for the Poisson equation as a series of spherical
harmonics, which yields
\begin{equation}
  q_{lm} = \int Y^*_{lm}(\theta^\prime, \phi^\prime)\, {r^\prime}^l \rho(\mathbf{x}^\prime)\, d^3x^\prime. \label{multipole_moments_original}
\end{equation}
Some simplification of Equation \ref{spherical_harmonic_expansion} can
be achieved by using the addition theorem for spherical harmonics:
\begin{align}
  &\frac{4\pi}{2l+1} \sum_{m=-l}^{l} Y^*_{lm}(\theta^\prime,\phi^\prime)\, Y_{lm}(\theta, \phi) = P_l(\text{cos}\, \theta) P_l(\text{cos}\, \theta^\prime) \notag \\
  &\ \ + 2 \sum_{m=1}^{l} \frac{(l-m)!}{(l+m)!} P_{l}^{m}(\text{cos}\, \theta)\, P_{l}^{m}(\text{cos}\, \theta^\prime)\, \left[\text{cos}(m\phi)\, \text{cos}(m\phi^\prime) + \text{sin}(m\phi)\, \text{sin}(m\phi^\prime)\right].
\end{align}
Here the $P_{l}^{m}$ are the associated Legendre polynomials and the
$P_l$ are the Legendre polynomials. After some algebraic
simplification, the potential outside of the mass distribution can be
written in the following way:
\begin{equation}
  \phi(\mathbf{x}) \approx -G\sum_{l=0}^{l_{\text{max}}} \left[Q_l^{(0)} \frac{P_l(\text{cos}\, \theta)}{r^{l+1}} + \sum_{m = 1}^{l}\left[ Q_{lm}^{(C)}\, \text{cos}(m\phi) + Q_{lm}^{(S)}\, \text{sin}(m\phi)\right] \frac{P_{l}^{m}(\text{cos}\, \theta)}{r^{l+1}} \right].
\end{equation}
The modified multipole moments are:
\begin{align}
  Q_l^{(0)}   &= \int P_l(\text{cos}\, \theta^\prime)\, {r^{\prime}}^l \rho(\mathbf{x}^\prime)\, d^3 x^\prime \\
  Q_{lm}^{(C)} &= 2\frac{(l-m)!}{(l+m)!} \int P_{l}^{m}(\text{cos}\, \theta^\prime)\, \text{cos}(m\phi^\prime)\, {r^\prime}^l \rho(\mathbf{x}^\prime)\, d^3 x^\prime \\
  Q_{lm}^{(S)} &= 2\frac{(l-m)!}{(l+m)!} \int P_{l}^{m}(\text{cos}\, \theta^\prime)\, \text{sin}(m\phi^\prime)\, {r^\prime}^l \rho(\mathbf{x}^\prime)\, d^3 x^\prime.
\end{align}
Our strategy for the multipole boundary conditions, then, is to pick
some value $l_{\text{max}}$ that is of sufficiently high order to
capture the distribution of mass on the grid, evaluate the discretized
analog of the modified multipole moments for $0 \leq l \leq
l_{\text{max}}$ and $1 \leq m \leq l$, and then directly compute the
value of the potential on all of the boundary zones. This is
ultimately an $\mathcal{O}(N^3)$ operation, the same order as the
monopole approximation, and the wall time required to calculate the
boundary conditions will depend on the chosen value of
$l_{\text{max}}$.

The number of $l$ values calculated is controlled by
\runparam{gravity.max\_multipole\_order} in your inputs file. By
default, it is set to \texttt{0}, which means that a monopole
approximation is used. There is currently a hard-coded limit of
$l_{\text{max}} = 50$. This is because the method used to generate the
Legendre polynomials is not numerically stable for arbitrary $l$
(because the polynomials get very large, for large enough $l$).

\item \textbf{Direct Sum}

Up to truncation error caused by the discretization itself, the
boundary values for the potential can be computed exactly by a direct
sum over all cells in the grid. Suppose I consider some ghost cell
outside of the grid, at location $\mathbf{r}^\prime \equiv (x^\prime,
y^\prime, z^\prime)$. By the principle of linear superposition as
applied to the gravitational potential,
\begin{equation}
  \phi(\mathbf{r}^\prime) = \sum_{\text{ijk}} \frac{-G \rho_{\text{ijk}}\, \Delta V_{\text{ijk}}}{\left[(x - x^\prime)^2 + (y - y^\prime)^2 + (z - z^\prime)^2\right]^{1/2}},
\end{equation}
where $x = x(i)$, $y = y(j)$ and $z = z(k)$ are constructed in the
usual sense from the zone indices. The sum here runs over every cell
in the physical domain (that is, the calculation is $\mathcal{O}(N^3)$
for each boundary cell). There are $6N^2$ ghost cells needed for the
Poisson solve (since there are six physical faces of the domain), so
the total cost of this operation is $\mathcal{O}(N^5)$ (this only
operates on the coarse grid, at present). In practice, we use the
domain decomposition inherent in the code to implement this solve: for
the grids living on any MPI task, we create six $N^2$ arrays
representing each of those faces, and then iterate over every cell on
each of those grids, and compute their respective contributions to all
of the faces. Then, we do a global reduce to add up the contributions
from all cells together. Finally, we place the boundary condition
terms appropriate for each grid onto its respective cells.

This is quite expensive even for reasonable sized domains, so this
option is recommended only for analysis purposes, to check if the
other methods are producing accurate results. It can be enabled by
setting \runparam{gravity.direct\_sum\_bcs}{\tt = 1} in your inputs file.

\end{itemize}

\subsection{{\tt PrescribedGrav}}

With {\tt PrescribedGrav}\footnote{Note: The {\tt PrescribedGrav}
  option and text here were contributed by Jan Frederik Engels of
  University of Gottingen.}, gravity can be defined as a function that
is specified by the user.  The option is allowed in 2D and 3D.  To
define the gravity vector, copy {\tt prescribe\_grav\_nd.f90} from
{\tt Source/gravity/} to your run directory.  The makefile system will always
choose this local copy of the file over the one in another directory.
Then define the components of gravity inside a loop over the grid
inside the file.  If your problem uses a radial gravity in the form
$g(r)$, you can simply adapt {\tt
  ca\_prescribe\_grav\_gravityprofile}, otherwise you will have to
adapt {\bf ca\_prescribe\_grav}, both are located in {\tt
  prescribed\_grav\_nd.90}.

\subsection{Point Mass}

Pointmass gravity works with all other forms of gravity, it is not a
separate option.  Since the Poisson equation is linear in potential
(and its derivative, the acceleration, is also linear), the point mass
option works by adding the gravitational acceleration of the point
mass onto the acceleration from whatever other gravity type is under
in the simulation.

Note that point mass can be $< 0$.

A useful option is {\tt point\_mass\_fix\_solution}.  If set to {\tt
  1}, then it takes all zones that are adjacent to the location of the
{\tt center} variable and keeps their density constant.  Any changes
in density that occur after a hydro update in those zones are reset,
and the mass deleted is added to the pointmass.  (If there is
expansion, and the density lowers, then the point mass is reduced and
the mass is added back to the grid).  This calculation is done in {\tt
  pm\_compute\_delta\_mass()} in {\tt
  Source/gravity/pointmass\_nd.f90}.

\section{GR correction}

In the cases of compact objects or very massive stars, the general
relativity (GR) effect starts to play a role\footnote{Note: The GR
  code and text here were contributed by Ken Chen of Univ. of
  Minnesota.}.  First, we consider the hydrostatic equilibrium due to
effects of GR then derive GR-correction term for Newtonian gravity.
The correction term is applied to the monopole approximation only when
{\tt USE\_GR = TRUE} is set in the {\tt GNUmakefile}.

The formulae of GR-correction here are based on \cite{grbk1}. For
detailed physics, please refer to \cite{grbk2}. For describing very
strong gravitational field, we need to use Einstein field equations
\begin{equation}\label{field}
R_{ik}-\frac{1}{2}g_{ik}R=\frac{\kappa}{c^{2}}T_{ik} \quad , \quad
\kappa=\frac{8\pi G}{c^{2}}\quad ,
\end{equation}
where $R_{ik}$ is the Ricci tensor, $g_{ik}$ is the metric tensor, $R$
is the Riemann curvature, $c$ is the speed of light and $G$ is
gravitational constant. $T_{ik}$ is the energy momentum tensor, which
for ideal gas has only the non-vanishing components $T_{00}$ =
$\varrho c^2$ , $T_{11}$ = $T_{22}$ = $T_{33}$ = $P$ ( contains rest
mass and energy density, $P$ is pressure). We are interested in
spherically symmetric mass distribution. Then the line element $ds$
for given spherical coordinate $(r, \vartheta, \varphi)$ has the
general form
\begin{equation}\label{metric}
  ds^{2} = e^{\nu}c^{2}dt^{2}-e^{\lambda}dr^{2}-r^{2}(d\vartheta^{2}+\sin^{2}
  \vartheta d\varphi) \quad ,
\end{equation}
with $\nu = \nu(r)$, $\lambda = \lambda(r)$. Now we can put the
expression of $T_{ik}$ and $ds$ into (\ref{field}), then field
equations can be reduced to 3 ordinary differential equations:
\begin{equation}\label{diff1}
   \frac{\kappa P}{c^{2}} =
   e^{-\lambda}\left (\frac{\nu^{\prime}}{r}+\frac{1}{r^{2}} \right )-\frac{1}{r^{2}}
   \quad ,
\end{equation}
\begin{equation}\label{diff2}
  \frac{\kappa P}{c^{2}} =
  \frac{1}{2}e^{-\lambda}\left (\nu^{\prime\prime}+\frac{1}{2}{\nu^{\prime}}^{2}+\frac{\nu^
    {\prime}-\lambda^{\prime}}{r}
   -\frac{\nu^{\prime}\lambda^{\prime}}{2} \right ) \quad ,
\end{equation}
\begin{equation}\label{diff3}
  \kappa \varrho =
  e^{-\lambda}\left (\frac{\lambda^{\prime}}{r}-\frac{1}{r^{2}}\right )+\frac{1}{r^{2}} \quad ,
\end{equation}
where primes means the derivatives with respect to $r$. After
multiplying with $4\pi r^2$, (\ref{diff3}) can be integrated and
yields
\begin{equation}\label{gmass1}
  \kappa m = 4\pi r (1-e^{-\lambda}) \quad ,
\end{equation}
the $m$ is called ``gravitational mass'' inside r defined as
\begin{equation}\label{gmass2}
  m = \int_{0}^{r}4\pi r^{2}  \varrho dr\quad .
\end{equation}
For the $r = R$, $m$ becomes the mass $M$ of the star. $M$ contains
not only the rest mass but the whole energy (divided by $c^2$), that
includes the internal and gravitational energy. So the $\varrho =
\varrho_0 +U/c^2$ contains the whole energy density $U$ and rest-mass
density $\varrho_0$.  Differentiation of (\ref{diff1}) with respect to
$r$ gives $P = P^{\prime}(\lambda,\lambda^{\prime},
\nu,\nu^{\prime},r)$, where
$\lambda,\lambda^{\prime},\nu,\nu^{\prime}$ can be eliminated by
(\ref{diff1}), (\ref{diff2}), (\ref{diff3}). Finally we reach
\textit{Tolman-Oppenheinmer-Volkoff(TOV)} equation for hydrostatic
equilibrium in general relativity:
\begin{equation}\label{tov}
  \frac{dP}{dr} = -\frac{Gm}{r^{2}}\varrho \left (1+\frac{P}{\varrho
    c^{2}}\right )\left (1+\frac{4\pi r^3 P}{m c^{2}}\right ) \left (1-\frac{2Gm}{r c^{2}} \right)^{-1} \quad .
\end{equation}
For Newtonian case $c^2 \rightarrow  \infty $, it reverts to usual form
\begin{equation}\label{newton}
  \frac{dP}{dr} = -\frac{Gm}{r^{2}}\varrho \quad .
\end{equation}
Now we take effective monopole gravity as
\begin{equation}\label{tov2}
\tilde{g} = -\frac{Gm}{r^{2}} (1+\frac{P}{\varrho
  c^{2}})(1+\frac{4\pi r^3 P}{m c^{2}}) (1-\frac{2Gm}{r c^{2}})^{-1}  \quad .
\end{equation}
For general situations, we neglect the $U/c^2$ and potential energy in
m because they are usually much smaller than $\varrho_0$. Only when
$T$ reaches $10^{13} K$ ($KT \approx m_{p} c^2$, $m_p$ is proton mass)
before it really makes a difference. So (\ref{tov2}) can be expressed
as
\begin{equation}\label{tov3}
  \tilde{g} = -\frac{GM_{\rm enclosed}}{r^{2}} \left (1+\frac{P}{\varrho
    c^{2}} \right )\left (1+\frac{4\pi r^3 P}{M_{\rm enclosed} c^{2}} \right ) \left (1-\frac{2GM_{\rm enclosed}}{r c^{2}} \right )^{-1} \quad ,
\end{equation}
where $M_{enclosed}$ has the same meaning as with the {\tt
  MonopoleGrav} approximation.

\section{Hydrodynamics Source Terms}

There are several options to incorporate the effects of gravity into
the hydrodynamics system.  The main parameter here is {\tt
  castro.grav\_source\_type}.

\begin{itemize}

\item {\tt castro.grav\_source\_type = 1} : we use a
  standard predictor-corrector formalism for updating the momentum and
  energy. Specifically, our first update is equal to $\Delta t \times
  \mathbf{S}^n$ , where $\mathbf{S}^n$ is the value of the source
  terms at the old-time (which is usually called time-level $n$).  At
  the end of the timestep, we do a corrector step where we subtract
  off $\Delta t / 2 \times \mathbf{S}^n$ and add on $\Delta t / 2
  \times \mathbf{S}^{n+1}$, so that at the end of the timestep the
  source term is properly time centered.

\item {\tt castro.grav\_source\_type = 2} : we do something very
  similar to {\tt 1}. The major difference is that when evaluating the
  energy source term at the new time (which is equal to $\mathbf{u}
  \cdot \mathbf{S}^{n+1}_{\rho \mathbf{u}}$, where the latter is the
  momentum source term evaluated at the new time), we first update the
  momentum, rather than using the value of $\mathbf{u}$ before
  entering the gravity source terms. This permits a tighter coupling
  between the momentum and energy update and we have seen that it
  usually results in a more accurate evolution.

\item {\tt castro.grav\_source\_type = 3} : we do the same momentum
  update as the previous two, but for the energy update, we put all of
  the work into updating the kinetic energy alone. In particular, we
  explicitly ensure that $(rho e)$ maintains the same, and update
  $(rho K)$ with the work due to gravity, adding the new kinetic
  energy to the old internal energy to determine the final total gas
  energy.  The physical motivation is that work should be done on the
  velocity, and should not directly update the temperature---only
  indirectly through things like shocks.

\item {\tt castro.grav\_source\_type = 4} : the energy update is done
  in a ``conservative'' fashion.  The previous methods all evaluate
  the value of the source term at the cell center, but this method
  evaluates the change in energy at cell edges, using the
  hydrodynamical mass fluxes, permitting total energy to be conserved
  (excluding possible losses at open domain boundaries).  See
  \cite{katzthesis} for some more details.
\end{itemize}


\subsection{\label{ref:Chip8emulator}Chip{}-8 Emulator}
Chip8 is a kind of assembly language for a long-gone architecture.
This plugin runs games written using the chip8 instructions.
To start a game open a \fname{.ch8} file in the \setting{File Browser}

There are lots of tiny Chip8 games (usually only about 256 bytes to a
couple of KB) which were made popular by the HP48
calculator's emulator for them. The original Chip8 had
64$\times$32 pixel graphics, and the new superchip emulator supports 128$\times$64
graphics.

The only problem is that they are based on a 4$\times$4 keyboard, but since most
games do not use all of the buttons, this can easily be worked around.

To do this, one may put a \fname{.c8k} file with the same name as the
original program which contains new key mappings (for \fname{BLINKY.ch8}, one
writes a \fname{BLINKY.c8k} file). That \fname{.c8k} file contains 16
characters describing the mapping from the Chip8 keyboard to the default key
mapping (that way, several Chip8 keys can be pressed using only one
Rockbox key). For example, a file containing the single line:
\begin{code}
    0122458469ABCDEF
\end{code}
would correspond to the following non-default mappings:

3 $\rightarrow$ 2, 6 $\rightarrow$ 8, 7 $\rightarrow$4, 8 $\rightarrow$ 6.

The default keymappings are:
\begin{table}
    \begin{center}
    \begin{tabularx}{.9\textwidth}{c|ccccccccccccccccc}
    \toprule
    Chip8 & Off & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9
        & A & B & C & D & E & F\\
    \midrule
    \begin{sideways}Key\end{sideways}
        &
        % key "off"
        \begin{sideways}
        \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
        \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu}
        \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD,SANSA_C200_PAD%
          ,GIGABEAT_PAD,MROBE100_PAD,SANSA_FUZE_PAD,SANSA_FUZEPLUS_PAD}
            {\ButtonPower}
        \opt{GIGABEAT_S_PAD}{\ButtonBack}
        \opt{PBELL_VIBE500_PAD}{\ButtonRec}
        \opt{SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}{\ButtonRew}
        \opt{MPIO_HD200_PAD}{\ButtonRec + \ButtonPlay}
        \opt{MPIO_HD300_PAD}{Long \ButtonMenu}
        \end{sideways}
        &
        % Key "0"
        \begin{sideways}
        \opt{SANSA_FUZEPLUS_PAD}{\ButtonVolDown}
        \opt{SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}{\ButtonFF}
        \end{sideways}
        &
        % "Key "1"
        \begin{sideways}
        \opt{SANSA_FUZEPLUS_PAD}{\ButtonBack}
        \opt{RECORDER_PAD}{\ButtonFOne}
        \opt{ONDIO_PAD,SANSA_FUZEPLUS_PAD}{\ButtonUp}
        \opt{GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD}{\ButtonMenu}
        \opt{MPIO_HD200_PAD,MPIO_HD300_PAD}{\ButtonRew}
        \end{sideways}
        &
        % Key "2"
        \begin{sideways}
        \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD}
            {\ButtonScrollBack}
        \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD%
          ,RECORDER_PAD,ONDIO_PAD,SANSA_FUZEPLUS_PAD,GIGABEAT_S_PAD%
          ,MROBE100_PAD,PBELL_VIBE500_PAD,SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}{\ButtonUp}
        \opt{IRIVER_H10_PAD}{\ButtonScrollUp}
        \opt{SANSA_C200_PAD}{\ButtonVolUp}
        \opt{MPIO_HD200_PAD,MPIO_HD300_PAD}{\ButtonFF}
        \end{sideways}
        &
        % Key "3"
        \begin{sideways}
        \opt{RECORDER_PAD}{\ButtonFThree}
        \opt{MROBE100_PAD,SANSA_FUZEPLUS_PAD}{\ButtonPlay}
        \opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolDown}
        \opt{MPIO_HD200_PAD}{\ButtonFunc}
        \opt{MPIO_HD300_PAD}{\ButtonMenu}
        \end{sideways}
        &
        % Key "4"
        \begin{sideways}
        \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IPOD_4G_PAD%
            ,IPOD_3G_PAD,IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD%
            ,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD%
            ,SANSA_FUZE_PAD,PBELL_VIBE500_PAD,SANSA_FUZEPLUS_PAD,SAMSUNG_YH92X_PAD%
            ,SAMSUNG_YH820_PAD}{\ButtonLeft}
        \opt{MPIO_HD200_PAD}{\ButtonRec}
        \opt{MPIO_HD300_PAD}{\ButtonEnter}
        \end{sideways}
        &
        % Key "5"
        \begin{sideways}
        \opt{RECORDER_PAD}{\ButtonPlay}
        \opt{ONDIO_PAD}{\ButtonMenu}
        \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD%
            ,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD%
            ,SANSA_FUZE_PAD,SANSA_FUZEPLUS_PAD}
            {\ButtonSelect}
        \opt{IPOD_4G_PAD,IPOD_3G_PAD,IRIVER_H10_PAD,SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}%
            {\ButtonPlay}
        \opt{PBELL_VIBE500_PAD}{\ButtonOK}
        \opt{MPIO_HD200_PAD}{\ButtonPlay}
        \opt{MPIO_HD300_PAD}{\ButtonRec}
        \end{sideways}
        &
        % Key "6"
        \begin{sideways}
        \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IPOD_4G_PAD%
            ,IPOD_3G_PAD,IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD%
            ,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD%
            ,SANSA_FUZE_PAD,PBELL_VIBE500_PAD,SANSA_FUZEPLUS_PAD,SAMSUNG_YH92X_PAD%
            ,SAMSUNG_YH820_PAD}{\ButtonRight}
        \opt{MPIO_HD200_PAD}{\ButtonVolDown}
        \opt{MPIO_HD300_PAD}{\ButtonPlay}
        \end{sideways}
        &
        % Key "7"
        \begin{sideways}
        \opt{RECORDER_PAD}{\ButtonFTwo}
        \opt{MROBE100_PAD}{\ButtonDisplay}
        \opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolUp}
        \opt{MPIO_HD200_PAD}{\ButtonVolUp}
        \opt{MPIO_HD300_PAD}{\ButtonScrollUp}
        \opt{SANSA_FUZEPLUS_PAD}{\ButtonBottomLeft}
        \end{sideways}
        &
        % Key "8"
        \begin{sideways}
        \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD%
            ,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD,SAMSUNG_YH92X_PAD%
            ,SAMSUNG_YH820_PAD}{\ButtonDown}
        \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD}
            {\ButtonScrollFwd}
        \opt{IAUDIO_X5_PAD,SANSA_FUZEPLUS_PAD}{\ButtonDown}
        \opt{IRIVER_H10_PAD,MPIO_HD300_PAD}{\ButtonScrollDown}
        \opt{SANSA_C200_PAD}{\ButtonVolDown}
        \end{sideways}
        &
        % Key "9"
        \begin{sideways}
        \opt{RECORDER_PAD}{\ButtonOn}
        \opt{GIGABEAT_PAD}{\ButtonA}
        \opt{GIGABEAT_S_PAD}{\ButtonPlay}
        \opt{SANSA_FUZEPLUS_PAD}{\ButtonBottomRight}
        \end{sideways}
        &
        % Key "A"
        \begin{sideways}
          \opt{SANSA_FUZEPLUS_PAD}{\ButtonVolUp}
        \end{sideways}
        &
        % Key "B"
        &
        % Key "C"
        &
        % Key "D"
        &
        % Key "E"
        &
        % Key "F"
    \\\bottomrule
    \end{tabularx}
    \end{center}
\end{table}

Some places where can you can find \fname{.ch8} files:
\begin{itemize}
\item The PluginChip8 page on www.rockbox.org has several attached:
\wikilink{PluginChip8}
\item Check out the HP48 chip games section:
\url{http://www.hpcalc.org/hp48/games/chip/}
\item Links to other chip8 emulators:
\url{http://www.zophar.net/chip8.html}
\end{itemize}


%!TEX root = ../thesis.tex
\chapter{Isogeometric enhanced SBFEM in 2D}
\label{Iso_sec:main}
\section{Introduction}
\paragraph{}
The main objective of this chapter is to combine the concept of isogeometric analysis and the SBFEM.
Non-uniform rational B-splines (NURBS) basis functions are employed to approximate the unknown fields in the circumferential direction.
This provides a seamless integration with the CAD model.
The method is further extended to problems with singularities within the framework of linear elastic fracture mechanics and to dynamic analysis.
The proposed method enhances the conventional IGA and the salient features of the method are:
    \begin{itemize}
        \item No tensor-product patches as only the boundary information is required for the stress analysis
        \item Feasible to have a n-sided polygonal domain of mixed type/order of the element on the edges,
                which leads to high flexibility in meshing and mesh transition
        \item Model strain/stress singularities without enrichment
        \item No internal mesh when studying the dynamic response at high frequencies
    \end{itemize}

This chapter organized as follows.
Section.~\ref{iso_section:formulation} provides an overview of the SBFEM and important equations pertaining to linear elasticity,
followed by extending the formulation to linear elastic fracture mechanics in Section~\ref{iso_section:fracture}.
After that, methods that perform the interpolation of surface traction and displacement will be presented in Section~\ref{iso_section:surface_traction} and Section~\ref{iso_section:interpolation}.
Numerical integration with NURBS will be mentioned in Section~\ref{iso_section:numerical_integration} before the accuracy and the convergence properties of the proposed techniques being demonstrated with benchmark problems in the context of linear elasticity and linear elastic fracture mechanics in Section~\ref{iso_section:examples}, followed by concluding remarks in the last section.
This chapter is published \citep{NATARAJAN2015733}.
%=================================================================================================================================%
\input{isogeometric_sbfem/sbfem_formulation.tex}
\input{isogeometric_sbfem/sbfem_linear_fracture.tex}
\input{isogeometric_sbfem/sbfem_surface_traction.tex}
\input{isogeometric_sbfem/sbfem_displacement_interpolation.tex}
\input{isogeometric_sbfem/nurbs_numerical_integrations.tex}
%=================================================================================================================================%
\section{Numerical examples}
\label{iso_section:examples}
\paragraph{}
In this section, the accuracy and the convergence properties of the proposed method are demonstrated with a few
    benchmark problems.
First, the proposed method is applied to thick cantilever beam bending, to a plate with a center
    circular hole and to an L-shaped bracket.
In the case of L-shaped bracket both the static and the dynamic responses are studied.
The results are compared with analytical solution where available and with the results obtained using quadratic
    Lagrange shape functions.
In the latter part of the section, problems involving strong discontinuities (e.g., plate with an edge crack,
    angled crack in an orthotropic body) are solved to illustrate the effectiveness of the proposed method.
It is noted that, when the proposed method is applied to problems involving strong discontinuities, no special
    treatment is required, such as, the augmentation of finite element basis or IGA with asymptotic functions
    \citep{Benson2010} \citep{De2011}.
For the purpose of error estimation and convergence studies, the relative error, L 2 and H 1 norms are used.
The displacement norm is given by:
    \begin{equation}
        \| u - u^h \|_{L^2(\Omega)}=
        \sqrt{
            \int_{\Omega}\left[
                \left(
                    u-u^h
                \right) \cdot
                \left(
                    u-u^h
                \right)
            \right]
        }
    \end{equation}
%
where $u^h$ is the numerical solution and $u$ is the analytical solution or a reference solution.
The energy norm is given by
    \begin{equation}
        \| u - u^h \|_{H^1(\Omega)}=
        \sqrt{
            \int_{\Omega}\left[
                \left(
                    \epsilon - \epsilon^h
                \right)^T D
                \left(
                    \epsilon - \epsilon^h
                \right)
            \right]
        }
    \end{equation}
%
For the purpose of numerical integration of NURBS basis functions, we employ higher order Gaussian quadrature over each span of the NURBS basis functions.
Other quadrature rules are possible as outlined in \citep{Hug2010}.
For Lagrange basis functions, conventional Gauss–Lobatto quadrature is employed.

\input{isogeometric_sbfem/ex_cantilever_beam.tex}

\input{isogeometric_sbfem/ex_circular_hole.tex}

\input{isogeometric_sbfem/ex_l_shaped_bracket.tex}

\input{isogeometric_sbfem/ex_circular_disk_edge_crack.tex}

\input{isogeometric_sbfem/ex_edge_crack.tex}

\input{isogeometric_sbfem/ex_angled_crack.tex}

\input{isogeometric_sbfem/ex_bi_material_plate_with_notch.tex}

%=================================================================================================================================%
\section{Conclusions}
\paragraph{}
In this chapter, the NURBS basis functions are employed to approximate the unknown fields in the circumferential direction within the framework of the SBFEM.
The accuracy, effectiveness and the convergence properties of the proposed method are demonstrated with benchmark problems in linear elasticity and linear elastic fracture mechanics.
From the numerical studies, it can be observed that the NURBS basis functions yield superior accuracy when compared to Lagrange basis functions of the same order.
The proposed method overcomes the disadvantages of both the isogeometric finite element analysis and the isogeometric boundary element method.
Like in the IGAFEM no fundamental solution is required and like in the IGABEM the spatial dimension is reduced by one.
However, for complicated geometries, to meet the star convexity, subdivision into smaller sub-domains is required.
When applied to problems with singularities, the proposed method does not require additional functions to span the solution space.
Moreover, the proposed framework does not require internal discretization to study the dynamic response at high frequencies.


In this section, we present a method to solve the synthesis problem of finding
a set of production rules that produce a given set $\mu$ of molecules.
Our method \textsc{SugarSynth} is Algorithm~\ref{alg:sugar-synth}.
Here, we are considering only the single compartment case.
The generalizations are discussed in
\choosefinal{the extended version~\cite{arxiv-this}.}{ Appendix~\ref{sec:variations}.}

% At a high level, our method is iterative.
% The method first synthesizes a set of rules $R$ that can produce the molecules in input set $\mu$, i.e., $\mu \subseteq P(S,R)$.
% However, there is also an additional requirement that a molecule
% that is not in $\mu$ is not producible by the synthesized rules $R$.
% Therefore, the method looks for the producible molecules that are not in $\mu$, called
% {\em counterexample molecule}.
% If there is no such molecule, our method terminates and reports
% the synthesized rules.
% If there is a molecule in $P(S,R) - \mu$, we add constraints that says
% that look for rules
% that do not generate
% the molecule and go for another iteration.
% Now let us look at the details of the method.

\input{alg-synth.tex}

\subsection{\textsc{SugarSynth} in detail}

The method assumes that the input set $\mu$ is finite.
This is a reasonable assumption because
even if a set of rules can produce
an unbounded number of molecules,
no biology will exhibit an infinite set in a cell.
Our method
bounds the search space of production rules.
The method also takes two numbers as input:
$d$ is the maximum height of the learned rules
and
$n$ is the maximum number of them.
% The parameters eliminate potential
% unbounded search space.
If the method fails to find production rules,
the user may call the method with larger parameters.
% However, we do not expect to find a large number of or sized rules
% because chemical reactions do not usually have many conditional
% on the precursors and do not apply large changes in a single step.
First, the method initializes $S$ with the set of monomers occurring
in $\mu$
and sets $w$ to be the maximum arity of any monomer in $S$.

We use templates to model the search space of rules.
A template is a tree that has a depth and
the internal nodes of the tree have the same number of children.
Two variables label each node. %of the template.
One variable is for choosing the sugar at the node and the other is for describing
the `situation' of the node.
% The first variable at the node encodes choices of
% sugar monomers or their absence.
The domain of the first variables is $S \union \{\bot\}$.
Let $SVars$ be the unbounded set of variables with the domain.
We will use the pool of $SVars$ to add variables to the templates.

A node in a production rule can be in four situations.
In Figure~\ref{fig:rule-parts}, we illustrate the situations.
The first situation is when a node is in the expanding part, which are shown in
dark gray. % nodes are the expanding nodes.
The second situation is when a node is not in the rule.
The dashed area are the absent nodes.
Among the matching nodes, we have two cases.
\begin{wrapfigure}{r}{0.35\textwidth}
  % \vspace{-12mm}
        \center
  \begin{tikzpicture}[shorten >=1pt,thick,node distance=1cm,on grid,scale=0.5]
    \node[loc] (v0) {$v_0$};
    \node[sqloc, below right of=v0] (v1) {$v_e$};
    \draw [->] plot [smooth] coordinates { (v0.south)
          ($(v0.south)+(3mm,-2mm)$)
          ($(v0.south)+(10mm,1mm)$)
          % ($(v0.south)+(9mm,-6mm)$)
          % ($(v0.east)+(8mm,-8mm)$)
          (v1.north) };
    % \path[->] (v0) edge (v1);
    % \path[->,dashed] (v1) edge (v2);
    % \path[->] (v1) edge (v3);
    \fill[fill=gray,opacity=0.2]
    (0,0) -- ++(-1.5cm,-1.7cm) -- ++(1.2cm,-1.2cm) -- ++(6cm,0cm) -- cycle;
    \fill[fill=gray,opacity=0.4]
    (v1.center) -- ++(-1.5cm,-1.5cm) -- ++(3cm,0cm) -- cycle;
    \draw[dashed] (-1.5cm,-1.7cm) -- ++(-1.2cm,-1.2cm) -- ++(2.4cm,0cm) -- cycle;
  \end{tikzpicture}
  \caption{Parts of production rules in the rule templates.}
  \label{fig:rule-parts}
  \vspace{-8mm}
\end{wrapfigure}
The third situation is when a node is in the matching part
and has expanding descendants.
The nodes on the solid path from $v_0$ to the root $v_e$ of the expanding part are in the third situation.
% the nodes that are ancestors of expanding part among the matching nodes.
Finally, the fourth situation is the rest of the nodes
in the matching part, which is in light gray.
% The nodes in the rest of the light gray area are in the fourth situation.
A variable is mapped to a node to encode the four situations.
Let $K =\{Expand,Absent,MatchAns,Match\}$ be the set of symbols to
indicate the situations.
Let $KVars$ be an unbounded set of variables with domain $K$.
% We will use the pool of $KVars$ to add variables to the templates.
Our templates are sufficiently expressive to cover all aspects of biology, which are defined as follows.

\begin{df}
For given integers $d$ and $w$,
a {\em rule template} $t = (V, \nu, \kappa, C, v_{0r})$ is a labeled full tree with depth $d$ and
each internal node has $w$ children, where
$V$ is a set of nodes, $\nu : V \maps SVars$ maps nodes to distinct
sugar choice variables,
$\kappa : V \maps KVars$ maps nodes to distinct situation variables,
$C : V \times \naturals \pmaps V$ maps the indexed children of nodes,
and
$v_{0r} \in V$ is the root of the tree.
\end{df}

For a node $v$ in a template if we assign $\kappa(v) = Absent$,
we call the node {\em absent}. Otherwise, we call the node {\em present}.
We will also be searching for the molecules that may be produced by the learned rules.
Therefore, we need to define the search space for the molecules.
We use templates for defining the search space.
We limit the template size using a parameter,
namely the height of the template.
\begin{df}
For given integers $h$ and $w$,
a {molecule template} $\hat{m} = (V, \nu, C, v_{0m})$ is a labeled full tree with height $h$ and
each internal node has $w$ children, where
$V$ is a set of nodes, $\nu : V \maps SVars$ maps nodes to sugar choice variables,
$C : V \times \naturals \pmaps V$ maps the indexed children of nodes,
and
$v_{0m} \in V$ is the root.
\end{df}

In the Algorithm at line~\ref{line:createRtemp}, we call \textsc{MakeTemplatesRule}( $S$, $d$, $w$, $n$) to create $n$ templates for
height $d$ and children width $w$.
% We get $d$ and $n$ as input, and
% we let $w$ be the maximum arity of any sugar that occurs in $\mu$.
Since $w$ is the maximum arity of any sugar, we can map any node to any sugar.
% We also assume that templates
% returned by $\textsc{MakeTemplatesRule}$ do not share variables.
% We obtain a production rule from a template by assigning values
% to the variables of the template.
% Not all the assignments may result in a valid rule.
Next at line~\ref{line:ruleCorr}, we will construct constraints
that encode the set of valid rules.
A valid assignment to the variables in
a template  $t = (V, \nu, \kappa, C, r)$ must
satisfy the following six conditions.
% The first two encode the basic agreement among variables.
% The third encodes the tree structure of the rule.
% The last three encode the relative positions of the four
% parts of the rule.
\begin{enumerate}
\item If a node is present, then it is labeled with a sugar.\\
  %Otherwise, we ignore the label.
$
\Land_{s \in S} \Land_{v \in V} (\kappa(v) \neq Absent \limplies \nu(v) \neq \bot )
$
\item
  % The number of children of a node should match with the arity of the labeled sugar.
  % The following formula states that

  The children that are at greater arity than that of the label
  are absent.\\
$
\Land_{s \in S} \Land_{i \in (arity(s),w] }\Land_{v \in V} (\nu(v) = s \limplies \kappa( C(v,i) ) = Absent )
$
\item If a node is present, then the parent of the node is also present.\\
  $
  \Land_{{\text{internal node } v \in V}}
  \Land_{i\in[1,w]} (\kappa(C(v,i) ) \neq Absent \limplies \kappa( v ) \neq Absent )
  $
\item If a node is $Expand$, then its children are also $Expand$ if present.\\
  % The following constraints state that once one reached the expanding part, there are no descendants that are matching.
  $
\Land_{i\in[1,w]} \Land_{{\text{internal node } v \in V}} (\kappa(v) = Expand \limplies \kappa(C(v,i)) \in \{Expand,Absent\}   )
$
\item If a node is $Match$, then its children are also $Match$ if present.\\
  % Similarly, the following constraints state that once one reached the matching part without expanding descendants, there are no descendants that are expanding.
$
\Land_{i\in[1,w]} \Land_{{\text{internal node } v \in V}} (\kappa(v) = Match \limplies \kappa(C(v,i)) \in \{Match,Absent\}   )
$
\item If a node is $MatchAns$, then exactly one child is $MatchAns$ or $Expand$.\\
  % The following constraints encode that there is exactly one subtree that is expanding part
  % by stating that there is no branching in $MatchAns$ nodes and they form a path.
\mbox{}\hspace{-5mm}
$
\Land_{v \in V} (\kappa(v) = MatchAns \limplies \sum_{i\in[1,w]}( \kappa(C(v,i)) \in \{MatchAns,Expand\}) = 1
$
\end{enumerate}

The call to $\textsc{RuleTemplateCorrectness}$ at
line~\ref{line:ruleCorr} creates the above constraints
and stores them in $tCons$.
% Next,
At line~\ref{line:createMtemp}, we use the call to \textsc{MakeTemplateMol}($S$, $h$, $w$) to
create a molecule template of height $h$ and children width $w$.
%
Our method searches for unwanted producible molecules up to the height of $h$,
which we set to the maximum of the heights of molecules in $\mu$.
%
The choice of $h$ is arbitrary.
% %
% We assume if the rules could have produced a molecule with height less than $h$,
% then it must be in $\mu$.
% On the other hand,
% We ignore the potential formation of the large size of molecules.
% %
% Since we observe only finite molecules in any wet experiment, we may assume
% there may be large producible molecules, but we did not observe them.
% However, this point is debatable and $h$ may be viewed as
% a parameter of the whole method.
%
Similar to the rule templates, not all assignments to molecule template variables
are valid.
We add the following conditions for
valid assignments for molecule template $\hat{m} = (V, \nu, C, \hat{v_0})$.
% The first  two conditions encode the tree structure of the molecule and
% matching the number of children with label arity for each node.
% The second encodes that the height of the molecule is large enough.
% The last encodes that new molecule must not be the same as any molecule in $\mu$.
\begin{enumerate}
\item If a node is present, then the parent of the nodes is also present.\\
  $
  \Land_{i\in[1,w]}\Land_{{\text{internal node } v \in V}} (\nu(C(v,i) ) \neq \bot \limplies \nu( v ) \neq \bot )
  $
\item The children count of a node matches with the arity of the labeled sugar.\\
  $
  \Land_{s \in S} \Land_{i \in (arity(s),w] }\Land_{v \in V} (\nu(v) = s \limplies \kappa( C(v,i) ) = Absent )
  $
% \item At least one of the leaves is present. This is for
%   avoiding the trivial solution.\\
%   $
%   \Lor_{ v \in V \text{ and } depth(v) > d' } \nu( v ) \neq \bot,
%   $
%   where $d'$ is a number close to and smaller than $height(\hat{v_0})$.
%   This allows us to look for all molecules that are close
%   to height $h$.
%   We choose $d' = h-d$, where $d$ is the height of the rule templates.
  % This $d'$ ensures that we do not miss producible molecules that
  % can not have exact height $h$ but is slightly larger than $h$.
  % Then, there must be another producible
  % molecule that is a subtree of the molecule and has height in
  % between $h$ and $h-d$
  % because the maximum depth of a rule is $d$.
\item We find a molecule that is not in $\mu$.
  We encode $\Land_{{(\_,\_,\_, v_0)\in \mu}}  Neq(\hat{v_0},v_0)$, where
   predicate $Neq$ be recursively defined as follows.\\
  $Neq(v, v') :=\; \nu(v) \neq M(v') \lor
  \Lor_{{i \in [1,w]}} Neq( C(v,i), C(v',i ) )$\\
  $Neq(v,\bot) :=\;  \nu(v) \neq \bot$
  % \begin{align*}
  % Neq(v, v') :=\;&   \nu(v) \neq M(v') \lor
  % \Lor_{\mathclap{i \in [1,w]}} Neq( C(v,i), C(v',i ) )\\
  %   Neq(v,\bot) :=\;&  \nu(v) \neq \bot
  % \end{align*}
  % The constraint is
  % % \begin{align*}
  % % \end{align*}
  % In our implementation,
  % we have an option to also ignore the subtrees of
  % the molecules of $\mu$.
\end{enumerate}
%
In our method, the call to $\textsc{MolTemplateCorrectness}$ at
line~\ref{line:molCorr} generates the above constraints and stores them in
$mCons$.

We need to encode that the rules do generate the molecules
in $\mu$ and do not generate any other.
Using procedure $\textsc{EncodeProduce}$, we generate
the corresponding constraints.
We will discuss the procedure in-depth shortly.
Let us continue with~\textsc{SugarSynth}.
At line~\ref{line:molenc}, we call $\textsc{EncodeProduce}$ for
each molecule in $\mu$ and generate constraints $pCons$ stating that
the solutions of the templates will produce the molecules in $\mu$.

After producing the constraints $tCons$, $mCons$, and $pCons$,
the method enters in the loop.
It first checks the satisfiability of conjunction
$tCons \land pCons \land nCons$, where $nCons$ is $\ltrue$ in the first iteration
and will encode constraints related to counterexample molecules.
If the conjunction is unsatisfiable, there are no rules of
the input number and height,
and the method returns failure of synthesis.
If it is satisfiable, it constructs the rules at line~\ref{line:getR} from
%the satisfying assignment $a$
and stores them in $R$.

At line~\ref{line:consNewR}, we construct constraints $rCons$ again using
$\textsc{EnocdeProduce}$ that says that template molecule $\hat{m}$
is generated by rules $R$.
We check the satisfiability of $rCons \land mCons$.
If it is not satisfiable, we have found the rules that generate exactly
the molecules in $\mu$ and the loop terminates.
Otherwise, we use the satisfying assignment to create a
counterexample molecule $m'$.
At line~\ref{line:negCons}, we add constraints to $nCons$ stating that
all possible applications of template rules in $T$ must not produce $m'$.
We use shorthand $F \landplus G$ for $ F := F \land G$.
As we will see that $\textsc{EncodeProduce}$ introduces fresh variable
maps $\tau$ and $cuts$ in the encoding.
Since we negate the returned formula by $\textsc{EncodeProduce}$
and then we check the satisfiability,
% the encoding will not be correct
% due to the fresh variables.
we need to introduce universal quantifiers over the
fresh variables. %before adding to $nCons$.
% Intuitively, the universal quantifiers say that all possible
% application patterns of the learned rules do not produce $m'$.
Afterwards, the loop goes to the next iteration.
% Since the domain of all the variables is finite, eventually the loop must
% terminate.

\subsection{\textsc{EncodeProduce} in detail}

Now let us look at the encoding generated by $\textsc{EncodeProduce}$.
The process of production of molecules adds pieces of trees
one after another.
In order to show that a molecule is producible by a set of production rules,
we need to find the nodes where the production rules are applied,
the rules that are applied on the nodes, and
the order of the application of the rules.
% The encoding is like encoding bounded executions of programs.
To model the production due to the application of the rules,
we attach three maps to the molecule nodes.
\begin{itemize}
\item Let $cuts$ map each node to a Boolean variable
indicating the node is the point where a rule is applied to
expand the molecule.
We say points of the applications of the production
rules as {\em cuts} of the tree.
% All the nodes that are in between the cuts are added in a single step.

\item Let $rmatch$ map each node to a rule indicating
  the rule that is applied to expand at the node.
  We need to match a rule to a node if it is a cut point.
  % If a node is cut point, we need to the rules that added the nodes
\item Let $\tau$ map each node to an integer variable
  indicating the time point when the node was added to the molecule.
  Since already added nodes in a molecule decide what can be added later,
  we need to record the order of the addition.
  % If we do not capture the order in our encoding, we may wrongly declare
  % that a molecule is producible while it is not due to the matching
  % constraints.
\end{itemize}

Algorithm~\ref{alg:produce} presents function $\textsc{EncodeProduce}$
that returns the encoding.
It takes a molecule $m$ and a set of rules $T$.
Both the inputs can be template or concrete.
% The function is tolerant of the variations, but
Our presentation assumes that the molecule is concrete and
the rules are templates.
This will cover the case when the $\textsc{EncodeProduce}$ is called at
line~\ref{line:molenc} in Algorithm~\ref{alg:sugar-synth}.
However, at line \ref{line:consNewR} the molecule is a template
and the rules are concrete, which we will discuss later.
% We will discuss the handling of this situation at the end of this subsection.
$\textsc{EncodeProduce}$ uses the help of three other supporting functions,
$\textsc{EncodeP}$, $\textsc{MatchTree}$, and $\textsc{MatchCut}$.
% All of them are presented in algorithm~\ref{alg:produce}.

$\textsc{EncodeProduce}$ returns constraints stating for each node $v$
and rule template $t$,
if $v$ is at a cut and $t$ is applied at $v$, then $t$ must match
at the node $v$.
We require $rmatch(v)$ to be equal to some rule.
% Therefore, if $v$ is a cut node, some template must be applied.
Since we are matching with a template rule, we do not know the
position of the root of expanding nodes.
We enumerate to all possible depths from $1$ to $d-1$ for finding
the root.
For each $\ell \in [1,d)$, we call $\textsc{EncodeP}( v, t, \ell)$
to construct the constraints encoding that $t$ is applied at $v$
and the depth of the root of the expanding nodes is at depth $\ell$.

In $\textsc{EncodeP}$, we can traverse up from $v$ for $\ell$ steps to
find the node to match the root of $t$.
% Naturally,
It returns $\lfalse$ if there
is no $\ell$th ancestor of $v$. % i.e., there is no match.
The variable $mark$ is the timestamp for $v$.
% During matching, we will add constraints stating that the matching part of the
% template should match to the nodes added before $mark$
% and expanding part of the template should match with nodes that
% are added at or after $mark$.
The variable $c$ collects the  constraints as they are
generated. % and $c$ is initially $\ltrue$.
The variable $v_r$ is initially equal to the root $v_{0r}$ of $t$
and traverses the nodes in $t$.
The while loop at line~\ref{line:encodep-while} starts with
the $\ell$th ancestor from $v$,
matches all the ancestors up to the parent of $v$.
As the loop traverses down, it also traverses $t$
using variable $v_r$.
In each iteration, $v_r$ is updated to the $j$th child due to lines
\ref{line:encodep-next-vr} and \ref{line:encodep-update-vr}
if the ancestors of $v$ also traverse along the $j$th child.
% (see if condition at line \ref{line:encodep-jth-child-cond}).

\vspace{-10mm}
\input{alg-encode-produce.tex}

% Let us consider the body of the loop.
Let $v'$ be the $i$th ancestor at some iteration of the loop.
At line~\ref{line:encodep-ans-match}, the loop adds constraints stating that
the corresponding node $v_r$ in $t$ is
$MatchAns$, sugar matches in $v_r$ and $v'$, and
node $v'$ was added before $mark$.
The loop at line~\ref{line:encodep-sub-for-loop}, iterates over
children of $v'$.
If there is a child of $v'$ that is not along the path to
$v$, it is matched at line~\ref{line:mtree} with the corresponding
child of $v_r$ by calling $\textsc{MatchTree}$, which
will be discussed shortly.
% traverses
% rule template and molecule and generate constraints to encode that their
% nodes match.
% We will discuss $\textsc{MatchTree}$ shortly.
% $\textsc{MatchTree}$ is also called with a third parameter
% $mark$ and a Boolean value as the fourth parameter.
% We will discuss the procedure shortly.
If the $j$th child of $v'$ is along the path to $v$,
we get node $v'_r$ for updating
$v_r$ for the next iteration of the while loop.
% After the while loop in $\textsc{EncodeP}$, $v_r$ is the
% candidate node for the root of expanding nodes.
After the while loop in $\textsc{EncodeP}$ at line \ref{line:encodep-vr-expand}, we declare $v_r$
is $Expand$,  match the node $v$
with the corresponding node $v_r$ in the template rule by calling
$\textsc{MatchTree}$, and also call to match the cut pattern at
the subtree of $v$ with the template rule.

$\textsc{MatchTree}$ is a recursive procedure and matches
sugar assignments between the molecule and the rule template.
If the rule template node $v_r$ does not exist, then
there is nothing to match and it returns $\ltrue$ at
line~\ref{line:matchtree-vr-absent}.
At line~\ref{line:matchtree-v-absent}, we encode if the molecule node $v$ does not exist, then the rule node must also
be flagged absent. %Otherwise, the match will fail.
Otherwise, we add constraints
that if $v_r$ is not absent in the template, then
the labels of $v$ and $v_r$ must match at line~\ref{line:matchtree-cons}.
At the same line, $\textsc{MatchTree}$ also adds constraints $tCons$ that
nodes are added in the molecule in the correct order.
The last two inputs of the function are timestamp $mark$ and a bit $isExpand$,
which tells us that the matching nodes should be added before or after $mark$.
The calls to $\textsc{MatchTree}$ from \textsc{EncodeP} use the
$isExpand$ appropriately.
% to indicate that nodes correspond to the
% matching part of the rule are added before and expanding part nodes
% are added later.
Afterwords at line~\ref{line:matchtree-recurse},
the procedure calls itself for the children of $v$ and $v_r$.
% to generate the same constraints for the subtree.

Once a rule is applied to a molecule, all the
nodes inside the expanding part are added together.
Therefore, there should be no cuts within the set of added nodes.
Furthermore, if there are children nodes below the added nodes,
they must be added due to the application of some other rule.
Therefore, the children are at the cut points.
We call the above requirement {\em cut pattern}.
$\textsc{MatchCuts}$ is a recursive function over the trees, and matches
cut patterns between the molecule node $v$ and the rule template node $v_r$.
The cuts must occur whenever nodes of the rule template transition
from present to absent.
For helping to detect the transition,
the third parameter is a constraint that encodes that the parent of $v_r$
is absent or not.
% If $v$ does not exist, then there is no constraint to add therefore
% the procedure returns $\ltrue$ at line~\ref{line:mcut-no-v}.
% If $v_r$ does not exist, then it returns constraints encoding
% that if the parent of $v_r$ was not absent, then $v$ must be at a cut at line~\ref{line:mcut-no-vr}.
% If both $v$ and $v_r$ exist, then we add constraints
% that if the parent of $v_r$ is not absent, $v_r$ is
% flagged to be absent in the learned rule
% if and only if $v$ is the cut points at line~\ref{line:mcut-cons}.
% $\textsc{MatchCuts}$ recursively traverses the children of $v$ and $v_r$
% and generates the constraints for the cut pattern.
% The constraints added by the procedure are guarded by the presence of parents
% because we need to enable constraints only when there is a possibility of transition
% from presence to absence.
The call to $\textsc{MatchCuts}$ in \textsc{EncodeP} passes $\lfalse$ as the third input.
Even if the parent of $v_r$ is present,
$v_r$ is a cut point adding cut pattern constraints for the node will create inconsistency.
Therefore, we are passing $\lfalse$.

In the case when we call \textsc{EncodeProduce} with template molecule and
concrete rules.
We swap the roles of $\nu$ and $M$ at their occurrences
at line \ref{line:encodep-ans-match} in \textsc{EncodeP} and
line \ref{line:matchtree-cons} in \textsc{MatchTree}.
Furthermore, $\kappa(v_r)$ is a concrete value.
% depending on the situation of $v_r$ in the rule.
In the functions, the variable is to be replaced by the
evaluated value of $\kappa(v_r)$.

\begin{theorem}
  If \textsc{SugarSynth}($\mu$, $d$, $n$) returns  rules $R$, then if $R$ produces a molecule that has depth less than $h+1$, the it is in $\mu$ (soundness).
  If it fails to find rules, there are no rule sets within the budget of $d$ and  $n$ (completeness).
\end{theorem}

The soundness is true by construction.
% Our algorithm always terminates.
At each iteration, at least one solution, i.e,
a set of rules is discarded.
In fact, we discard many because in each iteration we reject all rule sets that may produce a counterexample molecule.
Since the set of all possible rules is finite, we terminate.
Therefore, the completeness holds.
% In the worst case, the entire search space is explored.

% On the other hand,
% if $v_r$ is also present, then $v$ must not be any cut point.

%--------------------- DO NOT ERASE BELOW THIS LINE --------------------------

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "main"
%%% End:


%%%%%%%%%%%%%%%%%%%%
%
% DIRECTIONS
% Students count off 1, 2, 3, ..., 7, do the one question,
% then explain their answer to their neighbor.
% Perhaps volunteers fill out answer key (+doc camera).
%
% TO PRINT SOLUTIONS
% Typeset with class option "answers",
% ie, \documentclass[10pt, answers]{exam}
%
%%%%%%%%%%%%%%%%%%%%

\RequirePackage{luatex85}
\documentclass[10pt, answers]{exam}
\usepackage{tikz, pgfplots, amsmath, mathtools, multicol, xargs, setspace}
%\pgfplotsset{compat=1.15}
\usepackage[letterpaper, margin=0.5in, column sep=1in]{geometry}
\setlength\parindent{0mm}

% define macro \Repeat{integer}{content}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \Repeat \prg_replicate:nn
\ExplSyntaxOff

\usepackage{hyperref}

\setlength\fillinlinelength{0.7in}
\setlength\answerclearance{0.7ex}
\CorrectChoiceEmphasis{\bfseries\color{red}}

% diagram for questions on pages 1 and 3
\def\yscaleone{2.6} % = amount to shrink diagram in y direction
\newcommand\diagram{
\fullwidth{
\vspace{-1em}
\begin{center}
\begin{tikzpicture}
  [very thick, yscale=1/\yscaleone]
  % grid
%  \draw[gray, semithick, ystep=100, xstep=2, xshift=-1cm] (1,0) grid (12,20.5);
  \draw[gray, semithick, xstep=100, ystep=2, xshift=-1cm] (0,0) grid (15.25,20.5);
  % x- and y-axes
  \draw[<->, semithick] (-1,21) -- node[pos=0.03, right] {$y$} (-1,0) -- node[pos=0.99, above] {$x$} (14.5,0);
  % labels on y-axis
  \foreach \y in {0,10,...,200}
  \draw (-1,\y/10) node[left] {\y};
  % labels on x-axis
  \foreach \x in {1,...,12}
  \draw (\x,0) node[below] {\x};
  % vertical asymptotes
  \foreach \x in {8,...,12}
  \draw[dashed] (\x,0) -- (\x,20.5);
  % horizontal asymptotes
  \foreach \y in {9,6}
  \draw[dashed] (-1,\y) -- (14.25,\y);
  % plot five curves on left half
  \draw[smooth] plot coordinates{(-1,8.85) (0.2,8.6) (1,7) (2,2) (3.15,1.15) (4,5)};
  \draw (4,8) -- (5,7);
  \draw (5,16) to [bend right=10] (6,10);
  \draw (6,14) -- (7,13);
  \draw (7,17) to [bend left=10]  (8,11);
  % plot five asymptotic curves on right half
  \draw[smooth] plot coordinates {(8.1,20.5) (8.2,15) (8.8,15) (8.9,20.5)};
  \draw[smooth] plot coordinates {(9.1,20.5) (9.2,12) (9.8,8) (9.9,0)};
  \draw[smooth] plot coordinates {(10.1,20.5) (10.2,13) (10.8,13) (10.9,20.5)};
  \draw[smooth] plot coordinates {(11.1,0) (11.2,10.5) (11.8,10.5) (11.9,0)};
  \draw[smooth] plot coordinates {(12.1,0) (12.4,5) (14.25,5.85)};
  % open circles
  \foreach \x/\y in {2/2, 3/1, 4/5, 4/8, 5/7, 5/16, 6/10, 7/17, 8/11}
  \draw[black, fill=white, yscale=\yscaleone] (\x,\y/\yscaleone) circle (3pt);
  % closed circles
  \foreach \x/\y in {1/7, 3/4, 5/19, 6/14, 7/13, 8/3, 11/15, 12/18}
  \draw[black, fill=black, yscale=\yscaleone] (\x,\y/\yscaleone) circle (2.5pt);
  % f(x) label
  \draw (1.5,15) node[fill,white] {\color{black} \huge$f(x)$};
  \end{tikzpicture}
  \end{center}
  }

  \vspace{-1em}
  }

\newcommandx\myfillin[6][1=\relax,2=black,3=white,usedefault]{
  \\[-0.7ex]
  \color{#2}
  {#1 \lim_{x\to\mathrlap{\mathbf{#4}}\phantom{0^+}}{}}
  \smash{#5}
  &\color{#2}=\color{white}
  \rlap{\hspace{0.5\fillinlinelength}\clap{\color{#3}\bfseries\text{#6}}}
  \color{white}
  \fillin[#6]
  }

% template for questions 1 through 12 on page 1
\newcommandx\threelim[4]{
\question $\left\{\begin{aligned}
  \\[-6ex]
  \myfillin[\color{white}]{}{f(\arabic{question})}{#1}
  \myfillin{\arabic{question}^-}{f(x)}{#2}
  \myfillin{\arabic{question}^+}{f(x)}{#3}
  \myfillin{\arabic{question}}{f(x)}{#4}
  \end{aligned}\right.$
  }

% template for questions 15 through 26 on page 2
\newcommandx\fivelim[6][
  1={{grid=none, ticks=none}}, 2=\relax, 3=black, usedefault
  ]{
  \def\displayfx{#4}
  \def\displayfzero{#5}
  \def\axisfunction{#6}
  \def\axisstyleoptions{#1}
  \def\axisoptions{#2}
  \def\colordoublelimit{#3}
  \fivelimcontinued
  }
\newcommandx\fivelimcontinued[9][
  1=\relax, 2=\relax, 3=\relax, 4=\relax, 5=\relax, 6=\relax,
  7=white, 8=white, 9=white, usedefault
  ]{
  \question
  \(\begin{matrix}
  \begin{tikzpicture}
  \begin{axis}[
    every axis/.append style={font=\tiny},
    xmin=-3.1, xmax=3.1,
    ymin=-2.4, ymax=2.4,
    samples=99,
    major tick length={0},
    line width=1pt,
    axis lines=center, height=1.6in, width=2in, grid=major,
    restrict y to domain=-2.4:2.4,
    % title={\normalsize{\unboldmath$\displaystyle f(x) = #1$}},
    extra y tick style={y tick label style={right}},
    \axisstyleoptions,
    % samples=59 % speed up compile for testing
    ]
    \addplot [black, smooth, thick, domain=-3:3] {\axisfunction};
    \axisoptions
    \end{axis}
    \end{tikzpicture}
    \end{matrix}\)

  \vspace{-3mm}
  \fullwidth{\(\begin{aligned}
    \myfillin[\color{white}][][#7]{}{\displayfzero}{#1}
    \myfillin[][][#8]{0^-}{\displayfx}{#2}
    \myfillin[][][#8]{0^+}{\displayfx}{#3}
    \myfillin[][\colordoublelimit][#8]{0}{\displayfx}{#4}
    \myfillin[][][#9]{-\infty}{\displayfx}{#5}
    \myfillin[][][#9]{+\infty}{\displayfx}{#6}
    \end{aligned}\)}
  }

\newcommand\opencircle[1]{
  \draw[black, fill=white, thick](axis cs:{#1}) circle [radius=2pt];
  }
\newcommand\closecircle[1]{
  \fill[black] (axis cs:{#1}) circle [radius=2pt];
  }
\newcommand\asymptote[2]{
  \draw[dashed, blue, line width=0.8mm]
  (axis cs: #1) -- (axis cs: #2);
  }

\thispagestyle{empty}
\pagestyle{empty}
\begin{document}
\diagram

\begin{questions}
\section{Find Limits Graphically}
\begin{multicols}3
\threelim{70}{70}{70}{70}
\threelim{undefined}{20}{20}{20}
\threelim{40}{10}{10}{10}
\threelim{undefined}{50}{80}{DNE}
\threelim{190}{70}{160}{DNE}
\threelim{140}{100}{140}{DNE}
\threelim{130}{130}{170}{DNE}
\end{multicols}

\section{Find Limits Involving Infinity Graphically}
\begin{multicols}3
\threelim{30}{110}{$+\infty$}{DNE}
\threelim{undefined}{$+\infty$}{$+\infty$}{$+\infty$}
\threelim{undefined}{$-\infty$}{$+\infty$}{DNE}
\threelim{150}{$+\infty$}{$-\infty$}{DNE}
\threelim{180}{$-\infty$}{$-\infty$}{$-\infty$}
\bigskip
\question $\lim\limits_{x\to \mathbf{-\infty}}f(x) = \color{white}\fillin[90]$
\question $\lim\limits_{x\to \mathbf{+\infty}}f(x) = \color{white}\fillin[60]$
\end{multicols}

\clearpage
\section{Famous Functions}
\setlength\columnsep{8mm}
\raggedcolumns
\begin{multicols}4
\fivelim[][\asymptote{-3,0}{3,0}\asymptote{0,-2}{0,2}]
  {1/x}{1/0}{1/x}
  [undefined][$-\infty$][$+\infty$][DNE][0][0]
\fivelim[samples={501}, xtick={0}, ytick={0}][][white]
  {\sqrt x}{\sqrt0}{sqrt(x)}
  [0][DNE][0][][DNE][$+\infty$]
\fivelim[ytick={1}, xtick={0}][asymptote{-3,0}{3,0}]
  {e^x}{e^0}{e^x}
  [1][1][1][1][0][$+\infty$]
\fivelim[][\asymptote{0,-2}{0,2}][white]
  {\ln x}{\ln0}{ln(x)}
  [undefined][DNE][$-\infty$][][DNE][$+\infty$]
\end{multicols}

\vfill
\begin{multicols}4
\fivelim[][\asymptote{-3,0}{3,0}\asymptote{0,-2}{0,2}]
  {1/x^2}{1/0^2}{1/abs(x)}
  [undefined][$+\infty$][$+\infty$][$+\infty$][0][0]
\fivelim[][{\addplot[black, smooth, thick, domain=-3:3] (x^3,x);}]
  {\sqrt[3]x}{\sqrt[3]0}{0}
  [0][0][0][0][$-\infty$][$+\infty$]
\fivelim{|x|}{|0|}{abs(x)}
  [0][0][0][0][$+\infty$][$+\infty$]
\fivelim[ytick={1}, extra y ticks={-1}, xtick={0}, samples={501}]
  [\opencircle{0,1} \opencircle{0,-1}]
  {|x|/x}{|0|/0}{floor(x/10)*2+1}
  [undefined][$-1$][1][DNE][$-1$][1]
\end{multicols}

\vfill
\begin{multicols}4
\fivelim{\sin x}{\sin 0}{sin(deg(x)*2)}
  [0][0][0][0][DNE][DNE][][][red]
\fivelim[ytick={-1,1},xtick={0}][\opencircle{0,1}\asymptote{-3,0}{3,0}]
  {\sin(x)/x}{\sin(0)/0}{cos(deg(x*6))*exp(-abs(x/1.25))}
  [undefined][1][1][1][0][0]
\fivelim[ytick={-1,1},xtick={0},samples={720}][\asymptote{-3,0}{3,0}]
  {\sin(1/x)}{\sin(1/0)}{sin(deg(1/x*1.5))}
  [undefined][DNE][DNE][DNE][0][0][red][red]
\fivelim[ytick={-2,-1,1,2},xtick={-2,-1,1,2}][
  {\draw[black,thick] (axis cs:-2,-2) edge[-] (axis cs:-1,-2);}
  {\draw[black,thick] (axis cs:-1,-1) edge[-] (axis cs:0,-1);}
  {\draw[black,thick] (axis cs:0,0) edge[-] (axis cs:1,0);}
  {\draw[black,thick] (axis cs:1,1) edge[-] (axis cs:2,1);}
  {\draw[black,thick] (axis cs:2,2) edge[-] (axis cs:3,2);}
  \closecircle{-2,-2} \closecircle{-1,-1} \closecircle{0,0}
  \closecircle{1,1} \closecircle{2,2} \opencircle{-1,-2}
  \opencircle{0,-1} \opencircle{1,0} \opencircle{2,1}
  ]{\lfloor x\rfloor}{\lfloor0\rfloor}{0}[0][$-1$][0][DNE][$-\infty$][$+\infty$]

%%% OMIT, BUT PRETTY: x*sin(1/x)
%\fivelim[ytick={-1,1},xtick={0},samples={720}][\opencircle{0,0}]{x\sin(1/x)}{0\sin(1/0)}{x/6*sin(deg(6/x)) * 0.7*(6-1.2*abs(x))}[undefined][0][0][0][1][1]
\end{multicols}

\newpage
\setstretch{0.1}
\diagram
\vspace{-4mm}
\setlength\columnsep{0.5in}
\section{Identify Infinite, Jump, Removable Discontinuities Graphically}

\vspace{-1mm}
\setlength\fillinlinelength{0.8in}
\question We say $f$
  \rlap{is \fillin[continuous][1in] \textbf{at} $\pmb{x=a}$ if}%
  \phantom{has a \fillin[\textbf{removable}][0.8in] \textbf{discontinuity at} $\pmb{x=a}$ if}
  ${f(a) ={}} \lim\limits_{\mathclap{x\to a^-}}f(x) = \lim\limits_{\mathclap{x\to a^+}}f(x)$
  and all three exist and are finite.

\question We say $f$
  has a \fillin[\textbf{removable}] \textbf{discontinuity at} $\pmb{x=a}$ if
  ${f(a) \ne{}} \lim\limits_{\mathclap{x\to a^-}}f(x) = \lim\limits_{\mathclap{x\to a^+}}f(x)$
  and the last two exist and are \rlap{finite.}

\question We say $f$
  has a \fillin[\textbf{jump}] \textbf{discontinuity at} $\pmb{x=a}$ if
  $\phantom{f(a)={}}\lim\limits_{\mathclap{x\to a^-}}f(x) \ne \lim\limits_{\mathclap{x\to a^+}}f(x)$
  and both exist and are finite.

\question We say $f$
  has a \fillin[\textbf{infinite}] \textbf{discontinuity at} $\pmb{x=a}$ if
  $\phantom{f(a)={}}\lim\limits_{\mathclap{x\to a^-}}f(x)$ or $ \lim\limits_{\mathclap{x\to a^+}}f(x)$
  is infinite and both exist.

\setlength\fillinlinelength{1.5in}
\question The function $f$ above is continuous (cts) at the following integers between 1 and 12: \fillin[1].
\question The function $f$ above has removable discontinuities at the following integers: \fillin[2, 3].
\question The function $f$ above has jump discontinuities at the following integers: \fillin[4, 5, 6, 7].
\question The function $f$ above has infinite discontinuities at the following integers: \fillin[8, 9, 10, 11, 12].

\section{Continuity on an Interval}
\vspace{-4mm}
\question We say $f$ is
  \textbf{continuous on the open interval
  \boldmath $(a,b)$}
  if $f$ is continuous at every $x$
  in $(a,b)$.
  \par Find the union of all open intervals
  \textbf{on which $f$
  is continuous}.
  \\[3ex] (Set-builder notation) \fillin[\smash{\raisebox{2mm}{\pmb{$\{x\mid x\ne 2,3,4,\dots,12\}$}}}][5in]
  \\[3ex] (Interval notation) \fillin[\smash{\raisebox{2mm}{\pmb{$
  (-\infty,2)\cup(2,3)\cup(3,4)\cup\dots\cup(11,12)\cup(12,\infty)
  $}}}][5in]
\question We say $f$ is \textbf{continuous everywhere}
  if $f$ is continuous at every $x$ in \fillin[\pmb{$(-\infty,\infty)$}].
\question We say $f$ is
  \textbf{a continuous function}
  if $f$ is continuous at every
  $x$ in its \fillin[domain].

\vspace{-1mm}
\section{Left and Right Continuity}
\vspace{-4mm}

\question We say $f$
  is \fillin[left continuous] \textbf{at} $\pmb{x=a}$ if
  ${f(a) ={}} \smash{\lim\limits_{\mathclap{x\to a^-}}}f(x)$
  and both exist and are finite.

\question We say $f$
  is \fillin[right continuous] \textbf{at} $\pmb{x=a}$ if
  ${f(a) ={}} \smash{\lim\limits_{\mathclap{x\to a^+}}}f(x)$
  and both exist and are finite.

\question The function $f$ above is left continuous at the following integers between 1 and 12: \fillin[1, 7].
\question The function $f$ above is right continuous at the following integers between 1 and 12: \fillin[1, 6].

\question We say $f$ is \textbf{continuous on the closed interval \boldmath $[a,b]$}
  if $f$ is continuous at every $x$ in the \emph{open} interval $(a,b)$
  \\[1ex]
  and is \fillin[right continuous][2in] at $x=a$
  and is \fillin[left continuous][2in] at $x=b$.

\question The function $f$ above is continuous on the closed interval [ \fillin[6][5mm],\fillin[7][5mm] ] with integer endpoints between 1 and 12.
%
\end{questions}
\end{document}


%-----------------------------------------------------------------------------
\chapter{Functions}
\label{Chp:Functions}

The LAGraph library is composed of the following groups of functions:
\begin{itemize}

\item Context: Functions that manage the context or environment of an instance of the
LAGraph library.

\item Graph Algorithms: Functions that implement a Graph Algorithm.

\item Utilities: Functions that support implementation of Graph Algorithms or support
users of LAGraph.

\end{itemize}

We need to discuss the rules used in naming the functions and defining their argument
lists.

\section{Context}

LAGraph init, finalize and other functions that manage the environment of an instance of LAGraph.

\section{Graph Algorithms}

List the algorithms here.  Then have a subsection with the definition of each algorithms.

%TGM Here is an example of a method definitiion from GraphBLAS

\subsection{{\sf vxm}: Vector-matrix multiply}

Multiplies a (row) vector with a matrix on an semiring. The result is a vector.

\paragraph{\syntax}

\begin{verbatim}
        GrB_Info GrB_vxm(GrB_Vector             w,
                         const GrB_Vector       mask,
                         const GrB_BinaryOp     accum,
                         const GrB_Semiring     op,
                         const GrB_Vector       u,
                         const GrB_Matrix       A,
                         const GrB_Descriptor   desc);
\end{verbatim}

\paragraph{Parameters}

\begin{itemize}[leftmargin=1.1in]
    \item[{\sf w}]    ({\sf INOUT}) An existing GraphBLAS vector.  On input,
    the vector provides values that may be accumulated with the result of the
    vector-matrix product.  On output, this vector holds the results of the
    operation.

    \item[{\sf mask}] ({\sf IN}) An optional ``write'' mask that controls which
    results from this operation are stored into the output vector {\sf w}. The
    mask dimensions must match those of the vector {\sf w}. If the
    {\sf GrB\_STRUCTURE} descriptor is {\em not} set for the mask, the domain of the
    {\sf mask} vector must be of type {\sf bool} or any of the predefined
    ``built-in'' types in Table~\ref{Tab:PredefinedTypes}.  If the default
    mask is desired (\ie, a mask that is all {\sf true} with the dimensions of {\sf w}),
    {\sf GrB\_NULL} should be specified.

    \item[{\sf accum}] ({\sf IN}) An optional binary operator used for accumulating
    entries into existing {\sf w} entries.
    %: ${\sf accum} = \langle \bDout({\sf accum}),\bDin1({\sf accum}),
    %\bDin2({\sf accum}), \odot \rangle$.
    If assignment rather than accumulation is
    desired, {\sf GrB\_NULL} should be specified.

    \item[{\sf op}]   ({\sf IN}) Semiring used in the vector-matrix
    multiply.
    %: ${\sf op}=\langle \bDout({\sf op}),\bDin1({\sf op}),\bDin2({\sf op}),\oplus,\otimes,0 \rangle$.

    \item[{\sf u}]    ({\sf IN}) The GraphBLAS vector holding the values for
    the left-hand vector in the multiplication.

    \item[{\sf A}]    ({\sf IN}) The GraphBLAS matrix holding the values
    for the right-hand matrix in the multiplication.

    \item[{\sf desc}] ({\sf IN}) An optional operation descriptor. If
    a \emph{default} descriptor is desired, {\sf GrB\_NULL} should be
    specified. Non-default field/value pairs are listed as follows:  \\

    \hspace*{-2em}\begin{tabular}{lllp{2.7in}}
        Param & Field  & Value & Description \\
        \hline
        {\sf w}    & {\sf GrB\_OUTP} & {\sf GrB\_REPLACE} & Output vector {\sf w}
        is cleared (all elements removed) before the result is stored in it.\\

        {\sf mask} & {\sf GrB\_MASK} & {\sf GrB\_STRUCTURE}   & The write mask is
        constructed from the structure (pattern of stored values) of the input
        {\sf mask} vector. The stored values are not examined.\\

        {\sf mask} & {\sf GrB\_MASK} & {\sf GrB\_COMP}   & Use the
        complement of {\sf mask}. \\

        {\sf A}    & {\sf GrB\_INP1} & {\sf GrB\_TRAN}   & Use transpose of {\sf A}
        for the operation. \\
    \end{tabular}
\end{itemize}

\paragraph{Return Values}

\begin{itemize}[leftmargin=2.1in]
    \item[{\sf GrB\_SUCCESS}]         In blocking mode, the operation completed
    successfully. In non-blocking mode, this indicates that the compatibility
    tests on dimensions and domains for the input arguments passed successfully.
    Either way, output vector {\sf w} is ready to be used in the next method of
    the sequence.

    \item[{\sf GrB\_PANIC}]           Unknown internal error.

    \item[{\sf GrB\_INVALID\_OBJECT}] This is returned in any execution mode
    whenever one of the opaque GraphBLAS objects (input or output) is in an invalid
    state caused by a previous execution error.  Call {\sf GrB\_error()} to access
    any error messages generated by the implementation.

    \item[{\sf GrB\_OUT\_OF\_MEMORY}] Not enough memory available for the operation.

    \item[{\sf GrB\_UNINITIALIZED\_OBJECT}] One or more of the GraphBLAS objects
    has not been initialized by a call to {\sf new} (or {\sf dup} for matrix or
    vector parameters).

    \item[{\sf GrB\_DIMENSION\_MISMATCH}] Mask, vector, and/or matrix
    dimensions are incompatible.

    \item[{\sf GrB\_DOMAIN\_MISMATCH}]    The domains of the various vectors/matrices are
    incompatible with the corresponding domains of the semiring or
    accumulation operator, or the mask's domain is not compatible with {\sf bool}
    (in the case where {\sf desc[GrB\_MASK].GrB\_STRUCTURE} is not set).
\end{itemize}

\paragraph{Description}

{\sf GrB\_vxm} computes the vector-matrix product ${\sf w}^T = {\sf
u}^T \oplus . \otimes {\sf A}$, or, if an optional binary accumulation
operator ($\odot$) is provided, ${\sf w}^T = {\sf w}^T \odot
\left({\sf u}^T \oplus . \otimes {\sf A}\right)$ (where matrix {\sf A}
 can be optionally transposed).  Logically, this operation
occurs in three steps:
\begin{enumerate}[leftmargin=0.85in]
\item[\bf Setup] The internal vectors, matrices and mask used in the computation are formed and their domains/dimensions are tested for compatibility.
\item[\bf Compute] The indicated computations are carried out.
\item[\bf Output] The result is written into the output vector, possibly under control of a mask.
\end{enumerate}

Up to four argument vectors or matrices are used in the {\sf GrB\_vxm} operation:
\begin{enumerate}
	\item ${\sf w} = \langle \bold{D}({\sf w}),\bold{size}({\sf w}),\bold{L}({\sf w}) = \{(i,w_i) \} \rangle$
	\item ${\sf mask} = \langle \bold{D}({\sf mask}),\bold{size}({\sf mask}),\bold{L}({\sf mask}) = \{(i,m_i) \} \rangle$ (optional)
	\item ${\sf u} = \langle \bold{D}({\sf u}),\bold{size}({\sf u}),\bold{L}({\sf u}) = \{(i,u_i) \} \rangle$
	\item ${\sf A} = \langle \bold{D}({\sf A}),\bold{nrows}({\sf A}), \bold{ncols}({\sf A}),\bold{L}({\sf A}) = \{(i,j,A_{ij}) \} \rangle$
\end{enumerate}

The argument matrices, vectors, the semiring, and the accumulation operator (if provided)
are tested for domain compatibility as follows:
\begin{enumerate}
	\item If {\sf mask} is not {\sf GrB\_NULL}, and ${\sf desc[GrB\_MASK].GrB\_STRUCTURE}$
    is not set, then $\bold{D}({\sf mask})$ must be from one of the pre-defined types of
    Table~\ref{Tab:PredefinedTypes}.

	\item $\bold{D}({\sf u})$ must be compatible with $\bDin1({\sf op})$ of the semiring.

	\item $\bold{D}({\sf A})$ must be compatible with $\bDin2({\sf op})$ of the semiring.

	\item $\bold{D}({\sf w})$ must be compatible with $\bDout({\sf op})$ of the semiring.

	\item If {\sf accum} is not {\sf GrB\_NULL}, then $\bold{D}({\sf w})$ must be compatible with $\bDin1({\sf accum})$ and $\bDout({\sf accum})$ of the
	accumulation operator and $\bDout({\sf op})$ of the semiring must be compatible with $\bDin2({\sf accum})$ of the accumulation operator.
\end{enumerate}
Two domains are compatible with each other if values from one domain can be cast
to values in the other domain as per the rules of the C language.
In particular, domains from Table~\ref{Tab:PredefinedTypes} are all compatible
with each other. A domain from a user-defined type is only compatible with itself.
If any compatibility rule above is violated, execution of {\sf GrB\_vxm} ends and
the domain mismatch error listed above is returned.

From the argument vectors and matrices, the internal matrices and mask used in
the computation are formed ($\leftarrow$ denotes copy):
\begin{enumerate}
	\item Vector $\vector{\widetilde{w}} \leftarrow {\sf w}$.

	\item One-dimensional mask, $\vector{\widetilde{m}}$, is computed from
    argument {\sf mask} as follows:
	\begin{enumerate}
		\item If ${\sf mask} = {\sf GrB\_NULL}$, then $\vector{\widetilde{m}} =
        \langle \bold{size}({\sf w}), \{i, \ \forall \ i : 0 \leq i <
        \bold{size}({\sf w}) \} \rangle$.

		\item If {\sf mask} $\ne$ {\sf GrB\_NULL},
        \begin{enumerate}
            \item If ${\sf desc[GrB\_MASK].GrB\_STRUCTURE}$ is set, then
            $\vector{\widetilde{m}} =
            \langle \bold{size}({\sf mask}), \{i : i \in \bold{ind}({\sf mask}) \} \rangle$,
            \item Otherwise, $\vector{\widetilde{m}} =
            \langle \bold{size}({\sf mask}), \{i : i \in \bold{ind}({\sf mask}) \wedge
            ({\sf bool}){\sf mask}(i) = \true \} \rangle$.
        \end{enumerate}

		\item	If ${\sf desc[GrB\_MASK].GrB\_COMP}$ is set, then
        $\vector{\widetilde{m}} \leftarrow \neg \vector{\widetilde{m}}$.
	\end{enumerate}

	\item Vector $\vector{\widetilde{u}} \leftarrow {\sf u}$.

	\item Matrix $\matrix{\widetilde{A}} \leftarrow {\sf desc[GrB\_INP1].GrB\_TRAN} \ ? \ {\sf A}^T : {\sf A}$.
\end{enumerate}

The internal matrices and masks are checked for shape compatibility. The following
conditions must hold:
\begin{enumerate}
	\item $\bold{size}(\vector{\widetilde{w}}) = \bold{size}(\vector{\widetilde{m}})$.

	\item $\bold{size}(\vector{\widetilde{w}}) = \bold{ncols}(\matrix{\widetilde{A}})$.

	\item $\bold{size}(\vector{\widetilde{u}}) = \bold{nrows}(\matrix{\widetilde{A}})$.
\end{enumerate}
If any compatibility rule above is violated, execution of {\sf GrB\_vxm} ends and
the dimension mismatch error listed above is returned.

From this point forward, in {\sf GrB\_NONBLOCKING} mode, the method can
optionally exit with {\sf GrB\_SUCCESS} return code and defer any computation
and/or execution error codes.

We are now ready to carry out the vector-matrix multiplication and any additional
associated operations.  We describe this in terms of two intermediate vectors:
\begin{itemize}
    \item $\vector{\widetilde{t}}$: The vector holding the product of vector
    $\vector{\widetilde{u}}^T$ and matrix $\matrix{\widetilde{A}}$.
    \item $\vector{\widetilde{z}}$: The vector holding the result after
    application of the (optional) accumulation operator.
\end{itemize}

The intermediate vector $\vector{\widetilde{t}} = \langle
\bDout({\sf op}), \bold{ncols}(\matrix{\widetilde{A}}),
%\bold{L}(\vector{\widetilde{t}}) =
\{(j,t_j) : \bold{ind}(\vector{\widetilde{u}}) \cap
\bold{ind}(\matrix{\widetilde{A}}(:,j)) \neq \emptyset \} \rangle$
is created.  The value of each of its elements is computed by
\[t_j = \bigoplus_{k \in \bold{ind}(\vector{\widetilde{u}}) \cap
\bold{ind}(\matrix{\widetilde{A}}(:,j))} (\vector{\widetilde{u}}(k)
\otimes \matrix{\widetilde{A}}(k,j)),\] where $\oplus$ and $\otimes$
are the additive and multiplicative operators of semiring {\sf op},
respectively.

%-----------------------------------------------------------------------------

\section{Utilities}

Import, Export, and other functions to support users and LAGraph algorithm developers.


\subsubsection{\tt ipplusand}
\label{benchmarkiplusand}

{\tt ipplusand} is a synthetic AKS benchmark that performs
a Boolean-Boolean ({\apl B\qplus\qdot\qand\qtran\0B}) matrix product on
arrays of shape {\tt [ 800, 800]}.

We expect that \wlf and \awlf should exhibit similar performance
on this benchmark.


% This LaTeX was auto-generated from an M-file by MATLAB.
% To make changes, update the M-file and republish this document.

\subsection*{gSinSatT.m}

\begin{par}
\textbf{Summary:} Test the gSin and gSat functions. Check the predictions using Monte Carlo and the derivatives by finite differences.
\end{par} \vspace{1em}
\begin{verbatim}function gSinSatT(fcn, m, v, i, e)\end{verbatim}
\begin{par}
\textbf{Input arguments:}
\end{par} \vspace{1em}
\begin{verbatim}fcn      'gSin' or 'gSat'
m         mean of input distribution                         [D x 1]
v         covariance matrix of input distribution            [D x D]
i         vector of indices of elements to augment           [I x 1]
e         (optional) scaling vector; default: 1              [I x 1]\end{verbatim}
\begin{par}
Copyright (C) 2008-2013 by Marc Deisenroth, Andrew McHutchon, Joe Hall, and Carl Edward Rasmussen.
\end{par} \vspace{1em}
\begin{par}
Last modified: 2013-03-21
\end{par} \vspace{1em}

\begin{lstlisting}
function gSinSatT(fcn, m, v, i, e)
\end{lstlisting}

\subsection*{Code}

\begin{lstlisting}
if nargin < 2
  D = 4;
  m = randn(D,1);
  v = randn(D); v = v*v'+eye(D);
  i = [1;2; 4]; I = length(i);
  e = exp(randn(size(i)));
else
  D = length(m);
end

n = 1e6;               % monte Carlo sample size
delta = 1e-4;          % for finite difference approx

x = bsxfun(@plus, m, chol(v)'*randn(D,n));
switch func2str(fcn)
  case 'gSin', y = bsxfun(@times, e, sin(x(i,:)));
  case 'gSat', y = bsxfun(@times, e, 9*sin(x(i,:))/8+sin(3*x(i,:))/8);
  otherwise, error('Can only handle gSin and gSat')
end

[M, V, C] = fcn(m, v, i, e);
Q = cov([x' y']); Qv = Q(D+1:end,D+1:end); Qc  = v\Q(1:D,D+1:end);

disp(['mean: ', func2str(fcn), '  Monte Carlo'])
disp([M mean(y,2)]); disp([' ']);

disp(['var:  ', func2str(fcn), '  Monte Carlo'])
disp([V(:) Qv(:)]); disp([' ']);

disp(['cov:  ', func2str(fcn), '  Monte Carlo'])
disp([C(:) Qc(:)]); disp(' ');

disp('dMdm')
for j = 1:I
  d = checkgrad(@gSinT0, m, delta, v, i, e, j, fcn);
  disp(['this was element # ' num2str(j) '/' num2str(I)]);
  if d > 1e-6; keyboard; end
end
disp(' ');

disp('dVdm')
for j = 1:I*I
  d = checkgrad(@gSinT1, m, delta, v, i, e, j, fcn);
  disp(['this was element # ' num2str(j) '/' num2str(I*I)]);
  if d > 1e-6; keyboard; end
end
disp(' ');

disp('dCdm')
for j = 1:I*D
  d= checkgrad(@gSinT2, m, delta, v, i, e, j, fcn);
  disp(['this was element # ' num2str(j) '/' num2str(I*D)]);
  if d > 1e-6; keyboard; end
end
disp(' ');

disp('dMdv')
for j = 1:I
  d = checkgrad(@gSinT3, v(tril(ones(length(v)))==1), delta, m, i, e, j, fcn);
  disp(['this was element # ' num2str(j) '/' num2str(I)]);
  if d > 1e-6; keyboard; end
end
disp(' ');

disp('dVdv')
for j = 1:I*I
  d = checkgrad(@gSinT4, v(tril(ones(length(v)))==1), delta, m, i, e, j, fcn);
  disp(['this was element # ' num2str(j) '/' num2str(I*I)]);
  if d > 1e-6; keyboard; end
end
disp(' ');

disp('dCdv')
for j = 1:I*D
  d = checkgrad(@gSinT5, v(tril(ones(length(v)))==1), delta, m, i, e, j, fcn);
  disp(['this was element # ' num2str(j) '/' num2str(I*D)]);
  if d > 1e-6; keyboard; end
end
\end{lstlisting}

\begin{lstlisting}
function [f, df] = gSinT0(m, v, i, e, j, fcn)
[M, V, C, dMdm] = fcn(m, v, i, e);
f = M(j); df = dMdm(j,:);

function [f, df] = gSinT1(m, v, i, e, j, fcn)
[M, V, C, dMdm, dVdm] = fcn(m, v, i, e);
dVdm = reshape(dVdm,[size(V) length(m)]);
dd = length(M); p = fix((j+dd-1)/dd); q = j-(p-1)*dd;
f = V(p,q); df = squeeze(dVdm(p,q,:));

function [f, df] = gSinT2(m, v, i, e, j, fcn)
[M, V, C, dMdm, dVdm, dCdm] = fcn(m, v, i, e);
dCdm = reshape(dCdm,[size(C) length(m)]);
dd = length(M); p = fix((j+dd-1)/dd); q = j-(p-1)*dd;
f = C(p,q); df = squeeze(dCdm(p,q,:));

function [f, df] = gSinT3(v, m, i, e, j, fcn)
d = length(m);
vv(tril(ones(d))==1) = v; vv = reshape(vv,d,d);
vv = vv + vv' - diag(diag(vv));
[M, V, C, dMdm, dVdm, dCdm, dMdv] = fcn(m, vv, i, e);
dMdv = reshape(dMdv,[length(M) size(vv)]);
f = M(j); df = squeeze(dMdv(j,:,:));
df = df+df'-diag(diag(df)); df = df(tril(ones(d))==1);

function [f, df] = gSinT4(v, m, i, e, j, fcn)
d = length(m);
vv(tril(ones(d))==1) = v; vv = reshape(vv,d,d);
vv = vv + vv' - diag(diag(vv));
[M, V, C, dMdm, dVdm, dCdm, dMdv, dVdv] = fcn(m, vv, i, e);
dVdv = reshape(dVdv,[size(V) size(vv)]);
dd = length(M); p = fix((j+dd-1)/dd); q = j-(p-1)*dd;
f = V(p,q); df = squeeze(dVdv(p,q,:,:));
df = df+df'-diag(diag(df)); df = df(tril(ones(d))==1);

function [f, df] = gSinT5(v, m, i, e, j, fcn)
d = length(m);
vv(tril(ones(d))==1) = v; vv = reshape(vv,d,d);
vv = vv + vv' - diag(diag(vv));
[M, V, C, dMdm, dVdm, dCdm, dMdv, dVdv, dCdv] = fcn(m, vv, i, e);
dCdv = reshape(dCdv,[size(C) size(vv)]);
dd = length(M); p = fix((j+dd-1)/dd); q = j-(p-1)*dd;
f = C(p,q); df = squeeze(dCdv(p,q,:,:));
df = df+df'-diag(diag(df)); df = df(tril(ones(d))==1);
\end{lstlisting}