\chapter{Simulation}\label{ch10}
\section{Introduction}

One of the important benefits of using a simulator like \Le is that a circuit designer can simulate digital systems to determine logic flaws or weaknesses that must be addressed before a physical \ac{IC} is manufactured. This chapter introduces the concept of simulation and includes several examples of simulated systems.

%***************************************************************************
% Section: Finite State Machines
%***************************************************************************
\section{Finite State Machines}
\label{SIM:sec:finite_state_machines}

\subsection{Introduction}
\label{SIM:subsec:intro_to_finite_state_machines}

%TODO: Maybe expand this to include Unified Modeling Language???

Sequential logic circuits are dynamic and the combined inputs and outputs of the circuit at any given stable moment is called a \emph{state}. Over time, a circuit changes states as triggering events take place. As an example, a traffic signal may be green at some point but change to red because a pedestrian presses the  ``cross'' button. The current state of the system would be ``green'' but the triggering event (the ``cross'' button) changes the state to ``red.''

The mathematical model of a sequential circuit is called a \ac{FSM}. A \acl{FSM} is an abstract model of a sequential circuit where each state of the circuit is indicated by circles and various triggering events are used to sequence a process from one state to the next. The behavior of many devices can be represented by a \acl{FSM} model, including traffic signals, elevators, vending machines, and robotic devices. \aclp{FSM} are an analysis tool that can help to simplify sequential circuits.

There are two fundamental \ac{FSM} models: Moore and Mealy. These two models are generalizations of a state machine and differ only in the way that the outputs are generated. A Moore machine generates an output as a function of only the current state while a Mealy machine generates an output as a function of the current state plus the inputs into that state. Moore machines tend to be safer since they are only activated on a clock pulse and are less likely to create unwanted feedback when two different modules are interconnected; however, Mealy machines tend to be simpler and have fewer states than a Moore machine. Despite the strengths and weaknesses for each of these two \acp{FSM}, in reality, they are so similar that either can be effectively used to model any given circuit and the actual \ac{FSM} chosen by the designer is often little more than personal preference.

\subsection{Moore Finite State Machine}
\label{SIM:subsec:moore_finite_state_machine}

The Moore \ac{FSM} is named after Edward F. Moore, who presented the concept in a $ 1956 $ paper, \emph{Gedanken-experiments on Sequential Machines}. The output of a Moore \ac{FSM} depends only on its current state. The Moore \ac{FSM} is typically simpler than a Mealy \ac{FSM} so modeling hardware systems is usually best done using a Moore \ac{FSM}.

As an example of a Moore \ac{FSM} imagine a simple candy vending machine that accepts either five cents or ten cents at a time and vends a handful of product when $ 15 $ cents has been deposited (no change is returned). Figure \ref{SIM:fig:moore_vending_machine_fsm} is a Moore \ac{FSM} diagram for this vending machine.

\begin{figure}[H]
  \caption{Moore Vending Machine FSM}
  \label{SIM:fig:moore_vending_machine_fsm}
  \myfloatalign
  \begin{tikzpicture} [scale=1.00]
  \usepgflibrary{shapes.multipart} % for the multipart nodes
  % make all path lines (the node shapes) a little thicker
  \tikzstyle{every path}=[line width=0.50mm]

  % Draw the lines
  \node [circle split,draw] (00) at (2.00, 4) {$ 0.00 $ \nodepart{lower} $ 0 $};
  \node [circle split,draw] (05) at (4.50, 4) {$ 0.05 $ \nodepart{lower} $ 0 $};
  \node [circle split,draw] (10) at (7.00, 4) {$ 0.10 $ \nodepart{lower} $ 0 $};
  \node [circle split,draw] (15) at (9.50, 4) {$ 0.15 $ \nodepart{lower} $ 1 $};

  % ``N'' Arrows
  \draw[->] (00.east) .. controls (3.25,4)  .. node[above] {N} (05.west);
  \draw[->] (05.east) .. controls (5.75,4)  .. node[above] {N} (10.west);
  \draw[->] (10.east) .. controls (8.25,4)  .. node[above] {N-D} (15.west);

  % ``D'' Arrows
  \draw[->] (00.north east) .. controls (4.50,5.25)  .. node[above] {D} (10.north west);
  \draw[->] (05.north east) .. controls (7.00,5.25)  .. node[above] {D} (15.north west);

  % ``Vend'' Arrow
  \draw[->] (15.south) .. controls (7.00,2.25) and (4.50,2.25)  .. node[below] {} (00.south);
  ;
  \end{tikzpicture}
\end{figure}

In Figure \ref{SIM:fig:moore_vending_machine_fsm}, imagine that five cents is deposited between each state circle (that action is indicated by the arrows labeled with an $ N $, for Nickel). The output at each state is zero (printed at the bottom of each circle) until the state reaches $ 0.15 $ in the last circle, then the output changes to one (the product is vended). After that state is reached the system resets to state $ 0.00 $ and the entire process starts over. If a user deposits ten cents, a Dime, then one of the nickel states is skipped.

\subsection{Mealy Finite State Machine}
\label{SIM:subsec:mealy_finite_state_machines}

The Mealy machine is named after George H. Mealy, who presented the concept in a $ 1955 $ paper, \emph{A Method for Synthesizing Sequential Circuits}. The Mealy \ac{FSM} output depends on both its current state and the inputs. Typically a Mealy machine will have fewer states than a Moore machine, but the logic to move from state to state is more complex.

As an example of a Mealy \ac{FSM}, the simple candy vending machine introduced in Figure \ref{SIM:fig:moore_vending_machine_fsm} can be redesigned. Recall that the machine accepts either five cents or ten cents at a time and vends a handful of product when $ 15 $ cents has been deposited (no change is returned). Figure \ref{SIM:fig:mealy_vending_machine_fsm} is a Mealy \ac{FSM} diagram for this vending machine.

\begin{figure}[H]
  \caption{Mealy Vending Machine FSM}
  \label{SIM:fig:mealy_vending_machine_fsm}
  \myfloatalign
  \begin{tikzpicture} [scale=1.00]
  \usepgflibrary{shapes.multipart} % for the multipart nodes
  % make all path lines (the node shapes) a little thicker
  \tikzstyle{every path}=[line width=0.50mm]

  % Draw the lines
  \node [circle,draw] (00) at (2.00, 4) {$ 0.00 $};
  \node [circle,draw] (05) at (5.00, 4) {$ 0.05 $};
  \node [circle,draw] (10) at (8.00, 4) {$ 0.10 $};
  %  \node [circle,draw] (15) at (9.50, 4) {$ 0.15 $};

  % ``N'' Arrows
  \draw[->] (00.east) .. controls (3.50,4)  .. node[above] {N/$0$} (05.west);
  \draw[->] (05.east) .. controls (6.50,4)  .. node[above] {N/$0$} (10.west);

  % ``D'' Arrows
  \draw[->] (00.north east) .. controls (4.00,5.25) and (6.00,5.25)  .. node[above] {D/$0$} (10.north west);
  \draw[->] (05.south west) .. controls (3.50,3.60)  .. node[below] {D/$1$} (00.south east);

  % ``Vend'' Arrow
  \draw[->] (10.south west) .. controls (6.00,2.50) and (3.00,2.50)  .. node[below] {N-D/$1$} (00.south);
  ;
  \end{tikzpicture}
\end{figure}

In Figure \ref{SIM:fig:mealy_vending_machine_fsm} the states are identified by the amount of money that has been deposited, so the first state on the left ($ 0.00 $) is when no money has been deposited. Following the path directly to the right of the first state, if five cents (indicated by ``N'' for a nickel) is deposited, then the output is zero (no candy is dispensed) and the state is changed to $ 0.05 $. If another five cents is deposited, the output remains zero and the state changes to $ 0.10 $. At that point, if either five or ten cents (``N'' or ``D'') is deposited, then the output changes to $ 1 $ (candy is dispensed) and the state resets to $ 0.00 $. By following the transition arrows various combinations of inputs and their resulting output can be traced.

Because the Mealy \ac{FSM} reacts immediately to any input it requires one less state than the Moore machine (compare Figures \ref{SIM:fig:moore_vending_machine_fsm} and \ref{SIM:fig:mealy_vending_machine_fsm}). However, since Moore machines only change states on a clock pulse they tend to be more predictable (and safer) when integrated into other modules. Finally, Mealy machines tend to react faster than Moore machines since they do not need to wait for a clock pulse and, generally, are implemented with fewer gates. In the end, whether to design with a Mealy or a Moore machine is left to the designer's discretion and, practically speaking, most designers tend to favor one type of \ac{FSM} over the other. The simulations in this book use Moore machines because they tend to be easier to understand and more stable in operation.

\subsection{Finite State Machine Tables}
\label{SIM:subsec:finite_state_machine_tables}

Many designers enjoy using Moore and Mealy \ac{FSM} diagrams as presented in Figures \ref{SIM:fig:moore_vending_machine_fsm} and \ref{SIM:fig:mealy_vending_machine_fsm}; however, others prefer to design with a finite state machine table that lists all states, inputs, and outputs. As an example, imagine a pedestrian crosswalk in the middle of a downtown block. The crosswalk has a traffic signal to stop traffic and a \emph{Cross / Don't Cross} light for pedestrians. It also has a button that pedestrians can press to make the light change so it is safe to cross.

This system has several states which can be represented in a \emph{State Table}. The traffic signal can be Red, Yellow, or Green and the pedestrian signal can be Walk or Don't Walk. Each of these signals can be either zero (for \emph{Off}) or one (for \emph{On}). Also, there are two triggers for the circuit; a push button (the \emph{Cross} button that a pedestrian presses) and a timer (so the walk light will eventually change to don't walk). If the button is assumed to be one when it is pressed and zero when not pressed, and the timer is assumed to be one when a certain time interval has expired but zero otherwise, then State Table \ref{SIM:tab:crosswalk_state_table} can be created.

\begin{table}[H]
  \sffamily
  \newcommand{\head}[1]{\textcolor{white}{\textbf{#1}}}
  \begin{center}
    \rowcolors{2}{gray!10}{white} % Color every other line a light gray
    \begin{tabular}{ccccccccccccc}
      \rowcolor{black!75}
      & \multicolumn{5}{c}{\head{Current State}} & \multicolumn{2}{c}{\head{Trigger}} & \multicolumn{5}{c}{\head{Next State}} \\
      & R & Y & G & W & D & Btn & Tmr & R & Y & G & W & D \\
      \hline
      1 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 1 \\
      2 & 0 & 0 & 1 & 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0 & 1 \\
      3 & 0 & 1 & 0 & 0 & 1 & X & 0 & 1 & 0 & 0 & 1 & 0 \\
      4 & 1 & 0 & 0 & 1 & 0 & X & 1 & 0 & 0 & 1 & 0 & 1
    \end{tabular}
  \end{center}
  \caption{Crosswalk State Table}
  \label{SIM:tab:crosswalk_state_table}
\end{table}

The various states are $ R $ (for \emph{Red}), $ Y $ (for \emph{Yellow}), and $ G $ (for \emph{Green}) traffic lights, and $ W $ (for \emph{Walk}) and $ D $ (for \emph{Don't Walk}) pedestrian lights. The \emph{Btn} (for \emph{Cross Button}) and \emph{Tmr} (for \emph{Timer}) triggers can, potentially, change the state of the system.

Row One on this table shows that the traffic light is Green and the pedestrian light is Don't Walk. If the button is not pressed (it is zero) and the timer is not active (it is zero), then the next state is still a Green traffic light and Don't Walk pedestrian light; in other words, the system is quiescent. In Row Two, the button was pressed (\emph{Btn} is one); notice that the traffic light changes state to Yellow, but the pedestrian light is still Don't Walk. In Row Three, the current state is a Yellow traffic light with Don't Walk pedestrian light (in other words, the \emph{Next State} from Row Two), the $ X $ for the button means it does not matter if it is pressed or not, and the next state is a Red traffic light and Walk pedestrian light. In Row Four, the timer expires (it changes to one at the end of the timing cycle), and the traffic light changes back to Green while the pedestrian light changes to Don't Walk.

While Table \ref{SIM:tab:crosswalk_state_table} represents a simplified traffic light system, it could be extended to cover all possible states. Since Red, Yellow, and Green can never all be one at one time, nor could Walk and Don't Walk, the designer must specifically define all of the states rather than use a simple binary count from $ 00000 $ to $ 11111 $. Also, the designer must be certain that some combinations never happen, like a Green traffic light and a Walk pedestrian light at the same time, so those must be carefully avoided.

State tables can be used with either Mealy or Moore machines and a designer could create a circuit that would meet all of the requirements from the state table and then realize that circuit to actually build a traffic light system.

%***************************************************************************
% Section: Elevator
%***************************************************************************
\section{Elevator}
\label{SIM:sec:elevator}

As a simple example of a \ac{FSM}, imagine an elevator control circuit. For simplicity, this elevator is in a five story building and buttons like ``door open'' will be ignored. There are two ways the elevator can be called to a given floor: someone could push the floor button on the elevator to ride to that floor or someone could push the call button beside the elevator door on a floor.

 Figure \ref{SIM:fig:elevator} is the Moore \ac{FSM} for this circuit:

\begin{figure}[H]
  \caption{Elevator}
  \label{SIM:fig:elevator}
  \myfloatalign
  \begin{tikzpicture} [scale=1.00]
  \usepgflibrary{shapes.multipart} % for the multipart nodes
  % make all path lines (the node shapes) a little thicker
  \tikzstyle{every path}=[line width=0.50mm]

  % Draw the lines
  \node [circle split,draw] (S1) at (4.00, 5.00) {$ S1 $ \nodepart{lower} $ 1 $};
  \node [circle split,draw] (S2) at (5.80, 3.75) {$ S2 $ \nodepart{lower} $ 2 $};
  \node [circle split,draw] (S3) at (4.90, 2.00) {$ S3 $ \nodepart{lower} $ 3 $};
  \node [circle split,draw] (S4) at (3.10, 2.00) {$ S4 $ \nodepart{lower} $ 4 $};
  \node [circle split,draw] (S5) at (2.20, 3.75) {$ S5 $ \nodepart{lower} $ 5 $};

  % edge connectors
  \draw (S1.south) -- (S2.west);
  \draw (S2.west)  -- (S3.north);
  \draw (S3.north) -- (S4.north);
  \draw (S4.north) -- (S5.east);
  \draw (S5.east)  -- (S1.south);
  % cross connectors
  \draw (S1.south) -- (S3.north);
  \draw (S1.south) -- (S4.north);
  \draw (S2.west)  -- (S5.east);
  \draw (S2.west)  -- (S4.north);
  \draw (S3.north) -- (S5.east);

  % Loops
  \draw (S1) edge [in=0,out=30,loop] node[above] {1} ();
  \draw (S2) edge [in=15,out=345,loop] node[above] {2} ();
  \draw (S3) edge [in=0,out=330,loop] node[above] {3} ();
  \draw (S4) edge [in=180,out=210,loop] node[above] {4} ();
  \draw (S5) edge [in=165,out=195,loop] node[above] {5} ();

  % Reset input
  \draw[->] (2.50,5.50) .. controls (3.00,5.75) .. node[below] {Rst}  (S1.north west);

  \end{tikzpicture}
\end{figure}

In Figure \ref{SIM:fig:elevator} the various floors are represented by the five states (S1-S5). While the elevator is at a floor then the output from the circuit is the floor number. The elevator is quiescent while in any one state and if a user pushes the button for that same floor then nothing will happen, which is illustrated by the loops starting and coming back to the same state. The star pattern in the middle of the \ac{FSM} illustrates that the elevator can move directly from one state to any other state. Finally, a Reset signal will automatically move the elevator to state S1.

%***************************************************************************
% Section: CPU
%***************************************************************************
\section{Central Processing Unit}
\label{SIM:sec:cpu}

\subsection{Introduction}
\label{SIM:subsec:intro_to_cpu}

The \acf{CPU} is the core of any computer, tablet, phone, or other computer-like device. While many definitions of \ac{CPU} have been offered, many quite poetic (like the ``heart'' or ``brain'' of a computer); probably the best definition is that the \ac{CPU} is the intersection of software and hardware. The \ac{CPU} contains circuitry that converts the ones and zeros that are stored in memory (a ``program'') into controlling signals for hardware devices. The \ac{CPU} retrieves and analyzes bytes that are contained in a program, turns on or off multiplexers and control buffers so data are moved to or from various devices in the computer, and permits humans to use a computer for intellectual work. In its simplest form, a \ac{CPU} does nothing more than fetch a list of instructions from memory and then execute those instructions one at a time. This chapter explores \acp{CPU} from a theoretical perspective.

\subsubsection{Concepts}

A \ac{CPU} processes a string of ones and zeros and uses the information in that binary code to enable/disable circuits or hardware devices in a computer system. For example, a \ac{CPU} may execute a binary code and create electronic signals that first place data on the computer's data bus and then spins up the hard drive to store that data. As another example, perhaps the \ac{CPU} detects a key press on a keyboard, transfers that key's code to memory and also sends a code to the monitor where specific pixels are activated to display the letter pressed.

Figure \ref{sim:fig:simple_data_flow_control_circuit} illustrates a very simple circuit used to control the flow of data on a data bus.

\begin{figure}[H]
  \caption{Simple Data Flow Control Circuit}
  \label{sim:fig:simple_data_flow_control_circuit}
  \myfloatalign
  \begin{tikzpicture} [circuit logic US, scale=1.00]
  % make all path lines (the node shapes) a little thicker
  \tikzstyle{every path}=[line width=0.50mm]

  % Keyboard
  \node[minimum width=2.0cm,draw] (g01) at (5.00,4.00) {Keyboard};
  \node[] (kbd) at (4.15,4.00) {};

  % Monitor
  \node[minimum width=2.0cm,draw] (g02) at (5.00,3.00) {Monitor};
  \node[] (mon) at (4.15,3.00) {};

  % Memory
  \node[minimum size=2.0cm,draw] (g03) at (5.00,1.00) {Memory};
  \node[] (min) at (4.15,1.50) {};
  \node[] (mot) at (4.15,0.50) {};

  % Buffers
  \node[buffer,inputs={n},scale=0.5,rotate=180] (buf_01) at (3.50,4.0) {};
  \node[buffer,inputs={n},scale=0.5]            (buf_02) at (3.50,3.0) {};
  \node[buffer,inputs={n},scale=0.5]            (buf_03) at (3.50,1.5) {};
  \node[buffer,inputs={n},scale=0.5,rotate=180] (buf_04) at (3.50,0.5) {};

  % Demux
  \node[trapezium,rotate=90,minimum size=1.0cm,draw] (g04) at (1.00,1.00) {};
  \node[label={[label distance=-0.55cm]0:$1$}] (1in) at (0.0,1.00) {};
  \node[label={[font=\scriptsize,label distance=-0.35cm]0:Din}] (n1) at (0.65,1.00) {};
  \node[label={[font=\scriptsize,label distance=-0.35cm]180:A}] (oA) at (1.35,1.35) {};
  \node[label={[font=\scriptsize,label distance=-0.35cm]180:B}] (oB) at (1.35,0.65) {};
  \node[label={[font=\scriptsize,label distance=-0.50cm]270:S}] (S) at (0.80,0.50) {};

  % Labels
  \node[circle,pin=135:Data] at (2.75,4) {};
  \node[circle,pin=135:A] at (1.85,3.55) {};
  \node[circle,pin=225:B] at (2.25,0.00) {};

  % Draw the lines
  \draw

  (1in) -- (n1)
  (0.8,0.0) -- (S)

  % Data Bus
  (2.75,0.5) -- (2.75,4)
  (2.75,4.0) -- (buf_01.out)
  (2.75,3.0) -- (buf_02.in)
  (2.75,1.5) -- (buf_03.in)
  (2.75,0.5) -- (buf_04.out)

  % Connect buffers to devices
  (kbd) -- (buf_01.in)
  (mon) -- (buf_02.out)
  (min) -- (buf_03.out)
  (mot) -- (buf_04.in)

  % Dmux A to Kbd+mem
  (oA) -- (1.85,1.35)
  (1.85,1.35) -- (1.85,3.55) -- (3.50,3.55)
  (1.85,1.35) -- (1.85,0.95) -- (3.50,0.95)
  (3.50,3.85) -- (3.50,3.55) % Ctrl out of Buf 1
  (3.50,1.30) -- (3.50,0.95) % Ctrl out of Buf 3

  % Dmux B to Mon+mem
  (oB) -- (2.25,0.65)
  (2.25,0.65) -- (2.25,2.45) -- (3.50,2.45)
  (2.25,0.65) -- (2.25,0.00) -- (3.50,0.00)
  (3.50,2.80) -- (3.50,2.45) % Ctrl out of Buf 2
  (3.50,0.30) -- (3.50,0.00) % Ctrl out of Buf 4

  ;
  \end{tikzpicture}
\end{figure}

In Figure \ref{sim:fig:simple_data_flow_control_circuit}, the demultiplexer at the bottom left corner of the circuit controls four control buffers that, in turn, control access to the data bus. When output $ A $ is active then input from the Keyboard is stored in Memory; but when output $ B $ is active then output from memory is sent to the monitor. By setting the select bit in the demultiplexer the circuit's function can be changed from reading the keyboard to writing to the monitor using a single data bus.

In a true \ac{CPU}, of course, there are many more peripheral devices, along with an \ac{ALU}, registers, and other internal resources to control. Figure \ref{sim:fig:simplified_cpu_block_diagram} is a block diagram for a simplified \ac{CPU}.

\begin{figure}[H]
  \caption{Simplified CPU Block Diagram}
  \label{sim:fig:simplified_cpu_block_diagram}
  \myfloatalign
  \begin{tikzpicture} [circuit logic US, scale=1.00]
  % make all path lines (the node shapes) a little thicker
  \tikzstyle{every path}=[line width=0.50mm]

  % Blocks
  \node[minimum width=3.5cm,draw] (blk01) at (4.00,6.00) {Control};
  \node[minimum width=3.5cm,draw] (blk02) at (4.00,5.00) {ALU};
  \node[minimum width=3.5cm,draw] (blk03) at (4.00,4.00) {General Regs};
  \node[minimum width=3.5cm,draw] (blk04) at (4.00,3.00) {Program Counter};
  \node[minimum width=3.5cm,draw] (blk05) at (4.00,2.00) {Address Reg};
  \node[minimum width=3.5cm,draw] (blk06) at (4.00,0.75) {RAM};
  \node[minimum width=3.5cm,draw] (blk07) at (9.00,3.50) {Peripherals};

  % The block nodes
  \node[] (blk01e) at (2.42,6.00) {};
  \node[] (blk02e) at (2.42,5.00) {};
  \node[] (blk03e) at (2.42,4.00) {};
  \node[] (blk04e) at (2.42,3.00) {};
  \node[] (blk05e) at (2.42,2.00) {};
  \node[] (blk06e) at (2.42,0.75) {};

  \node[] (blk01w) at (5.58,6.00) {};
  \node[] (blk02w) at (5.58,5.00) {};
  \node[] (blk03w) at (5.58,4.00) {};
  \node[] (blk04w) at (5.58,3.00) {};
  \node[] (blk05w) at (5.58,2.00) {};
  \node[] (blk06w) at (5.58,0.75) {};

  \node[] (blk05s) at (4.00,1.80) {};
  \node[] (blk06n) at (4.00,0.85) {};

  % Labels
  \node[circle,pin=135:Control] at (1.5,4) {};
  \node[circle,pin=45:Data]     at (6.5,4) {};
  \node[circle,pin=180:Address] at (4.00,1.35) {};

  % Draw the lines
  \draw
  (6.5,0.75) -- (6.5,6.0) % Data Bus Line
  (1.5,0.75) -- (1.5,6.0) % Control Bus Line
  ;

  % Arrows to Data Bus
  \draw[<->](blk01w) -- (6.5,6.0);
  \draw[<->](blk02w) -- (6.5,5.0);
  \draw[<->](blk03w) -- (6.5,4.0);
  \draw[<->](blk04w) -- (6.5,3.0);
  \draw[<-] (blk05w) -- (6.5,2.0);
  \draw[<->](blk06w) -- (6.5,0.75);

  % Arrows to Control Bus
  \draw[->](blk01e)   -- (1.5,6.0);
  \draw[->](1.5,5.0)  -- (blk02e);
  \draw[->](1.5,4.0)  -- (blk03e);
  \draw[->](1.5,3.0)  -- (blk04e);
  \draw[->](1.5,2.0)  -- (blk05e);
  \draw[->](1.5,0.75) -- (blk06e);

  \draw[<->](6.5,3.5) -- (7.25,3.5); % Arrow to peripherals block

  \draw[->](blk05s) -- (blk06n); % Arrow between addr and RAM blocks
  ;
  \end{tikzpicture}
\end{figure}

The \ac{CPU} in Figure \ref{sim:fig:simplified_cpu_block_diagram} has three bus lines:

\begin{itemize}
  \item \textsc{Control}. This bus contains all of the signals needed to activate control buffers, multiplexers, and demultiplexers in order to move data.
  \item \textsc{Data}. This contains the data being manipulated by the \ac{CPU}.
  \item \textsc{Address}. This is the address for the next instruction to fetch from \ac{RAM}.
\end{itemize}

There are several blocks in the \ac{CPU} in Figure \ref{sim:fig:simplified_cpu_block_diagram}:

\begin{itemize}
  \item \textsc{Control}. This block contains the circuitry necessary to decode an instruction that was fetched from \ac{RAM} and then activate the various devices needed to control the flow of data within the \ac{CPU}.
  \item \textsc{\ac{ALU}}. This is an \acl{ALU} designed for the application that is using this \ac{CPU}.
  \item \textsc{General Registers}. Most \acp{CPU} include a number of general registers that temporarily hold binary numbers or instructions.
  \item \textsc{Program Counter}. This is a register that contains the address of the next instruction to fetch from \ac{RAM}.
  \item \textsc{Address Register}. This contains the address for the current \ac{RAM} operation.
  \item \textsc{\ac{RAM}}. While most computers and other devices have a large amount of \ac{RAM} outside the \ac{CPU}, many \acp{CPU} are constructed with a small amount of internal \ac{RAM} for increased operational efficiency. This type of high-speed \ac{RAM} is usually called cache (pronounced ``cash'').
\end{itemize}

In operation, the \ac{CPU} moves the value of the Program Counter to the Address Register and then fetches the instruction contained at that \ac{RAM} address. That instruction is then sent to the Control circuit where it is decoded. The Control circuit activates the appropriate control devices to execute the instruction. This process is repeated millions of times every second while the \ac{CPU} executes a program.

\subsubsection{History}

\acp{CPU} from the early days of computing (circa $ 1950 $) were custom made for the computer on which they were found. Computers in those early days were rather rare and there was no need for a general-purpose \ac{CPU} that could function on multiple platforms. By the $ 1960 $s \emph{IBM} designed a family of computers based on the design of the \emph{System/$ 360 $}, or \emph{S/$ 360 $}. The goal was to have a number of computers use the same \ac{CPU} so programs written for one computer could be executed on another in the same family. By doing this, \emph{IBM} hoped to increase their customer loyalty.

\acp{CPU} today can be divided into two broad groups: \ac{CISC} (pronounced like ``sisk'') and \ac{RISC}. Early computers, like the IBM S/$ 360 $ had a large, and constantly growing, set of instructions, and these types of \acp{CPU} were referred to as \ac{CISC}. However, building the circuits needed to execute all of those instructions became ever more challenging until, in the late $ 1980 $s, computer scientists began to design \ac{RISC} \acp{CPU} with fewer instructions. Because there were fewer \ac{CPU} instructions circuits could be smaller and faster, but the trade off was that occasionally a desired instruction had to be simulated by combining two or more other instructions, and that creates longer, more complex computer programs. Nearly all computers, cell phones, tablets, and other computing devices in use today use a \ac{RISC} architecture.

More recent developments in \acp{CPU} include ``pipelining'' where the \ac{CPU} can execute two or more instructions simultaneously by overlapping them, that is, fetching and starting an instruction while concurrently finishing the previous instruction. Another innovation changed compilers such that they can create efficient \ac{VLIW} codes that combine several instructions into a single step. Multi-threading \acp{CPU} permit multiple programs to execute simultaneously and multi-core \acp{CPU} use multiple \ac{CPU} cores on the same substrate so programs can execute in parallel.

\acp{CPU}, indeed, all hardware devices, are normally designed using an \ac{HDL} like Verilog to speed development and ensure high quality by using peer review before an \ac{IC} is manufactured. It is possible to find Open Source Verilog scripts for many devices, including \ac{CPU} cores\footnote{\url{http://www.opencores.org}}, so designers can begin with mature, working code and then ``tweak'' it as necessary to match their particular project.

\subsubsection{CPU Design Principles}

\ac{CPU} design commonly follows these steps:

\paragraph{Analysis of Intended Use} Designing a \ac{CPU} starts with an analysis of its intended use since that will determine the type of \ac{CPU} that must be built. A simple four-bit \ac{CPU} --- that is, all instructions are only four-bits wide --- is more than adequate for a simple device like a microwave oven, but for a cell phone or other more complex device, a 16-bit, or larger, \ac{CPU} is needed.

\paragraph{The Instruction Set} After the purpose of the \ac{CPU} is defined then an instruction set is created. \ac{CPU} instructions control the physical flow of bits through the \ac{CPU} and various components of a computer. While an instruction set looks something like a programming language, it is important to keep in mind that an instruction set is very different from the more familiar higher-level programming languages like \emph{Java} and \emph{C++}.

\ac{CPU} instructions are 16-bit (or larger) words that are conceptually divided into two sections: the operational code (\emph{opcode}) and data. There are several classes of instructions, but three are the most common:

\begin{itemize}
  \item \textsc{R (Register)}. These instructions involve some sort of register activity. The quintessential R-Type instruction is \lstinline[columns=fixed]|ADD|, where the contents of two registers are added together and the sum is placed in another register.
  \item \textsc{I (Immediate)}. These instructions include data as part of the instruction word and something happens immediately with that data. As an example, the \lstinline[columns=fixed]|LDI| instruction immediately loads a number contained in the instruction word into a specified register.
  \item \textsc{J (Jump)}. These instructions cause the program flow to jump to a different location. In older procedural programming languages (like \emph{C} and \emph{Basic}) these were often called \lstinline[columns=fixed]|GOTO| statements.
\end{itemize}

\paragraph{Assembly Language} A computer program is nothing more than a series of ones and zeros organized into words the bit-width of the instruction set,  commonly $ 32 $-bit or $ 64 $-bit. Each word is a single instruction and a series of instructions forms a program in \emph{machine code} that looks something like this:

\begin{align}
  \label{SIM:eq:sample_machine_code}
  0000 0000 0000 0000\\
  \nonumber
  1001 0001 0000 1010\\
  \nonumber
  1001 0010 0000 1001\\
  \nonumber
  0111 0011 0001 1000\\
  \nonumber
  0110 0000 0010 0011
\end{align}

A \ac{CPU} fetches and executes one $ 16 $-bit word of the machine code at a time. If a programmer could write machine code directly then the \ac{CPU} could execute it without needing to compile it first. Of course, as it is easy to imagine, no one actually writes machine code due to its complexity.

The next level higher than machine code is called \emph{Assembly}, which uses easy-to-remember abbreviations (called ``mnemonics'') to represent the available  instructions. Following is the assembly language program for the machine code listed above:

\begin{verbatim}
  Label Mnemonic Operands    Comment
  START NOP      0 0 0       No Operation
        LDI      1 0 a       R1  <- 0ah
        LDI      2 0 9       R2  <- 09h
        SHL      3 1 4       R3  <- R1 << 8
        XOR      0 2 3       Acc <- R2 XOR R3
\end{verbatim}

Each line of assembly has four parts. First is an optional \emph{Label} that can be used to indicate various sections of the program and facilitates ``jumps'' around the program; second is the mnemonic for the code being executed; third are one or more operands; and fourth is an optional comment field.

\marginpar{Machine code is \ac{CPU} specific so code written for one type of computer could not be used on any other type of computer.}

Once the program has been written in Assembly, it must be ``assembled'' into machine code before it can be executed. An assembler is a fairly simply program that does little more than convert a file containing assembly code into instructions that can be executed by the \ac{CPU}. The assembly program presented above would be assembled into Machine Code \ref{SIM:eq:sample_machine_code}.

\paragraph{Programming Languages}

Many high level programming languages have been developed, for example \emph{Java} and \emph{C++}. These languages tend to be easy to learn and can enable a programmer to quickly create very complex programs without digging into the complexity of machine code.

Programs written in any of these high-level languages must be either interpreted or compiled before they can be executed. Interpreters are only available for ``scripting'' languages like \emph{PERL} and \emph{Python} and they execute the source code one line at a time. In general, interpreters cannot optimize the code so they are not efficient; but they enable a programmer to quickly ``try out'' some bit of code without having to compile it. A compiler, on the other hand, converts the entire program to machine code (normally referred to as ``object'' code by a compiler) and then creates an executable file. A compiler also optimizes the code so it executes as efficiently as possible.

In the end, there are dozens of different programming languages, but they all eventually reduce programming instructions to a series of ones and zeros which the \ac{CPU} can execute.

\subsubsection{State Machine}

Because a \ac{CPU} is little more than a complex \ac{FSM}, the next step in the design process is to define the various states and the operations that take place within each state. In general, an operating \ac{CPU} cycles endlessly through three primary states:

\begin{itemize}
  \item \textsc{Fetch} an instruction from memory. Instructions take the form of 16-bit numbers similar in appearance to $ 1001 0001 0000 1010 $.
  \item \textsc{Decode} the instruction. The instruction fetched from memory must be decoded into something like ``Add the contents of Register $ 2 $ to Register $ 3 $ and save the results in Register 1.''
  \item \textsc{Execute} the instruction.
\end{itemize}

In general, the way that a \ac{CPU} functions is to fetch a single instruction from \ac{RAM} and then decode and execute that instruction. As an example, consider the Assembly example introduced above:

\begin{Verbatim}[commandchars=~\[\], samepage=true, fontfamily=courier]
Label Mnemonic Operands    Comment
START NOP      0 0 0       No Operation
      LDI      1 0 a       R1  <- 0ah
      LDI      2 0 9       R2  <- 09h
      SHL      3 1 4       R3  <- R1 << 8
      XOR      0 2 3       Acc <- R2 XOR R3
\end{Verbatim}

Each line is an instruction and the \ac{CPU} would fetch and execute each instruction from \ac{RAM} in order. The purpose of this short code snip is to load a $ 16 $-bit register with a number when only $ 8 $ bits are available in the opcode. The eight high order bits are loaded into Register one and the eight low order bits are loaded into Register two. The high order bits are shifted to the left eight places and then the two registers are \lstinline[columns=fixed]|XOR|'d together:

\begin{enumerate}
  \item \lstinline[columns=fixed]|NOP|: This is a ``no operation'' instruction so the \ac{CPU} does nothing.
  \item \lstinline[columns=fixed]|LDI|: The number $ 0A_{16} $ is loaded into register one. This is the value of the high-order bits desired in the $ 16 $-bit number.
  \item \lstinline[columns=fixed]|LDI|: The number $ 09_{16} $ is loaded into register two.  This is the value of the low-order bits desired in the $ 16 $-bit number.
  \item \lstinline[columns=fixed]|SHL|: Register three is loaded with the value of register one shifted left eight places.
  \item \lstinline[columns=fixed]|XOR|: The Accumulator is loaded with the value of register two \lstinline[columns=fixed]|XOR|'d with 4egister three. This leaves the accumulator with a \lstinline[columns=fixed]|16|-bit number, $ 0A09_{16} $ that was loaded eight bits at a time.
\end{enumerate}

\subsection{CPU States}
\label{SIM:subsec:cpu_states}

The first task that a \ac{CPU} must accomplish is to fetch and decode an instruction held in memory. Figure \ref{SIM:fig:cpu_state_diagram} is a simplified state diagram that shows the first two \ac{CPU} states as \emph{Fetch} and \emph{Decode}. After that, all of the different instructions would create their own state (for simplicity, only three instructions are shown in the Figure \ref{SIM:fig:cpu_state_diagram}).

\begin{figure}[H]
  \caption{CPU State Diagram}
  \label{SIM:fig:cpu_state_diagram}
  \myfloatalign
  \begin{tikzpicture} [scale=1.00]
  \usepgflibrary{shapes.multipart}
  \usetikzlibrary{trees}
  % make all path lines (the node shapes) a little thicker
  \tikzstyle{every path}=[line width=0.50mm]

  \node(F0) {Fetch}
    child {node {Decode}
      child {node {NOP}}
      child {node {ADD}}
      child {node {ADI}}
      child {node {...}}
    };
  ;
  \end{tikzpicture}
\end{figure}

The \ac{CPU} designer would continue to design states for all instructions and end each state with a loop back to Fetch in order to get the next instruction out of \ac{RAM}.

Designing a \ac{CPU} is no insignificant task and is well beyond the scope of this book. However, one of the labs in the accompanying lab manual design a very simple processor that demonstrates how bits are moved around a circuit based upon control codes.


\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage[T1]{fontenc}
\usepackage[USenglish]{babel}
\usepackage[nodayofweek,level]{datetime}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{tikz}
\usetikzlibrary{intersections,arrows.meta}
\usepackage{pgfplots}
\usepackage[scr]{rsfso}
\usepackage{array}
\usepackage{stackengine}
\stackMath

\usepackage{tikz,pgfplots}

\pgfplotsset{compat=1.10}
% Uncomment to use %fillbetween" function
% otherwise leave commented because
% the red highlighting is annoying
%\usepgfplotslibrary{fillbetween}

% Change due date below
\newcommand{\dueDate}{\formatdate{13}{10}{2017}}

\begin{document}

%\selectlanguage{USenglish}

\title{Homework: Week 3}
\author{Joseph Ismailyan}
\date{}
\maketitle
\begin{flushleft}
Math 100 \\
Due: \dueDate \\
Professor Boltje \\
MWF 9:20a-10:25a
\end{flushleft}

% Insert first section here
% Minipage creates the columns
\begin{minipage}[t]{0.40\textwidth}

\section*{Section 2.7}
\subsection*{6.}
Translate to English: \\$  \exists n \in \mathbb{N}, \forall X \in \mathscr{P}(\mathbb{N}) , |X| < n$\\

Translated: There exists a natural number $ n $ for every subset $ X $ of $ \mathbb{N} $ where $ |X| <n $.\\

This can be proven false with a simple counter example as follows: \\ $ X=\{1,2\} \text{ and } n=1 \text{ then } |X| > n$

\section*{Section 2.9}
\subsection*{6.}
Translate to SL:\\
For every positive number $ \varepsilon $ there is a positive number $ M $ for which \\$ |f(x)-b|<\varepsilon $, whenever $ x>M $.\\

Logic:

$\forall \varepsilon\in\mathbb{R},\varepsilon\geq 0, \exists M\in\mathbb{R},M\geq 0,$
\\
$
(x>M) \implies (|f(x)-b|<\varepsilon)
$

\end{minipage}
% Creates verticle line
\hfill\vline\hfill
\begin{minipage}[t]{0.45\textwidth}

\section*{Section 2.10}
\subsection*{8.}
Translate: If $ x $ is a rational number and $ x \neq 0 $, then $ \tan(x) $ is not a rational number.\\

SL: $ (x\in \mathbb{Q} \land x\neq 0)  \implies (tan(x) \notin \mathbb{Q})$ \\
Negation:$ x\in \mathbb{Q} \land x\neq 0 \land tan(x) \in \mathbb{Q}$ \\

Translation (Answer):  $ x $ is a rational number and $ x \neq 0 $ and $ \tan(x) $ is a rational number.

\section*{Section 3.1}
\subsection*{4.}
Question: Five cards are dealt off of a standard 52-card deck and lined up in a row. How
many such line-ups are there in which all 5 cards are of the same suit?

Answer: $ 13*12*11*10*9 = 154,440 $
\subsection*{12.}
Answer: $ 5^5-(4^5+(5*4^4))=821$

\end{minipage}
\pagebreak

\begin{minipage}[t]{0.40\textwidth}

\section*{Section 3.2}
\subsection*{8.}
Answer: There are 4 places the odd sequence could start.\\
$ O = \text{odd}, E = \text{even} $

$$ \stackon{4}{O}\stackon{3}{O}\stackon{2}{O}\stackon{1}{O}\stackon{3}{E}\stackon{2}{E}\stackon{1}{E}  = \stackunder{144}{+}
$$
$$ \stackon{3}{E}\stackon{6}{O}\stackon{3}{O}\stackon{2}{O}\stackon{1}{O}\stackon{2}{E}\stackon{1}{E}  = \stackunder{144}{+}
$$
$$ \stackon{3}{E}\stackon{2}{E}\stackon{4}{O}\stackon{3}{O}\stackon{2}{O}\stackon{1}{O}\stackon{1}{E}  = \stackunder{144}{+}
$$
$$ \stackon{3}{E}\stackon{2}{E}\stackon{1}{E}\stackon{4}{O}\stackon{3}{O}\stackon{2}{O}\stackon{1}{O}  = 144
$$
$ \text{Total}: 576 $

\section*{Section 3.3}
\subsection*{10.}
Answer: $ \binom{5}{3}\binom{7}{2} = 210$
\subsection*{12.}
Answer: \\$ \binom{21}{10}\binom{11}{11} =352,716$

\end{minipage}
% Creates verticle line
\hfill\vline\hfill
\begin{minipage}[t]{0.45\textwidth}
\section*{Section 3.4}
\subsection*{12.}
Show that:
\[
\binom{n}{k}\binom{k}{m}=\binom{n}{m}\binom{n-m}{k-m}
\]
LHS:\\
\[=\frac{n!}{k!(n-k)!}*\frac{k!}{m!(k-m)!}\]
\[=\frac{n!}{m!(n-k)!(k-m)!}\]
RHS:\\
\[=\frac{n!}{m!(n-m)!}*\frac{n-m!}{(k-m)![(n-m)-(k-m)]!}\]
\[=\frac{n!}{m!(k-m)![n-m-k+m]!}\]
\[=\frac{n!}{m!(k-m)!(n-k)!}\]

\[\frac{n!}{m!(n-k)!(k-m)!} = \frac{n!}{m!(k-m)!(n-k)!}\]

\[\therefore \binom{n}{k}\binom{k}{m}=\binom{n}{m}\binom{n-m}{k-m}\]

\end{minipage}
\pagebreak

\end{document}


\documentclass{article}
\usepackage{fullpage}
\usepackage{nopageno}
\usepackage{amsmath}
\allowdisplaybreaks

\newcommand{\abs}[1]{\left\lvert #1 \right\rvert}

\begin{document}
\title{Notes}
\date{January 24, 2014}
\maketitle
how to count subsets consiting of r object from n types (m\&m's/colors)

ordered arrangement or unordered

no repetition of types/colors, repetition with infinite supply, repetition with restricted supply

$x_i$ of type $i$

number one from worksheet is ordered with repetition with infinite supply

2.2 ordered arrangement with no repetition: $\frac{n!}{(n-r)!}=P(n,r)$

2.4 ordered arrangement with repetition and restricted supply: $\frac{n!}{(n-r)!x_1!x_2!...}$

2.4 ordered arrangement with repetition and infinite supply: $n^r$

2.3 unordered arrangement with no repetition: $\frac{P(n,r)}{r!}=\frac{n!}{(n-r)!r!}=\left(\begin{array}{c}n\\r\end{array}\right)$

2.5 unordered arrangement with repetition and an infinite supply: $\left(\begin{array}{c}r+n-1\\r\end{array}\right)$

unordered arrangement with repetition and a restricted supply: harder

\subsection*{example 1}
how many positive integral solutions of $x_1+x_2+x_3+x_4+x_5=42$ are there where positive is $\geq0$

$x_1|x_2|x_3|x_4|x_5$ and put 42 things in every part. it unordered repetition with infinite supply. $\left(\begin{array}{c}42+5-1\\42\end{array}\right)$

\subsection*{example 2}
how  many integral solutions to $x_1+x_2+x_3=10, x_1\geq-8, x_2\geq2, x_3\geq0$

$x_1+8=y_1, x_2-2=y_2, x_3=y_3$ so $y_1+y_2+y_3=16$ and the answer is $\left(\begin{array}{c}16+3-1\\16\end{array}\right)$

\subsection*{example 3}
take a chessboard (8x8) take out all the pieces but rooks, now we have 4 rooks that we want to place such that they aren't attacking.

\end{document}


    \filetitle{chowlin}{Chow-Lin distribution of low-frequency observations over higher-frequency periods}{tseries/chowlin}

	\paragraph{Syntax}\label{syntax}

\begin{verbatim}
[Y2,B,RHO,U1,U2] = chowlin(Y1,X2)
[Y2,B,RHO,U1,U2] = chowlin(Y1,X2,range,...)
\end{verbatim}

\paragraph{Input arguments}\label{input-arguments}

\begin{itemize}
\item
  \texttt{Y1} {[} tseries {]} - Low-frequency input tseries object that
  will be distributed over higher-frequency observations.
\item
  \texttt{X2} {[} tseries {]} - Tseries object with regressors used to
  distribute the input data.
\item
  \texttt{range} {[} numeric {]} - Low-frequency date range on which the
  distribution will be computed.
\end{itemize}

\paragraph{Output arguments}\label{output-arguments}

\begin{itemize}
\item
  \texttt{Y2} {[} tseries {]} - Output data distributed with higher
  frequency.
\item
  \texttt{B} {[} numeric {]} - Vector of regression coefficients.
\item
  \texttt{RHO} {[} numeric {]} - Actually used autocorrelation
  coefficient in the residuals.
\item
  \texttt{U1} {[} tseries {]} - Low-frequency regression residuals.
\item
  \texttt{U2} {[} tseries {]} - Higher-frequency regression residuals.
\end{itemize}

\paragraph{Options}\label{options}

\begin{itemize}
\item
  \texttt{'constant='} {[} \emph{\texttt{true}} \textbar{}
  \texttt{false} {]} - Include a constant term in the regression.
\item
  \texttt{'log='} {[} \texttt{true} \textbar{} \emph{\texttt{false}} {]}
  - Logarithmise the data before distribution, de-logarithmise
  afterwards.
\item
  \texttt{'ngrid='} {[} numeric \textbar{} \emph{\texttt{200}} {]} -
  Number of grid search points for finding autocorrelation coefficient
  for higher-frequency residuals.
\item
  \texttt{'rho='} {[} \emph{\texttt{'estimate'}} \textbar{}
  \texttt{'positive'} \textbar{} \texttt{'negative'} \textbar{} numeric
  {]} - How to determine the autocorrelation coefficient for
  higher-frequency residuals.
\item
  \texttt{'timeTrend='} {[} \texttt{true} \textbar{}
  \emph{\texttt{false}} {]} - Include a time trend in the regression.
\end{itemize}

\paragraph{Description}\label{description}

Chow,G.C., and A.Lin (1971). Best Linear Unbiased Interpolation,
Distribution and Extrapolation of Time Series by Related Times Series.
Review of Economics and Statistics, 53, pp.~372-75.

See also Appendix 2 in Robertson, J.C., and E.W.Tallman (1999). Vector
Autoregressions: Forecasting and Reality. FRB Atlanta Economic Review,
1st Quarter 1999, pp.4-17.

\paragraph{Example}\label{example}


\chapter{Description of Alternative 5-D Initial Density}\label{ext:pde-5d-initial}

\begin{figure}
\centering
  \includegraphics[width=0.675\linewidth]{figures/pde-highd/pde-highd-alt_initial_D5_m100.png}
\caption{
Knowledge of the behavior of $g$ at the boundaries allows for more than half of each of the three remaining intervals in five dimensions to be ruled out as infeasible regions when we look at high-probability samples from the 2-D SIP solution.
}
\label{fig:pde-highd-5d-study}
\end{figure}

In Figure~\ref{fig:pde-highd-5d-study}, we plot the parameter samples whose relative ratios exceeded $1/1000$ and note that they sweep out a family of curves that can be used to estimate bounds not only on $\lambda_2$ and $\lambda_4$ (the previous $\lambda_1$ and $\lambda_2$ from the 2-D problem)\---which exhibit correlation structure\---but also on the remaining three knots.
To form the intervals shown in orange in Fig.~\ref{fig:pde-highd-5d-study}, we take the upper and lower bounds of the curves passing through the vertical lines drawn at the three new knot values.
To be conservative, we multiply our lower bound by $1.2$ and the upper by $0.8$.
With these choices, we are still more than halving the interval-length in each direction as compared to the previous 5-D problem.
One could establish a lower tolerance for accepting likely samples and avoid the multiplication factor, or make any number of other choices for a refined initial density.
However, a thorough exploration of how to best leverage the ratio of observed to predicted densities is left to future work, and will always be highly problem--dependent.

% \section{Capturing Correlation Structure from 2-D SIP Solution}
For the two remaining directions, we want to capture the correlation structure that we were able to visually identify in Fig.~\ref{fig:pde-highd-2d-updated} and impose a uniform density over the support of the set.
To achieve this desired refinement of an initial density, we perform a singular-value decomposition on the likely samples from the scalar--valued 2-D solution, since there are so many more samples\footnote{ The scalar-valued contour was found to better characterize the direction of the equivalence class, suggesting perhaps a justifiable use for solving the problem with it. We could have formed an estimate of the updated density from using the vector--valued QoI and sampled from that instead. Many such approaches can be looked into in the future and are briefly discussed in the last section of this chapter.}.
The singular vectors are used to transform the vector-valued samples, and a uniform sampling is performed over the rectangular bounding box for these points, shown in the center of Figure~\ref{fig:pde-highd-2d-study}.
These generated samples, however, leave $\pspace$ when transformed back to their native space, as seen in the left panel.
To ameliorate this problem, we instead perform sampling in a while-loop, sampling from this uniform box and rejecting any that would get mapped back outside $\pspace$, until we reach our desired thousand samples.

\begin{figure}[htbp]
\centering
  \includegraphics[width=0.95\linewidth]{figures/pde-highd/pde-highd-alt_initial_D2_m100}
\caption{
Generating proposal samples for the two directions informed by solving the 2-D inverse problem, aided by singular-value decompositions and an ad-hoc sampling procedure.
}
\label{fig:pde-highd-2d-study}
\end{figure}

Analogously speaking, we set out to define a computational open cover for the relatively high-probability samples.
In the center panel of Fig~\ref{fig:pde-highd-2d-study}, there are corner-regions of the space we want to avoid wasting samples on as well, so we reject samples that have squared two-norm greater than $0.05$ from their nearest vector--valued sample.
This sampling procedure produces the set shown in orange on the right side of the figure (ten thousand shown to demonstrate coverage).
One thousand of these samples are kept at random and joined with the samples generated from the three other directions.


% =========================================================================
% -------------------------------------------------------------------------
% Thermal:
% -------------------------------------------
%
%  Non-isothermal (heat)
%
% -------------------------------------------------------------------------

\section{Thermal Flow Processes}

\label{sec:thermal-processes}

\subsection{Overview}

Heat flow and thermal conduction is an important aspect of many geochemical systems
affecting chemical processes through changes in equilibrium and kinetic rate constants.
Non-isothermal conditions can also result in buoyancy driven flow leading to convection cells
and causing fingering phenomena due to differences in density.

%\subsection{Data Needs}

Equations of state for fluid density, internal energy and/or enthalpy are needed
in addition to heat capacity and thermal conductivity of the porous medium.
Often the fluid properties for a complex mixture are unknown and the pure phase end member properties are used.

%---------------------------------------------------------------------------------------------
% Conservation Equations - Energy.
%---------------------------------------------------------------------------------------------
\subsection{Model Equations}

As heat flow is coupled to the Darcy flux, the heat equation itself is coupled to the flow equation
as well as reactive transport equations through heat generated by chemical reactions.
Conversely the flow and reactive transport equations are coupled to the heat equation
through the temperature dependence of fluid properties such as density, viscosity, internal energy and enthalpy,
and equilibrium thermodynamic and kinetic rate constants.

\subsubsection{Partially saturated flow with water vapors}

In the case of isothermal Richards equations it was possible to neglect water vapors, as
presumably their concentration was the same everywhere.
In the case when temperature variations cannot be neglected the effects of water vapors could be significant.

The Richards equation is derived from the conservation of liquid mass equation.
Thus, changing vapor concentrations introduce an additional term
$$
  -\bnabla \cdot \left( \K_g \bnabla \frac{p_v}{p_g} \right)
$$
into \eqref{eq:Darcy}, where
$p_v$ and $p_g$ [$\upa$] are the vapor and the gas pressures, respectively,
and
$\K_g$ is the effective diffusion coefficient of the water vapors.
The gas pressure is presumed to be equal to the atmospheric one,
while water vapor pressure is derived from the equilibrium of liquid and gas phases:
\[
  p_v = P_\text{sat} (T) \exp\left(\frac{P_\text{cgl}}{\eta_l RT}\right),
\]
where
$P_\text{sat}$ is the saturated vapor pressure,
$P_\text{cgl}$ is the capilary gas-liquid pressure, and
$R$ is the ideal gas constant.

The Richards equation with gas vapors takes the form
\begin{subequations}\label{eq:Richards with vapors}
\begin{align}
  \frac{\partial \theta(p_l)}{\partial t}
  &=
  -\bnabla \cdot (\eta_l \bq_l)
  -\bnabla \cdot \left( \K_g \bnabla \frac{p_v}{p_g} \right)
  + Q,
  \\
  \bq_l
  &=
  -\frac{\K k_{rl}}{\mu_l} (\bnabla p_l - \rho_l \bg),
\end{align}
\end{subequations}
where
$\eta_l$ is the molar liquid density,
$Q$ is source or sink term [$\ukg \ucdot \um^{-3} \ucdot \us^{-1}$],
$\K$ is absolute permeability tensor,
$\mu_l$ is liquid viscosity,
$\rho_l$ is liquid density, and
$k_{rl}$ is relative permeability.
The total volumetric water content $\theta$ has to be modified to include
the vapors
$$
  \theta = \phi \eta_l\, s_l + \phi (1-\eta_l) X_l,
$$
where $X_l$ is molar fraction of water vapors.

The effective diffusion coeficient of water vapor is given by
\[
  \K_g = \phi g_g \tau_g \eta_g D_g,
\]
where $s_g$ is gas saturation,
$\tau_g$ is the gas tortuosity,
$\eta_g$ is the molar density of gas, and
$D_g$ is the gas diffusion coefficient.
The later, based on the TOUGHT2 model, is
\[
  D_g = D_\text{ref} \frac{P_\text{ref}}{p_g} \left(\frac{T}{T_\text{ref}}\right)^\alpha,
\]
where
$D_\text{ref} = 2.14\times 10^{-5}$,
$P_\text{ref}$ is the atmospheric pressure,
$T_\text{ref} = 273.15$,
$\alpha=1.8$.
Finally, we need a model for the gas tortuosity
for which we use \citet{millington1961permeability}
model
\[
  \tau_g = \phi^\beta, s_g^\gamma,
  \qquad \beta = 1/3, \quad \gamma = 7/3.
\]

\subsubsection{Energy Conservation Equation}
\label{sec:Energy}

The Richards equation with water vapor is coupled with the conservation of energy equation.
One form of such equation in a porous medium with porosity $\phi$ is given by
\begin{align}
\label{eq:energy_balance}
  \frac{\partial}{\partial t} \Big[
  \phi \rho_l u_l s_l
  +
  (1-\phi )\rho_r u_r
  \Big] \
  + \ &
  \boldsymbol{\nabla} \cdot \left[
  -\frac{\K k_{rl} }{\mu _l } (\boldsymbol{\nabla} p_l
  -
  \rho _{\alpha} g \boldsymbol{e}_z)\rho _l h_l
  -
  Q_T
  \right]
  \eq
  Q_e,
\end{align}
where
$\rho_{r}$ and $\rho_{l}$ are the density,
$u_{r}$ and $u_l$ are the internal energy
of the rock and the liquid phases, respectively;
$\K$ is the absolute permeability tensor,
$k_{rl}$ is the relative permeability coefficient,
$s_l$ is the liquid saturation,
$\mu_l$ is fluid viscosity,
$h_l$ is the enthalpy of the liquid phase,
$Q_T$ represents thermal conduction and radiation, and
$Q_{e} $ is a source or sink of energy.
Note that the energy consumed/produced by chemical reactions is included in this last term.

The primary variables in \eqref{eq:energy_balance} are the pressure $p_l$
and the temperature $T$.
The internal energies $u_r$ and $u_l$ are both functions of temperature.
Assuming that the internal energy $u_r$ and the thermal conduction $Q_T$
have linear dependence on temperature,
$$
  u_r = c_r T \qquad \text{and}\qquad Q_T=\kappa T,
$$
the equation \eqref{eq:energy_balance} takes the form
\EQ
  \frac{\partial}{\partial t}
  \Big[ \phi s_l \rho_l u_l
  +
  (1-\phi) \rho_r c_r T \Big]
  +
  \boldsymbol{\nabla}\cdot \Big[
  \bq_l \rho_l h_l
  -
  \kappa\boldsymbol{\nabla} T\Big]
  \eq
  Q_e,
\EN
where
$T$ refers to temperature,
$\bq_l$ is the Darcy velocity
\EQ
  \bq_l
  =
  -\frac{\K k_{rl} }{\mu _l }
  \left(
  \boldsymbol{\nabla} p_l
  -
  \rho _{\alpha} g \boldsymbol{e}_z
  \right),
\EN
the coefficient $\kappa$ denotes the thermal conductivity of the medium and
$c_r$ refers to the specific heat of the porous medium.
The internal energy and enthalpy are related by the equation
\EQ
  u_l \eq h_l -\frac{p_l}{\rho_l}.
\EN
Thermal conductivity if often described by the phenomenological relation given by \citet{somerton1974high}
\EQ\label{cond}
  \kappa \eq \kappa_{\rm dry} + \sqrt{s_l^{}} (\kappa_{\rm sat} - \kappa_{\rm dry}),
\EN
where $\kappa_{\rm dry}$ and $\kappa_{\rm sat}$ are dry and fully saturated rock thermal conductivities,
and $s_l$ denotes the saturation state of the liquid.

\paragraph{Evapotranspiration. }
%
Evapotranspiration models should include all the processes that convert water from the aqueous phase into water in the gaseous phase,
i.e., water vapor.
This should also account for evaporation from soil and plant surfaces and plant transpiration and include options
where these components vary wiith soil properties and structure of the plant canopy.

\paragraph{Equation of State.}
%
For multicomponent system, equation of state (EOS) data is required for water and all the NAPL components.
Typically these are EOS for pure substances that are combined for mixtures.
A basic EOS relates density to pressure and temperature.
The form for the EOS is typically cubic such as the Soave-Redlich-Kwong (SRK) or the
Peng-Robinson (PR) models.
Tabular models are also in common use.

Mixture thermodynamics is used to combine pure phase EOS's for the application.
The EPA lists over 80 potential NAPL components
(volatile organic compounds or VOCs) that can cause groundwater
contamination and has data bases with at least some properties for these
contaminants.

\paragraph{Mixture Internal Energy and Enthalpy.}
%
These will generally follow the simple additive rule based of
component values and mass fraction. Consideration must be also given
to heats of solution.

\subsection{Boundary Conditions}

The boundary conditions for the thermal flow
\eqref{eq:Richards with vapors}-\eqref{eq:energy_balance}
consist of the conditions for each of the equations.
%the Richards equation with vapor
%<F6>\eqref{eq:Richards with vapors} and those for the conservation of energy equation \eqref{eq:energy_balance}.
The choice of the boundary conditions for \eqref{eq:Richards with vapors} are identical to those of Isothermal equaiton.
We repeat those equations here for the sake of self-contained presentation.
The boundary conditions for conservation of energy equation \eqref{eq:energy_balance}
may take the form of specified temperature or heat flux including zero temperature gradient.
Initial conditions include specifying the temperature over the computational domain
such as a constant value or derived from the geothermal gradient.

\paragraph{Specified temperature boundary conditions.}
These are Dirichlet type conditions on the temperature saying
that at the boundary $\Gamma_{TD}$
\begin{align}
  T(\bx,t) = T_b(\bx,t), \quad \bx\in \Gamma_{TD},
\end{align}
where the temperature $T_b(\bx,t)$ is given.

\paragraph{Specified heat flux boundary conditions.}
These are Neumann type boundary conditiosn on the temperature saying that
at the boundary $\Gamma_{TN}$
\begin{align}
  \partial_{\bn} T(\bx,t) = \partial_{\bn} T_b(\bx,t), \quad \bx\in \Gamma_{TD},
\end{align}
where the temperature $\partial_{\bn} T_b(\bx,t)$ is given.

\paragraph{Boundary of prescribed pressure or head.}
This involves the specification of a fixed pressure or hydrostatic head on boundary $\Gamma_{lD}$.
For instance, a boundary of this kind occurs whenever the flow domain is adjacent to a body of open water.
Segments A-B and E-F in Fig.~\ref{fig:bc_flow} are examples of a boundary of prescribed potential.
The pressure or head boundary conditions are given functions, e.g.
\begin{equation}
\label{eq:BC pressure Darcy PS thermal}
  p_l(\bx,t) = p_{b}(\bx,t), \quad \bx \in \Gamma_{lD}.
\end{equation}

\paragraph{Boundary of prescribed flux.}
This involves the specification of the flux normal to the boundary $\Gamma_{lN}$
(see segment C-D in Figure \ref{fig:bc_flow}):
\begin{equation}
\label{eq:BC flux Darcy PS thermal}
  \bq_l\cdot \bn = q_{b}(\bx,t), \quad \bx \in \Gamma_{lN},
\end{equation}
where $q_b$ [$\um\ucdot\us^{-1}$] is the given boundary flux.
For infiltration at the top horizontal surface, it equals to the Darcy velocity
and referred to as the infiltration velocity.

\paragraph{Semipervious boundary (or mixed boundary condition).}
This boundary condition is more complicated than the first two as it involves a case
in which local conditions within the computational domain influence the flux in or
out of the domain.
This type of boundary occurs when the porous medium domain is in contact with
a body of water continuum (or another porous medium domain, see for instance segments
A-B and E-F in Fig.~\ref{fig:bc_flow}), however, a relatively thin semipervious layer
separates the two domains:
\begin{equation}
\label{eq:BC semipervious Darcy PS thermal}
  \bq_l \cdot \bn = I\, \left(p (\bx,t) - p_{b}(\bx,t) \right), \quad \bx \in \Gamma_R.
\end{equation}
where $I$ is an impedance and $p_{b}(\bx,t)$ is the given external pressure.

\paragraph{Seepage face.}
As is shown in Fig.~\ref{fig:bc_flow} (see segments B-C and D-E), seepage face (or surface)
is always present when a phreatic surface ends at the down-stream external boundary of flow domain.
In this case the phreatic surface is tangent to the boundary of the porous medium at points C and D.
Along a seepage surface, water emerges from the flow domain, trickling downward to the adjacent body of water.

A seepage surface is defined as the boundary
where water leaves the ground surface and then continues to flow in a thin film along its surface.
Being exposed to the atmosphere, the pressure along the seepage face is equal to the atmospheric pressure
(i.e. capillary pressure $p_{c}=0$).

The geometry of the seepage face is known (as it coincides with the boundary of the porous medium),
except for its limit (points C and D in Figure \ref{fig:bc_flow})
which is also lying on the (a priori) unknown phreatic surface.
The location of this point is, therefore, part of the required solution.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PROBLEM 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Problem 1}

A homogeneous U-235 reactor is operating at full power, 10,000 W/cm$^3$. 13\% of neutrons are absorbed in resonances, 2\% of all fission events are fast fissions, and 10\% of neutrons leak from the reactor. Assume 2.4 neutrons and 200 MeV are produced per fission, the fission cross section is 0.6 cm$^{-1}$, and the absorption cross section is 1 cm$^{-1}$.
\begin{enumerate}[a)]
\item Ignoring depletion, calculate the excess reactivity of this reactor.
\item The reactor scrams (immediately jumps to zero power). The plot below gives the negative reactivity as a function of time due to the accumulation of xenon in the reactor. Estimate at which point the reactor could no longer be returned to operation. About how long would this deadtime last?
\end{enumerate}
\begin{center}
\vspace{1cm}
\includegraphics[width=12cm]{xenon-deadtime}
\end{center}
\vfill
$200\text{ MeV} = 3.204\times10^{-11}\text{ J}$


%!TEX root = ../Thesis.tex
\chapter{Python Code for Restricted 3-Body Problem} \label{app:code-r3b}
% cSpell:disable
% spellcheck-off
\section{Main Script} \label{app:code-testing}
Calling all the other functions, initiating searches, and storing interesting orbits that has been found (filename: testing.py).
\begin{adjustwidth*}{0cm}{-0.4cm}
\begin{lstlisting}[language=Python]
import os
import time
from math import pi,cos,sin
import numpy as np
import matplotlib.pyplot as plt
from const import *
import reduced3body as r3b

try:
    threads = int(os.environ["OMP_NUM_THREADS"])
except KeyError:
    threads = 1

runtime = time.time()

# Precalculated initial Conditions
#demo = 'earth_orbit'
#demo = 'lunar_orbit'
#demo = 'hohmann'
#demo = '3_day_hohmann'
#demo = '1_day_hohmann'
#demo = 'reverse_hohmann'
demo = 'low_energy_short'
#demo = 'low_energy_long'
#demo = 'earth_to_L1'

# or Search for trajectories
#demo = 'search_hohmann'
#demo = 'search_low_energy'
#demo = 'search_low_energy_parts8'
#demo = 'search_refine'

n = 1000000

# Set coordinates
if demo == 'earth_orbit':
    duration = (2.0*pi*leo_orbit/leo_orbit_vel)/(unit_time*day)
    r = leo_orbit/unit_len
    v = 0.99732*leo_orbit_vel/unit_vel
    theta = 0
    x = r*cos(theta)
    y = r*sin(theta)
    vx = -v*y/r
    vy = v*x/r
    pos = 0
    ang = 0
    burn = 0
    x0 = earth_pos_x+x
    y0 = y
    px0 = vx-y0
    py0 = vy+x0
elif demo == 'lunar_orbit':
    duration = (2.0*pi*lunar_orbit/lunar_orbit_vel)/(unit_time*day)
    r = lunar_orbit/unit_len
    v = 0.99732*lunar_orbit_vel/unit_vel
    theta = 0
    x = r*cos(theta)
    y = r*sin(theta)
    vx = -v*y/r
    vy = v*x/r
    pos = 0
    ang = 0
    burn = 0
    x0 = moon_pos_x+x
    y0 = y
    px0 = vx-y0
    py0 = vy+x0
elif demo == 'hohmann':
    #demo = 'search_refine'
# --------------------------------------------------------------------------
    duration = 5/unit_time
    pos      = -2.086814820119193
    ang      = -0.000122173047640
    burn     = 3.111181716545691/unit_vel
    x0       = -0.020532317163607
    y0       = -0.014769797663479
    px0      = 9.302400979050308
    py0      = -5.289712560652044
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.111182 km/s
# dV(moon-capture) = 0.800682 km/s
# dV(total)        = 3.911863 km/s
# Flight-time      = 4.300078 days
# --------------------------------------------------------------------------
elif demo == 'reverse_hohmann':
# --------------------------------------------------------------------------
    duration = 4/unit_time
    pos      = -2.282942228154665
    ang      = 0.000000000000000
    burn     = -3.149483130653266/unit_vel
    x0       = -0.023249912090507
    y0       = -0.012853859046429
    px0      = -8.098481905534163
    py0      = 6.978997254692934
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.149483 km/s
# dV(moon-capture) = 0.968488 km/s
# dV(total)        = 4.117971 km/s
# Flight-time      = 3.875497 days
# --------------------------------------------------------------------------
elif demo == 'low_energy_long':
# --------------------------------------------------------------------------
    duration = 195/unit_time
    pos      = 3.794182930145708
    ang      = 0.023901745288554
    burn     = 3.090702702702703/unit_vel
    x0       = -0.025645129237870
    y0       = -0.010311570301966
    px0      = 6.539303578815582
    py0      = -8.449205705334165
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.090703 km/s
# dV(moon-capture) = 0.704114 km/s
# dV(total)        = 3.794816 km/s
# Flight-time      = 194.275480 days
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
    #demo = 'search_refine'
#    duration = 195/unit_time
#    pos      = 3.794182930145708
#    ang      = 0.023901745288554
#    burn     = 3.090702702702703/unit_vel
#    x0       = -0.025645129237870
#    y0       = -0.010311570301966
#    px0      = 6.539303578815583
#    py0      = -8.449205705334164
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.090703 km/s
# dV(moon-capture) = 0.704114 km/s
# dV(total)        = 3.794817 km/s
# Flight-time      = 194.275480 days
# --------------------------------------------------------------------------
elif demo == 'low_energy_short':
    #demo = 'search_refine'
# --------------------------------------------------------------------------
    duration = 41/unit_time
    pos      = -0.138042744751570
    ang      = -0.144259374836607
    burn     = 3.127288444444444/unit_vel
    x0       = 0.004665728429046
    y0       = -0.002336647636098
    px0      = 1.904735175752430
    py0      = 10.504985512873279
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.127288 km/s
# dV(moon-capture) = 0.768534 km/s
# dV(total)        = 3.895822 km/s
# Flight-time      = 40.617871 days
# --------------------------------------------------------------------------
elif demo == '3_day_hohmann':
    #demo = 'search_refine'
# --------------------------------------------------------------------------
    duration = 3/unit_time
    pos      = -2.272183066647597
    ang      = -0.075821466029764
    burn     = 3.135519748743719/unit_vel
    x0       = -0.023110975767437
    y0       = -0.012972499765730
    px0      = 8.032228991913522
    py0      = -7.100537706154897
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.135520 km/s
# dV(moon-capture) = 0.879826 km/s
# dV(total)        = 4.015346 km/s
# Flight-time      = 2.999939 days
# --------------------------------------------------------------------------
elif demo == '1_day_hohmann':
    #demo = 'search_refine'
    duration = 1/unit_time
    pos      = -2.277654673852600
    ang      = 0.047996554429844
    burn     = 3.810000000000000/unit_vel
    x0       = -0.023181791813268
    y0       = -0.012912351430812
    px0      = 8.764829132987316
    py0      = -7.263069305305378
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.810000 km/s
# dV(moon-capture) = 3.319455 km/s
# dV(total)        = 7.129455 km/s
# Flight-time      = 0.997234 days
# --------------------------------------------------------------------------
elif demo == 'earth_to_L1':
    demo = 'search_refine'
# --------------------------------------------------------------------------
    duration = 191/unit_time
    pos      = 2.843432239707429
    ang      = 0.000000000000000
    burn     = 3.091851851851852/unit_vel
    x0       = -0.028385246222264
    y0       = 0.004988337832881
    px0      = -3.136296304910217
    py0      = -10.217405925499762
# --------------------------------------------------------------------------
# dV(earth-escape) = 3.091852 km/s
# dV(at L1)        = 0.676226 km/s
# dV(total)        = 3.768078 km/s
# Flight-time      = 190.001881 days
# --------------------------------------------------------------------------

#################### FUNCTION CALLS ####################

if demo == 'search_hohmann':
    tlist,xlist,ylist,pxlist,pylist,errlist,hlist = r3b.hohmann(threads,n)
elif demo == 'search_low_energy':
    tlist,xlist,ylist,pxlist,pylist,errlist,hlist = r3b.low_energy(threads,n)
elif demo == 'search_low_energy_parts8':
    tlist,xlist,ylist,pxlist,pylist,errlist,hlist = r3b.low_energy_parts8(threads,n)
elif demo == 'search_refine':
    tlist,xlist,ylist,pxlist,pylist,errlist,hlist = r3b.refine(threads,n,duration,pos,ang,burn,x0,y0,px0,py0)
else:
    tlist,xlist,ylist,pxlist,pylist,errlist,hlist = r3b.trajectory(n,duration,pos,ang,burn,x0,y0,px0,py0)
Hlist = pxlist**2/2 + pylist**2/2 + ylist*pxlist - xlist*pylist - (1-mu)/np.sqrt(np.power(mu+xlist,2)+np.power(ylist,2)) - mu/np.sqrt(np.power(1-mu-xlist,2)+np.power(ylist,2))
print("# Final position: %f %f" %(xlist[n-1],ylist[n-1]))
print("# Final impulse: %f %f" % (pxlist[n-1],pylist[n-1]))
print("# Final H: %f" % (Hlist[n-1]))
runtime = time.time()-runtime
print("# Total runtime = %3.2fs" % (runtime))
print("# --------------------------------------------------------------------------")
print("# --- Done with FUNCTION CALLS")
#exit()

#################### PLOTS: POSITION ####################

xlist1 = xlist[:n/2]
ylist1 = ylist[:n/2]
xlist2 = xlist[n/2:]
ylist2 = ylist[n/2:]

Xlist1 = xlist[:n/2]*np.cos(tlist[:n/2]) - ylist[:n/2]*np.sin(tlist[:n/2])
Ylist1 = xlist[:n/2]*np.sin(tlist[:n/2]) + ylist[:n/2]*np.cos(tlist[:n/2])
Xlist2 = xlist[n/2:]*np.cos(tlist[n/2:]) - ylist[n/2:]*np.sin(tlist[n/2:])
Ylist2 = xlist[n/2:]*np.sin(tlist[n/2:]) + ylist[n/2:]*np.cos(tlist[n/2:])

Xlist_earth = earth_pos_x*np.cos(tlist)
Ylist_earth = -earth_pos_x*np.sin(tlist)

Xlist_moon = moon_pos_x*np.cos(tlist)
Ylist_moon = moon_pos_x*np.sin(tlist)

# Rel. err
plt.figure()
plt.plot(tlist*unit_time, errlist)
plt.xlabel("time (days)")
plt.ylabel("step error")
plt.yscale('log')

# Step sizes
plt.figure()
plt.plot(tlist*unit_time, hlist)
plt.xlabel("time (days)")
plt.ylabel("step size")
plt.yscale('log')

# Total energy
havg = np.sum(Hlist)/n
hrelerr = (Hlist-havg)/havg
plt.figure()
plt.plot(tlist*unit_time, hrelerr)
plt.xlabel("time (days)")
plt.ylabel("Hamiltonian rel. err (arbitrary units)")

# Zoom earth
xlim = 0.02
ylim = 0.02
xmin = earth_pos_x-xlim
xmax = earth_pos_x+xlim
ymin = -ylim
ymax = ylim
plt.figure()
earth=plt.Circle((earth_pos_x,0),earth_radius/unit_len,color='blue')
earthorbit1=plt.Circle((earth_pos_x,0),(leo_orbit-orbit_range)/unit_len,color='g',fill=False)
earthorbit2=plt.Circle((earth_pos_x,0),(leo_orbit+orbit_range)/unit_len,color='g',fill=False)
plt.gcf().gca().add_artist(earth)
plt.gcf().gca().add_artist(earthorbit1)
plt.gcf().gca().add_artist(earthorbit2)
plt.plot(xlist1,ylist1,'r-')
plt.plot(xlist2,ylist2,'k-')
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.gca().set_aspect('equal', adjustable='box')
plt.xlabel("x-position (arbitrary units)")
plt.ylabel("y-position (arbitrary units)")

# Zoom moon
xlim = 0.0055
ylim = 0.0055
xmin = moon_pos_x-xlim
xmax = moon_pos_x+xlim
ymin = -ylim
ymax = ylim
plt.figure()
moon=plt.Circle((moon_pos_x,0),moon_radius/unit_len,color='grey')
moonorbit1=plt.Circle((moon_pos_x,0),(lunar_orbit-orbit_range)/unit_len,color='g',fill=False)
moonorbit2=plt.Circle((moon_pos_x,0),(lunar_orbit+orbit_range)/unit_len,color='g',fill=False)
plt.gcf().gca().add_artist(moon)
plt.gcf().gca().add_artist(moonorbit1)
plt.gcf().gca().add_artist(moonorbit2)
plt.plot(xlist1,ylist1,'r-')
plt.plot(xlist2,ylist2,'k-')
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.gca().set_aspect('equal', adjustable='box')
plt.xlabel("x-position (arbitrary units)")
plt.ylabel("y-position (arbitrary units)")

# View center of mass
xlim = 1.3
ylim = 1.3
xmin = -xlim
xmax = xlim
ymin = -ylim
ymax = ylim

# Position plot (X,Y)
plt.figure()
plt.plot(Xlist1,Ylist1,'r')
plt.plot(Xlist2,Ylist2,'k')
plt.plot(Xlist_earth, Ylist_earth, 'blue')
plt.plot(Xlist_moon, Ylist_moon, 'grey')
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.gca().set_aspect('equal', adjustable='box')
plt.xlabel("x-position (arbitrary units)")
plt.ylabel("y-position (arbitrary units)")

# Position plot (x,y)
plt.figure()
plt.plot(xlist1,ylist1,'r-')
plt.plot(xlist2,ylist2,'k-')
earth=plt.Circle((earth_pos_x,0),earth_radius/unit_len,color='blue')
earthorbit1=plt.Circle((earth_pos_x,0),(leo_orbit-orbit_range)/unit_len,color='g',fill=False)
earthorbit2=plt.Circle((earth_pos_x,0),(leo_orbit+orbit_range)/unit_len,color='g',fill=False)
moon=plt.Circle((moon_pos_x,0),moon_radius/unit_len,color='grey')
moonorbit1=plt.Circle((moon_pos_x,0),(lunar_orbit-orbit_range)/unit_len,color='g',fill=False)
moonorbit2=plt.Circle((moon_pos_x,0),(lunar_orbit+orbit_range)/unit_len,color='g',fill=False)
plt.gcf().gca().add_artist(earth)
plt.gcf().gca().add_artist(earthorbit1)
plt.gcf().gca().add_artist(earthorbit2)
plt.gcf().gca().add_artist(moon)
plt.gcf().gca().add_artist(moonorbit1)
plt.gcf().gca().add_artist(moonorbit2)
plt.plot(L1_pos_x,0,'gx')
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.gca().set_aspect('equal', adjustable='box')
plt.xlabel("x-position (arbitrary units)")
plt.ylabel("y-position (arbitrary units)")
#plt.savefig('fig/r3b/r3b_y(x)_euler_symplectic.pdf',bbox_inches='tight')
plt.show()
plt.close()
print("# --- Done with PLOTS")
\end{lstlisting}
\end{adjustwidth*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Constants} \label{app:code-constants}
Constants defined for the rest of the program to use (filename: const.py)

\begin{adjustwidth*}{0cm}{-0.4cm}
\begin{lstlisting}[language=Python]
from math import pi,sqrt,pow

# Table constants
earth_moon_distance = 384400.0 # km
moon_orbit_duration = 27.322 # days
earth_radius = 6367.4447 # km
earth_mass = 5.9721986e24
moon_mass = 7.34767309e22
G = 6.67384e-11 # m^3 kg^-1 s^-2
moon_radius = 1737.1 # km
leo_orbit = 160.0+earth_radius # km
lunar_orbit = 100.0+moon_radius # km
orbit_range = 10.0 # km
day = 24.0*3600.0 # s

# Units
unit_len = earth_moon_distance # km
unit_time = moon_orbit_duration/(2.0*pi) # days
unit_vel = unit_len/(unit_time*day) # km/s

# Gravitational constants
mu = moon_mass/(earth_mass+moon_mass) # 1

# Calculation constants
leo_orbit_vel = sqrt(G*earth_mass/(leo_orbit*1000.0))/1000.0 # km/s
lunar_orbit_vel = sqrt(G*moon_mass/(lunar_orbit*1000.0))/1000.0 # km/s
moon_pos_x = 1-mu
earth_pos_x = -mu
L1_pos_x = (1-pow(mu/3.0,1.0/3.0))

\end{lstlisting}
\end{adjustwidth*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Plotter and Trajectory Finders} \label{app:code-plotter-trajectory}
trajectory plot trajectories, hohmann and low\_energy finds transfer orbits (filename: reduced3body.py - most of it).

\begin{adjustwidth*}{0cm}{-0.4cm}
\begin{lstlisting}[language=Python]
import time
from math import pi,sqrt
import numpy as np
from const import *
from numbapro import *
from search import search_mt, search, print_search_results
from symplectic import symplectic

# **BRUGER IKKE pos, ang, burn til noget, kun til print
def trajectory(n,duration,pos,ang,burn,x0,y0,px0,py0):
    """Integrate trajectory for the reduced 3-body problem.

    Args:
        n (int): Positions stored.
        duration (float): Time duration of simulation.
        x0 (float): Initial x-coordinate
        y0 (float): Initial y-coordinate
        px0 (float): Initial generalized x-momentum
        py0 (float): Initial generalized y-momentum

    Returns:
        Tuple of time-, x-, y-, px- and py lists.

    """
    print("# Running trajectory.")

    # Initialize arrays
    tlist = np.linspace(0,duration,n)
    xlist = np.zeros(n)
    ylist = np.zeros(n)
    pxlist = np.zeros(n)
    pylist = np.zeros(n)
    errlist = np.zeros(n)
    hlist = np.zeros(n)
    info = np.zeros(2)

    # Find orbits
    runtime = time.time()
    status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info)
    runtime = time.time()-runtime

    # Display result
    print_search_results(status,pos,ang,burn,x0,y0,px0,py0,info[0],info[1])
    print("# Runtime = %3.2fs" % (runtime))
    return tlist,xlist,ylist,pxlist,pylist,errlist,hlist

def hohmann(threads,n):
    """Finding Hohmann trajectory for the reduced 3-body problem.

    Args:
        n (int): Positions stored.

    Returns:
        Tuple of time-, x-, y-, px- and py lists.

    """

    print("# Running Hohmann.")

    # Hohmann trajectory < 6 days
    duration = 6/unit_time
    best_total_dv = 1e9
    positions = 100
    angles = 1
    burns = 200
    pos = -3*pi/4
    ang = 0
    burn = 3.11/unit_vel # Forward Hohmann
    #burn_low = -3.14/unit_vel # Reverse Hohmann

    # Super fast Hohmann trajectory < 1 days
    #duration = 3/unit_time
    #best_total_dv = 1e9
    #positions = 10
    #angles = 10
    #burns = 200
    #pos = -3*pi/4
    #ang = 0
    #burn = 3.7/unit_vel # Forward Hohmann

    pos_range = pi/4
    ang_range = pi/8
    burn_range = 0.1/unit_vel

    # Start search
    searches = 0
    max_searches = 5
    while searches < max_searches:
        runtime = time.time()
        searches += 1
        print("############## Search %i ###############" % (searches))
        print("# pos              = %f" % (pos))
        print("# ang              = %f" % (ang))
        print("# burn             = %f" % (burn))
        pos_low = pos-pos_range
        pos_high = pos+pos_range
        ang_low = ang-ang_range
        ang_high = ang+ang_range
        burn_low = burn-burn_range
        burn_high = burn+burn_range
        stat,pos,ang,burn,x0,y0,px0,py0,dv,toa = search_mt(threads,1,duration,positions,angles,burns,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high)

        if stat < 0:
            total_dv = abs(burn)+dv
            if best_total_dv > total_dv:
                best_total_dv = total_dv
                best_stat = stat
                best_pos = pos
                best_ang = ang
                best_burn = burn
                best_x0 = x0
                best_y0 = y0
                best_px0 = px0
                best_py0 = py0
                best_dv = dv
                best_toa = toa
            else:
                break

        pos_range *= 0.1
        ang_range *= 0.1
        burn_range *= 0.1

        runtime = time.time()-runtime
        print("# Search runtime   = %3.2fs" % (runtime))

    # Print best result
    print("################ Best ################")
    print("# Best dV(total)   = %f km/s" % (best_total_dv*unit_vel))
    print_search_results(best_stat,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa)

    # Initialize arrays
    tlist = np.linspace(0,duration,n)
    xlist = np.zeros(n)
    ylist = np.zeros(n)
    pxlist = np.zeros(n)
    pylist = np.zeros(n)
    errlist = np.zeros(n)
    hlist = np.zeros(n)
    info = np.zeros(2)

    # Do trajectory
    duration = 10/unit_time
    status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info)

    return tlist,xlist,ylist,pxlist,pylist,errlist,hlist

def low_energy(threads,n):
    """Finding low energy transfer trajectory for the reduced 3-body problem.

    Args:
        n (int): Positions stored.

    Returns:
        Tuple of time-, x-, y-, px- and py lists.

    """

    print("# Running low_energy.")

    # Low-energy trajectory < 200 days
    duration = 200/unit_time
    best_total_dv = 1e9
    positions = 100
    angles = 1
    burns = 200
    pos = -3*pi/4
    ang = 0
    burn = 3.12/unit_vel
    pos_range = pi
    ang_range = 0
    burn_range = 0.01/unit_vel

    # Start search
    searches = 0
    max_searches = 1
    while searches < max_searches:
        runtime = time.time()
        searches += 1
        print("############## Search %i ###############" % (searches))
        print("# pos              = %f" % (pos))
        print("# ang              = %f" % (ang))
        print("# burn             = %f" % (burn))
        pos_low = pos-pos_range
        pos_high = pos+pos_range
        ang_low = ang-ang_range
        ang_high = ang+ang_range
        burn_low = burn-burn_range
        burn_high = burn+burn_range
        stat,pos,ang,burn,x0,y0,px0,py0,dv,toa = search_mt(threads,1,duration,positions,angles,burns,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high)

        if stat < 0:
            total_dv = abs(burn)+dv
            if best_total_dv > total_dv:
                best_total_dv = total_dv
                best_stat = stat
                best_pos = pos
                best_ang = ang
                best_burn = burn
                best_x0 = x0
                best_y0 = y0
                best_px0 = px0
                best_py0 = py0
                best_dv = dv
                best_toa = toa
            else:
                break

        pos_range *= 0.1
        ang_range *= 0.1
        burn_range *= 0.1

        runtime = time.time()-runtime
        print("# Search runtime   = %3.2fs" % (runtime))

    # Initialize arrays
    tlist = np.linspace(0,duration,n)
    xlist = np.zeros(n)
    ylist = np.zeros(n)
    pxlist = np.zeros(n)
    pylist = np.zeros(n)
    errlist = np.zeros(n)
    hlist = np.zeros(n)
    info = np.zeros(2)

    # Do trajectory
    duration = toa+(2.0*pi*lunar_orbit/lunar_orbit_vel)/(unit_time*day)
    status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info)
    exit()
    return tlist,xlist,ylist,pxlist,pylist,errlist,hlist
\end{lstlisting}
\end{adjustwidth*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Search Helper Functions} \label{app:code-search}
Search helper functions, also implements all the paralellization (filename: search.py).
\begin{adjustwidth*}{0cm}{-0.4cm}
\begin{lstlisting}[language=Python]
"""
Brute-force search Module for reduced 3-body solver
===================================================

"""

from __future__ import print_function
import sys
import time
from math import ceil
import numpy as np
from multiprocessing import Pool
from const import *
from symplectic import symplectic

def print_search_results(stat,pos,ang,burn,x0,y0,px0,py0,dv,toa):
    print("# --------------------------------------------------------------------------")
    print("duration = %i/unit_time" % (max(1,int(ceil(toa*unit_time)))))
    print("pos      = %.15lf" % (pos))
    print("ang      = %.15lf" % (ang))
    print("burn     = %.15lf/unit_vel" % (burn*unit_vel))
    print("x0       = %.15lf" % (x0))
    print("y0       = %.15lf" % (y0))
    print("px0      = %.15lf" % (px0))
    print("py0      = %.15lf" % (py0))
    print("# --------------------------------------------------------------------------")
    print("# dV(earth-escape) = %f km/s" % (abs(burn)*unit_vel))
    if stat > 0 and stat < 100:
        print("# Min moon distance= %f" % (stat))
    elif stat < 0:
        print("# dV(moon-capture) = %f km/s" % (dv*unit_vel))
        print("# dV(total)        = %f km/s" % ((abs(burn)+dv)*unit_vel))
        print("# Flight-time      = %f days" % (toa*unit_time))
    else:
        print("# Crashed on earth!")
    print("# --------------------------------------------------------------------------")
    sys.stdout.flush()

def search(thread,threads,n,duration,positions,angles,burns):

    #print("Start thread=%i" % (thread))

    # Initialize arrays
    xlist = np.zeros(n)
    ylist = np.zeros(n)
    pxlist = np.zeros(n)
    pylist = np.zeros(n)
    errlist = np.zeros(n)
    hlist = np.zeros(n)
    info = np.zeros(2)

    # Search for orbits
    trials = len(positions)*len(angles)*len(burns)
    ld1 = len(angles)*len(burns)
    ld2 = len(burns)
    trial = 0
    hit_earth = 0
    hit_moon = 0
    best_status = 1e9
    progress = -1
    i = thread
    while i < trials:

        # One-to-one mapping of i -> (pos_i,ang_i,burn_i)
        pos_i = i//ld1
        ang_i = (i-pos_i*ld1)//ld2
        burn_i = i-pos_i*ld1-ang_i*ld2
        i += threads

        # Find launch setup
        pos = positions[pos_i]
        ang = angles[ang_i]
        burn = burns[burn_i]

        # Calculate initial conditions
        r = leo_orbit/unit_len
        x0 = np.cos(pos)*r
        y0 = np.sin(pos)*r
        rx = -y0/r
        ry = x0/r
        vx = (leo_orbit_vel/unit_vel)*rx
        vy = (leo_orbit_vel/unit_vel)*ry
        x0 += earth_pos_x
        bx = np.cos(ang)*rx-np.sin(ang)*ry
        by = np.sin(ang)*rx+np.cos(ang)*ry
        px0 = (burn/abs(burn))*vx+burn*bx-y0 # Sign of burn decides rotational direction of launch
        py0 = (burn/abs(burn))*vy+burn*by+x0

        # Call symplectic integration
        # status > 0     : Closest distance to moon achieved
        # status < 0     : Hit the moon using status=dV(moon)-10000 to get into orbit
        # status == 100  : Collided with earth
        #if thread == 1:
        #    print(n,duration,x0,y0,px0,py0)
        status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info)
        if status == 100:
            hit_earth += 1
        if status < 0:
            hit_moon += 1
        if status < best_status:
            best_status = status
            best_pos = pos
            best_ang = ang
            best_burn = burn
            best_x0 = x0
            best_y0 = y0
            best_px0 = px0
            best_py0 = py0
            best_dv = info[0]
            best_toa = info[1]

        # Show progress
        if thread == 0: # only thread 0
            if (100*trial/(1+trials//threads))//10 > progress:
                progress = (100*trial/(1+trials//threads))//10
                print(progress*10,end="% ")
                sys.stdout.flush()
            trial += 1
        #if thread == 13:
         #   print("thread=%i status=%f best_status=%f trial=%i(%i) pos=%f ang=%f burn=%f" % (thread,status,best_status,trial,trials,pos,ang,burn))

    #print("End thread=%i" % (thread))

    return best_status,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa,hit_earth,hit_moon

def search_worker(args):
    return search(args[0], args[1], args[2], args[3], args[4], args[5], args[6])

def search_mt(threads,n,duration,num_pos,num_ang,num_burn,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high):

    # Time search
    runtime = time.time()

    # Set search space
    positions = np.linspace(pos_low,pos_high,num_pos)
    angles = np.linspace(ang_low,ang_high,num_ang)
    burns = np.linspace(burn_low,burn_high,num_burn)
    if num_pos == 1:
        positions[0] = (pos_high+pos_low)/2.0
    if num_ang == 1:
        angles[0] = (ang_high+ang_low)/2.0
    if num_burn == 1:
        burns[0] = (burn_high+burn_low)/2.0
    if num_burn == 2:
        burns[0] = burn_low
        burns[1] = burn_high
    trials = num_pos*num_ang*num_burn
    print(positions)
    print(angles)
    print(burns*unit_vel)

    # Set threads
    threads = min(threads,num_pos)

    # Do multi-threaded search
    print("# --------------------------------------------------------------------------")
    print("# Threads:          %6i" % (threads))
    print("# Trials:           %6i (" % (trials), end="")
    if threads == 1:
        # Single thread
        best_status,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa,hit_earth,hit_moon = search(0,num_pos,n,duration,positions,angles,burns)
    else:
        # Multi-threading
        chunk = num_pos/threads
        args = [[i,threads,n,duration,positions,angles,burns] for i in range(threads)]
        pool = Pool()
        result = pool.map(search_worker, args)
        pool.close()
        pool.join()

        # Reduce results from all threads
        best_status = 1e9
        hit_earth = 0
        hit_moon = 0
        for i in range(threads):
            status = result[i][0]
            if status < best_status:
                best_status = status
                best_pos = result[i][1]
                best_ang = result[i][2]
                best_burn = result[i][3]
                best_x0 = result[i][4]
                best_y0 = result[i][5]
                best_px0 = result[i][6]
                best_py0 = result[i][7]
                best_dv = result[i][8]
                best_toa = result[i][9]
                hit_earth += result[i][10]
                hit_moon += result[i][11]

    print("100%)")
    print("# No interception:  %6i (%i%%)" % (trials-hit_earth-hit_moon,100*(trials-hit_earth-hit_moon)/trials))
    print("# Crashed on earth: %6i (%i%%)" % (hit_earth,100*hit_earth/trials))
    print("# Hit moon:         %6i (%i%%)" % (hit_moon,100*hit_moon/trials))
    runtime = time.time()-runtime
    print("# Runtime:          %6.2fs" % (runtime))
    if best_status < 100:
        print_search_results(best_status,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa)
        return best_status,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa
    else:
        return best_status,0,0,0,0,0,0,0,0,0
\end{lstlisting}
\end{adjustwidth*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Symplectic Adaptive Verlet and Symplectic Euler Integrators} \label{app:code-symplectic}
Implemeting the symplectic algorithms from Chapter \ref{ch:numerical-analysis} (filename: symplectic.py).

\begin{adjustwidth*}{0cm}{-0.4cm}
\begin{lstlisting}[language=Python]
"""
Reduced 3-Body Problem Solver Module
====================================
"""

from math import pi,sqrt
import numpy as np
from numbapro import *
from const import *

@jit
def F(x,y):
    mux = mu+x
    mux2 = mux*mux
    mumx = 1-mux
    mumx2 = mumx*mumx
    y2 = y*y
    denum1 = 1.0/((mux2+y2)*sqrt(mux2+y2))
    denum2 = 1.0/((mumx2+y2)*sqrt(mumx2+y2))
    Fx = (mu-1.0)*mux*denum1+mu*mumx*denum2
    Fy = (mu-1.0)*y*denum1-mu*y*denum2
    return Fx,Fy

@jit
def explicit_euler_step(h,x,y,px,py):
    Fx,Fy = F(x,y)
    vx = px+y
    vy = py-x
    vpx = Fx+py
    vpy = Fy-px
    x += vx*h
    y += vy*h
    px += vpx*h
    py += vpy*h
    return x,y,px,py

@jit
def symplectic_euler_step(h,x,y,px,py):
    # Step 1
    vx = px+y
    x = (x+(vx+py*h)*h)/(1.0+h*h)
    vy = py-x
    y += vy*h
    # Step 2
    Fx,Fy = F(x,y)
    vpx = Fx+py
    vpy = Fy-px
    px += vpx*h
    py += vpy*h
    return x,y,px,py

@jit
def symplectic_verlet_step(h,x,y,px,py):
    hh = 0.5*h
    denum = 1.0/(1.0+hh*hh)
    # Step 1
    vx = px+y
    x = (x+(vx+py*hh)*hh)*denum
    vy = py-x
    y += vy*hh
    # Step 2
    Fx,Fy = F(x,y)
    vpx = Fx+py
    vpy = Fy-px
    px = (px+(2.0*vpx+(vpy+Fy)*hh)*hh)*denum
    py += (vpy+Fy-px)*hh
    # Step 3
    vx = px+y
    vy = py-x
    x += vx*hh
    y += vy*hh
    return x,y,px,py

@jit #('void(int64, float64, float64, float64, float64, float64, float64, float64[:], float64[:], float64[:], float64[:])')
def symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info):

    # Initialize initial conditions
    h = 1e-6
    hmin = 1e-10
    # tol = 1e-9
    tol = 10
    maxsteps = duration
    x = x0
    y = y0
    px = px0
    py = py0
    err = 1e-15
    status = 1
    target_dist = 1
    target = 1; target_pos_x = moon_pos_x
    #target = 2; target_pos_x = L1_pos_x
    target_pos_y = 0

    # Time reset
    t = 0
    for i in range(n):

        # Store position
        xlist[i] = x
        ylist[i] = y
        pxlist[i] = px
        pylist[i] = py
        errlist[i] = err
        hlist[i] = h

        # Integrate time period
        dt = duration*(i+1)/n
        count = 0
        while t < dt:
            # Safety on iterations
            count += 1
            if count > 10000000:
                count = 0
                hmin = 2*hmin

            # Adaptive symplectic euler/midpoint
            x1,y1,px1,py1 = symplectic_euler_step(h,x,y,px,py)
            x2,y2,px2,py2 = symplectic_verlet_step(h,x,y,px,py)

            # Relative local error of step
            err = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)/(x2*x2+y2*y2))

            # Accept the step only if the weighted error is no more than the
            # tolerance tol.  Estimate an h that will yield an error of tol on
            # the next step and use 0.8 of this value to avoid failures.
            if err < tol or h <= hmin:

                # Accept step
                x = x2
                y = y2
                px = px2
                py = py2

                # Forward time by step
                t = t+h
                # h = max(hmin, h*max(0.1, 0.8*sqrt(tol/err)))

            else:
                # No accept, reduce h to half
                h = max(hmin, 0.5*h)

            # How close are we to the moon?
            rx = x-target_pos_x
            ry = y-target_pos_y
            r = sqrt(rx*rx+ry*ry)
            target_dist = min(target_dist,r)

            # Check if we hit the target
            if status == 1:
                if target == 1:
                    r_low = (lunar_orbit-orbit_range)/unit_len
                    r_high = (lunar_orbit+orbit_range)/unit_len
                else:
                    r_low = 0
                    r_high = orbit_range/unit_len

                if r > r_low and r < r_high:

                    # Current velocity
                    vx = px+y
                    vy = py-x

                    if target == 1:

                        # Project velocity onto radius vector and subtract
                        # so velocity vector is along orbit
                        vr = (vx*rx+vy*ry)/r
                        vx = vx-vr*rx/r
                        vy = vy-vr*ry/r

                        # Now ajust velocity to lunar orbit velocity
                        vt = sqrt(vx*vx+vy*vy)
                        px = (lunar_orbit_vel/unit_vel)*vx/vt-y
                        py = (lunar_orbit_vel/unit_vel)*vy/vt+x

                        # Total velocity change
                        dv = sqrt(vr*vr+(vt-lunar_orbit_vel/unit_vel)*(vt-lunar_orbit_vel/unit_vel))
                    else:
                        dv = sqrt(vx*vx+vy*vy)

                    # Store info
                    info[0] = dv
                    info[1] = t

                    # Finish?
                    status = -10000+dv
                    if n == 1:
                        return status

            # Check if we hit the earth
            r = (x-earth_pos_x)*(x-earth_pos_x)+y*y
            r_high = earth_radius/unit_len
            if r < r_high*r_high:
                return 100 # Hit earth surface

    if status >= 0:
        status = target_dist

    return status
\end{lstlisting}
\end{adjustwidth*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%