diff --git a/docs/.readthedocs.yaml b/docs/.readthedocs.yaml
new file mode 100644
index 0000000..de40631
--- /dev/null
+++ b/docs/.readthedocs.yaml
@@ -0,0 +1,22 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version, and other tools you might need
+build:
+ os: ubuntu-24.04
+ tools:
+ python: "mambaforge-latest"
+
+sphinx:
+ configuration: docs/conf.py
+
+conda:
+ environment: conda.yml
+
+formats:
+ - htmlzip
+ - pdf
+ - epub
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..ee23016
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = src
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/README b/docs/README
deleted file mode 100644
index 434a2a5..0000000
--- a/docs/README
+++ /dev/null
@@ -1,2 +0,0 @@
-The documentation in this directory, AcceleratorLattice.jl/docs, is for the Markdown "quick reference guide".
-The LaTeX AcceleratorLattice manual files are in AcceleratorLattice.jl/manual.
diff --git a/docs/README-DOCS.md b/docs/README-DOCS.md
new file mode 100644
index 0000000..3ae4997
--- /dev/null
+++ b/docs/README-DOCS.md
@@ -0,0 +1,41 @@
+# How to Write Documentation
+
+The documentation uses the [MyST](https://mystmd.org/) markup language and renders to [Sphinx](https://www.sphinx-doc.org) as HTML, PDF or EPUB documents.
+
+In order to build the documentation locally, from your AcceleratorLattice directory,
+create a software environment using the commands
+```{code} bash
+conda env create -y -f docs/conda.yml # This only needs to be done once.
+conda activate myst # Do this with any new window.
+```
+
+and compile via
+
+::::{tab-set}
+
+:::{tab-item} HTML
+```{code} bash
+make html
+```
+:::
+
+:::{tab-item} PDF
+```{code} bash
+make latexpdf
+```
+:::
+
+::::
+
+Open the file `docs/build/html/index.html` with your web browser to visualize.
+You are now ready to edit the markdown files that compose the documentation!
+
+If you like to atuomatically rebuild changes on save of edited files,
+run in your AcceleratorLattice directory:
+```{code} bash
+sphinx-autobuild docs/src docs/build/html
+```
+and open the URL shown in the terminal, usually [http://127.0.0.1:8000](http://127.0.0.1:8000).
+
+If you add new markdown files, do not forget to add them to the table of contents defined `docs/index.md`.
+Finally, once you are happy with your changes, do not forget to commit and push them to your branch and open a pull request on GitHub.
diff --git a/docs/conda.yml b/docs/conda.yml
new file mode 100644
index 0000000..8e0a02b
--- /dev/null
+++ b/docs/conda.yml
@@ -0,0 +1,26 @@
+# For local development, from your lattice-standard directory, create the environment like this:
+# conda env create -y -f conda.yml
+# conda activate tracking
+#
+name: myst
+
+channels:
+ - conda-forge
+ - nodefaults
+
+dependencies:
+ - docutils
+ - python
+ - myst-parser
+ - pip
+ - pybtex
+ - pygments
+ - recommonmark
+ - sphinx
+ - sphinx-autobuild
+ - sphinx-book-theme
+ - sphinx-copybutton
+ - sphinx-design
+ - sphinxcontrib-bibtex
+ - sphinxcontrib-napoleon
+# - sphinx_rtd_theme
diff --git a/docs/make.jl b/docs/make.jl
deleted file mode 100644
index 43e676a..0000000
--- a/docs/make.jl
+++ /dev/null
@@ -1,15 +0,0 @@
-using Pkg
-using Documenter, AcceleratorLattice
-
-
-makedocs(
- sitename = "AcceleratorLattice.jl",
- authors = "David Sagan",
- format=Documenter.HTMLWriter.HTML(size_threshold = nothing),
- pages =
- [
- "home" => "index.md",
- ]
-)
-
-deploydocs(; repo = "github.com/bmad-sim/AcceleratorLattice.jl.git")
diff --git a/docs/scripts/tex_convert.jl b/docs/scripts/tex_convert.jl
new file mode 100644
index 0000000..92a22c5
--- /dev/null
+++ b/docs/scripts/tex_convert.jl
@@ -0,0 +1,246 @@
+file = "design"
+
+lines = readlines("../manual/" * file * ".tex", keep = true)
+fout = open("src/" * file * ".md", "w")
+
+#--------------------------------------------------
+
+function sub_str(str, left, right)
+ if !occursin(left, str); return ""; end
+ str = split(str, left)[2]
+ if !occursin(right, str); return str; end
+ return split(str, right)[1]
+end
+
+#--------------------------------------------------
+
+function str_replace(line, end_line = true)
+ line = replace(line, "``" => "\"", "''" => "\"") # ``abc'' -> "abc" This must be before other replacements.
+ line = replace(line, r"\\item\[(.*?)\]" => s"- **\1**")
+ line = replace(line, r"\\begin{example}" => "```{code} yaml")
+ line = replace(line, r"\\end{example}" => "```")
+ line = replace(line, r"\\vn{(.*?)}" => s"`\1`") # "\vn{XXX}" -> "`XXX`"
+ line = replace(line, r"\\accellat" => "AcceleratorLattice")
+ line = replace(line, r"\\scibmad" => "SciBmad")
+ line = replace(line, r"\\bmad" => "Bmad")
+ line = replace(line, r"\\julia" => "Julia")
+ line = replace(line, r"\\sref{(.*?)}" => s"[](#\1)")
+ line = replace(line, r"\\ref{(.*?)}" => s"[](#\1)")
+ line = replace(line, r"\\fig{(.*?)}" => s"{numref}`\1`")
+ line = replace(line, r"\\cite{([^}]*?),([^}]*?)}" => s"{footcite:p}`\1;\2`")
+ line = replace(line, r"\\cite{(.*?)}" => s"{footcite:p}`\1`")
+ line = replace(line, r"\\calO" => "\\cal O", r"\\bfr" => "{\\bf r}")
+ line = replace(line, r"\\\\" => "")
+ if occursin("\$", line)
+ words = split(line, "\$")
+ line = ""
+ for n in 1:2:length(words)-1
+ line *= words[n] * "{math}`" * words[n+1] * "`"
+ end
+ if isodd(length(words)); line *= words[end]; end
+ end
+
+ if end_line
+ return line * "\n"
+ else
+ return line
+ end
+end
+
+#--------------------------------------------------
+
+nn = 0
+while nn < length(lines)
+ global nn += 1
+ line = strip(lines[nn])
+
+ #------------
+
+ if startswith(line, "\\chapter")
+ line = replace(line, "\\chapter{" => "# ", "}" => "")
+
+ line2 = lines[nn+1]
+ if startswith(line2, "\\label")
+ line2 = replace(line2, "\\label{" => "(", "}" => ")=")
+ write(fout, line2)
+ write(fout, line)
+ nn += 1
+ else
+ write(fout, "(c:X)=\n")
+ write(fout, line)
+ end
+
+ continue
+ end
+
+ #------------
+
+ if startswith(line, "\\section") ||startswith(line, "\\subsection")
+ line = "## " * sub_str(line, "section{", "}")
+
+ line2 = lines[nn+1]
+ if startswith(line2, "\\label")
+ line2 = replace(line2, "\\label{" => "(", "}" => ")=")
+ write(fout, line2)
+ write(fout, line)
+ nn += 1
+ else
+ write(fout, "(s:X)=\n")
+ write(fout, line)
+ end
+
+ continue
+ end
+
+ #------------
+
+ if strip(line) == "\\item"
+ lines[nn+1] = "- " * lines[nn+1]
+ continue
+ end
+
+ #------------
+
+ if startswith(line, "\\begin{tabular}")
+
+ if occursin("indnt", lines[nn+2])
+ nn += 1
+ prefix = strip(split(lines[nn])[1])
+
+ while true
+ nn += 1
+ line = strip(lines[nn])
+ if startswith(line, "\\end{tabular}"); break; end
+
+ suffix = strip(sub_str(line, "\\indnt", "&"))
+ doc = strip(sub_str(line, "--", "\\"))
+ write(fout, "- $prefix$suffix - $doc\n")
+ end
+
+ elseif occursin("& --", lines[nn+1])
+ while true
+ nn += 1
+ line = strip(lines[nn])
+ if startswith(line, "\\end{tabular}"); break; end
+ if startswith(line, "\\bottomrule"); break; end
+ words = split(line, "&")
+ who = words[1]
+ doc = strip(sub_str(words[2], "--", "\\\\"))
+ write(fout, "- $who - $doc\n")
+ end
+
+ else
+ write(fout, "Need custom handling!!!!\n")
+ end
+
+ continue
+ end
+
+
+ #------------
+
+ if startswith(line, "\\begin{table}")
+ write(fout, "```{csv-table}\n")
+ write(fout, ":align: center\n")
+
+ while true
+ nn += 1
+ line = strip(lines[nn])
+ if startswith(line, "\\end{table}"); break; end
+
+ if startswith(line, "{\\tt"); continue; end
+ if startswith(line, "\\centering"); continue; end
+ if startswith(line, "}"); continue; end
+ if startswith(line, "\\end{tabular}"); continue; end
+ if startswith(line, "\\caption"); continue; end
+ if startswith(line, "\\label"); continue; end
+ if startswith(line, "\\bottomrule"); continue; end
+ if startswith(line, "\\midrule"); continue; end
+
+ if startswith(line, "\\begin{tabular}")
+ nn += 1
+ line = lines[nn]
+ write(fout, ":header: \"Element\", \"Element\"\n")
+ continue
+ end
+
+ words = split(line, "&")
+ lab1 = sub_str(words[2], "ref{", "}")
+ lab2 = sub_str(words[4], "ref{", "}")
+ write(fout, "[$(strip(words[1]))](#$lab1), [$(strip(words[3]))](#$lab2)\n")
+ end
+
+ write(fout, "```\n")
+ continue
+ end
+
+ #------------
+ # Figure
+
+ if startswith(line, "\\begin{figure}")
+ while true
+ nn += 1
+ line = strip(lines[nn])
+ if startswith(line, "\\end{figure}"); break; end
+ if startswith(line, "\\centering"); continue; end
+
+ if startswith(line, "\\label")
+ write(fout, ":name: $(sub_str(line, "\\label{", "}"))\n")
+ continue
+ end
+
+ if startswith(line, "\\includegraphics")
+ line = replace(line, r"\[.*?\]" => "")
+ write(fout, "```{figure} figures/$(sub_str(line, "includegraphics{", ".pdf}")).svg\n")
+ continue
+ end
+
+ write(fout, str_replace(line))
+ end
+ write(fout, "```\n")
+ continue
+ end
+
+ #------------
+ # Ele parameter groups in ele-types.tex
+
+ if startswith(line, "\\TOPrule");
+ nn += 1 # Skip "\begin{example}"
+
+ while true
+ nn += 1
+ line = lines[nn]
+ if startswith(line, "\\end"); break; end
+ if startswith(line, "\\centering"); continue; end
+
+ words = split(line, "->")
+ ws2 = split(words[2], "\\sref{")
+ w1 = strip(words[1])
+ w2 = strip(split(ws2[2], "}")[1])
+ w3 = strip(ws2[1])
+ write(fout, "- [**$w1**](#$w2): $w3\n")
+ end
+
+ nn += 1
+ continue
+ end
+
+ #------------
+
+ if startswith(line, "\\newpage"); continue; end
+ if startswith(line, "\\begin{description}"); continue; end
+ if startswith(line, "\\end{description}"); continue; end
+ if startswith(line, "\\vspace"); continue; end
+ if startswith(line, "\\hfill"); continue; end
+ if line == "{tt"; continue; end
+ if line == "}"; continue; end
+ if line == "\\end{tabular}"; continue; end
+
+ line = str_replace(line)
+ write(fout, line)
+end
+
+write(fout, "```{footbibliography}\n")
+write(fout, "```\n")
+
+close(fout)
\ No newline at end of file
diff --git a/docs/src/bibliography.bib b/docs/src/bibliography.bib
new file mode 100644
index 0000000..e31efde
--- /dev/null
+++ b/docs/src/bibliography.bib
@@ -0,0 +1,153 @@
+@article{Abell:RF-maps,
+ title = {Numerical computation of high-order transfer maps for rf cavities},
+ author = {Abell, Dan T.},
+ journal = {Phys. Rev. ST Accel. Beams},
+ volume = {9},
+ issue = {5},
+ pages = {052001},
+ numpages = {13},
+ year = {2006},
+ month = {5},
+ publisher = {American Physical Society},
+ doi = {10.1103/PhysRevSTAB.9.052001},
+ url = {https://link.aps.org/doi/10.1103/PhysRevSTAB.9.052001}
+}
+
+@article{Appleby:Merlin2020,
+ author = "Appleby, Robert B. and Barlow, Roger J. and Kruecker, Dirk and Molson, James and Rowan, Scott and Tygier, Sam and Rafique, Haroon and Walker, Nicholas and Wolski, Andrzej",
+ title = "{Merlin++, a flexible and feature-rich accelerator physics and particle tracking library}",
+ eprint = "2011.04335",
+ archivePrefix = "arXiv",
+ primaryClass = "physics.acc-ph",
+ doi = "10.1016/j.cpc.2021.108204",
+ journal = "Comput. Phys. Commun.",
+ volume = "271",
+ pages = "108204",
+ year = "2022"
+}
+
+@article{Iadarola:Xsuite2023,
+ author = "Iadarola, G. and others",
+ title = "{Xsuite: an integrated beam physics simulation framework}",
+ eprint = "2310.00317",
+ archivePrefix = "arXiv",
+ primaryClass = "physics.acc-ph",
+ month = "9",
+ year = "2023"
+}
+
+@inproceedings{Borland:Elegant2000,
+ author = "Borland, M.",
+ title = "{elegant: A Flexible SDDS-Compliant Code for Accelerator Simulation}",
+ booktitle = "{6th International Computational Accelerator Physics Conference (ICAP 2000)}",
+ reportNumber = "LS-287",
+ doi = "10.2172/761286",
+ year = "2000"
+}
+
+@INPROCEEDINGS{Grote:MAD1989,
+ author={Grote, H. and Iselin, F.C. and Keil, E. and Niederer, J.},
+ booktitle={Proceedings of the 1989 IEEE Particle Accelerator Conference, . 'Accelerator Science and Technology},
+ title={The MAD program},
+ year={1989},
+ volume={},
+ number={},
+ pages={1292-1294 vol.2},
+ keywords={Computer graphics;Particle beam measurements},
+ doi={10.1109/PAC.1989.73426}
+}
+
+@book{Lee:Physics,
+ author = {Lee, S Y},
+ title = {Accelerator Physics},
+ publisher = {WORLD SCIENTIFIC},
+ year = {2019},
+ doi = {10.1142/11111},
+ address = {},
+ edition = {4th},
+ URL = {https://www.worldscientific.com/doi/abs/10.1142/11111},
+ eprint = {https://www.worldscientific.com/doi/pdf/10.1142/11111}
+}
+
+@article{McMillan:Multipoles,
+title = {Multipoles in Cylindrical Coordinates},
+journal = {Nuclear Instruments and Methods},
+volume = {127},
+number = {3},
+pages = {471-474},
+year = {1975},
+issn = {0029-554X},
+doi = {https://doi.org/10.1016/S0029-554X(75)80021-8},
+url = {https://www.sciencedirect.com/science/article/pii/S0029554X75800218},
+author = {Edwin M. McMillan},
+}
+
+@inproceedings{Newton:map,
+ author = {D. Newton and A. Wolski},
+ title = {{Fast, Accurate Calculation of Dynamical Maps from Magnetic Field Data Using Generalised Gradients}},
+ booktitle = {Proc. PAC'09},
+ pages = {3943--3945},
+ paper = {TH6PFP099},
+ venue = {Vancouver, Canada, May 2009},
+ series = {Particle Accelerator Conference},
+ number = {23},
+ publisher = {JACoW Publishing, Geneva, Switzerland},
+ year = {2009},
+ language = {english}
+}
+
+@article{Sagan:Bmad2006,
+ author = "D. Sagan",
+ title = "{Bmad: A relativistic charged particle simulation library}",
+ booktitle = "{Computational accelerator physics. Proceedings, 8th
+ International Conference, ICAP 2004, St. Petersburg,
+ Russia, June 29-July 2, 2004}",
+ journal = "Nucl. Instrum. Meth.",
+ volume = "A558",
+ number = "1",
+ year = "2006",
+ pages = "356-359",
+ issn = "0168-9002",
+ doi = "https://doi.org/10.1016/j.nima.2005.11.001",
+ note = "Proceedings of the 8th International Computational Accelerator Physics Conference",
+ keywords = "Simulation, Particle accelerators, Relativistic beams",
+ SLACcitation = "%%CITATION = NUIMA,A558,356;%%"
+}
+
+@inproceedings{Sagan:wiggler,
+ author={Sagan, D. and Crittenden, J.A. and Rubin, D. and Forest, E.},
+ booktitle={Proceedings of the 2003 Particle Accelerator Conference},
+ title={A magnetic field model for wigglers and undulators},
+ year={2003},
+ volume={2},
+ number={},
+ pages={1023-1025 Vol.2},
+ keywords={Undulators;Magnetic fields;Magnetic field measurement;Storage rings;Magnetic analysis;Superconducting magnets;Fourier transforms;Apertures;Maxwell equations;Nonlinear distortion},
+ doi={10.1109/PAC.2003.1289592}}
+
+@article{Venturini:LHC-Quads,
+ author = "Venturini, M. and Abell, D. and Dragt, A.",
+ journal={Proceedings, 1998 International Computational Accelerator Physics Conference},
+ title = "{Map computation from magnetic field data and application to the LHC high gradient quadrupoles}",
+ pages = "184--188",
+ year = "1998"
+}
+
+@article{Venturini:magmaps,
+ title={Accurate computation of transfer maps from magnetic field data},
+ author={Venturini, Marco and Dragt, Alex J},
+ journal={Nuclear Instruments and Methods in Physics Research Section A: Accelerators, Spectrometers, Detectors and Associated Equipment},
+ volume={427},
+ number={1-2},
+ pages={387--392},
+ year={1999},
+ publisher={Elsevier}
+}
+
+@unpublished{Zhou:SADmaps,
+ author = {Zhou, D. and Oide, K.},
+ title = {Maps Used in SAD},
+ institution = {KEK},
+ year = {2015},
+ note = {}
+}
\ No newline at end of file
diff --git a/docs/src/bookkeeping.md b/docs/src/bookkeeping.md
new file mode 100644
index 0000000..5fbc097
--- /dev/null
+++ b/docs/src/bookkeeping.md
@@ -0,0 +1,95 @@
+(c:bookkeeping)=
+# Lattice Bookkeeping
+Bookkeeping in AcceleratorLattice mainly involves making sure that dependent parameters are updated as needed.
+This includes dependent parameters within a lattice element, propagating changes through the lattice,
+and lord/slave bookkeeping.
+
+Note: An element in a branch has a pointer to the branch (`Ele.branch`) and the branch has
+a pointer to the lattice (`Branch.lat`). So a lattice element "knows" about the lattice it
+is in. On the other hand, elements in beam lines don't have pointers to the beamline. This is
+an important factor when setting up forks.
+
+%---------------------------------------------------------------------------------------------------
+(s:lord.slave.book)=
+## Lord/Slave Bookkeeping
+There are two types of lords/slave groupings:
+```{code} yaml
+Superposition: Super lords / Super Slaves [](#c:super)
+Multipass: Multipass lords Multipass Slaves [](#c:multipass)
+```
+
+The lord and slave slave status of a lattice element is contained in the `LordSlaveStatusParams`
+parameter group. The components of this group are ([](#s:lord.slave.g)):
+```{code} yaml
+lord_status::Lord.T - Lord status.
+slave_status::Slave.T - Slave status.
+```
+
+For a given element, some combinations of lord and slave status are not possible. The possibilities are:
+```{csv-table}
+
+slave_status , .NOT, .SUPER, .MULTIPASS
+`.NOT` , X, X, X
+`.SUPER` , X, ,
+`.MULTIPASS` , X, X,
+```
+Notice that the only possibility for an element to simultaneously be both a lord and a slave is
+for a super lord being a multipass slave.
+
+%---------------------------------------------------------------------------------------------------
+(s:X)=
+## Girders
+`Girders` support a set of supported elements. A `Girder` may support other `Girders`
+and so a hierarchy of `Girders` may be constructed. While a `Girder` may support many elements,
+any given element may only be supported by one `Girder`.
+
+`Girder` elements may support super and multipass lord elements, a `Girder` will never support
+slave elements directly. This includes any super lord element that is also a multipass slave.
+
+A `Girder` element will have a `Vector{Ele`} parameter of supported elements `.supported`.
+Supported elements will have a `.girder` parameter pointing to the supporting `Girder`.
+Elements that do not have a supporting `Girder` will not have this parameter.
+
+%---------------------------------------------------------------------------------------------------
+(s:super.book)=
+## Superposition
+Super lords are formed when elements are superimposed on top of other elements ([](#c:super)).
+The AcceleratorLattice bookkeeping routines and take changes to lord element parameters and set the
+appropriate slave parameters.
+
+When there is a set of lattice elements that are in reality the same physical element, a
+multipass lord can be used to represent the common physical element [](#c:multipass).
+The AcceleratorLattice bookkeeping routines and take changes to lord element parameters and set the
+appropriate slave parameters.
+
+`Girder` lords support other elements (possibly including other `Girder` lords). Alignment
+shifts of a `Girder` lord will shift the supported elements accordingly.
+
+%---------------------------------------------------------------------------------------------------
+(s:lord.slave)=
+## Lord/Slave Element Pointers
+All three types of lord elements contain a `Vector{ele`} of elements called `slaves`.
+
+%---------------------------------------------------------------------------------------------------
+(s:access)=
+## Element Parameter Access
+%---------------------------------------------------------------------------------------------------
+(s:changed.param)=
+## Changed Parameters and Auto-Bookkeeping
+Importance of using pop!, insert!, push! and set! when modifying the branch.ele array.
+
+The `ele.changed` parameter (which is actually `ele.pdict[:changed]`) is a dictionary.
+The keys of this dict will be either symbols of the changed parameters or
+will be an element parameter group.
+When the key is a symbol of a changed parameter,
+the dict value will be the old value of the parameter. These dict entries are set by the
+overloaded `Base.setproperty(ele, param_sym, value)` function.
+When the key is an element parameter group, the dict value will be the string `"changed"`.
+These dict entries are set by functions that do lord/slave bookkeeping.
+
+When bookkeeping is done, entries from the `ele.changed` dict are removed when the corresponding
+parameter(s) are bookkeeped. If there are dict entries that remain after all bookkeeping is done,
+this is an indication of a problem and a warning message is printed.
+
+```{footbibliography}
+```
diff --git a/docs/src/conf.py b/docs/src/conf.py
new file mode 100644
index 0000000..10f4a25
--- /dev/null
+++ b/docs/src/conf.py
@@ -0,0 +1,30 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'AcceleratorLattice.jl'
+copyright = '2025, under CC-BY 4.0 License'
+author = 'David Sagan'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = ['myst_parser', 'sphinx_design', 'sphinxcontrib.bibtex']
+bibtex_bibfiles = ['bibliography.bib']
+myst_enable_extensions = ["colon_fence", "amsmath"]
+numfig = True
+
+templates_path = ['_templates']
+exclude_patterns = []
+
+
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = 'sphinx_book_theme'
+## html_static_path = ['_static']
diff --git a/docs/src/construction.md b/docs/src/construction.md
new file mode 100644
index 0000000..f7ee43a
--- /dev/null
+++ b/docs/src/construction.md
@@ -0,0 +1,27 @@
+(c:construct-lat)=
+# Constructing Lattices
+Note:
+```{code} yaml
+@ele qq = Quadrupole()
+bl = beamline([.., qq, ..., qq, ...], ...)
+```
+Here changing parameters of qq will affect the parameters of the qq's in any beamline.
+However, lattice expansion constructs the lattice with copies of qq so changing the
+parameters of qq will not affect any of the copies in the lattice. This is done so that
+parameters in the various qq's in the lattice are independent and an therefore differ from each
+other.
+
+Branch geometry is inherited from the root line. To use a line with the "wrong" geometry, create
+a new line using the old line with the "correct" geometry. EG
+ln2 = beamline(ln1.name, [ln1], geometry = CLOSED)
+lat = Lattice([ln2])
+
+Note: OPEN and CLOSED are aliases for BranchGeometry.OPEN and BranchGeometry.CLOSED
+
+* Show how to construct a Bmad replacement line using a function.
+
+* Show how to get the effect of a Bmad List by replacing elements after expansion.
+
+* Default name for end element is `"endN"` where N is the index of the branch.
+```{footbibliography}
+```
diff --git a/docs/src/custom.md b/docs/src/custom.md
new file mode 100644
index 0000000..8b29e80
--- /dev/null
+++ b/docs/src/custom.md
@@ -0,0 +1,25 @@
+(c:custom-lat)=
+# Customizing Lattices
+
+%---------------------------------------------------------------------------------------------------
+`Custom Lattice Element Parameters`
+
+Custom parameters may be added to lattice elements but methods need to be created to tell AcceleratorLattice
+how to handle these parameters.
+
+* Define element parameter group
+
+* Need to extend:
+ELE_PARAM_INFO_DICT
+PARAM_GROUPS_LIST
+param_group_info
+
+
+%---------------------------------------------------------------------------------------------------
+`Custom Lattice Elements`
+
+* Need to extend:
+ele_param_groups
+
+```{footbibliography}
+```
diff --git a/docs/src/design.md b/docs/src/design.md
new file mode 100644
index 0000000..40d3165
--- /dev/null
+++ b/docs/src/design.md
@@ -0,0 +1,105 @@
+(c:design)=
+# Design Decisions
+This chapter discusses some of the design decisions that were made in the planning of AcceleratorLattice.
+Hopefully this information will be useful as AcceleratorLattice is developed in the future.
+The design of AcceleratorLattice is heavily influenced by the decades of experience constructing and maintaining
+Bmad --- both in terms of what works and what has not worked.
+
+First a clarification. The name Bmad
+can be used in two senses. There is Bmad the Fortran software toolkit
+that can be used to create simulation programs. But Bmad can also be used to refer to the
+ecosystem of toolkit and Bmad based programs that have been developed over the years --- the
+most heavily used program being Tao. In the discussion below, Bmad generally refers to the toolkit
+since it is the toolkit that defines the syntax for Bmad lattice files.
+
+paragraph{Bmad history:}
+To understand Bmad it helps to understand some of the history of Bmad. The Bmad toolkit
+started out as a modest project for calculating Twiss parameters and closed orbits within online control
+programs for the Cornell CESR storage ring. As such, the lattice structure was simply an array
+of elements. That is, early Bmad did not have the concept of interlocking branches, and tracking was very simple ---
+there was only one tracking method, symplecticity was ignored and ultra-relativistic and
+paraxial approximations were used.
+Bmad has come a long way from the early days but design decisions made early on still haunt the Bmad
+toolkit.
+
+paragraph{Julia itself is the design language:}
+One of the main problems with Bmad --- and many other simulation programs like MAD, Elegant, SAD, etc. ---
+is that the design language is some custom construct with custom syntax put together by a team that
+never has enough manpower. This both greatly limits the versatility of language as well as adding
+the burden of developing and maintaining the language. Julia was chosen for AcceleratorLattice
+due to the ability of using Julia as the design language.
+
+There are many design decisions that flow from the fact that Julia is used for the design language
+so decisions are made to follow the "Julia way".
+For example, case sensitivity of names, indexing of branch element arrays starting at 1 (Bmad uses 0),
+etc.
+
+paragraph{Separation of tracking and lattice description:}
+One of the first AcceleratorLattice design decisions was to separate particle tracking from the lattice description.
+This was done since experience with Bmad showed that properly doing lattice bookkeeping is vastly
+more complicated when tracking is involved. This is especially true when the User can choose
+among multiple tracking methods for a given element and the User is free to vary the tracking method
+on-the-fly.
+
+The decision to separate lattice and tracking was also inspired by the PTC code of Etienne Forest.
+The fact that Bmad did not make this separation complicated Bmad's lattice element structure,
+the `ele_struct`,
+to the extent that the `ele_struct` is the most complicated structure in all of Bmad. And
+having complicated structures is an impediment to code sustainability.
+The lack of a separation in Bmad also made bookkeeping more complicated in cases where, for example,
+Twiss parameters were to be calculated under differing conditions (EG varing initial
+particle positions) but the `ele_struct` can only hold Twiss parameters for one specific
+condition.
+
+paragraph{Lattice branches:}
+The organization of the lattice into branches with each branch having an array of elements has
+worked very well with Bmad and so is used with AcceleratorLattice. The relatively minor difference is
+that with AcceleratorLattice the organization of the branches is more logical with multiple lord branches
+with each lord branch containing only one type of lord.
+
+paragraph{No Controllers:}
+Bmad has control element types called `groups` and `overlays`. Elements of these types
+can control the parameters of other elements.
+The ability to define controllers has been tremendously useful, for example,
+to simulate machine control from a control room. Nevertheless, controllers are not implemented
+with AcceleratorLattice. The reason for this is that there is no need to define controllers since the Julia
+language provides all the necessary tools to construct control functions that have a versatility
+much greater than the ones in Bmad.
+
+paragraph{Type stability:}
+Type stability is {em not} a major concern with AcceleratorLattice. The reason being that compared to
+the time needed for tracking and track analysis, lattice instantiation
+and manipulation does not take an appreciable amount of time. For tracking, where computation time
+is a hugh consideration, an interface layer can be
+used to translate lattice parameters to a type stable form. Of much greater importance is the
+flexibility of AcceleratorLattice to accomodate changing needs and software sustainability.
+Hence all element, branch, and lattice structures contain a Dict (always called `pdict`) which
+can store arbitrary information.
+
+paragraph{Lattice element structure:}
+All lattice element structs are very simple: They contain a single Dict and all element information
+is stored within this Dict. This means that there is no restriction as to what can be stored
+in an element adding custom information to an element simple.
+And the ability to do customization easily is very important.
+
+Within an element Dict, for the most part, parameters are grouped into "element group" structs.
+A flattened structure, that is, without the element group structs, would be the correct strategy
+if the number of possible parameters for a given element type was not as large as it is.
+However, the parameterization of an element can be complicated.
+For example, a field table describing the field in an element has a grid of field points plus
+parameters to specify the distance between points, the frequency (if the field is oscillating), etc.
+In such a case, where the number of parameters is large, and with the parameters falling into
+logical groups, using substructures if preferred. Another consideration is that parameter groups
+help remove the conflict that occurs when multiple parameters logically should have the same name.
+For example, if an element is made up of different parts and multipole parts can have independent
+misalignments, parameter groups help keep the offset parameters distinct.
+
+paragraph{Defining multipoles using normal and skew strengths along with a tilt:}
+The reason why for any order multipole there are three components,
+normal, skew and tilt, that describe the field when only two would be sufficient is due convenience.
+Having normal and skew components is convenient when magnet has multiple windings that control
+both independently. A common case is combined horizontal and vertical steering magnets. On the
+other hand, being able to "misalign" the multipole using the `tilt` component is also
+useful.
+```{footbibliography}
+```
diff --git a/docs/src/ele-anatomy.md b/docs/src/ele-anatomy.md
new file mode 100644
index 0000000..882f69e
--- /dev/null
+++ b/docs/src/ele-anatomy.md
@@ -0,0 +1,249 @@
+(c:ele)=
+# Lattice Elements
+
+This chapter discusses lattice elements including how to create them and how to manipulate them.
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.types)=
+## Element Types
+
+Lattice element types (`Quadrupole`, `RFCavity`, etc.) are structs that inherit from the abstract
+type `Ele`. Lattice elements documentation is in chapter~[](#c:ele.types).
+In the REPL, to see a list of all element types, use the command `subtypes(Ele)`:
+```{code} yaml
+ julia> subtypes(Ele)
+ 41-element Vector\{Any\}:
+ ACKicker
+ BeamBeam
+ BeginningEle
+ Bend
+ ...
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.def)=
+## Instantiating a Lattice Element
+
+Elements are defined using the `@ele` or `@eles` macros.
+The general syntax of the `@ele` macro is:
+```{code} yaml
+ @ele eleName = eleType(param1 = val1, param2 = val2, ...)
+```
+where `eleName` is the name of the element, `eleType` is the type of element,
+`param1`, `param2`,
+etc. are parameter names and `val1`, `val2`, etc. are the parameter values.
+Example:
+```{code} yaml
+ @ele qf = Quadrupole(L = 0.6, Kn1 = 0.370)
+```
+The `@ele` macro will construct a Julia variable with the name `eleName`.
+Additionally, the element
+that this variable references will also hold `eleName` as the name of the element. So with this
+example, `qf.name` will be the string `"qf"`. If multiple elements are being defined in a
+group, a single
+`@eles` macro can be used instead of multiple `@ele` macros using the syntax:
+```{code} yaml
+ @eles begin
+ eleName1 = eleType1(p11 = v11, p12 = v12, ...)
+ eleName2 = eleType2(p21 = v21, p22 = v22, ...)
+ ... etc...
+ end
+```
+Example:
+```{code} yaml
+ @eles begin
+ s1 = Sextupole(L = ...)
+ b2 = Bend(...)
+ ...
+ end
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.groups)=
+## Element Parameter Paramss
+
+Generally, element parameters are grouped into "`element` `parameter` `group`"
+structs which inherit from the abstract type `EleParams`.
+Element parameter documentation is in Chapter~[](#c:ele.groups). In the REPL,
+To see a list of parameter groups, use the `suptypes` function:
+```{code} yaml
+ julia> subtypes(EleParams)
+ 28-element Vector{Any}:
+ BodyShiftParams
+ ApertureParams
+ BMultipoleParams
+ ...
+```
+Chapter~[](#c:ele.types) documents the parameters groups that are associated with any particular element type.
+In the REPL, the associated parameter groups can be viewed using Julia's help function. Example:
+```{code} yaml
+ help?> Quadrupole
+ mutable struct Quadrupole <: Ele
+ Type of lattice element.
+
+ Associated parameter groups
+ ===========================
+ • BodyShiftParams -> Element position/orientation shift.
+ • ApertureParams -> Vacuum chamber aperture.
+ • BMultipoleParams -> Magnetic multipoles.
+ • EMultipoleParams -> Electric multipoles.
+ • FloorParams -> Floor position and orientation.
+ • LengthParams -> Length and s-position parameters.
+ • LordSlaveParams -> Element lord and slave status.
+ • MasterParams -> Contains field_master parameter.
+ • ReferenceParams -> Reference energy and species.
+ • DescriptionParams -> String labels for element.
+ • TrackingParams -> Default tracking settings.
+```
+Alternatively,
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.params)=
+## Element Parameters
+
+For example, the `LengthParams` holds the length and s-positions of the element and is defined by:
+```{code} yaml
+ @kwdef struct LengthParams <: EleParams
+ L::Number = 0.0 # Length of element
+ s::Number = 0.0 # Starting s-position
+ s_downstream::Number = 0.0 # Ending s-position
+ orientation::Int = 1 # Longitudinal orientation
+ end
+```
+The `@kwdef` macro automatically defines a keyword-based constructor for `LengthParams`.
+See the Julia manual for more information on `@kwdef`.
+To see a list of all element parameter groups use the `subtypes(EleParamterParams)` command.
+To see the components of a given group use the `fieldnames` function. For information on
+a given element parameter use the `info(::Symbol)` function where the argument is the
+symbol corresponding to the component. For example, the information on
+the `s_downstream` parameter which is a field of the `LengthParams` is:
+```{code} yaml
+ julia> info(:s_downstream)
+ User name: s_downstream
+ Stored in: LengthParams.s_downstream
+ Parameter type: Number
+ Units: m
+ Description: Longitudinal s-position at the downstream end.
+```
+Notice that the argument to the `info` function is the symbol associated with the parameter.
+the "user name" is the name used when setting the parameter. For instance, if `q` is a
+lattice element, `q.s_downstream` would be used to access the `s_downstream` component of `q`.
+This works, even though `s_downstream` is not a direct component of an element, since the dot
+selection operator for lattice elements has been overloaded as explained in [](#s:ele.access).
+For most parameters, the user name and the name of the corresponding component in the element parameter
+group are the same. However, there are exceptions. For example:
+```{code} yaml
+ julia> info(:theta)
+ User name: theta_floor
+ Stored in: FloorParams.theta
+ Parameter type: Number
+ Units: rad
+ Description: Element floor theta angle orientation
+```
+In this example, the user name is `theta_floor` so that this parameter can be set via
+```{code} yaml
+ @ele bg = BeginningEle(theta_floor = 0.3) # Set at element definition time.
+ bg.theta_floor = 2.7 # Or set after definition.
+```
+But the component in the `FloorParams` is `theta` so
+```{code} yaml
+ bg.FloorParams.theta = 2.7 # Equivalent to the set above.
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.access)=
+## How Element Parameters are Stored in an Element
+
+All lattice element types have a single field of type `Dict\{Symbol,Any\`} named `pdict`.
+The values of `pdict` will, with a few exceptions, be an
+element parameter group. The corresponding key for a parameter group in `pdict` is the symbol associated
+with the type. For example, a `LengthParams` struct would be stored in `pdict[:LengthParams]`.
+
+To (partially) hide the complexity of parameter groups, the dot selection operator is overloaded for elements.
+This is achieved by overloading the `Base.setproperty` and `Base.getproperty` functions,
+which get called when the dot selection operator is used.
+For example, if `q` is an element instance, `q.s` will get mapped to `q.pdict[:LengthParams].s`.
+Additionally, `q.LengthParams` is mapped to `q.pdict[:LengthParams]`.
+
+Besides simplifying the syntax, overloading the dot selection operator has a second purpose which
+is to allow the AcceleratorLattice bookkeeping routines to properly do dependent parameter bookkeeping ([](#param.depend)).
+To illustrate this, consider the following two statements which both set the `s_downstream`
+parameter of an element named `q1`:
+```{code} yaml
+ q1.pdict[:Length_group].s_downstream = q1.pdict[:Length_group].s +
+ q1.pdict[:Length_group].L
+ q1.s_downstream = q1.s + q1.L
+```
+These two statements are not equivalent. The difference is that in the first statement when
+`setproperty` is called to handle `q1.pdict`, the code will simply return `q1.pdict`
+(the code knows that `pdict` is special) and do nothing else.
+However, with the second statement, `setproperty` not only sets
+`q1.s_downstream` but additionally records the set by adding an entry to
+`q1.pdict[:changed]` which is a dict within `pdict`.
+The key of the entry will, in this case, be the symbol `:s_downstream`
+and the value will be the old value of the parameter.
+When the `bookkeeper(::Lattice)` function is called ([](#xxx)), the bookkeeping code will use the
+entries in `ele.pdict[:changed]` to limit the bookkeeping to what is necessary and thus
+minimize computation time.
+Knowing what has been changed is also important in resolving what
+dependent parameters need to be changed.
+For example, if the bend `angle` is changed, the bookkeeping code will set the
+bending strength `g` using the equation `g` = `angle` / `L`. If, instead,
+`g` is changed, the bookkeeping code will set `angle` appropriately.
+
+While the above may seem complicated, in practice the explicit use of `q1.pdict` should be avoided
+since it prevents the bookkeeping from dealing with dependent parameters.
+The place where `q1.pdict` is needed is in the bookkeeping code itself to avoid infinite loops.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:param.depend)=
+## Bookkeeping and Dependent Element Parameters
+
+After lattice parameters are changed, the function `bookkeeper(::Lattice)` needs to be called
+so that dependent parameters can be updated.
+Since bookkeeping can take a significant amount of time if bookkeeping is done every time
+a change to the lattice is made, and since there is no good way to tell when bookkeeping should
+be done, After lattice expansion, `bookkeeper(::Lattice)` is never called directly by AcceleratorLattice
+functions and needs to be called by the User when appropriate (generally before tracking or
+other computations are done).
+
+Broadly, there are two types of dependent parameters: intra-element dependent parameters where
+the changed parameters and the dependent parameters are all within the same element and
+cascading dependent parameters where changes to one element cause changes to parameters of
+elements downstream.
+
+The cascading dependencies are:
+%
+\item [s-position dependency:]
+Changes to an elements length `L` or changes to the beginning element's `s` parameter will
+result in the s-positions of all downstream elements changing.
+%
+\item [Reference energy dependency:] Changes to the be beginning element's reference energy (or
+equivilantly the referece momentum), or changes to the `voltage` of an `LCavity` element
+will result in the reference energy of all downstream elements changing.
+%
+- **Floor position dependency:**
+The position of a lattice element in the floor coordinate system ([](#s:floor)) is affected
+by a) the lengths of all upstream elements, b) the bend angles of all upstream elements, and c)
+the position in floor coordinates of the beginning element.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.new.type)=
+## Defining a New Element Type
+
+To construct a new type, use the `@construct_ele_type` macro. Example:
+```{code} yaml
+ @construct_ele_type MyEle
+```
+And this defines a new type called `MyEle` which inherits from the abstract type `Ele` and
+defines `MyEle` to have a single field called `pdict` which is of type `Dict\{Symbol,Any\`}.
+This macro also pushes the name
+
+%---------------------------------------------------------------------------------------------------
+(s:ele.new.param)=
+## Defining New Element Parameters
+
+```{footbibliography}
+```
diff --git a/docs/src/ele-param-groups.md b/docs/src/ele-param-groups.md
new file mode 100644
index 0000000..7cc5b59
--- /dev/null
+++ b/docs/src/ele-param-groups.md
@@ -0,0 +1,1181 @@
+(c:ele.groups)=
+# Element Parameters
+Generally, element parameters are grouped into "`element` `parameter` `group`"
+types. How these groups are used in a lattice element is discussed in [](#c:ele).
+This chapter discusses the groups in detail.
+
+The parmeter groups are:
+```{csv-table}
+
+:align: center
+:header: "Element", "Element"
+
+[ACKickerParams](#s:ackicker.g), [LengthParams](#s:length.g)
+[FloorParams](#s:floor.g), [LordSlaveStatusParams](#s:lord.slave.g)
+[ApertureParams](#s:aperture.g), [MasterParams](#s:master.g)
+[BMultipoleParams](#s:bmultipole.g), [FloorParams](#s:orientation.g)
+[BeamBeamParams](#s:beam.beam.g), [OriginEleParams](#s:origin.ele.g)
+[BendParams](#s:bend.g), [PatchParams](#s:patch.g)
+[DescriptionParams](#s:descrip.g), [RFParams](#s:rf.g)
+[DownstreamReferenceParams](#s:dreference.g), [RFAutoParams](#s:rfauto.g)
+[EMultipoleParams](#s:emultipole.g), [ReferenceParams](#s:reference.g)
+[ForkParams](#s:fork.g), [SolenoidParams](#s:solenoid.g)
+[GirderParams](#s:girder.g), [TrackingParams](#s:tracking.g)
+[InitParticleParams](#s:init.particle.g), [TwissParams](#s:twiss.g)
+```
+
+Element parameter groups inherit from the abstract type `EleParams` which
+in turn inherits from `BaseEleParams`. Some
+parameter groups have sub-group components.
+These sub-groups also inherit from `BaseEleParams`:
+```{code} yaml
+abstract type BaseEleParams end
+abstract type EleParams <: BaseEleParams end
+abstract type EleParameterSubParams <: BaseEleParams end
+```
+
+To see which element types contain a given group, use the `info(::EleParams)`
+method. Example:
+```{code} yaml
+julia> info(ApertureParams)
+ApertureParams: Vacuum chamber aperture.
+x_limit::Vector{Number} Min/Max horizontal aperture limits. (m)
+y_limit::Vector{Number} Min/Max vertical aperture limits. (m)
+...
+Found in:
+ACKicker
+BeamBeam
+BeginningEle
+...
+```
+
+To get information on a given element parameter, including what element group the parameter is in,
+use the `info(::Symbol)` function using the symbol corresponding to the parameter. For example,
+to get information on the multipole component `Ks2L` do:
+```{code} yaml
+julia> info(:Ks2L)
+User name: Ks2L
+Stored in: BMultipoleParams.Ks
+Parameter type: Number
+Units: 1/m^2
+Description: Skew, length-integrated, momentum-normalized,
+magnetic multipole of order 2.
+```
+
+Notes:
+begin{itemize}
+%
+- All parameter groups have associated docstrings that can be accessed using the REPL help system.
+%
+- NaN denotes a real parameter that is not set.
+%
+- Parameters marked "dependent" are parameters calculated by AcceleratorLattice and not settable by the User.
+%
+- There are several lattice element parameters that are not stored in a parameter group but are stored
+alongside of the parameter groups in the element Dict. Included is the element's name, and information
+on lords and slaves of the element.
+%
+end{itemize}
+
+To simplify the structure of a lattice element, certain element parameters are not stored in the
+element structure but are calculated as needed. These "`output`" cannot be set.
+See [](#s:ele.access) for details.
+
+%---------------------------------------------------------------------------------------------------
+(s:ackicker.g)=
+## ACKickerParams
+The `ACKickerParams` holds parameters associated with `ACKicker` elements.
+
+The parameters of this group are:
+```{code} yaml
+amp_function::Function - Amplitude function.
+```
+
+
+%---------------------------------------------------------------------------------------------------
+(s:alignment.g)=
+## BodyShiftParams
+caption[Element alignment.]
+{BodyShiftParams parameters The reference point is the origin
+about which the element alignment is calculated.
+A) For straight elements, the reference point is in the center of the element.
+For `Bend` elements, the reference point is at the midpoint of the chord connecting
+the entrance point to the exit point. The drawing for the bend is valid for a `ref_tilt`
+of zero. For non-zero `ref_tilt`, the outward direction from the bend center will not be
+the {math}`x`-axis.
+} label{f:alignment}
+```
+
+{Alignment geometry. A) `z_rot` (or `z_rot_tot`) rotation. B) Combined
+`offset[1]` with `y_rot` (or `offset_tot[1]` with `y_rot_tot`).
+} label{f:alignment}
+```
+
+The `BodyShiftParams` gives the alignment (position and angular orientation) of the physical element
+relative to the nominal position defined by the branch coordinates ([](#s:orient)).
+Alignment is specified with respect to the "alignment reference point" of an element as shown
+in Fig~[](#s:alignment). The `Bend` reference point is chosen to be the center of the chord
+connecting the two ends.
+This reference point was chosen over using the midpoint on the reference orbit arc since a
+common simulation problem is to simulate a bend with a `z_rot` keeping the entrance and exit
+endpoints fixed.
+
+The parameters of the `BodyShiftParams` are:
+```{code} yaml
+offset::Vector - {math}`[x, y, z]` offset.
+x_rot::Number - Rotation around the x-axis.
+y_rot::Number - Rotation around the z-axis.
+z_rot::Number - Rotation around the z-axis.
+```
+If the element is supported by a `Girder`, the alignment parameters are with respect to the
+orientation of the `Girder` position. If there is no supporting `Girder`, the alignment
+parameters are with respect to the branch reference coordinates. There are output alignment
+parameters:
+```{code} yaml
+q_shift::Quaternion - Quaternion representation of x_rot, y_rot, z_rot.
+offset_tot::Vector - {math}`[x, y, z]` offset.
+x_rot_tot::Number - Rotation around the x-axis.
+y_rot_tot::Number - Rotation around the z-axis.
+z_rot_tot::Number - Rotation around the z-axis.
+q_shift_tot::Quaternion - Quaternion representation of tot rotations.
+```
+The "total alignment" parameters which have a `_tot` suffix are always the alignment
+of the element with with respect to the branch coordinates.
+If there is no support `Girder`, the total alignment will be the same as the "relative"
+(non-tot) alignment.
+
+The relative alignment can be set by the User.
+The total alignment is computed by AcceleratorLattice based upon the relative alignment and the alignment
+of any `Girder`. `Girder` elements themselves also have both relative and total
+alignments since Girders can support other Girders.
+
+The `q_shift` output parameter gives the quaternion representation of
+`x_rot`, `y_rot` and `z_rot`. Similarly, the`q_shift_tot` output parameter gives the
+quaternion representation of `x_rot_tot`, `y_rot_tot` and `z_rot_tot`.
+
+%---------------------------------------------------------------------------------------------------
+(s:aperture.g)=
+## ApertureParams
+{
+A) RECTANGULAR and ELLIPTICAL apertures. As drawn, `x_limit[1]` and `y_limit[1]` are
+negative and `x_limit[2]` and `y_limit[2]` are positive. B) The VERTEX aperture is defined
+by a set of vertices.
+} label{f:apertures}
+```
+
+The `ApertureParams` stores information about apertures an element may have.
+The parameters of this group are:
+```{code} yaml
+x_limit::Vector{Number} - Min/Max x-aperture limits. (m)
+y_limit::Vector{Number} - Min/Max y-aperture limits. (m)
+aperture_shape::ApertureShape - Aperture shape. Default: ELLIPTICAL
+aperture_at::BodyLoc.T - Aperture location. Default: BodyLoc.ENTRANCE_END
+wall::Wall2D - Aperture defined by vertex array.
+custom_aperture::Dict - Custom aperture information.
+aperture_shifts_with_body::Bool
+- Alignment affects aperture? Default: false.
+```
+
+The aperture location is set by the `aperture_at` parameter. Possible values are
+given by the `BodyLoc` enum group ([](#s:bodyloc)). The default is `BodyLoc.ENTRANCE_END`.
+The `.EVERYWHERE` location might be problematic for some types of particle tracking and
+so might not be always available.
+
+The `aperture_shape` parameter selects the shape of the aperture. Possible values are
+given by the `ApertureShape` Holy trait group.
+```{code} yaml
+RECTANGULAR - Rectangular shape.
+ELLIPTICAL - Elliptical shape.
+VERTEX - Shape defined by set of vertices.
+CUSTOM_SHAPE - Shape defined with a custom function.
+```
+
+For `RECTANGULAR` and `ELLIPTICAL` shapes the `x_limit` and `y_limit` parameters are
+used to calculate the aperture as shown in {numref}`f:apertures`A. For an `ELLIPTICAL` aperture,
+a particle with position {math}`(x, y)` is outside of the aperture if any
+one of the following four conditions is true:
+```{code} yaml
+1) x < 0 and y < 0 and (x/x_limit[1])^2 + (y/y_limit[1])^2 > 1
+2) x < 0 and y > 0 and (x/x_limit[1])^2 + (y/y_limit[2])^2 > 1
+3) x > 0 and y < 0 and (x/x_limit[2])^2 + (y/y_limit[1])^2 > 1
+4) x > 0 and y > 0 and (x/x_limit[2])^2 + (y/y_limit[2])^2 > 1
+```
+For a `RECTANGULAR` aperture the corresponding four conditions are:
+```{code} yaml
+1) x < x_limit[1]
+2) x > x_limit[2]
+3) y < y_limit[1]
+4) y > y_limit[2]
+```
+
+Default values for the limits are `-Inf` for `x_limit[1]` and `y_limit[1]` and
+`Inf` for `x_limit[2]` and `y_limit[2]`.
+
+The `misalignment_moves_aperture` parameter determines whether misaligning an element
+([](#s:alignment.g)) affects the placement of the aperture. The default is `false`.
+A common case where `misalignment_moves_aperture` would be `false` is when a beam pipe,
+which incorporates the aperture, is not physically touching the surrounding magnet element.
+When tracking a particle, assuming that there are only apertures at the element ends,
+the order of computation with `misalignment_moves_aperture` set to `false` is
+```{code} yaml
+1) Start at upstream end of element
+2) Check upstream aperture if there is one.
+3) Convert from branch coordinates to body coordinates.
+4) Track through the element body.
+5) Convert from body coordinates to branch coordinates.
+6) Check downstream aperture if there is one.
+7) End at downstream end of element.
+```
+With `misalignment_moves_aperture` set to `true`, the computation order is
+```{code} yaml
+1) Start at upstream end of element
+2) Convert from branch coordinates to body coordinates.
+3) Check upstream aperture if there is one.
+4) Track through the element body.
+5) Check downstream aperture if there is one.
+6) Convert from body coordinates to branch coordinates.
+7) End at downstream end of element.
+```
+
+The `CUSTOM_SHAPE` setting for `aperture_shape` indicates whether a User supplied function
+is used to calculate whether the particle has hit the aperture. The function is stored
+in the `custom_aperture` parameter. The `custom_aperture` parameter is a Dict that stores
+the aperture function along with any data that the aperture calculation needs. The aperture
+function must be stored in `custom_aperture[:function]` and this function will be
+called with the signature
+```{code} yaml
+custom_aperture[:function](position::Vector, ele::Ele) -> ParticleState
+```
+where `position` is the phase space 6-vector of the particle, `ele` is the element
+with the aperture, and a `ParticleState` ([](#s:particlestate)) value is returned.
+
+The `VERTEX` setting for `aperture_shape` is for defining an aperture using a
+set of vertex points as illustrated in {numref}`f:apetures`B. Between vertex points, the aperture
+can can follow a straight line or the arc of an ellipse. The vertex points are specified by
+setting the `section` parameter of `ApertureParams`. Example:
+```{code} yaml
+wall = Wall2D([Vertex1([1.0, 4.0]), Vertex1([-1.0, 4.0, 6.0]),
+Vertex1([-5.0, 1.0]), Vertex1([-5.0, -1.0]),
+Vertex1([1.0, -1.5)]], r0 = [-2.5, 0.5])
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:bmultipole.g)=
+## BMultipoleParams
+The `BMultipoleParams` group stores magnetic multipole strengths. Also see `EMultipoleParams`.
+The parameters of this group are:
+```{code} yaml
+vec::Vector{BMultipole1}
+```
+This group stores a vector of `BMultipole1` structs.
+The `BMultipole1` structure stores the values for a magnetic multipole of a given order.
+Only orders where there is a non-zero multipole are stored and there is no maximum limit to the
+order that can be stored. The multipoles will be stored in increasing order.
+
+The `BMultipole1` structure has components:
+```{code} yaml
+Kn::Number - Normal normalized component. EG: "Kn2", "Kn2L".
+Ks::Number - Skew multipole component. EG: "Ks2", "Ks2L".
+Bn::Number - Normal field component.
+Bs::Number - Skew field component.
+tilt::Number - Rotation of multipole around z-axis.
+order::Int - Multipole order.
+integrated::Union{Bool,Nothing} - Integrated multipoles or not?
+```
+The `order` component gives the multipole order.
+There is storage for both normalized (`Kn` and `Ks`) and unnormalized (`Bn` and `Bs`)
+field strengths. The letter "`n`" designates the normal component and "`s`" designates
+the skew component.
+The AcceleratorLattice bookkeeping code will take care of calculating the normalized field if the unnormalized
+field is set and vice versa. The reason why the structure has three components,
+normal, skew and tilt, that describe the field when only two would be sufficient is due convenience.
+Having normal and skew components is convenient when magnet has multiple windings that control
+both independently. A common case is combined horizontal and vertical steering magnets. On the
+other hand, being able to "misalign" the multipole using the `tilt` component is also
+useful.
+
+The dot selection operator for an element ([](#s:ele.access)) is overloaded so that
+magnetic multipole parameters for order {math}`J` can be accessed using the following notation:
+{tt
+Need custom handling!!!!
+Name & Stored In & Normalized & Integrated & Description midrule
+KnJ & Kn & Yes & No & Normal field.
+KsJ & Ks & Yes & No & Skew field.
+KnJL & Kn & Yes & Yes & Normal field.
+KsJL & Ks & Yes & Yes & Skew field.
+BnJ & Bn & No & No & Normal field.
+BsJ & Bs & No & No & Skew field.
+BnJL & Bn & No & Yes & Normal field.
+BsJL & Bs & No & Yes & Skew field.
+tiltJ & tilt & -- & -- & Field tilt.
+integratedJ & integrated & -- & -- & Integrated fields?
+bottomrule
+Substitute the multipole order for {math}`J` in the above table. For example, `Ks2L` is the
+normalized length-integrated skew field component of order 2.
+
+Notice that both integrated
+and non-integrated fields are potentially stored in the same component of `BMultipole1`.
+Which type is stored is determined by the `integrated` logical. If `true`, the integrated
+value is stored and vice versa. The `integrated` setting can be different for different orders.
+The setting of `integrated` for a given order is determined by whether the first field component
+to be set for that order is an integrated quantity or not. After the value of `integrated` is set,
+an error will be thrown if a something that has the opposite sense in terms of integration is
+set. For example:
+```{code} yaml
+@ele qq = Quadrupole(l = 0.6, Ks0L = 1.0) # 0th order multipole is integrated
+qq.Bn1 = 0.3 # 1st order multipole is not integrated
+qq.Ks1 = 0.5 # This is OK.
+println(qq.integrated0) # Will print "true"
+println(qq.Bn0) # Can use non-integrated component.
+qq.Bn0 = 0.7 # Cannot set non-integrated component! error thrown!
+toggle_integrated!(qq, MAGNETIC, 0) # toggle integrated setting for order 0.
+```
+In the above example, the 0th order multipole is initialized using `Ks0L` so that
+multipole will have the `integrated` component set to `true` and non-integrated values
+cannot be set. However, independent of the setting of `integrated`, both integrated and
+non-integrated quantities can always be used in an equation. To change the value of `integrated`,
+use the `toggle_integrated!` function. This function also translates the values stored in the
+field components of the structure so that the field will stay constant.
+
+The setting of `integrated` for a given multipole will also determine what stays constant
+of the length of the magnet changes. If `integrated` is `true`, the integrated values
+will be invariant and vice versa for `integrated` being `false`. Similarly, the setting
+of the `field_master` parmeter ([](#s:master.g)) will determine whether normalized or
+unnormalized quantities will stay constant if the reference energy is varied.
+
+%---------------------------------------------------------------------------------------------------
+(s:beam.beam.g)=
+## BeamBeamParams
+The parameters of this group are:
+```{code} yaml
+n_slice::Number - Number of slices the Strong beam is divided into.
+n_particle::Number - Number of particle in the strong beam.
+species::Species - Strong beam species. Default is weak particle species.
+z0_crossing::Number - Weak particle phase space z when strong beam center
+- passes the BeamBeam element.
+repetition_freq:: Number - Strong beam repetition rate.
+twiss::Twiss - Strong beam Twiss at IP.
+sig_x::Number - Strong beam horizontal sigma at IP.
+sig_y::Number - Strong beam vertical sigma at IP.
+sig_z::Number - Strong beam longitudinal sigma.
+bbi_constant::Number - BBI constant. Set by Bmad. See manual.
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:bend.g)=
+## BendParams
+The `BendParams` stores the parameters that characterize the shape of a `Bend` element
+[](#s:bend). The only relavent shape parameter that is not in the `BendParams` is the
+length `L` which is in the `LengthParams`.
+
+The parameters of this group are:
+```{code} yaml
+bend_type::BendType.T - Type of bend. Default: BendType.SECTOR.
+angle::Number - Reference bend angle.
+g::Number - Reference bend strength = 1/radius.
+bend_field_ref::Number - Reference bend field.
+L_chord::Number - Chord length.
+tilt_ref::Number - Reference tilt.
+e1::Number - Entrance end pole face rotation.
+e2::Number - Exit end pole face rotation.
+e1_rect::Number - Entrance end pole face rotation.
+e2_rect::Number - Exit end pole face rotation.
+edge_int1::Number - Entrance end fringe field integral.
+edge_int2::Number - Exit end fringe field integral
+exact_multipoles::ExactMultipoles.T - Default: ExactMultipoles.OFF
+```
+
+
+Associated output parameters:
+```{code} yaml
+rho::Number - Reference bend radius.
+L_sagitta::Number - Sagitta length.
+bend_field::Number - Actual dipole field in the plane of the bend.
+norm_bend_field::Number - Actual dipole strength in the plane of the bend.
+```
+
+{centering
+```{figure} figures/bend.svg
+caption[Bend geometry]{
+Bend geometry. Red dots are the entry and exit points that define the origin for the
+coordinate systems at the entry end {math}`(s_1, x_1)` and exit ends {math}`(s_2, x_2)` respectively.
+In the figure, the angle `alpha` is denoted {math}`alpha` and the radius
+`rho` is denoted {math}`rho`.
+A) Bend geometry with positive bend angle. For the geometry shown,
+`g`, `angle`, `rho`, `e1`, `e2`, `e1_rect`, and `e2_rect` are all positive.
+B) Bend geometry with negative bend angle. For the geometry shown,
+`g`, `angle`, `rho`, `e1`, `e2`, `e1_rect`, and `e2_rect` are all negative.
+Note: The figures are drawn for zero `ref_tilt` where the rotation axis is parallel to the
+{math}`y`-axis.
+}
+:name: f:bend
+}
+```
+
+In detail:
+%
+- **angle** Newline
+The total Reference bend angle. A positive `angle` represents a
+bend towards negative {math}`x` as shown in {numref}`f:bend`.
+%
+- **bend_field_ref** Newline
+The `bend_field_ref` parameter is the reference magnetic bending field which is the field
+that is needed for the reference particle to be bent in a circle of radius `rho`
+and the placement of lattice elements downstream from the bend. The actual ("total") field is
+a vector sum of
+`bend_field_ref` plus the value of the `Bn0` and `Bs0` multipoles. If `tilt0` and `Bs0`
+are zero, the actual field is
+```{code} yaml
+B-field (total) = bend_field_ref + Bn0
+```
+See the discussion of `g` and `Kn0` below for more details.
+%
+- **bend_field (output param), norm_bend_field (output_param)** Newline
+The actual dipole bend field ignoring any skew field component which is set by `Bs0`.
+The relation between this and `bend_field_ref` is
+```{code} yaml
+bend_field = bend_field_ref + Bn0 * cos(tilt0) + Bs0 * sin(tilt0)
+```
+%
+- **bend_type** Newline
+The `bend_type` parameter sets the "logical shape" of the bend.
+This parameter is of type `BendType.T` ([](#s:bendtype)) and can take values of
+```{code} yaml
+BendType.RECTANGULAR - or
+BendType.SECTOR - The default
+```
+The logical shape of a bend, in most situations, is irrelevant.
+The only case where the logical shape is used is when the bend angle is varied.
+In this case, for a `SECTOR` bend, the face angles `e1` and `e2` are
+held constant and `e1_rect` and `e2_rect` are varied to keep Eqs{eeaeea} satisfied.
+%
+- **e1, e2** Newline
+The values of `e1` and `e2` gives the rotation angle of the entrance and exit pole faces
+respectively with respect to the radial {math}`x_1` and {math}`x_2` axes as shown in {numref}`f:bend`.
+Zero `e1` and `e2` gives a wedge shaped magnet.
+Also see `e1_rect` and `e2_rect`. The relationship is
+begin{equation}
+parbox{30em} {
+e1 = e1_rect + angle/2
+e2 = e2_rect + angle/2
+label{eeaeea}
+end{equation}
+
+Note: The correspondence between `e1` and `e2` and the corresponding parameters used in the
+SAD program {footcite:p}`Zhou:SADmaps` is:
+```{code} yaml
+e1(AccelLattice) = e1(SAD) * angle + ae1(SAD)
+e2(AccelLattice) = e2(SAD) * angle + ae2(SAD)
+```
+%
+- **e1_rect, e2_rect**
+Face angle rotations like `e1` and `e2` except angles are measured with respect to
+fiducial lines that are parallel to each other and rotated by `angle`/2 from the radial
+{math}`x_1` and {math}`x_2` axes as shown in {numref}`f:sbend`.
+Zero `e1_rect` and `e2_rect` gives a rectangular magnet shape.
+%
+- **exact_multipoles** Newline
+The `exact_multipoles` switch can be set to one of:
+```{code} yaml
+off ! Default
+vertically_pure
+horizontally_pure
+```
+This switch determines if the multipole fields, both magnetic and electric, and including the
+`k1` and `k2` components, are corrected for the finite curvature of the reference orbit in a
+bend. See [](#s:field.exact) for a discussion of what `vertically` pure versus
+`horizontally` pure means. Setting `exact_multipoles` to `vertically_pure` means that the
+individual {math}`a_n` and {math}`b_n` multipole components are used with the vertically pure solutions
+begin{equation}
+bfB = sum_{n = 0}^infty left[ frac{a_n}{n+1} nabla phi_n^r + frac{b_n}{n+1} nabla phi_n^i right], qquad
+bfE = sum_{n = 0}^infty left[ frac{a_{en}}{n+1} nabla phi_n^i + frac{b_{en}}{n+1} nabla phi_n^r right]
+end{equation}
+and if `exact_multipoles` is set to `horizontally_pure` the horizontally pure solutions
+{math}`psi_n^r` and {math}`psi_n^i` are used instead of the vertically pure solutions {math}`phi_n^r` and
+{math}`phi_n^i`.
+%
+- **edge_int1, edge_int2** Newline
+The field integral for the entrance pole face `edge_int1` is given by
+begin{equation}
+text{edge}_1 = int_{pole} ! ! ds , frac{B_y(s) , (B_{y0} - B_y(s))}
+{2 , B_{y0}^2}
+label{fsbbb}
+end{equation}
+For the exit pole face there is a similar equation for `edge_int2`
+
+Note: In Bmad and MAD, these integrals are represented by the product of `fint` and `hgap`.
+
+Note: The SAD program uses `fb1+f1` for the entrance fringe and `fb2+f1` for the exit
+fringe. The correspondence between the two is
+begin{example2}
+edge_int1 = (fb1 + f1) / 12
+edge_int2 = (fb2 + f1) / 12
+end{example2}
+
+`edge_int1` and `edge_int2` can be related to the Enge function which is sometimes used to model the
+fringe field. The Enge function is of the form
+begin{equation}
+B_y(s) = frac{B_{y0}}{1 + exp[P(s)]}
+end{equation}
+where
+begin{equation}
+P(s) = C_0 + C_1 , s + C_2 , s^2 + C_3 , s^3 + , ldots
+end{equation}
+The {math}`C_0` term simply shifts where the edge of the bend is. If all the {math}`C_n` are zero except for
+{math}`C_0` and {math}`C_1` then
+begin{equation}
+C_1 = frac{1}{2 , text{field_int}}
+end{equation}
+%
+- **g, rho (output param)** Newline
+The Reference bending radius which determines the reference coordinate system is `rho` (see
+[](#s:ref)). `g` = `1/rho` is the "bend strength" and is proportional to the Reference
+dipole magnetic field. `g` is related to the reference magnetic field `bend_field_ref` via
+begin{equation}
+text{g} = frac{q}{p_0} , text{bend_field_ref}
+label{gqpb}
+end{equation}
+where {math}`q` is the charge of the reference particle and {math}`p_0` is the reference momentum. It is
+important to keep in mind that changing `g` will change the Reference orbit ([](#s:coords.3)) and
+hence will move all downstream lattice elements in space.
+
+The total bend strength felt by a particle is the vector sum of `g` plus the zeroth order
+magnetic multipole. If the multipole `tilt0` and `Ks0` is zero, the total bend strength is
+```{code} yaml
+norm_bend_field = g + Kn0
+```
+Changing the multipole strength `Kn0` or `Ks0` leaves the Reference orbit and the positions of
+all downstream lattice elements
+unchanged but will vary a particle's orbit. One common mistake when designing lattices is to vary
+`g` and not `Kn0` which results in downstream elements moving around. See Sref{s:ex.chicane}
+for an example.
+
+Note: A positive `g`, which will bend particles and the reference orbit in the {math}`-x` direction
+represents a field of opposite sign as the field due a positive `hkick`.
+%
+- **h1, h2** Newline
+The attributes `h1` and `h2` are the curvature of the entrance and exit pole faces.
+%
+- **L, L_arc, L_chord, L_sagitta (output param)** Newline
+The `L` parameter, which is in the `LengthParams` and not the `BendParams`,
+is the arc length of the reference trajectory through the bend.
+
+`L_chord` is the chord length from entrance point to exit point.
+The `L_sagitta` parameter is the sagitta length (The sagitta is the distance
+from the midpoint of the arc to the midpoint of the chord). `L_sagitta` can be negative and will have
+the same sign as the `g` parameter.
+%
+- **L_rectangle** Newline
+The `L_rectangle` parameter is the "rectangular" length defined to be the distance between the
+entrance and exit points. The coordinate system used for the calculation is defined by the setting
+of `fiducial_pt`. {numref}`f:rbend` shows `l_rectangle` for `fiducial_pt` set to
+`entrance_end` (the coordinate system corresponds to the entrance coordinate system of the bend).
+In this case, and in the case where `fiducial_pt` is set to `exit_end`, the rectangular
+length will be {math}`rho sinalpha`. If `fiducial_pt` is set to `none` or `center`,
+`l_rectangle` is the same as the chord length.
+%
+- **ref_tilt** Newline
+The `ref_tilt` attribute rotates a bend about the longitudinal axis at the entrance face of the
+bend. A bend with `ref_tilt` of {math}`pi/2` and positive `g` bends the element in the {math}`-y`
+direction ("downward"). See {numref}`f:tilt.bend`. It is important to understand that `ref_tilt`,
+unlike the `tilt` attribute of other elements, bends both the reference orbit along with the
+physical element. Note that the MAD `tilt` attribute for bends is equivalent to the Bmad
+`ref_tilt`. Bends in Bmad do not have a `tilt` attribute.
+
+Important! Do not use `ref_tilt` when doing misalignment studies for a machine. Trying to misalign
+a dipole by setting `ref_tilt` will affect the positions of all downstream elements! Rather, use the
+`tilt` parameter.
+
+%---------------
+
+The attributes `g`, `angle`, and `L` are mutually dependent. If any two are specified for
+an element AcceleratorLattice will calculate the appropriate value for the third.
+
+In the local coordinate system ([](#s:ref)), looking from "above" (bend viewed from positive
+{math}`y`), and with `ref_tilt` = 0, a positive `angle` represents a particle rotating clockwise. In
+this case. `g` will also be positive. For counterclockwise rotation, both `angle` and `g`
+will be negative but the length `l` is always positive. Also, looking from above, a positive
+`e1` represents a clockwise rotation of the entrance face and a positive `e2` represents a
+counterclockwise rotation of the exit face. This is true irregardless of the sign of `angle` and
+`g`. Also it is always the case that the pole faces will be parallel when
+```{code} yaml
+e1 + e2 = angle
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:descrip.g)=
+## DescriptionParams
+The components of this group are element descriptive strings:
+```{code} yaml
+type::String
+ID::String
+class::String
+```
+For example
+```{code} yaml
+@ele q1 = Quadrupole(type = "rotating quad", ...)
+```
+
+These strings can be used to in element searching:
+```{code} yaml
+eles(lat, "type = "*rot*") # Can use these strings in searching
+```
+In this example `lat` is the lattice that contains `q1` and the `eles` function
+will return a vector of all elements whose `type` string has the substring "`rot`"
+in it.
+
+%---------------------------------------------------------------------------------------------------
+(s:dreference.g)=
+## DownstreamReferenceParams
+The components of this group are:
+```{code} yaml
+species_ref_downstream::Species - Reference species.
+pc_ref_downstream::Number - Reference momentum*c.
+E_tot_ref_downstream::Number - Reference total energy.
+```
+
+Associated output parameters are:
+```{code} yaml
+β_ref_downstream::Number - Reference v/c.
+γ_ref_downstream::Number - Reference relativistic gamma factor.
+```
+
+This group holds the reference energy and species at the downstream end of an element.
+Also see the `ReferenceParams` ([](#s:reference.g)) documentation.
+This group and `ReferenceParams` group are always paired.
+That is, these two are always both present or both not present in any given element.
+
+For most elements, the values of the parameters in `DownstreamReferenceParams` will
+be the same as the values in the corresponding `ReferenceParams` parameters.
+That is, the value of `species_ref_downstream` in `DownstreamReferenceParams` will be the same
+as the value of `species_ref` in `ReferenceParams`, the value of `pc_ref_downstream`
+will be the same as `pc_ref`, etc. Elements where the reference energy (here "energy" refers
+to either pc_ref, E_tot_ref, β, or γ) differs between upstream and downstream
+include `LCavity` and `Patch` elements.
+Elements where the reference energy and species differ between upstream and downstream include
+`Foil` and `Converter` elements.
+
+Parameters of the `DownstreamReferenceParams` are not user settable and are
+calculated by the AcceleratorLattice bookkeeping routines. See the `ReferenceParams` documentation
+for how these parameters are calculated.
+
+%---------------------------------------------------------------------------------------------------
+(s:emultipole.g)=
+## EMultipoleParams
+The `EMultipoleParams` group stores electric multipole strengths. Also see `BMultipoleParams`.
+The parameters of this group are:
+```{code} yaml
+vec::Vector{EMultipole1}
+```
+This group stores a vector of `EMultipole1` structs.
+The `EMultipole1` structure stores the values for a electric multipole of a given order.
+Only orders where there is a non-zero multipole are stored and there is no maximum limit to the
+order that can be stored. The multipoles will be stored in increasing order.
+
+The `EMultipole1` structure has components:
+```{code} yaml
+En::Number - Normal field component.
+Es::Number - Skew field component.
+Etilt::Number - Rotation of multipole around z-axis.
+order::Int - Multipole order.
+Eintegrated::Union{Bool,Nothing} - Integrated multipoles or not?
+```
+The `order` component gives the multipole order.
+There is storage for unnormalized (`En` and `Es`) field strengths however, unlike magnetic
+multipoles, there are no components for normalized field strengths.
+The letter "`n`" designates the normal component and "`s`" designates the skew component.
+There is also a `Etilt` component which will tilt the entire multipole [](#???).
+The reason why the structure has three components,
+normal, skew and tilt, that describe the field when only two would be sufficient is due convenience.
+Having normal and skew components is convenient when magnet has multiple windings that control
+both independently.
+
+The dot selection operator for an element ([](#s:ele.access)) is overloaded so that
+electric multipole parameters for order {math}`J` can be accessed using the following notation:
+{tt
+Need custom handling!!!!
+Name & Stored In & Integrated & Description midrule
+EnJ & En & No & Normal field.
+EsJ & Es & No & Skew field.
+EnJL & En & Yes & Normal field.
+EsJL & Es & Yes & Skew field.
+EtiltJ & Etilt & -- & Field tilt.
+EintegratedJ & Eintegrated & -- & Integrated fields?
+bottomrule
+Substitute the multipole order for {math}`J` in the above table. For example, `Es2L` is the
+normalized length-integrated skew field component of order 2.
+
+Notice that both integrated
+and non-integrated fields are potentially stored in the same component of `EMultipole1`.
+Which type is stored is determined by the `Eintegrated` logical. If `true`, the integrated
+value is stored and vice versa. The `Eintegrated` setting can be different for different orders.
+The setting of `Eintegrated` for a given order is determined by whether the first field component
+to be set for that order is an integrated quantity or not. After the value of `Eintegrated` is set,
+an error will be thrown if a something that has the opposite sense in terms of integration is
+set. For example:
+```{code} yaml
+@ele qq = Quadrupole(l = 0.6, Es0L = 1.0) # 0th order is integrated
+qq.En1 = 0.3 # 1st order multipole is not integrated
+qq.Es1 = 0.5 # This is OK.
+println(qq.Eintegrated0) # Will print "true"
+println(qq.En0) # Can use non-integrated component.
+toggle_integrated!(qq, ELECTRIC, 0) # change integrated setting for order 0.
+```
+In the above example, the 0th order multipole is initialized using `Es0L` so that
+multipole will have the `Eintegrated` component set to `true` and non-integrated values
+cannot be set. However, independent of the setting of `Eintegrated`, both integrated and
+non-integrated quantities can always be used in an equation. To change the value of `Eintegrated`,
+use the `toggle_integrated!` function. This function also translates the values stored in the
+field components of the structure so that the field will stay constant.
+
+The setting of `Eintegrated` for a given multipole will also determine what stays constant
+of the length of the magnet changes. If `Eintegrated` is `true`, the integrated values
+will be invariant with length changes and vice versa if `integrated` is `false`.
+Similarly, the setting of the `field_master` parmeter ([](#s:master.g)) will determine
+whether normalized or unnormalized quantities will stay constant if the reference energy is varied.
+
+%---------------------------------------------------------------------------------------------------
+(s:fork.g)=
+## ForkParams
+The components of this group are:
+```{code} yaml
+to_line::Union{BeamLine,Branch} - Beam line to fork to
+to_ele::Union{String,Ele} - Element forked to.
+direction::Int - Longitudinal Direction of injected beam.
+propagate_reference::Bool - Propagate reference species and energy?
+```
+
+This group is used with a `Fork` element and specifies how the fork element attaches to
+another branch.
+
+Propagate will be done initially, even with `propagate_reference` set to false, if the
+reference species or reference energy is not set in beginning element of the forked to branch.
+
+%---------------------------------------------------------------------------------------------------
+(s:girder.g)=
+## GirderParams
+The components of this group are:
+```{code} yaml
+supported::Vector{Ele} - Elements supported by girder.
+```
+
+
+%---------------------------------------------------------------------------------------------------
+(s:init.particle.g)=
+## InitParticleParams
+The components of this group are:
+```{code} yaml
+orbit::Vector{Number} - Phase space 6-vector.
+spin::Vector{Number} - Spin 3-vector. ```
+
+%---------------------------------------------------------------------------------------------------
+(s:length.g)=
+## LengthParams
+The components of this group are:
+```{code} yaml
+L::Number - Length of element.
+s::Number - Starting s-position.
+s_downstream::Number - Ending s-position.
+orientation::Int - Longitudinal orientation. +1 or -1.
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:lord.slave.g)=
+## LordSlaveStatusParamslabel{s:lord.enum}
+label{s:slave.enum}
+
+The components of this group are:
+```{code} yaml
+lord_status::Lord.T - Lord status.
+slave_status::Slave.T - Slave status.
+```
+
+The possible values of `lord_status` are:
+- Lord.NOT - Not a lord
+- Lord.SUPER - Is a Super lord (
+- Lord.MULTIPASS - Is a Multipass lord (
+
+The possible values of `lord_status` are:
+- Slave.NOT - Not a slave
+- Slave.SUPER - Is a Super slave (
+- Slave.MULTIPASS - Multipass slave (
+
+All elements in a tracking branch have this element group even if the type of element (For example,
+`Drift` elements) is such that the element will never be a lord or a slave.
+
+Notice that elements that are supported by a `Girder` are not marked as slaves to the `Girder`
+although the supported elements will have a pointer to the supporting girder.
+
+This group is used in lattice element lord/slave bookkeeping ([](#c:lord.slave.book)). See this
+section for more details.
+
+%---------------------------------------------------------------------------------------------------
+(s:master.g)=
+## MasterParams
+The components of this group are:
+```{code} yaml
+is_on::Bool = true
+field_master::Bool = false # Does field or normalized field stay constant with energy changes?
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:orientation.g)=
+## FloorParams
+The `FloorParams` stores the nominal (calculated without alignment shifts)
+position and angular orientation in the floor coordinates of the upstream end of the element.
+system. The components of this group are:
+```{code} yaml
+r::Vector - [x,y,z] position. Accessed using `r_floor`
+q::Quaternion - Quaternion orientation. Accessed using `q_floor`.
+```
+
+
+
+
+%---------------------------------------------------------------------------------------------------
+(s:origin.ele.g)=
+## OriginEleParams
+The components of this group are:
+```{code} yaml
+origin_ele::Ele - Origin reference element. Default is NULL_ELE.
+origin_ele_ref_pt::Loc.T - Origin reference point. Default is Loc.CENTER.
+```
+
+The `OriginEleParams` is used with `Fiducial`, `FloorShift`, and `Girder` elements.
+The `OriginEleParams` is used to set the coordinate reference frame from which
+the orientation set by the `BodyShiftParams` is measured. To specify that the floor coordinates are
+to be used, set the `origin_ele` to `NULL_ELE`. Typically this is the same as using the
+beginning element of the first branch of a lattice as long as the first element does not have
+any orientation shifts.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:patch.g)=
+## PatchParams
+```{figure} figures/patch.svg
+caption[Patch Element.]
+{A) A `patch` element can align its exit face arbitrarily with respect to its entrance face. The
+red arrow illustrates a possible particle trajectory form entrance face to exit face. B) The
+reference length of a `patch` element, if `ref_coords` is set to the default value of
+`exit_end`, is the longitudinal distance from the entrance origin to the exit origin using the
+reference coordinates at the exit end as shown. If `ref_coords` is set to `entrance_end`, the
+length of the patch will be equal to the `z_offset`.}
+:name: f:patch
+```
+
+The components of this group are:
+```{code} yaml
+t_offset::Number - Time offset.
+E_tot_offset::Number - Total energy offset. Default is NaN (not used).
+E_tot_exit::Number - Fix total energy at exit end. Default is NaN (not used).
+pc_exit::Number - Reference momentum*c at exit end. Default is NaN (not used).
+flexible::Bool - Flexible patch? Default is false.
+L_user::Number - User set Length? Default is NaN (length calculated by bookkeeping code).
+ref_coords::BodyLoc.T - Reference coordinate system used inside the patch. Default is BodyLoc.EXIT_END.
+```
+
+A straight line element like a `drift` or a `quadrupole` has the exit face parallel to the
+entrance face. With a `patch` element, the entrance and exit faces can be arbitrarily oriented
+with respect to one another as shown in {numref}`f:patch`A.
+
+index{rigid patch}index{inflexible patch}
+index{flexible patch}
+There are two different ways the orientation of the exit face is determined. Which way is used is
+determined by the setting of the `flexible` attribute. With the `flexible` attribute set to
+`False`, the default, The exit face of the `patch` will be determined from the offset, tilt
+and pitch attributes as described in [](#s:patch.coords). This type of `patch` is called
+"rigid" or "inflexible" since the geometry of the `patch` is solely determined by the
+`patch`'s attributes as set in the lattice file and is independent of everything else. Example:
+```{code} yaml
+pt: patch, z_offset = 3.2 ! Equivalent to a drift
+```
+
+With `flexible` set to `True`, the exit face is taken to be the reference frame of the
+entrance face of the next element in the lattice. In this case, it must be possible to compute the
+reference coordinates of the next element before the reference coordinates of the `patch` are
+computed. A `flexible` `patch` will have its offsets, pitches, and tilt as dependent
+parameters ([](#s:depend)) and these parameters will be computed appropriately. Here the
+`patch` is called "flexible" since the geometry of the patch will depend upon the geometry of
+the rest of the lattice and, therefore, if the geometry of the rest of the lattice is modified (is
+"flexed"), the geometry of the `patch` will vary as well. See Section~[](#s:ex.erl) for an
+example.
+
+The coordinates of the lattice element downstream of a `flexible` `patch` can be computed
+if there is a `fiducial` element ([](#s:fiducial)) somewhere downstream or if there is a
+`multipass_slave` ([](#c:multipass)) element which is just downstream of the `patch` or at
+most separated by zero length elements from the `patch`. In this latter case, the
+`multipass_slave` must represent an {math}`N`Th pass slave with {math}`N` greater than 1. This works since
+the first pass slave will be upstream of the `patch` and so the first pass slave will have its
+coordinates already computed and the position of the downstream slave will be taken to be the same
+as the first pass slave. Notice that, without the `patch`, the position of multipass slave
+elements are independent of each other.
+
+With `bmad_standard` tracking ([](#s:tkm)) A particle, starting at the upstream face of the
+`patch`, is propagated in a straight line to the downstream face and the suitable coordinate
+transformation is made to translate the particle's coordinates from the upstream coordinate frame to
+the downstream coordinate frame ([](#s:patch.std)). In this case the `patch` element can be
+thought of as a generalized `drift` element.
+
+If there are magnetic or electric fields within the `patch`, the tracking method through the
+`patch` must be set to either `runge_kutta` or `custom`. Example:
+```{code} yaml
+pa2: patch, tracking_method = runge_kutta, field_calc = custom,
+mat6_calc_method = tracking, ...
+```
+In order to supply a custom field when `runge_kutta` tracking is used, `field_calc`
+([](#s:integ)) needs to be set to `custom`. In this case, custom code must be supplied for
+calculating the fields as a function of position ([](#s:custom.ele)).
+
+The `E_tot_offset` attribute offsets the
+reference energy:
+```{code} yaml
+E_tot_ref(exit) = E_tot_ref(entrance) + E_tot_offset (eV)
+```
+Setting the `E_tot_offset` attribute will affect a particle's {math}`p_x`, {math}`p_y` and {math}`p_z` coordinates
+via Eqs{ppp} and eq{ppppp}. Notice that `E_tot_offset` does not affect a particle's actual
+energy, it just affects the difference between the particle energy and the reference energy.
+
+Alternatively, to set the reference energy, the `E_tot_set` or `p0c_set` attributes can be
+used to set the reference energy/momentum at the exit end. It is is an error if more than one of
+`E_tot_offset`, `E_tot_set` and `p0c_set` is nonzero.
+
+`Important`: Bmad may apply the energy transformation either before or after the coordinate
+transformation. This matters when the speed of the reference particle is less than {math}`c`. For this
+reason, and due to complications involving PTC, it is recommended to use two patches in a row when
+both the orbit and energy are to be patched.
+
+A `patch` element can have an associated electric or magnetic field ([](#s:fieldmap)). This can
+happen, for example, if a patch is used at the end of an injection line to match the reference
+coordinates of the injection line to the line being injected into ([](#s:ex.inj)) and the patch
+element is within the field generated by an element in the line being injected into. In such a case,
+it can be convenient to set what the reference coordinates are since the orientation of any fields
+that are defined for a patch element will be oriented with respect to the patch element's reference
+coordinates. For this, the `ref_coords`
+parameter of a patch can be used. Possible settings are:
+`ref_coords` are:
+```{code} yaml
+entrance_end !
+exit_end ! Default
+```
+The default setting of `ref_coords` is `exit_end` and with this the reference coordinates are
+set by the exit end coordinate system (see {numref}`f:patch`). If `ref_coords` is set to
+`entrance_end`, the reference coordinates are set by the entrance end coordinate system. Example:
+```{code} yaml
+p1: patch, x_offset = 1, x_pitch = 0.4 ! L = 0.289418 see below
+p2: p1, ref_coords = entrance_end ! L = 0
+```
+Here `p1` has `ref_coords` set to `exit_end` (the default). `p2` inherits the parameters
+of `p1` and sets `ref_coords` to `entrance_end`.
+
+It is important to keep in mind that if there are multiple patches in a row, while two different
+configurations may be the same in a geometrical sense the total length may not be the same. For
+example:
+```{code} yaml
+pA: patch, x_offset = 1 ! L = 0
+pB: patch, x_pitch = 0.4 ! L = 0
+sum: line = (pA, pB)
+```
+The configuration of `pA` followed by `pB` is equivalent geometrically to the `p1` patch
+above but the total length of the `(pA, pB)` line is zero which is different from the length of
+`p1`.
+
+Unfortunately, there is no intuitive way to define the "`length`" `L` of a patch. This is
+important since the transit time of the reference particle is the element length divided by the
+reference velocity. And the reference transit time will affect how the phase space {math}`z` coordinate
+changes through the patch via Eq{zbctt}. If the parameter `user_sets_length` is set to True, the
+value of `l` set in the lattice file will be used (default is zero). `user_sets_length` is set
+to False (the default), the length of a patch is calculated depending upon the setting of
+`ref_coords`. If `ref_coords` is set to `exit_end`, the length of the patch is calculated
+as the perpendicular distance between the origin of the patch's entrance coordinate system and the
+exit face of the patch as shown in {numref}`f:patch`B. If `ref_coords` is set to `entrance_end`,
+the length is calculated as the perpendicular distance between the entrance face and the origin of
+the exit coordinate system. In this case, the length will be equal to `z_offset`.
+
+To provide flexibility, the `t_offset` attribute can be
+used to offset the reference time. The reference time at the exit end of the patch
+`t_ref(exit)` is related to the reference time at the beginning of the patch `t_ref(entrance)`
+via
+```{code} yaml
+t_ref(exit) = t_ref(entrance) + t_offset + dt_travel_ref
+```
+where `dt_travel_ref` is the time for the reference particle to travel through the patch.
+`dt_travel_ref` is defined to be:
+```{code} yaml
+dt_travel_ref = L / beta_ref
+```
+Where `L` is the length of the `patch` and `beta_ref` is the reference velocity/c at the
+exit end of the element. That is, the reference energy offset is applied {em before} the reference
+particle is tracked through the patch. Since this point can be confusing, it is recommended that a
+`patch` element be split into two consecutive patches if the `patch` has finite `l` and
+`E_tot_offset` values.
+
+While a finite `t_offset` will affect the reference time at the end of a patch, a finite
+`t_offset` will {em not} affect the time that is calculated for a particle to reach the end of
+the patch. On the other hand, a finite `t_offset` will affect a particle's {math}`z` coordinate via
+Eqs{zbctt}. The change in {math}`z`, {math}`delta z` will be
+begin{equation}
+delta z = beta cdot c cdot text{t_offset}
+end{equation}
+where {math}`beta` is the normalized particle speed (which is independent of any energy patch). Another
+way of looking at this is to note that In a drift, if the particle is on-axis and on-energy, t and
+t_ref change but z does not change. In a time patch (a patch with only `t_offset` finite), t_ref
+and z change but t does not.
+
+When a lattice branch contains both normally oriented and reversed elements
+([](#s:ref.construct)), a `patch`, or series of `patches`, which reflects the {math}`z` direction
+must be placed in between. Such a `patch`, (or patches) is called a `reflection` `patch`.
+See Section~[](#s:reflect.patch) for more details on how a reflection patch is defined. In order
+to avoid some confusing conceptual problems involving the coordinate system through a reflection
+patch, Runge-Kutta type tracking is prohibited with a reflection patch.footnote
+{
+In general, Runge-Kutta type tracking through a patch is a waste of time unless electric or magnetic
+fields are present.
+
+index{wall}
+Since the geometry of a `patch` element is complicated, interpolation of the chamber wall in the
+region of a patch follows special rules. See section~[](#s:wall.vacuum) for more details.
+
+
+
+%---------------------------------------------------------------------------------------------------
+(s:rf.g)=
+## RFParams
+The components of this group are:
+```{code} yaml
+frequency::Number - RF frequency.
+harmon::Number - RF frequency harmonic number.
+voltage::Number - RF voltage.
+gradient::Number - RF gradient.
+phase::Number - RF phase.
+multipass_phase::Number - RF Phase added to multipass elements.
+cavity_type::Cavity.T - Cavity type. Default is Cavity.STANDING_WAVE.
+n_cell::Int - Number of cavity cells. Default is 1.
+```
+
+
+Whether `voltage` or `gradient` is kept constant with length changes is determined by
+the setting of `field_master` ([](#s:master.g)). If `field_master` is `true`, the
+`gradient` is kept constant and vice versa.
+
+%---------------------------------------------------------------------------------------------------
+(s:rfauto.g)=
+## RFAutoParams
+The components of this group are:
+```{code} yaml
+do_auto_amp::Bool - Will autoscaling set auto_amp? Default is true.
+do_auto_phase::Bool - Will autoscaling set auto_phase? Default is true.
+auto_amp::Number - Auto RF field amplitude scale value.
+auto_phase::Number - Auto RF phase value.
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:reference.g)=
+## ReferenceParams
+The components of this group are:
+```{code} yaml
+species_ref::Species - Reference species entering end.
+pc_ref::Number - Reference momentum*c upstream end.
+E_tot_ref::Number - Reference total energy upstream end.
+time_ref::Number - Reference time upstream end.
+time_ref_downstream::Number - Reference time downstream end.
+extra_dtime_ref::Number - User set reference time change.
+dE_ref::Number - Sets change in reference energy.
+```
+
+Associated output parameters are:
+```{code} yaml
+β_ref::Number - Reference v/c upstream end.
+γ_ref::Number - Reference relativistic gamma factor.
+```
+
+This group holds the reference energy, species, and time parameters at the upstream
+end of a lattice element.
+Also see the `DownstreamReferenceParams` group documentation ([](#s:dreference.g)).
+The `DownstreamReferenceParams` group holds the reference energy and species
+at the downstream end of the element.
+This group and `DownstreamReferenceParams` group are always paired.
+That is, these two are always both present or both not present in any given element.
+
+For a `Beginning` element, parameters of this group are user settable except for the
+`dvoltage_ref` parameter. For all other element types, except for `dvoltage_ref` and
+`extra_dtime_ref`, the parameters of this
+group are calculated by the AcceleratorLattice bookkeeping routines and are not user settable.
+
+For most elements, the values of the parameters in `DownstreamReferenceParams` will
+be the same as the values in the corresponding `ReferenceParams` parameters.
+That is, the value of `species_ref_downstream` in `DownstreamReferenceParams` will be the same
+as the value of `species_ref` in `ReferenceParams`, the value of `pc_ref_downstream`
+will be the same as `pc_ref`, etc. Elements where the reference energy (here "energy" refers
+to either pc_ref, E_tot_ref, β, or γ) differs between upstream and downstream are elements with
+a non-zero `dvoltage_ref` and include `LCavity` and `Patch` elements.
+Elements where the reference energy and species differ between upstream and downstream include
+`Foil` and `Converter` elements.
+
+For elements where `dvoltage_ref` is nonzero the downstream reference energy
+`E_tot_ref_downstream` is calculated from the upstream `E_tot_ref` via the equation
+```{code} yaml
+E_tot_ref_downstream = E_tot_ref + dvoltage_ref * |Q_ref|
+```
+where `|Q_ref|` is the magnitude of the charge of the reference particle in units of the
+fundamental charge. Once `E_tot_ref_downstream` has been calculated, the downstream values
+of pc, β, and γ are calculated using the standard formulas. Notice that `dvoltage_ref` is
+completely independent from the actual voltage seen by a particle which is set by the `voltage`
+parameter of the `RFParams`.
+
+The downstream reference time `time_ref_downstream` is calculated via
+```{code} yaml
+time_ref_downstream = time_ref + transit_time + extra_dtime_ref
+```
+where `transit_time` is the time to transit the element assuming a straight line trajectory
+and a linear energy change throughout the element. . The general formula
+for the transit time is
+```{code} yaml
+transit_time = L * (E_tot_ref + E_tot_ref_downstream) / (c * (pc_ref + pc_ref_downstream))
+```
+where `L` is the length of the element and `c` is the speed of light.
+For elements where there is no energy
+change (`dvoltage_ref` = 0), the transit time calculation simplifies to
+```{code} yaml
+transit_time = L / (β_ref * c)
+```
+
+The `extra_dtime_ref` parameter in the above is ment as a correction to take into account
+for particle motion that is not straight or acceleration that is not linear in energy. For example,
+in a wiggler, `extra_dtime_ref` can be used to correct for the oscillatory nature of the
+particle trajectories.
+Since AcceleratorLattice does not do tracking (see the discussion in [](#c:design)), `extra_dtime_ref`
+must be calculated by the User.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:solenoid.g)=
+## SolenoidParams
+The components of this group are:
+```{code} yaml
+Ksol::Number - Normalized solenoid strength.
+Bsol::Number - Solenoid field.
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:tracking.g)=
+## TrackingParams
+The components of this group are:
+```{code} yaml
+num_steps::Int - Number of steps.
+ds_step::Number - Step length.
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:twiss.g)=
+## TwissParams
+In development
+
+The components of this group are:
+```{code} yaml
+
+aaa
+```
+
+
+```{footbibliography}
+```
diff --git a/docs/src/ele-types.md b/docs/src/ele-types.md
new file mode 100644
index 0000000..30995e2
--- /dev/null
+++ b/docs/src/ele-types.md
@@ -0,0 +1,749 @@
+(c:ele.types)=
+# Lattice Element Types
+%---------------------------------------------------------------------------------------------------
+
+This chapter discusses the various types of elements
+available in AcceleratorLattice.
+These elements are:
+```{csv-table}
+
+:align: center
+:header: "Element", "Element"
+
+[ACKicker](#s:ackicker), [Marker](#s:marker)
+[BeamBeam](#s:beambeam), [Mask](#s:mask)
+[BeginningEle](#s:begin.ele), [Match](#s:match)
+[Bend](#s:bend), [Multipole](#s:mult)
+[Converter](#s:converter), [NullEle](#s:nullele)
+[Collimator](#s:collimator), [Octupole](#s:octupole)
+[CrabCavity](#s:crabcavity), [Patch](#s:patch)
+[Drift](#s:drift), [Quadrupole](#s:quadrupole)
+[EGun](#s:egun), [RFCavity](#s:rfcavity)
+[Fiducial](#s:fiducial), [Sextupole](#s:sextupole)
+[FloorShift](#s:floorshift), [Solenoid](#s:solenoid)
+[Foil](#s:foil), [Taylor](#s:taylor)
+[Fork](#s:fork), [ThickMultipole](#s:thickmult)
+[Girder](#s:girder), [Undulator](#s:undulator)
+[Instrument](#s:instrument), [UnionEle](#s:unionele)
+[Kicker](#s:kicker), [Wiggler](#s:wiggler)
+[LCavity](#s:lcavity), [](#)
+```
+
+
+%---------------------------------------------------------------------------------------------------
+(s:ackicker)=
+## ACKicker
+An `ac_kicker` element simulates a "slow" time dependent kicker element.
+
+NOTE: This Element is in development and is incomplete.
+Missing: Need to document amp_function function to return the kick amplitude.
+
+Element parameter groups associated with this element type are:
+- [**BodyShiftParams**](#s:align.g): Element position/orientation shift.
+- [**ApertureParams**](#s:aperture.g): Vacuum chamber aperture.
+- [**BMultipoleParams**](#s:bmultipole.g): Magnetic multipoles.
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**MasterParams**](#s:master.g): Contains field_master parameter.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+
+The calculated field will only obey Maxwell's equations in the limit that the time variation
+of the field is "slow":
+\begin{equation}
+\omega \ll \frac{c}{r}
+\end{equation}
+where {math}`\omega` is the characteristic frequency of the field variation, {math}`c`
+and {math}`r`
+ends of the element must be able to "communicate" (which happens at the speed of light) in a time
+scale short compared to the time scale of the change in the field.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:beambeam)=
+## BeamBeam
+A `beambeam` element simulates an interaction with an opposing
+("strong") beam traveling in the opposite direction.
+
+NOTE: This Element is in development and is incomplete
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+
+
+%---------------------------------------------------------------------------------------------------
+(s:begin.ele)=
+## BeginningEle
+A `BeginningEle` element must be present as the first element of every tracking branch.
+([](#s:branch.def)).
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**InitParticleParams**](#s:init.particle.g): Initial particle position and spin.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**TwissParams**](#s:twiss.g): Initial Twiss and coupling parameters.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+
+Example:
+```{code} yaml
+@ele bg = BeginningEle(species_ref = Species("proton"), pc_ref = 1e11)
+```
+
+
+%---------------------------------------------------------------------------------------------------
+(s:bend)=
+## Bend
+A `Bend` element represents a dipole bend. Bends have a design bend angle and bend radius
+which determines the location of downstream elements as documented in [](#s:branch.coords).
+The actual bending strength that a particle feels can differ from the design value as detailed
+below.
+
+Element parameter groups associated with this element type are:
+- [**BodyShiftParams**](#s:align.g): Element position/orientation shift.
+- [**ApertureParams**](#s:aperture.g): Vacuum chamber aperture.
+- [**BMultipoleParams**](#s:bmultipole.g): Magnetic multipoles.
+- [**BendParams**](#s:bend.g): Bend element parameters.
+- [**EMultipoleParams**](#s:emultipole.g): Electric multipoles.
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**MasterParams**](#s:master.g): Contains field_master parameter.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+
+```{figure} figures/bend.svg
+\caption[Bend geometry]{
+Bend geometry. Red dots are the entry and exit points that define the origin for the
+coordinate systems at the entry end {math}`(s_1, x_1)` and exit ends {math}`(s_2, x_2)`
+In the figure, the angle `alpha` is denoted {math}`\alpha`
+`rho` is denoted {math}`\rho`
+A) Bend geometry with positive bend angle. For the geometry shown,
+`g`, `angle`, `rho`, `e1`, `e2`, `e1_rect`, and `e2_rect` are all positive.
+B) Bend geometry with negative bend angle. For the geometry shown,
+`g`, `angle`, `rho`, `e1`, `e2`, `e1_rect`, and `e2_rect` are all negative.
+Note: The figures are drawn for zero `ref_tilt` where the rotation axis is parallel to the
+{math}`y`
+}
+:name: f:bend2
+```
+
+The `BendParams` group ([](#s:bend.g)) contains the parameters that define the shape of the bend.
+
+Example:
+```{code} yaml
+@ele b03w = Bend(l = 0.6, g = 0.017, kn1 = 0.003)
+```
+
+
+%---------------------------------------------------------------------------------------------------
+(s:collimator)=
+## Collimator
+`Collimators` are field free elements that can collimate beam particles.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+%---------------------------------------------------------------------------------------------------
+(s:converter)=
+## Converter
+`Converter` elements convert from one particle species to another.
+For example, converting electrons hitting on a metal target into positrons.
+
+NOTE: This Element is in development and is incomplete.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+%---------------------------------------------------------------------------------------------------
+(s:crabcavity)=
+## CrabCavity
+A `CrabCavity` is an RF cavity that gives a {math}`z`
+This is useful in colliding beam machines, where there is a finite crossing angle at the
+interaction point, to rotate the beams near the IP.
+
+NOTE: This Element is in development and is incomplete.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:drift)=
+## Drift
+A `Drift` is a field free element.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+%---------------------------------------------------------------------------------------------------
+(s:egun)=
+## EGun
+An `EGun` element represents an electron gun and encompasses a region starting from the cathode
+were the electrons are generated.
+
+NOTE: This Element is in development and is incomplete.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+%---------------------------------------------------------------------------------------------------
+(s:fiducial)=
+## Fiducial
+A `Fiducial` element is used to fix the position and orientation of the reference orbit within
+the floor coordinate system at the location of the `Fiducial` element. A `Fiducial` element
+will affect the floor floor coordinates ([](#s:floor)) of elements both upstream and downstream
+of the fiducial element.
+
+NOTE: This Element is in development and is incomplete.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**LordSlaveParams**](#s:lord.slave.g): Element lord and slave status.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:floorshift)=
+## FloorShift
+A `FloorShift` element shifts the reference orbit in the floor coordinate system without
+affecting particle tracking. That is, in terms of tracking, a `FloorShift` element is equivalent
+to a `Marker` ([](#s:marker)) element.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:foil)=
+## Foil
+A `Foil` element represents a planar sheet of material which can strip electrons from a particle.
+In conjunction, there will be scattering of the particle trajectory as well as an associated energy
+loss.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:fork)=
+## Fork
+```{figure} figures/fork-patch.svg
+\caption[Cornell/Brookhaven CBETA ERL/FFAG machine with fork elements.]
+{
+Section of the 8-pass (4 passes with increasing energy and 4 passes with decreasing energy)
+Cornell/Brookhaven CBETA ERL/FFAG machine. Fork elements are used to connect the
+injection line to the ring and to connect the ring to a diagnostic line. The geometry of the
+switchyard, used to correct the timings of the differing energy beams, is done using Patch elements.
+}
+:name: f:fork.cbeta
+```
+
+A `Fork` element marks a branching point in a lattice branch. Examples include `Fork` from
+a ring to an extraction line or an X-ray beam line, or `Fork` from the end of an injection line to
+someplace in a ring. An example is shown in {numref}`f:fork.cbeta`.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**TrackingParams**](#s:tracking.g): Default tracking settings.
+- [**ForkParams**](#s:fork.g): Fork parameters.
+- [**ReferenceParams**](#s:reference.g): Reference energy and species.
+- [**DownstreamReferenceParams**](#s:dreference.g): Reference energy and species at downstream end.
+
+The `branch` containing a `Fork` element is called the
+"`base` `branch`". The `branch` that the `Fork` element points to is called the
+"`forked-to` `branch`". The to_ele...
+
+Fork elements may be put in a lattice by including them in beamlines before a lattice
+is instantiated. After a lattice has been instantiated, Fork elements can be inserted
+by using the `superimpose!` or `insert!` functions.
+
+The components of this group are:
+```{code} yaml
+to_line::Union{BeamLine,Nothing} - Beam line to fork to. Default: nothing.
+to_ele::Union{String,Ele,Nothing} - Element forked to. Default: nothing.
+direction::Int - Longitudinal Direction of injected beam.
+```
+
+If `to_line` is set to a `BeamLine` -> New branch
+Otherwise the fork is to an existing lattice element.
+
+
+
+
+If a fork creates a new branch, and if the The reference energy or species type for the forked-to branch is the particle
+particle associated with a branch can be set by setting the `particle` attribute of the `Fork`
+element.
+
+
+\index{patch}
+Forked-to branches can themselves have `Fork` elements. A branch always starts out tangential to the
+line it is branching from. A `patch` element ([](#s:patch)) can be used to reorient the
+reference orbit as needed. Example:
+```{code} yaml
+@ele x_patch = Patch,(offset[1] = 0.01)
+@ele pb = Fork(to_line = x_line)
+@ele bgn = BeginningEle(p0c = 1e3, species_ref = Species("photon")
+! Photon reference momentum
+from_line = BeamLine([... a, pb, b, ...]) ! Defines base branch
+x_line = BeamLine([bgn, x_patch, x1, x2, ...]) ! Defines forked-to branch
+```
+In this example, a photon generated at the fork element `pb` with {math}`x = 0`
+`from_line` reference orbit through `pb` will, when transferred to the `x_line`, and
+propagated through `x_patch`, have an initial value for {math}`x` of {math}`-0.01`
+
+Forking elements have zero length and, like `Marker` elements, the position of a particle tracked
+through a `Fork` element does not change.
+
+Forking elements do not have orientational attributes like `x_pitch` and `tilt`
+([](#s:offset)). If the orientation of the forked-to branch needs to be modified, this can be
+accomplished using a `patch` element at the beginning of the line.
+
+\index{is_on}
+The `is_on` attribute, while provided for use by a program, is ignored by Bmad proper.
+
+If the reference orbit needs to be shifted when `Fork` from one ring to another ring, a patch can
+be placed in a separate "transfer" line to isolate it from the branches defining the
+rings. Example:
+```{code} yaml
+ring1: line = (... A, F1, B, ...) ! First ring
+x_line: line = (X_F1, X_PATCH, X_F2) ! "Transfer" line
+ring2: line = (... C, F2, D, ...) ! Second ring
+use, ring1
+
+f1: fork, to_line = x_line
+f2: fork, to_line = x_line, direction = -1
+x_patch: patch, x_offset = ...
+x_f1: fork, to_line = ring1, to_ele = f1, direction = -1
+x_f2: fork, to_line = ring2, to_ele = f2
+```
+Here the `fork` `F1` in `ring1` forks to `x_line` which
+in turn forks to `ring2`.
+
+The above example also illustrates how to connect machines for particles going in the reverse
+direction. In this case, rather than using a single `fork` element to connect lines, pairs of
+`fork` elements are used. `Ring2` has a `fork` element `f2` that points back through
+`x_line` and then to `ring1` via the `x_f1` fork. Notice that both `f2` and `x_f2`
+have their `direction` attribute set to -1 to indicate that the fork is appropriate for particles
+propagating in the -{math}`s`
+will, by default, connect to the downstream end of the `x_line`. The default setting of
+`direction` is 1.
+
+It is important to note that the setting of `direction` does not change the placement of elements
+in the forked line. That is, the global position ([](#s:global)) of any element is unaffected by
+the setting of `direction`. To shift the global position of a forked line, `patch`
+elements must be used. In fact, the `direction` parameter is merely an indicator to a program on
+how to treat particle propagation. The `direction` parameter is not used in any calculation done
+by Bmad.
+
+\index{beginning_ele}\index{fiducial}\index{fork}\index{photon_fork}
+\index{marker}\index{to_ele}
+The `to_ele` attribute for a `Fork` element is used to designate the element of the forked-to
+branch that the `Fork` element connects to. To keep things conceptually simple, the `to_ele`
+must be a "marker-like" element which has zero length and unit transfer matrix. Possible
+`to_ele` types are:
+```{code} yaml
+beginning_ele
+fiducial
+fork and photon_fork
+marker
+```
+When the `to_ele` is not specified, the default is to connect to the beginning of the forked-to
+branch if `direction` is 1 and to connect to the end of the downstream branch if `direction` is
+-1. In this case, there is never a problem connecting to the beginning of the forked-to branch since
+all branches have a `beginning_ele` element at the beginning. When connecting to the end of the
+forked-to branch the last element in the forked-to branch must be a marker-like element. Note that, by
+default, a marker element is placed at the end of all branches ([](#s:branch.construct))
+
+The default reference particle type of a branch line will be a `photon` is using a
+`photon_fork` or will be the same type of particle as the base branch if a `fork` element is
+used. If the reference particle of a branch line is different from the reference particle in the
+base branch, the reference energy (or reference momentum) of a forked-to branch line needs to be set
+using line parameter statements ([](#s:beginning)). If the reference particle of a branch line is
+the same as the reference particle in the base branch, the reference energy will default to the
+reference energy of the base branch if the reference energy is not set for the branch.
+
+Example showing an injection line branching to a ring which, in turn, branches to two x-ray lines:
+```{code} yaml
+inj: line = (..., br_ele, ...) ! Define the injection line
+use, inj ! Injection line is the root
+br_ele: fork, to_line = ring ! Fork element to ring
+ring: line = (..., x_br, ..., x_br, ...) ! Define the ring
+ring[E_tot] = 1.7e9 ! Ring ref energy.
+x_br: photon_fork, to_line = x_line ! Fork element to x-ray line
+x_line: line = (...) ! Define the x-ray line
+x_line[E_tot] = 1e3
+```
+
+The `new_branch` attribute is, by default, `True` which means that the lattice branch created
+out of the `to_line` line is distinct from other lattice branches of the same name. Thus, in the
+above example, the two lattice branches made from the `x_line` will be distinct. If
+`new_branch` is set to `False`, a new lattice branch will not be created if a lattice branch
+created from the same line already exists. This is useful, for example, when a chicane line branches
+off from the main line and then branches back to it.
+
+When a lattice is expanded ([](#s:expand)), the branches defined by the `use` statement
+([](#s:use)) are searched for fork elements that branch to new forked-to branches. If found, the
+appropriate branches are instantiated and the process repeated until there are no more branches to
+be instantiated. This process does {\em not} go in reverse. That is, the lines defined in a lattice
+file are not searched for fork elements that have forked-to instantiated branches. For example, if, in
+the above example, the use statement was:
+```{code} yaml
+use, x_line
+```
+then only the `x_line` would be instantiated and the lines `inj` and `ring` would be
+ignored.
+
+If the forked-to branch and base branch both have the same reference particle, and if the element
+forked into is the beginning element, the reference energy and momentum of the forked-to branch will be
+set to the reference energy and momentum at the fork element. In this case, neither the reference
+energy nor reference momentum of the forked-to branch should be set. If it is desired to have the
+reference energy/momentum of the forked-to branch different from what is inherited from the fork
+element, a patch element ([](#s:patch)) can be used at the beginning of the forked-to branch. In all
+other cases, where either the two branches have different reference particles or the fork connects
+to something other than the beginning element, there is no energy/momentum inheritance and either
+the reference energy or reference momentum of the forked-to branch must be set.
+
+How to analyze a lattice with multiple branches can be somewhat complex and will vary from program
+to program. For example, some programs will simply ignore everything except the root branch. Hopefully
+any program documentation will clarify the matter.
+
+%---------------------------------------------------------------------------------------------------
+(s:girder)=
+## Girder
+A `Girder` is a support structure that orients the elements that are attached to it in space. A
+girder can be used to simulate any rigid support structure and there are no restrictions on how the
+lattice elements that are supported are oriented with respect to one another. Thus, for example,
+optical tables can be simulated.
+
+```{figure} figures/girder.svg
+\caption[Girder example.] {
+Girder supporting three elements labeled `A`, `B`, and `C`. {math}`\cal O_A`
+frame at the upstream end of element `A` ([](#s:ref.construct)), {math}`\cal O_C`
+frame at the downstream end of element `C`, and {math}`\cal O_G`
+frame of the girder if the `origin_ele` parameter is not set. {math}`{\bf r}_{CA}`
+{math}`\cal O_A` to {math}`\cal O_C`. The length `l` of the girder is set to be the difference in {math}`s`
+points {math}`\cal O_C` and {math}`\cal O_A`
+}
+:name: f:girder
+```
+
+A `girder` is a support structure that orients the elements that are attached to it in space. A
+girder can be used to simulate any rigid support structure and there are no restrictions on how the
+lattice elements that are supported are oriented with respect to one another. Thus, for example,
+optical tables can be simulated.
+
+Element parameter groups associated with this element type are:
+- [**FloorParams**](#s:orientation.g): Floor floor position and orientation.
+- [**LengthParams**](#s:length.g): Length and s-position parameters.
+- [**DescriptionParams**](#s:descrip.g): Element descriptive strings.
+- [**BodyShiftParams**](#s:alignment.g): Alignment with respect to the reference.
+
+A simple example of a girder is shown in {numref}`f:girder`. Here a girder supports three
+elements labeled `A`, `B`, and `C` where `B` is a bend so the geometry is
+nonlinear. Such a girder may specified in the lattice file like:
+```{code} yaml
+lat = Lattice(...) # Create lattice
+create_external_ele(lat) # Optional: Create external elements
+@ele g1 = Girder(supported = [A, B, C], ...)
+create_girder!(g1)
+```
+The `create_girder` command must appear after the lattice has been constructed.
+The list of `supported` elements must contain only elements that are in a single
+lattice. Be careful here since lattice creation involves creating copies of the elments
+in the `BeamLines` that define the lattice. Use of the function `create_external_ele`
+may be useful here. The `find` function may also be used to search for the appropriate
+elements in the lattice.
+
+The list of supported elements does not have to be in any order and may contain elements from
+multiple branches. A `Girder` may not support slave elements.
+If a super slave or multipass slave element is in the list, the slave will
+be removed and the corresponding lords of the slave will be substituted into the list.
+
+A lattice element may have at most one `Girder` supporting it. However, a `Girder` can be
+supported by another `Girder` which in turn can be supported by a third `Girder`, etc. Girders
+that support other Girders must be defined in the lattice file after the supported girders are
+defined.
+
+If all the supported elements of a `Girder` are contained within a single lattice branch
+(lord elements are considered to be in the branch(s) that their slaves are in), The length `L`
+of the `Girder` is calculated by the difference in {math}`s`
+supported element with minimal {math}`s`
+the maximal {math}`s`
+set to `NaN`. The girder length is not used in any calculations.
+
+The reference frame from which a `Girder`'s orientation is measured is set by the
+`origin_ele` and `origin_ele_ref_point` parameters ([](#s:origin.ele.g)).
+Orientation shifts are controlled by the `BodyShiftParams` ([](#s:align.g)).
+
+When a girder is shifted in space, the elements
+it supports are also shifted. In this case, the orientation
+attributes give the orientation of
+the element with respect to the `girder`. The orientation with
+respect to the local reference coordinates is given by
+`x_offset_tot`, etc, which are computed from the orientation attributes
+of the element and the `girder`. An example will make this clear:
+```{code} yaml
+q1: quad, l = 2
+q2: quad, l = 4, x_offset = 0.02, x_pitch = 0.01
+d: drift, l = 8
+g4: girder = \{q1, q2\}, x_pitch = 0.002, x_offset = 0.03
+this_line: line = (q1, d, q2)
+use, this_line
+```
+\index{overlay}
+In this example, `g4` supports quadrupoles `q1` and `q2`.
+Since the supported elements are colinear, the computation is greatly
+simplified. The reference frame of `g4`, which is the default
+`origin` frame, is at {math}`s = 7`
+start of `q1` at at {math}`s = 0`
+at {math}`s = 14`
+centers so the {math}`s`
+```{code} yaml
+Element S_ref dS_from_g4
+q1 1.0 -6.0
+g4 7.0 0.0
+q2 12.0 5.0
+```
+Using a small angle approximation to simplify the calculation, the `x_pitch` of `g4` produces
+an offset at the center of `q2` of {math}`0.01 = 0.002 * 5`
+`q2`, give the total `x_offset`, denoted `x_offset_tot` of `q2` is
+{math}`0.06 = 0.01 + 0.03 + 0.02`
+The total `x_pitch`, denoted `x_pitch_tot`, of `q2` is {math}`0.022 = 0.02 + 0.001`
+
+A `Girder` that has its `is_on` attribute set to False is considered to be unsifted with
+respect to it's reference frame.
+
+%---------------------------------------------------------------------------------------------------
+(s:instrument)=
+## Instrument
+An `Instrument` is like a `Drift` except it represents some measurement device.
+
+%---------------------------------------------------------------------------------------------------
+(s:kicker)=
+## Kicker
+A `Kicker` element gives particles a kick.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:lcavity)=
+## LCavity
+An `LCavity` is a LINAC accelerating cavity. The main difference between an `RFCavity` and an
+`LCavity` is that, unlike an `RFCavity`, the reference energy ([](#s:ref.energy)) through
+an `LCavity` is not constant.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:marker)=
+## Marker
+A `Marker` is a zero length element meant to mark a position in the machine.
+
+%---------------------------------------------------------------------------------------------------
+(s:mask)=
+## Mask
+A `Mask` element defines an aperture where the mask area can
+essentially have an arbitrary shape.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:match)=
+## Match
+A `Match` element is used to adjust Twiss and orbit parameters.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:mult)=
+## Multipole
+A `Multipole` is a thin magnetic multipole lens.
+
+%---------------------------------------------------------------------------------------------------
+(s:nullele)=
+## NullEle
+A `NullEle` is used for bookkeeping purposes. For example, a `NullEle` can be used as
+the default value for a function argument or as a temporary place marker in a lattice.
+
+%---------------------------------------------------------------------------------------------------
+(s:octupole)=
+## Octupole
+An `Octupole` is a magnetic element with a cubic field dependence
+with transverse position ([](#s:mag.field)).
+
+%-----------------------------------------------------------------------------
+(s:patch)=
+## Patch
+
+```{figure} figures/patch-problem.svg
+\caption[The branch reference coordinates in a `Patch` element.]
+{The branch reference coordinates in a `Patch` element. The `Patch` element, shown
+schematically as an irregular quadrilateral, is sandwiched between elements `ele_a` and
+`ele_b`. `L` is the length of the `Patch`. In this example, the `Patch` has a finite
+`y_rot`.}
+:name: f:patch.prob
+```
+
+A `Patch` element shifts the reference orbit and time. Also see `FloorShift`
+([](#s:floorshift)) and `Fiducial` ([](#s:fiducial)) elements. A common application of a patch
+is to orient two branch lines with respect to each other.
+
+
+A `Patch` ([](#s:patch)) element is different in that there is no "natural" coordinate
+system to use within the Patch. This is generally not an issue when the region inside the
+Patch is field and aperture free since particle tracking can be done in one step from edge
+to edge. However, when there are fields or apertures an internal
+coordinate system is needed so that the fields or apertures can be unambiguously positioned.
+
+
+Generally, if a particle is reasonably near the branch reference curve, there is a one-to-one mapping
+between the particle's position and branch {math}`(x, y, s)`
+
+
+with a non-zero `x_rot` or non-zero `y_rot` breaks the one-to-one mapping. This is
+illustrated in {numref}`f:patch.prob`. The `Patch` element, shown schematically as an, irregular
+quadrilateral, is sandwiched between elements `ele_a` and `ele_b`. The branch coordinate system
+with origin at {math}`\alpha`
+the `Patch` has its origin labeled {math}`\gamma`
+taken to be the longitudinal distance from {math}`\alpha` to {math}`\gamma`
+coordinates defining the longitudinal direction. The "beginning" point of the `Patch` on the
+reference curve a distance `L` from point {math}`\gamma` is labeled {math}`\beta`
+
+In the branch {math}`(x, y, s)` coordinate system a particle at {math}`\alpha` will have some value {math}`s = s_0`
+particle at point {math}`\beta` will have the same value {math}`s = s_0` and a particle at {math}`\gamma`
+{math}`s = s_1 = s_0 + L`. A particle at point {math}`r_a`
+assigning {math}`(x, y, s)`
+the region of `ele_a`, the particle's {math}`s` position will be {math}`s_{a2}`
+value {math}`s_0`
+`ele_a` will have {math}`s \le s_0`
+the `Patch` region, the particle's {math}`s` position will be {math}`s_{a1}`
+{math}`s_0`
+`Patch` will have {math}`s \ge s_0`
+
+To resolve this problem, AcceleratorLattice considers a particle at position {math}`r_a`
+region. This means that there is, in theory, no lower limit to the {math}`s`
+the `Patch` region can have. This also implies that there is a discontinuity in the {math}`s`
+of a particle crossing the exit face of `ele1`. Typically, when particles are translated from the
+exit face of one element to the exit face of the next, this `Patch` problem does not appear. It
+only appears when the track between faces is considered.
+
+Notice that a particle at position {math}`r_b`
+be in either `ele_a` or the `Patch`. While this creates an ambiguity it does not complicate
+tracking.
+
+%---------------------------------------------------------------------------------------------------
+(s:quadrupole)=
+## Quadrupole
+A `Quadrupole` is a magnetic element with a linear field dependence
+with transverse offset ([](#s:mag.field)).
+
+
+%---------------------------------------------------------------------------------------------------
+(s:rfcavity)=
+## RFCavity
+An `RFCavity` is an RF cavity without acceleration generally used in a storage ring. The main
+difference between an `RFCavity` and an `LCavity` is that, unlike an `Lcavity`, the
+reference energy ([](#s:phase.space)) through an `RFCavity` is constant.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:sextupole)=
+## Sextupole
+A `Sextupole` is a magnetic element with a quadratic field
+dependence with transverse offset ([](#s:mag.field)).
+
+
+%---------------------------------------------------------------------------------------------------
+(s:solenoid)=
+## Solenoid
+A `solenoid` is an element with a longitudinal magnetic field.
+
+%---------------------------------------------------------------------------------------------------
+(s:taylor)=
+## Taylor
+A `Taylor` element is a Taylor map ([](#s:taylor.phys)) that maps the input orbital phase space and
+possibly spin coordinates of a particle to the output orbital and
+spin coordinates at the exit end of the element.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:thickmult)=
+## ThickMultipole
+A `ThickMultipole` is a general non-zero length multipole element.
+
+%---------------------------------------------------------------------------------------------------
+(s:undulator)=
+## Undulator
+An `Undulator` is and element with a periodic array of alternating bends.
+Also see `Wiggler` elements.
+
+NOTE: This Element is in development and is incomplete.
+
+%---------------------------------------------------------------------------------------------------
+(s:unionele)=
+## UnionEle
+A `UnionEle` is an element that contains a collection of other elements.
+A `UnionEle` is used when elements overlap spatially which happens with superposition ([](#c:super)).
+
+%---------------------------------------------------------------------------------------------------
+(s:wiggler)=
+## Wiggler
+A `Wiggler` is and element with a periodic array of alternating bends.
+Also see `Undulator` elements.
+
+NOTE: This Element is in development and is incomplete.
+```{footbibliography}
+```
diff --git a/docs/src/electromagnetic-fields.md b/docs/src/electromagnetic-fields.md
new file mode 100644
index 0000000..ea21fa8
--- /dev/null
+++ b/docs/src/electromagnetic-fields.md
@@ -0,0 +1,896 @@
+(c:X)=
+# Electromagnetic Fields
+%-----------------------------------------------------------------
+(s:mag.field)=
+## Magnetostatic Multipole Fields
+Start with the assumption that the local magnetic field has no longitudinal component
+(obviously this assumption does not work with, say, a solenoid). Following mad, ignoring
+skew fields for the moment, the vertical magnetic field along the {math}`y = 0` axis is expanded
+in a Taylor series
+begin{equation}
+B_y(x, 0) = sum_n B_n , frac{x^n}{n!}
+label{byx0b}
+end{equation}
+Assuming that the reference orbit is locally straight (there are correction terms if the
+reference orbit is curved ([](#s:field.exact))), the field is
+begin{alignat}{5}
+B_x &= &&B_1 y plus &&B_2 , xy
+&& plus && frac{1}{6} B_3 (3x^2 y - y^3) plus ldots CRNO
+B_y &= B_0 plus &&B_1 x + frac{1}{2} &&B_2 (x^2 - y^2)
+&& plus && frac{1}{6} B_3 (x^3 - 3x y^2) plus ldots
+label{bbb}
+end{alignat}
+The relation between the field {math}`B_n` and the normalized field {math}`K_n` is:
+begin{equation}
+K_n equiv frac{q , B_n}{P_0}
+label{kqlbp}
+end{equation}
+where {math}`q` is the charge of the reference particle (in units of the elementary charge), and {math}`P_0` is
+the reference momentum (in units of eV/c). Note that {math}`P_0/q` is sometimes written as {math}`Brho`. This
+is just an old notation where {math}`rho` is the bending radius of a particle with the reference energy
+in a field of strength {math}`B`. Notice that {math}`P_0` is the local reference momentum at the element which
+may not be the same as the reference energy at the beginning of the lattice if there are
+`lcavity` elements ([](#s:lcav)) present.
+
+The kicks {math}`Delta p_x` and {math}`Delta p_y` that a particle experiences going through a multipole field
+is
+begin{alignat}{5}
+Delta p_x & = frac{-q , L , B_y}{P_0} label{pqlbp1}
+& = -K_0 L ;-;
+&& K_1 L , x plus
+frac{1}{2} && K_2 L (y^2 - x^2) && plus
+&& frac{1}{6} K_3 L (3x y^2 - x^3) plus ldots
+nonumber
+Delta p_y & = frac{q , L , B_x}{P_0} label{pqlbp2}
+& =
+&& K_1 L , y plus
+&& K_2 L , xy && plus
+&& frac{1}{6} K_3L (3x^2 y - y^3) plus ldots nonumber
+end{alignat}
+A positive {math}`K_1L` quadrupole component gives horizontal focusing and vertical defocusing. The
+general form is
+begin{align}
+Delta p_x &= sum_{n = 0}^{infty} frac{K_n L}{n!}
+sum_{m = 0}^{2m le n}
+begin{pmatrix} n cr 2m end{pmatrix} ,
+(-1)^{m+1} , x^{n-2m} , y^{2m}
+Delta p_y &= sum_{n = 0}^{infty} frac{K_n L}{n!}
+sum_{m = 0}^{2m le n-1}
+begin{pmatrix} n cr 2m+1 end{pmatrix} ,
+(-1)^{m} , x^{n-2m-1} , y^{2m+1}
+end{align}
+where {math}`binom{a}{b}` ("a choose b") denotes a binomial coefficient.
+
+The above equations are for fields with a normal component only. If a given multipole field of order
+{math}`n` has normal {math}`B_n` and skew {math}`S_n` components and is rotated in the {math}`(x, y)` plane by an angle
+{math}`T_n`, the magnetic field at a point {math}`(x,y)` can be expressed in complex notation as
+begin{equation}
+B_y(x,y) + i B_x(x,y) =
+frac{1}{n!} (B_n + i S_n) , e^{-i(n+1)T_n} , e^{i n theta} , r^n
+label{bib1nb}
+end{equation}
+where {math}`(r, theta)` are the polar coordinates of the point {math}`(x, y)`.
+
+Note that, for compatibility with MAD, the {math}`K0L` component of a `Multipole` element rotates the
+reference orbit essentially acting as a zero length bend. This is not true for multipoles of any
+other type of element.
+
+Instead of using magnitude {math}`K_n` and rotation angle {math}`theta_n`, Another representation is using
+normal {math}`wt K_n` and skew {math}`wt S_n`. The conversion between the two are
+begin{align}
+wt K_n &= K_n , cos((n + 1) , T_n) CRNO
+wt S_n &= K_n , sin((n + 1) , T_n)
+end{align}
+
+Another representation of the magnetic field used by Bmad divides the fields into normal {math}`b_n` and
+skew {math}`a_n` components. In terms of these components the magnetic field for the {math}`n`Th order
+multipole is
+begin{equation}
+frac{q , L}{P_0} , (B_y + i B_x) = (b_n + i a_n) , (x + i y)^n
+label{qlpbb}
+end{equation}
+The {math}`a_n`, {math}`b_n` representation of multipole fields can be used in elements such as
+quadrupoles, sextupoles, etc. to allow "error" fields to be represented.
+The conversion between {math}`(a_n, b_n)` and {math}`(K_nL, S_nL, T_n)` is
+begin{equation}
+b_n + i a_n = frac{1}{n!} , (K_nL + i , S_nL) , e^{-i(n+1)T_n}
+end{equation}
+In the case where {math}`S_nL = 0`
+begin{align}
+K_n L &= n! , sqrt{a_n^2 + b_n^2}
+tan[(n+1) T_n] &= frac{-a_n}{b_n}
+end{align}
+To convert a normal magnet (a magnet with no skew component) into a skew magnet (a magnet with no
+normal component) the magnet should be rotated about its longitudinal axis with a rotation angle of
+begin{equation}
+(n+1) T_n = frac{pi}{2}
+end{equation}
+For example, a normal quadrupole rotated by {math}`45^circ` becomes a skew quadrupole.
+
+`Reference energy` scaling is applied if the `field_master` attribute ([](#s:field.master))
+is True for an element so that the multipole values specified in the lattice file are not reference
+energy normalized
+begin{equation}
+bigl[ a_n, b_n bigr] longrightarrow
+bigl[ a_n, b_n bigr] cdot frac{q}{P_0}
+label{ababq}
+end{equation}
+
+%-----------------------------------------------------------------
+(s:elec.field)=
+## Electrostatic Multipole Fields
+Except for the `elseparator` element, Bmad specifies DC electric fields using normal
+{math}`b_{en}` and skew {math}`a_{en}` components ([](#s:multip)). The potential {math}`phi_n` for the
+{math}`n`Th order multipole is
+begin{equation}
+phi_n = -re left[ frac{b_{en} - i a_{en}}{n + 1} , frac{(x + i y)^{n+1}}{r_0^n} right]
+label{pbian1}
+end{equation}
+where {math}`r_0` is a "measurement radius" set by the `r0_elec` attribute of an element
+([](#s:multip)).
+
+The electric field for the {math}`n`Th order multipole is
+begin{equation}
+E_x - i E_y = (b_{en} - i a_{en}) , frac{(x + i y)^n}{r_0^n}
+label{exiey}
+end{equation}
+Notice that the magnetic multipole components {math}`a_n` and {math}`b_n` are normalized by the
+element length, reference charge, and reference momentum (Eq{qlpbb}) while their electric
+counterparts are not.
+
+Using the paraxial approximation, The kick given a particle due to the electric field is
+begin{equation}
+frac{dp_x}{ds} = frac{q , E_x}{beta , P_0 , c}, qquad frac{dp_y}{ds} = frac{q , E_y}{beta , P_0 , c}
+end{equation}
+Where {math}`beta` is the normalized velocity.
+
+%-----------------------------------------------------------------
+(s:field.exact)=
+## Exact Multipole Fields in a Bend
+For static magnetic and electric multipole fields in a bend, the spacial dependence of the
+field is different from multipole fields in an element with a straight geometry as given
+by Eqs{qlpbb} and eq{exiey}. The analysis of the multipole fields in a bend here follows
+McMillan{footcite:p}`McMillan:Multipoles`.
+
+In the rest of this section, normalized coordinates {math}`rw = r / rho`, {math}`xw / = x /`
+rho{math}`, and `yw = y / rho{math}` will be used where `rho{math}` is the bending radius of the`
+reference coordinate system, {math}`r` is the distance, in the plane of the bend, from the bend
+center to the observation point, {math}`x` is the distance in the plane of the from the reference
+coordinates to the observation point and {math}`y` is the distance out-of-plane. With this
+convention {math}`rw = 1 + xw`.
+
+An electric or magnetic multipole can be characterized by a scalar potential {math}`phi` with
+the field given by {math}`-nabla phi`. The potential is a solution to Laplace's equation
+begin{equation}
+frac{1}{rw} , frac{partial}{partial , rw}
+left( rw , frac{partial , phi}{partial , rw} right) +
+frac{partial^2 phi}{partial , yw^2} = 0
+end{equation}
+As McMillian shows, it is also possible to calculate the magnetic field by constructing the
+appropriate vector potential. However, from a practical point of view, it is simpler to use the
+scalar potential for both the magnetic and electric fields.
+
+Solutions to Laplace's equation can be found in form
+begin{equation}
+phi_{n}^r = frac{-1}{1+n} sum_{p = 0}^{2p le n+1}
+begin{pmatrix} n + 1 cr 2 , p end{pmatrix} ,
+(-1)^{p} , F_{n+1-2p}(rw) , yw^{2p}
+label{pspn1}
+end{equation}
+and in the form
+begin{equation}
+phi_{n}^i = frac{-1}{1+n} sum_{p = 0}^{2p le n}
+begin{pmatrix} n + 1 cr 2p +1 end{pmatrix} ,
+(-1)^{p} , F_{n-2p}(rw) , yw^{2p+1}
+label{pspn2}
+end{equation}
+where {math}`binom{a}{b}` ("a choose b") denotes a binomial coefficient, and {math}`n` is the order
+number which can range from 0 to infinity.footnote
+{
+Notice that here {math}`n` is related to {math}`m` in
+McMillian's paper by {math}`m = n + 1`. Also note that the {math}`phi^r` and {math}`phi^i` here have a
+normalization factor that is different from McMillian.
+
+In Eq{pspn2} the {math}`F_p(rw)` are related by
+begin{equation}
+F_{p+2} = (p + 1) , (p + 2) , int_1^{rw} frac{drw}{rw}
+left[ int_1^{rw} drw , rw , F_{p} right]
+end{equation}
+with the "boundary condition":
+begin{align}
+F_0(rw) &= 1 CRNO
+F_1(rw) &= ln , rw
+end{align}
+This condition ensures that the number of terms in the sums in Eqs{pspn1} and eq{pspn2}
+are finite. With this condition, all the {math}`F_p` can be constructed:
+begin{align}
+F_1 &= ln , rw = xw - frac{1}{2}xw^2 + frac{1}{3}xw^3 - ldots CRNO
+F_2 &= frac{1}{2} (rw^2 - 1) - ln rw = xw^2 - frac{1}{3}xw^3 + frac{1}{4} xw^4 - ldots CRNO
+F_3 &= frac{3}{2} [-(rw^2 - 1) + (rw^2 + 1) ln rw] = xw^3 - frac{1}{2} xw^4 + frac{7}{20} xw^5 - ldots
+label{ffff}
+F_4 &= 3 [ frac{1}{8} (rw^4 - 1) + frac{1}{2} (rw^2 - 1) - (rw^2 + frac{1}{2}) ln rw] =
+xw^4 - frac{2}{5} xw^5 + frac{3}{10} xw^6 - ldots CRNO
+&text{Etc...} nonumber
+end{align}
+Evaluating these functions near {math}`xw = 0` using the exact {math}`rw`-dependent functions can be
+problematical due to round off error. For example, Evaluating {math}`F_4(rw)` at {math}`xw = 10^{-4}` results
+in a complete loss of accuracy (no significant digits!) when using double precision numbers. In
+practice, Bmad uses a Pad'e approximant for {math}`xw` small enough and then switches to the
+{math}`rw`-dependent formulas for {math}`xw` away from zero.
+
+For magnetic fields, the "real" {math}`phi_n^r` solutions will correspond to skew fields and the
+"imaginary" {math}`phi_n^i` solutions will correspond to normal fields
+begin{equation}
+bfB = -frac{P_0}{q , L} ,
+sum_{n = 0}^infty rho^n , left[ a_n , widetilde nabla phi_n^r + b_n , widetilde nabla phi_n^i right]
+label{bpql}
+end{equation}
+where the gradient derivatives of {math}`widetilde nabla` are with respect to the normalized
+coordinates. In the limit of infinite bending radius {math}`rho`, the above equations converge
+to the straight line solution given in Eq{qlpbb}.
+
+For electric fields, the "real" solutions will correspond to normal fields and the
+"imaginary" solutions are used for skew fields
+begin{equation}
+bfE = -sum_{n = 0}^infty rho^n , left[ a_{en} , widetilde nabla phi_n^i +
+b_{en} , widetilde nabla phi_n^r right]
+label{enrn}
+end{equation}
+And this will converge to Eq{exiey} in the straight line limit.
+
+In the vertical plane, with {math}`xw = 0`, the solutions {math}`phi_n^r` and {math}`phi_n^i` have the same
+variation in {math}`yw` as the multipole fields with a straight geometry. For example, the field
+strength of an {math}`n = 1` (quadrupole) multipole will be linear in {math}`yw` for {math}`xw = 0`. However, in the
+horizontal direction, with {math}`yw = 0`, the multipole field will vary like {math}`dF_2/dxw` which has
+terms of all orders in {math}`xw`. In light of this, the solutions {math}`phi_n^r` and {math}`phi_n^i` are
+called "vertically pure" solutions.
+
+It is possible to construct "horizontally pure" solutions as well. That is, it is possible to
+construct solutions that in the horizontal plane, with {math}`yw = 0`, behave the same as the corresponding
+multipole fields with a straight geometry. A straight forward way to do this, for some given
+multipole of order {math}`n`, is to construct the horizontally pure solutions, {math}`psi_n^r` and {math}`psi_n^i`,
+as linear superpositions of the vertically pure solutions
+begin{equation}
+psi_n^r = sum_{k = n}^infty C_{nk} , phi_k^r, qquad
+psi_n^i = sum_{k = n}^infty D_{nk} , phi_k^i
+label{p1rc}
+end{equation}
+with the normalizations {math}`C_{nn} = D_{nn} = 1`. The {math}`C_{nk}` and {math}`D_{nk}` are chosen, order
+by order, so that {math}`psi_n^r` and {math}`psi_n^i` are horizontally pure. For the real
+potentials, the {math}`C_{nk}`, are obtained from a matrix {math}`bfM` where {math}`M_{ij}` is the
+coefficient of the {math}`xw^j` term of {math}`(dF_i/dxw)/i` when {math}`F_i` is expressed as an expansion in
+{math}`xw` (Eq{ffff}). {math}`C_{nk}`, {math}`k = 0, ldots, infty` are the row vectors of the inverse
+matrix {math}`bfM^{-1}`. For the imaginary potentials, the {math}`D_{nk}` are constructed similarly
+but in this case the rows of {math}`bfM` are the coefficients in {math}`xw` for the functions {math}`F_i`.
+To convert between field strength coefficients, Eqs{bpql} and eq{enrn} and Eqs{p1rc}
+are combined
+begin{alignat}{3}
+a_n &= sum_{k = n}^infty frac{1}{rho^{k-n}} , C_{nk} , alpha_k, quad
+&a_{en} &= sum_{k = n}^infty frac{1}{rho^{k-n}} , D_{nk} , alpha_{ek}, CRNO
+b_n &= sum_{k = n}^infty frac{1}{rho^{k-n}} , D_{nk} , beta_k, quad
+&b_{en} &= sum_{k = n}^infty frac{1}{rho^{k-n}} , D_{nk} , beta_{ek}
+end{alignat}
+where {math}`alpha_k`, {math}`beta_k`, {math}`alpha_{ek}`, and {math}`beta_{ek}` are the corresponding coefficients
+for the horizontally pure solutions.
+
+When expressed as a function of {math}`rw` and {math}`yw`, the vertically pure solutions {math}`phi_n` have a
+finite number of terms (Eqs{pspn1} and eq{pspn2}). On the other hand, the horizontally
+pure solutions {math}`psi_n` have an infinite number of terms.
+
+The vertically pure solutions form a complete set. That is, any given field that satisfies
+Maxwell's equations and is independent of {math}`z` can be expressed as a linear combination of
+{math}`phi_n^r` and {math}`phi_n^i`. Similarly, the horizontally pure solutions form a complete
+set. [It is, of course, possible to construct other complete sets in which the basis
+functions are neither horizontally pure nor vertically pure.]
+
+This brings up an important point. To properly simulate a machine, one must first of all
+understand whether the multipole values that have been handed to you are for horizontally
+pure multipoles, vertically, pure multipoles, or perhaps the values do not correspond to
+either horizontally pure nor vertically pure solutions! Failure to understand this point
+can lead to differing results. For example, the chromaticity induced by a horizontally
+pure quadrupole field will be different from the chromaticity of a vertically pure
+quadrupole field of the same strength. With Bmad, the `exact_multipoles`
+([](#s:bend)) attribute of a bend is used to set whether multipole values are for
+vertically or horizontally pure solutions. [Note to programmers: PTC always assumes
+coefficients correspond to horizontally pure solutions. The Bmad PTC interface will
+convert coefficients as needed.]
+
+%-----------------------------------------------------------------
+(s:field.map)=
+## Map Decomposition of Magnetic and Electric Fields
+Electric and magnetic fields can be parameterized as the sum over a number of functions
+with each function satisfying Maxwell's equations. These functions are also referred to as
+"maps", "modes", or "terms". Bmad has three parameterizations:
+```{code} yaml
+Cartesian Map ! [](#s:cart.map.phys).
+Cylindrical Map ! [](#s:cylind.map.phys)
+Generalized Gradient Map ! [](#s:gen.grad.phys)
+```
+These parameterizations are three of the four `field map` parameterizations that Bmad
+defines [](#s:fieldmap).
+
+The `Cartesian map` decomposition involves a set of terms, each term a solution the
+Laplace equation solved using separation of variables in Cartesian coordinates. This
+decomposition can be used for DC but not AC fields. See [](#s:cart.map.phys).
+for more details. The syntax for specifying the `Cartesian map` decomposition
+is discussed in [](#s:cart.map).
+
+The `cylindrical map` decomposition can be used for both DC and AC fields. See
+[](#s:cylind.map.phys) for more details. The syntax for specifying the `cylindrical map`
+decomposition is discussed in [](#s:cylind.map).
+
+The `generalized gradient map` start with the cylindrical map decomposition but then express the
+field using coefficients derived from an expansion of the scalar potential in powers of the radius
+([](#s:gen.grad.phys)).
+
+%-----------------------------------------------------------------
+(s:cart.map.phys)=
+## Cartesian Map Field Decomposition
+Electric and magnetic fields can be parameterized as the sum over a number of functions
+with each function satisfying Maxwell's equations. These functions are also referred to as
+"maps", "modes", or "terms". Bmad has two types. The "`Cartesian`"
+decomposition is explained here. The other type is the `cylindrical` decomposition
+([](#s:cylind.map.phys)).
+
+The `Cartesian` decomposition implemented by Bmad involves a set of terms, each
+term a solution the Laplace equation solved using separation of variables in Cartesian
+coordinates. This decomposition is for DC electric or magnetic fields. No AC Cartesian Map
+decomposition is implemented by Bmad. In a lattice file, a `Cartesian` map is specified using
+the `cartesian_map` attribute as explained in Sec.~[](#s:cart.map).
+
+The `Cartesian` decomposition is modeled using an extension of the method of Sagan,
+Crittenden, and Rubin{footcite:p}`Sagan:wiggler`. In this decomposition, the magnetic(or electric
+field is written as a sum of terms {math}`B_i` (For concreteness the symbol {math}`B_i` is used but
+the equations below pertain equally well to both electric and magnetic fields) with:
+begin{equation}
+bfB(x,y,z) = sum_i bfB_i(x, y, z; A, k_x, k_y, k_z, x_0, y_0, phi_z, family)
+end{equation}
+Each term {math}`B_i` is specified using seven numbers {math}`(A, k_x, k_y, k_z,`
+x_0, y_0, phi_z){math}` and a switch called `family` which can be one of:`
+```{code} yaml
+x, qu
+y, sq
+```
+Roughly, taking the offsets {math}`x_0` and {math}`y_0` to be zero (see the equations below), the `x`
+`family` gives a field on-axis where the {math}`y` component of the field is zero. that is, the `x`
+family is useful for simulating, say, magnetic vertical bend dipoles. The `y` `family` has a
+field that on-axis has no {math}`x` component. The `qu` `family` has a magnetic quadrupole like
+(which for electric fields is skew quadrupole like) field on-axis and the `sq` `family` has a
+magnetic skew quadrupole like field on-axis. Additionally, assuming that the {math}`x_0` and {math}`y_0` offsets
+are zero, the `sq` family, unlike the other three families, has a nonzero on-axis {math}`z` field
+component.
+
+Each family has three possible forms These are designated as "`hyper-y`",
+"`hyper-xy`", and "`hyper-x`".
+
+For the `x` `family` the `hyper-y` form is:
+begin{alignat}{4}
+B_x &= &&A , &dfrac{k_x}{k_y} & cos(kxx) , cosh(kyy) , cos(kzz) CRNEG
+B_y &= &&A , & & sin(kxx) , sinh(kyy) , cos(kzz) CRNEG
+B_s &= -&&A , &dfrac{k_z}{k_y} & sin(kxx) , cosh(kyy) , sin(kzz) label{cm1}
+&&&&& text{with} ,, k_y^2 = k_x^2 + k_z^2 nonumber
+end{alignat}
+The `x` `family` `hyper-xy` form is:
+begin{alignat}{4}
+B_x &= &&A , &dfrac{k_x}{k_z} & cosh(kxx) , cosh(kyy) , cos(kzz) CRNEG
+B_y &= &&A , &dfrac{k_y}{k_z} & sinh(kxx) , sinh(kyy) , cos(kzz) CRNEG
+B_s &= -&&A , & & sinh(kxx) , cosh(kyy) , sin(kzz) label{cm3}
+&&&&& text{with} ,, k_z^2 = k_x^2 + k_y^2 nonumber
+end{alignat}
+And the `x` `family` `hyper-x` form is:
+begin{alignat}{4}
+B_x &= &&A , & & cosh(kxx) , cos(kyy) , cos(kzz) CRNEG
+B_y &= -&&A , &dfrac{k_y}{k_x} & sinh(kxx) , sin(kyy) , cos(kzz) CRNEG
+B_s &= -&&A , &dfrac{k_z}{k_x} & sinh(kxx) , cos(kyy) , sin(kzz) label{cm5}
+&&&&& text{with} ,, k_x^2 = k_y^2 + k_z^2 nonumber
+end{alignat}
+
+The relationship between {math}`k_x`, {math}`k_y`, and {math}`k_z` ensures that
+Maxwell's equations are satisfied. Notice that which form
+`hyper-y`, `hyper-xy`, and `hyper-x` a particular {math}`bfB_i`
+belongs to can be computed by Bmad by looking at the values of {math}`k_x`,
+{math}`k_y`, and {math}`k_z`.
+
+Using a compact notation where {math}`Ch equiv cosh`, subscript {math}`x` is {math}`kxx`, subscript {math}`z`
+is {math}`kzz`, etc., the `y` `family` of forms is:
+begin{alignat}{7}
+& text{Form} quad && text{hyper-y} quad && text{hyper-xy} quad && text{hyper-x} quad CRNO
+& B_x
+&-& A , dfrac{k_x}{k_y} , Se_x , Sh_y , Ce_z quad
+& & A , dfrac{k_x}{k_z} , Sh_x , Sh_y , Ce_z quad
+& & A , hphphp , Sh_x , Se_y , Ce_z quad CRNO
+& B_y
+& & A , hphphp , Ce_x , Ch_y , Ce_z quad
+& & A , dfrac{k_y}{k_z} , Ch_x , Ch_y , Ce_z quad
+& & A , dfrac{k_y}{k_x} , Ch_x , Ce_y , Ce_z quad label{family.y}
+& B_z
+&-& A , dfrac{k_z}{k_y} , Ce_x , Sh_y , Se_z quad
+&-& A , hphphp , Ch_x , Sh_y , Se_z quad
+&-& A , dfrac{k_z}{k_x} , Ch_x , Se_y , Se_z quad CRNO
+& text{with}
+&& k_y^2 = k_x^2 + k_z^2
+&& k_z^2 = k_x^2 + k_y^2
+&& k_x^2 = k_y^2 + k_z^2 nonumber
+end{alignat}
+
+the `qu` `family` of forms is:
+begin{alignat}{7}
+& text{Form} quad && text{hyper-y} quad && text{hyper-xy} quad && text{hyper-x} quad CRNO
+& B_x
+& & A , dfrac{k_x}{k_y} , Ce_x , Sh_y , Ce_z quad
+& & A , dfrac{k_x}{k_z} , Ch_x , Sh_y , Ce_z quad
+& & A , hphphp , Ch_x , Se_y , Ce_z quad CRNO
+& B_y
+& & A , hphphp , Se_x , Ch_y , Ce_z quad
+& & A , dfrac{k_y}{k_z} , Sh_x , Ch_y , Ce_z quad
+& & A , dfrac{k_y}{k_x} , Sh_x , Ce_y , Ce_z quad
+& B_z
+&-& A , dfrac{k_z}{k_y} , Se_x , Sh_y , Se_z quad
+&-& A , hphphp , Sh_x , Sh_y , Se_z quad
+&-& A , dfrac{k_z}{k_x} , Sh_x , Se_y , Se_z quad CRNO
+& text{with}
+&& k_y^2 = k_x^2 + k_z^2
+&& k_z^2 = k_x^2 + k_y^2
+&& k_x^2 = k_y^2 + k_z^2 nonumber
+end{alignat}
+
+the `sq` `family` of forms is:
+begin{alignat}{7}
+& text{Form} quad && text{hyper-y} quad && text{hyper-xy} quad && text{hyper-x} quad CRNO
+& B_x
+&-& A , dfrac{k_x}{k_y} , Se_x , Ch_y , Ce_z quad
+& & A , dfrac{k_x}{k_z} , Sh_x , Ch_y , Ce_z quad
+&-& A , hphphp , Sh_x , Ce_y , Ce_z quad CRNO
+& B_y
+& & A , hphphp , Ce_x , Sh_y , Ce_z quad
+& & A , dfrac{k_y}{k_z} , Ch_x , Sh_y , Ce_z quad
+& & A , dfrac{k_y}{k_x} , Ch_x , Se_y , Ce_z quad label{bsq}
+& B_z
+&-& A , dfrac{k_z}{k_y} , Ce_x , Ch_y , Se_z quad
+&-& A , hphphp , Ch_x , Ch_y , Se_z quad
+& & A , dfrac{k_z}{k_x} , Ch_x , Ce_y , Se_z quad CRNO
+& text{with}
+&& k_y^2 = k_x^2 + k_z^2
+&& k_z^2 = k_x^2 + k_y^2
+&& k_x^2 = k_y^2 + k_z^2 nonumber
+end{alignat}
+
+
+The singular case where {math}`k_x = k_y = k_z = 0` is not allowed. If a uniform field is needed, a term
+with very small {math}`k_x`, {math}`k_y`, and {math}`k_z` can be used. Notice that since {math}`k_y` must be non-zero for
+the `hyper-y` forms (remember, {math}`k_y^2 = k_x^2 + k_z^2` for these forms and not all {math}`k`'s can be
+zero), and {math}`k_z` must be non-zero for the `hyper-xy` forms, and {math}`k_x` must be nonzero for the
+`hyper-x` forms. The magnetic field is always well defined even if one of the {math}`k`'s is zero.
+
+Note: The vector potential for these fields is given in [](#s:wiggler.std).
+
+%-----------------------------------------------------------------
+(s:cylind.map.phys)=
+## Cylindrical Map Decomposition
+Electric and magnetic fields can be parameterized as the sum over a number of functions with each
+function satisfying Maxwell's equations. These functions are also referred to as "maps",
+"modes", or "terms". Bmad has two types. The "`cylindrical`" decomposition is explained
+here. The other type is the `Cartesian` decomposition ([](#s:cylind.map.phys)).
+
+In a lattice file, a `cylindrical` map is specified using the `cylindrical_map` attribute as
+explained in Sec.~[](#s:cylind.map).
+
+The `cylindrical` decomposition takes one of two forms depending upon whether the fields are time
+varying or not. The DC decomposition is explained in Sec.~[](#s:cylind.dc) while the RF
+decomposition is explained in Sec.~[](#s:cylind.ac).
+
+%-----------------------------------------------------------------
+(s:cylind.dc)=
+## DC Cylindrical Map Decomposition
+The DC `cylindrical` parametrization used by Bmad essentially follows Venturini et
+al.{footcite:p}`Venturini:LHC-Quads`. See Section~[](#s:fieldmap) for details on the syntax used to cylindrical
+maps in Bmad. The electric and magnetic fields are both described by a scalar potentialfootnote
+{
+Notice the negative sign here and in Eq{psps1k} compared to Venturini et al.{footcite:p}`Venturini:LHC-Quads`.
+This is to keep the definition of the electric scalar potential {math}`psi_E` consistent with the normal
+definition.
+begin{equation}
+bfB = -nabla , psi_B, qquad bfE = -nabla , psi_E
+label{bpep}
+end{equation}
+The scalar potentials both satisfy the Laplace equation {math}`nabla^2 , psi = 0`.
+The scalar potentials are decomposed as a sum of modes indexed by an integer {math}`m`
+begin{equation}
+psi_B = re left[ sum_{m = 0}^infty , psi_{Bm} right]
+end{equation}
+[Here and below, only equations for the magnetic field will be shown. The equations for the electric
+fields are similar.] The {math}`psi_{Bm}` are decomposed in {math}`z` using a discrete Fourier
+sum.footnote
+{
+Venturini uses a continuous Fourier transformation but Bmad uses a discrete
+transformation so that only a finite number of coefficients are needed.
+Expressed in cylindrical coordinates the decomposition of {math}`psi_{Bm}` is
+begin{equation}
+psi_{Bm} = sum_{n=-N/2}^{N/2-1} psi_{Bmn} =
+sum_{n=-N/2}^{N/2-1} frac{-1}{k_n} , e^{i , k_n , z} ,
+cos (m , theta - theta_{0m}) , b_m(n) , I_m(k_n , rho)
+label{psps1k}
+end{equation}
+where {math}`I_m` is a modified Bessel function of the first kind, and the
+{math}`b_m(n)` are complex coefficients. [For electric fields, {math}`e_m(n)` is
+substituted for {math}`b_m(n)`] In Eq{psps1k} {math}`k_n` is
+given by
+begin{equation}
+k_n = frac{2 pi , n}{N , dz}
+end{equation}
+where {math}`N` is the number of "sample points", and {math}`dz` is the longitudinal "distance between
+points". That is, the above equations will only be accurate over a longitudinal length {math}`(N-1)`
+, dz{math}`. Note: Typically the sum in Eq{psps1k} and other equations below runs from `0{math}` to `N-1{math}`.`
+Using a sum from {math}`-N/2` to {math}`N/2-1` gives exactly the same field at the sample points ({math}`z = 0, dz,`
+2,ds, ldots{math}`) and has the virtue that the field is smoother in between.`
+
+The field associated with {math}`psi_{Bm}` is for {math}`m = 0`:
+begin{align}
+B_rho &= re left[
+sum_{n=-N/2}^{N/2-1} e^{i , k_n , z} , b_0(n) ,
+I_1(k_n , rho) right] CRNO
+B_theta &= 0
+B_z &= re left[
+sum_{n=-N/2}^{N/2-1} i , e^{i , k_n , z} , b_0(n) ,
+I_0(k_n , rho) right]
+nonumber
+end{align}
+
+And for {math}`m neq 0`:
+begin{align}
+B_rho &= re left[
+sum_{n=-N/2}^{N/2-1} frac{1}{2} , e^{i , k_n , z} ,
+cos (m , theta - theta_{0m}) , b_m(n) ,
+Big[ I_{m-1}(k_n , rho) + I_{m+1}(k_n , rho) Big] right] CRNO
+B_theta &= re left[
+sum_{n=-N/2}^{N/2-1} frac{-1}{2} , e^{i , k_n , z} ,
+sin (m , theta - theta_{0m}) , b_m(n) ,
+Big[ I_{m-1}(k_n , rho) - I_{m+1}(k_n , rho) Big] right]
+B_z &= re left[
+sum_{n=-N/2}^{N/2-1} i , e^{i , k_n , z} ,
+cos (m , theta - theta_{0m}) , b_m(n) ,
+I_m(k_n , rho) right]
+nonumber
+end{align}
+
+While technically {math}`psi_{Bm0}` is not well defined due to the {math}`1/k_n` factor that is present, the
+field itself is well behaved. Mathematically, Eq{psps1k} can be corrected if, for {math}`n = 0`, the term
+{math}`I_m(k_n , rho) / k_n` is replaced by
+begin{equation}
+frac{I_m(k_0 , rho)}{k_0} rightarrow
+begin{cases}
+rho &text{if } m = 0
+rho/2 &text{if } m = 1
+0 &text{otherwise}
+end{cases}
+end{equation}
+
+The magnetic vector potential for {math}`m = 0` is constructed such that only {math}`A_theta` is non-zero
+begin{align}
+A_rho &= 0 CRNO
+A_theta &= re left[
+sum_{n=-N/2}^{N/2-1} frac{i}{k_n} , e^{i , k_n , z} , b_0(n) , I_1(k_n , rho) right]
+A_z &= 0 nonumber
+end{align}
+For {math}`m ne 0`, the vector potential is chosen so that {math}`A_theta` is zero.
+begin{align}
+A_rho &= re left[
+sum_{n=-N/2}^{N/2-1} frac{-i , rho}{2 , m} , e^{i , k_n , z} ,
+cos (m , theta - theta_{0m}) , b_m(n) ,
+Big[ I_{m-1}(k_n , rho) - I_{m+1}(k_n , rho) Big] right] CRNO
+A_theta &= 0
+A_z &= re left[
+sum_{n=-N/2}^{N/2-1} frac{-i , rho}{m} , e^{i , k_n , z} ,
+cos (m , theta - theta_{0m}) , b_m(n) ,
+I_m(k_n , rho) right] nonumber
+end{align}
+
+Note: The description of the field using `"generalized gradients"`{footcite:p}`Newton:map` is similar to
+the above equations. The difference is that, with the generalized gradient formalism, terms in
+{math}`theta` and {math}`rho` are expanded in a Taylor series in {math}`x` and {math}`y`.
+
+%-----------------------------------------------------------------
+(s:cylind.ac)=
+## AC Cylindrical Map Decomposition
+For RF fields, the `cylindrical` mode parametrization used by Bmad essentially
+follows Abell{footcite:p}`Abell:RF-maps`. The electric field is the real part of the complex field
+begin{equation}
+bfE({bf r}) = sum_{j=1}^M , bfE_j({bf r}) , exp[{-2 pi i , (f_j , t + phi_{0j})}]
+label{eseei}
+end{equation}
+where {math}`M` is the number of modes. Each mode satisfies the vector Helmholtz
+equation
+begin{equation}
+nabla^2 bfE_j + k_{tj}^2 , bfE_j = 0
+label{bke}
+end{equation}
+where {math}`k_{tj} = 2 , pi , f_j/c` with {math}`f_j` being the mode frequency.
+
+The individual modes vary azimuthally as {math}`cos(m , theta - theta_0)` where {math}`m` is a non-negative
+integer. [in this and in subsequent equations, the mode index {math}`j` has been dropped.] For the {math}`m =`
+0{math}` modes, there is an accelerating mode whose electric field is in the form`
+begin{align}
+E_rho({bf r}) &= sum_{n=-N/2}^{N/2-1} -e^{i , k_n , z} ,
+i , k_n , e_0(n) , wt I_1(kappa_n, rho) CRNO
+E_theta({bf r}) &= 0
+E_z({bf r}) &= sum_{n=-N/2}^{N/2-1}e^{i , k_n , z} ,
+e_0(n) , wt I_0(kappa_n, rho) nonumber
+end{align}
+where {math}`wt I_m` is
+begin{equation}
+wt I_m (kappa_n, rho) equiv frac{I_m(kappa_n , rho)}{kappa_n^m}
+end{equation}
+with {math}`I_m` being a modified Bessel function first kind, and {math}`kappa_n` is given by
+begin{equation}
+kappa_n = sqrt{k_n^2 - k_t^2} =
+begin{cases}
+sqrt{k_n^2 - k_t^2} & |k_n| > k_t
+-i , sqrt{k_t^2 - k_n^2} & k_t > |k_n|
+end{cases}
+end{equation}
+with
+begin{equation}
+k_n = frac{2 pi , n}{N , dz}
+end{equation}
+{math}`N` is the number of points where {math}`E_{zc}` is evaluated, and {math}`dz` is
+the distance between points. The length of the field region is {math}`(N-1) , dz`. When
+{math}`kappa_n` is imaginary, {math}`I_m(kappa_n , rho)` can be evaluated
+through the relation
+begin{equation}
+I_m(-i , x) = i^{-m} , J_m(x)
+end{equation}
+where {math}`J_m` is a Bessel function of the first kind.
+The {math}`e_0` coefficients can be obtained given knowledge of the field at some radius {math}`R` via
+begin{align}
+e_0(n) &= frac{1}{wt I_0(kappa_n, R)} , frac{1}{N} , sum_{p=0}^{N-1}
+e^{-2 pi i n p / N} , E_{z}(R, p , dz)
+end{align}
+
+The non-accelerating {math}`m = 0` mode has an electric field in the form
+begin{align}
+E_rho({bf r}) &= E_z({bf r}) = 0 CRNO
+E_theta({bf r}) &= sum_{n=-N/2}^{N/2-1}e^{i k_n z} ,
+b_0(n) , wt I_1(kappa_n, rho)
+end{align}
+where the {math}`b_0` coefficients can be obtained given knowledge of the field at some radius {math}`R` via
+begin{equation}
+b_0(n) = frac{1}{wt I_1(kappa_n, R)} , frac{1}{N} , sum_{p=0}^{N-1}
+e^{-2 pi i , n , p / N} , E_{theta}(R, p , dz)
+end{equation}
+
+For positive {math}`m`, the electric field is in the form
+begin{align}
+E_rho({bf r}) &= sum_{n=-N/2}^{N/2-1}
+-i , e^{i , k_n , z} ,
+left[
+k_n , e_m(n) , wt I_{m+1}(kappa_n, rho) +
+b_m(n) , frac{wt I_m(kappa_n, rho)}{rho}
+right]
+cos(m , theta - theta_{0m}) CRNO
+E_theta({bf r}) &= sum_{n=-N/2}^{N/2-1}
+-i , e^{i , k_n , z} ,
+left[
+k_n , e_m(n) , wt I_{m+1}(kappa_n, rho) , + right.
+& left. qquad qquad qquad qquad qquad qquad
+b_m(n) , left( frac{wt I_m(kappa_n, rho)}{rho} -
+frac{1}{m} , wt I_{m-1}(kappa_n, rho) right)
+right]
+sin(m , theta - theta_{0m}) CRNO
+E_z({bf r}) &= sum_{n=-N/2}^{N/2-1}e^{i , k_n , z} ,
+e_m(n) , wt I_m(kappa_n, rho) cos(m , theta - theta_{0m}) nonumber
+end{align}
+The `e_m` and `b_m` coefficients can be obtained given knowledge of the field at some radius {math}`R` via
+begin{align}
+e_m(n) &= frac{1}{wt I_m(kappa_n, R)} , frac{1}{N} , sum_{p=0}^{N-1}
+e^{-2 , pi , i , n , p / N} , E_{zc}(R, p , dz) CRNO
+b_m(n) &= frac{R}{wt I_m(kappa_n, R)} left[
+frac{1}{N} , sum_{p=0}^{N-1}
+i , e^{-2 , pi , i , n , p / N} , E_{rho c}(R, p , dz) -
+k_n , e_m(n) , wt I_{m+1}(kappa_n, R)
+right]
+end{align}
+where {math}`E_{rho c}`, {math}`E_{theta s}`, and {math}`E_{z c}` are defined by
+begin{align}
+E_rho(R, theta, z) &= E_{rho c}(R, z) , cos(m , theta - theta_{0m}) CRNO
+E_theta(R, theta, z) &= E_{theta s}(R, z) , sin(m , theta - theta_{0m})
+label{erpze}
+E_z(R, theta, z) &= E_{z c}(R, z) , cos(m , theta - theta_{0m}) nonumber
+end{align}
+
+The above mode decomposition was done in the gauge where the scalar potential {math}`psi` is zero. The
+electric and magnetic fields are thus related to the vector potential {math}`bfA` via
+begin{equation}
+bfE = -partial_t , bfA, qquad bfB = nabla times bfA
+end{equation}
+Using Eq{eseei}, the vector potential can be obtained from the electric field via
+begin{equation}
+bfA_j = frac{-i , bfE_j}{2 , pi , f_j}
+label{aiew}
+end{equation}
+
+Symplectic tracking through the RF field is discussed in Section~[](#s:symp.track). For the
+fundamental accelerating mode, the vector potential can be analytically integrated using the
+identity
+begin{equation}
+int dx ,frac{x , I_1 (a , sqrt{x^2+y^2})}{sqrt{x^2+y^2}} =
+frac{1}{a} , I_0 (a , sqrt{x^2+y^2})
+end{equation}
+
+%-----------------------------------------------------------------
+(s:gen.grad.phys)=
+## Generalized Gradient Map Field Modeling
+Bmad has a number of `field map` models that can be used to model electric or magnetic fields
+([](#s:fieldmap)). One model involves what are called `generalized gradients`{footcite:p}`Venturini:magmaps`.
+This model is restricted to modeling DC magnetic or electric fields. In a lattice file, the
+generalized gradient field model is specified using the `gen_grad_map` attribute as explained
+in Sec.~[](#s:gen.grad.map).
+
+The electric and magnetic fields are both described by a scalar potentialfootnote
+{
+Notice the negative sign here and in Eq{ppmpp} compared to Venturini et al.{footcite:p}`Venturini:magmaps`.
+This is to keep the definition of the electric scalar potential {math}`psi_E` consistent with the normal
+definition.
+begin{equation}
+bfB = -nabla , psi_B, qquad bfE = -nabla , psi_E
+label{bpep2}
+end{equation}
+The scalar potential is then decomposed into azimuthal components
+begin{equation}
+psi = sum_{m = 1}^infty psi_{m,s} , sin(m theta) + sum_{m = 0}^infty psi_{m,c} , cos(m theta)
+end{equation}
+where the {math}`psi_{m,alpha}` ({math}`alpha = c,s`) are characterized by a using functions
+{math}`C_{m,alpha}(z)` which are functions along the longitudinal {math}`z`-axis.
+begin{equation}
+psi_{m,alpha} = sum_{n = 0}^infty frac{(-1)^{n+1} m!}{4^n , n! , (n+m)!}
+, rho^{2n+m} , C_{m,alpha}^{[2n]}(z)
+label{ppmpp}
+end{equation}
+The notation {math}`[2n]` indicates the {math}`2n`Th derivative of {math}`C_{m,alpha}(z)`.
+
+From Eq{ppmpp} the field is given by
+begin{align}
+B_rho &= sum_{m = 1}^{infty} sum_{n = 0}^infty frac{(-1)^n , m! , (2n+m)}{4^n , n! , (n+m)!}
+rho^{2n+m-1} left[ C^{[2n]}_{m,s}(z) , sin mtheta + C^{[2n]}_{m,c}(z) , cos mtheta right] + CRNO
+& hspace{25 em} sum_{n = 1}^infty frac{(-1)^n , 2n}{4^n n! , n!} rho^{2n-1} , C^{[2n]}_{0,c}(z) CRNO
+B_theta &= sum_{m = 1}^{infty} sum_{n = 0}^infty frac{(-1)^n , m! , m}{4^n , n! , (n+m)!}
+rho^{2n+m-1} left[ C^{[2n]}_{m,s}(z) , cos mtheta - C^{[2n]}_{m,c}(z) , sin mtheta right]
+B_z &= sum_{m = 0}^{infty} sum_{n = 0}^infty frac{(-1)^n , m!}{4^n , n! , (n+m)!}
+rho^{2n+m} left[ C^{[2n+1]}_{m,s}(z) , sin mtheta + C^{[2n+1]}_{m,c}(z) , cos mtheta right] nonumber
+end{align}
+Even though the scalar potential only involves even derivatives of {math}`C_{m,alpha}`, the field is
+dependent upon the odd derivatives as well. The multipole index {math}`m` is such that {math}`m = 0` is for
+solenoidal fields, {math}`m = 1` is for dipole fields, {math}`m = 2` is for quadrupolar fields, etc. The
+`sin`--like generalized gradients represent normal (non-skew) fields and the `cos`--like one
+represent skew fields. The on-axis fields at {math}`x=y=0` are given by:
+begin{equation}
+(B_x, B_y, B_z) = (C_{1,c}, C_{1,s}, -C^{[1]}_{0,c})
+end{equation}
+
+The magnetic vector potential for {math}`m = 0` is constructed such that only {math}`A_theta` is non-zero
+begin{align}
+A_rho &= 0 CRNO
+A_theta &= sum_{n=1}^infty
+frac{(-1)^{n+1} , 2n}{4^n , n! , n!} rho^{2n-1} , C_{0,c}^{[2n-1]}
+A_z &= 0 nonumber
+end{align}
+For {math}`m ne 0`, the vector potential is chosen so that {math}`A_theta` is zero.
+begin{align}
+A_rho &= sum_{m = 1}^{infty} sum_{n=0}^infty
+frac{(-1)^{n} , (m-1)!}{4^n , n! , (n+m)!} rho^{2n+m+1} ,
+left[ C_{m,s}^{[2n+1]} cos(m theta) - C_{m,c}^{[2n+1]} , sin(m theta) right] CRNO
+A_theta &= 0
+A_z &= sum_{m = 1}^{infty} sum_{n=0}^infty
+frac{(-1)^n , (m-1)! , (2n+m)}{4^n , n! , (n+m)!} rho^{2n+m} ,
+left[ -C_{m,s}^{[2n]} cos(m theta) + C_{m,c}^{[2n]} , sin(m theta) right]
+nonumber
+end{align}
+
+The functions {math}`C_{m,alpha}(z)` are characterized by specifying {math}`C_{m,alpha}(z_i)` and derivatives
+at equally spaced points {math}`z_i`, up to some maximum derivative order {math}`N_{m,alpha}` chosen by the
+user. Interpolation is done by constructing an interpolating polynomial ("non-smoothing spline")
+for each GG of order {math}`2N_{m,alpha}+1` for each
+interval {math}`[z_i, z_{i+1}]` which has the correct derivatives from {math}`0` to {math}`N_{m,alpha}` at points {math}`z_i` and
+{math}`z_{i+1}`. The coefficients of the interpolating polynomial are easily calculated by inverting the
+appropriate matrix equation.
+
+The advantages of a generalized gradient map over a cylindrical or Cartesian map decomposition come
+from the fact that with generalized gradients the field at some point {math}`(x,y,z)` is only dependent
+upon the value of {math}`C_{m,alpha}(z)` and derivatives at points {math}`z_i` and {math}`z_{i+1}` where {math}`z` is in
+the interval {math}`[z_i, z_{i+1}]`. This is in contrast to the cylindrical or Cartesian map decomposition
+where the field at any point is dependent upon {em all} of the terms that characterize the
+field. This "`locality`" property of generalized gradients means that calculating coefficients
+is easier (the calculation of {math}`C_{m,alpha}(z)` at {math}`z_i` can be done using only the field near {math}`z_i`
+independent of other regions) and it is easier to ensure that the field goes to zero at the
+longitudinal ends of the element. Additionally, the evaluation is faster since only coefficients to
+either side of the evaluation point contribute. The disadvantage of generalized gradients is that
+since the derivatives are truncated at some order {math}`N_{m,alpha}`, the resulting field does not satisfy
+Maxwell's equations with the error as a function of radius scaling with the power {math}`rho^{m+N_{m,alpha}}`.
+
+It is sometimes convenient to express the fields in terms of Cartesian coordinates. For sine like
+even derivatives {math}`C_{m,s}^{[2n]}` the conversion is
+begin{align}
+left( B_x, B_y right) &= left( costheta , B_rho - sintheta , B_theta, ,
+sintheta , B_rho + costheta , B_theta right) CRNO
+&= frac{(-1)^n , m!}{4^n n! , (n+m)!} , C_{m,s}^{[2n]} , Big[ (n+m) , (x^2 + y^2)^n ,
+left( S_{xy}(m-1), , C_{xy}(m-1) right) , +
+label{bbtb}
+&hspace{13em} n , (x^2 + y^2)^{n-1} ,
+left( S_{xy}(m+1), , -C_{xy}(m+1) right) Big] nonumber
+end{align}
+and for the sine like odd derivatives {math}`C_{m,s}^{[2n+1]}`
+begin{equation}
+B_z = frac{(-1)^n , m!}{4^n n! , (n+m)!}
+(x^2 + y^2)^n , C^{[2n+1]}_{m,s}(z) , S_{xy}(m)
+end{equation}
+where the last term in Eq{bbtb} is only present for {math}`n > 0`.
+begin{align}
+S_{xy}(m) &equiv rho^m , sin mtheta =
+sum_{r=0}^{2r le m-1} (-1)^r begin{pmatrix} m cr 2r+1 end{pmatrix} ,
+x^{m-2r-1} , y^{2r+1} CRNO
+C_{xy}(m) &equiv rho^m , cos mtheta =
+sum_{r=0}^{2r le m} (-1)^r begin{pmatrix} m cr 2r end{pmatrix} ,
+x^{m-2r} , y^{2r}
+end{align}
+The conversion for the cosine like derivatives is:
+begin{align}
+left( B_x, B_y right) &=
+frac{(-1)^n , m!}{4^n n! , (n+m)!} , C_{m,c}^{[2n]} , Big[ (n+m) , (x^2 + y^2)^n ,
+left( C_{xy}(m-1), , -S_{xy}(m-1) right) , + CRNO
+&hspace{13em} n , (x^2 + y^2)^{n-1} ,
+left( C_{xy}(m+1), , S_{xy}(m+1) right) Big]
+B_z &= frac{(-1)^n , m!}{4^n n! , (n+m)!}
+(x^2 + y^2)^n , C^{[2n+1]}_{m,c}(z) , C_{xy}(m) nonumber
+end{align}
+
+%-----------------------------------------------------------------
+(s:rf.fields)=
+## RF fields
+The following describes the how RF fields are calculated when the `field_calc`
+attribute of an RF element is set to `bmad_standard`.footnote
+{
+Notice that the equations here are only relavent with the `tracking_method` for an RF element set
+to a method like `runge_kutta` where tracking through the field of an element is done. For
+`bmad_standard` tracking, Equations for `lcavity` tracking are shown in [](#s:lcavity.std)
+and `rfcavity` tracking in [](#s:rfcavity.std).
+Also see Section~[](#s:rf.fringe) for how fringe fields are calculated.
+
+With `cavity_type` set to `traveling_wave`, the setting of `longitudinal_mode` is ignored
+and the field is given by
+begin{align}
+E_s(r, phi, s, t) &= G , cosbigl( omega , t - k , s + 2 , pi , phi bigr) CRNO
+E_r(r, phi, s, t) &= -frac{r}{2} , G , k , sinbigl( omega , t - k , s + 2 , pi , phi bigr)
+B_phi(r, phi, s, t) &= -frac{r}{2 , c} , G , k , sinbigl( omega , t - k , s + 2 , pi , phi bigr) nonumber
+label{egot}
+end{align}
+where {math}`G` is the accelerating gradient, {math}`k = omega / c` is the wave number with {math}`omega` being the
+RF frequency.
+
+For standing wave cavities, with `cavity_type` set to `standing_wave`, the RF fields are
+modeled as {math}`N` half-wave cells, each having a length of {math}`lambda/2` where {math}`lambda = 2 , pi / k`
+is the wavelength. If the length of the RF element is not equal to the length of {math}`N` cells, the
+"active region" is centered in the element and the regions to either side are treated as field
+free.
+
+The field in the standing wave cell is modeled either with a {math}`p = 0` or {math}`p = 1` longitudinal mode
+(set by the `longitudinal_mode` element parameter). The {math}`p = 1` longitudinal mode models the
+fields as a pillbox with the transverse wall at infinity as detailed in Chapter 3, Section VI of
+reference {footcite:p}`Lee:Physics`
+begin{align}
+E_s(r, phi, s, t) &= 2 , G , cos(k , s) , cos(omega , t + 2 , pi , phi) CRNO
+E_r(r, phi, s, t) &= r , G , k , sin(k , s) , cos(omega , t + 2 , pi , phi)
+B_phi(r, phi, s, t) &= -frac{r}{c} , G , k , cos(k , s) , sin(omega , t + 2 , pi , phi) nonumber
+label{egot2}
+end{align}
+The overall factor of 2 in the equation is present to ensure that an ultra-relativistic particle
+entering with {math}`phi = 0` will experience an average gradient equal to {math}`G`.
+
+For the {math}`p = 0` longitudinal mode (which is the default), a "pseudo TM{math}`_{010}`" mode is used that
+has the correct symmetry:
+begin{align}
+E_s(r, phi, s, t) &= 2 , G , sin(k , s) , sin(omega , t + 2 , pi , phi) CRNO
+E_r(r, phi, s, t) &= -r , G , k , cos(k , s) , sin(omega , t + 2 , pi , phi)
+B_phi(r, phi, s, t) &= frac{r}{c} , G , k , sin(k , s) , cos(omega , t + 2 , pi , phi) nonumber
+label{egot3}
+end{align}
+```{footbibliography}
+```
diff --git a/docs/src/enums.md b/docs/src/enums.md
new file mode 100644
index 0000000..73df5a6
--- /dev/null
+++ b/docs/src/enums.md
@@ -0,0 +1,217 @@
+(c:enums)=
+# Enums and Holy Traits
+Enums ([](#s:enums)) and Holy traits ([](#s:holy)) are used to define "switches" which are
+variables whose value can be one of a set of named constants.
+A web search will provide documentation.
+
+The advantage of Holy traits is that they can be used with function dispatch. The disadvantage is
+that the same Holy trait value name cannot be used with multiple groups. Generally, if function
+dispatch is not needed (which is true for the majority of cases), switch groups are defined using enums.
+
+%---------------------------------------------------------------------------------------------------
+(s:enums)=
+## Enums
+AcceleratorLattice uses the package `EnumX.jl` to define enums (enumerated numbers).
+Essentially what happens is that for each enum group there is a group name, For example `BendType`,
+along with a set of values which, for `BendType`, is `SECTOR` and `RECTANGULAR`. Values
+are always referred to by their "full" name which in this example is `BendType.SECTOR` and
+`BendType.RECTANGULAR`. Exception: `BranchGeometry.CLOSED` and `BranchGeometry.OPEN` are
+used often enough so that the constants `OPEN` and `CLOSED` are defined.
+
+The group name followed by a `.T` suffix denotes the enum type.
+For example:
+```{code} yaml
+struct ApertureParams <: EleParams
+aperture_type::ApertureShape.T = ApertureShape.ELLIPTICAL
+aperture_at::BodyLoc.T = BodyLoc.ENTRANCE_END
+...
+```
+
+The `enum` function is used to convert a list into an enum group and export the names.
+The `enum` function also overloads `Base.string` so that something like `string(Lord.NOT)`
+will return `"Lord.NOT"` instead of just `"NOT"` (an issue with the EnumX.jl package).
+See the documentation for `enum` for more details.
+
+The `enum_add` function is used to add values to an existing enum group. See the documentation for
+`enum_add` for more details. This function is used with code extensions to customize AcceleratorLattice.
+
+The enum groups are:
+```{csv-table}
+:align: center
+:header: "Element", "Element"
+[BendType](#s:bendtype), [Slave](#s:slave.enum)
+[BodyLoc](#s:bodyloc), [Loc](#s:loc)
+[BranchGeometry](#s:branchgeometry), [Select](#s:select)
+[Cavity](#s:cavity), [ExactMultipoles](#s:exactmultipoles)
+[Lord](#s:lord.enum), [FiducialPt](#s:fiducialpt)
+[ParticleState](#s:particlestate), [](#)
+```
+%---------------------------------------------------------------------------------------------------
+(s:bendtype)=
+## BendType Enum Params
+Type of Bend element. Possible values:
+- BendType.SECTOR - Sector shape
+- BendType.RECTANGULAR - Rectangular shape
+
+`BendType` is used with the `bend_type` parameter of the `BendParams` parameter group
+([](#s:bend.g)). The `bend_type` parameter gives the "logical" shape of the bend.
+The setting of `bend_type` is only relavent when the bend curvature is varied.
+See [](#s:bend.g) for more details.
+
+%---------------------------------------------------------------------------------------------------
+(s:bodyloc)=
+## BodyLoc Enum Params
+Longitudinal location with respect to an element's body coordinates.
+Possible values:
+- BodyLoc.ENTRANCE_END - Body entrance end
+- BodyLoc.CENTER - Element center
+- BodyLoc.EXIT_END - Body exit end
+- BodyLoc.BOTH_ENDS - Both ends
+- BodyLoc.NOWHERE - No location
+- BodyLoc.EVERYWHERE - Everywhere
+
+`BodyLoc` enums are are useful to locate things that are "attached" to an element.
+For example, specifying where apertures are placed.
+
+%---------------------------------------------------------------------------------------------------
+(s:branchgeometry)=
+## BranchGeometry Enum Params
+Geometry of a lattice branch. Used for setting a branche's `geometry` parameter.
+Possible values:
+- BranchGeometry.OPEN - Open geometry like a Linac. Default
+- BranchGeometry.CLOSED - Closed geometry like a storage ring.
+
+A branch with a `CLOSED` geometry is something like a storage ring where the particle beam
+recirculates through the machine. A branch with an `OPEN` geometry is something like a linac.
+In this case, the initial Twiss parameters need to be
+specified at the beginning of the branch. If the
+`geometry` is not specified, `OPEN` is the default.
+
+Since the geometry is widely used, `OPEN` and `CLOSED` have been defined and
+can be used in place of `BranchGeometry.OPEN` and `BranchGeometry.CLOSED`.
+
+Notice that by specifying a `CLOSED` geometry, it does {em not} mean that the downstream end of
+the last element of the branch has the same floor coordinates ([](#s:floor)) as the floor
+coordinates at the beginning. Setting the geometry to `CLOSED` simply signals to a program to
+compute the periodic orbit and periodic Twiss parameters as opposed to calculating orbits and Twiss
+parameters based upon initial orbit and Twiss parameters given at the beginning of the branch. Indeed,
+it is sometimes convenient to treat branches as closed even though there is no closure in the floor
+coordinate sense. For example, when a machine has a number of repeating "periods", it may be
+convenient to only use one period in a simulation. Since AcceleratorLattice ignores closure in the floor
+coordinate sense, it is up to the lattice designer to ensure that a branch is truly geometrically
+closed if that is desired.
+
+%---------------------------------------------------------------------------------------------------
+(s:cavity)=
+## Cavity Enum Params
+Type of RF cavity.
+Possible values:
+- Cavity.STANDING_WAVE - Standing wave cavity
+- Cavity.TRAVELING_WAVE - Traveling wave cavity
+
+%---------------------------------------------------------------------------------------------------
+(s:particlestate)=
+## ParticleState Enum Params
+State of a particle.
+Possible values:
+- ParticleState.PREBORN - State before emission from cathode.
+- ParticleState.ALIVE - Alive and kicking.
+- ParticleState.LOST - Particle has been lost.
+- ParticleState.LOST_NEG_X - Hit aperture in the -x direction.
+- ParticleState.LOST_POS_X - Hit aperture in the +x direction.
+- ParticleState.LOST_NEG_Y - Hit aperture in the -y direction.
+- ParticleState.LOST_POS_Y - Hit aperture in the +y direction.
+- ParticleState.LOST_PZ - Lost all forward momentum.
+- ParticleState.LOST_Z - Out of RF bucket.
+
+The `LOST` value is used when it is not possible to assign the particle state to one of the
+other lost values.
+
+The `.LOST_PZ` value is used by {math}`s`
+able to handle particles changing their longitudinal motion direction. For tracking something
+like dark current electrons which can go back and forth longitudinally, a time based tracker
+is needed.
+
+%---------------------------------------------------------------------------------------------------
+(s:loc)=
+## Loc Enum Params
+Longitudinal location with respect to element's branch coordinates.
+Possible values:
+- Loc.UPSTREAM_END - Upstream element end
+- Loc.CENTER - center of element
+- Loc.INSIDE - Somewhere inside
+- Loc.DOWNSTREAM_END - Downstream element end
+
+
+%---------------------------------------------------------------------------------------------------
+(s:select)=
+## Select Enum Params
+Specifies where to select if there is a choice of elements or positions.
+Possible values:
+- Select.UPSTREAM - Select upstream
+- Select.DOWNSTREAM - Select downstream
+
+
+%---------------------------------------------------------------------------------------------------
+(s:exactmultipoles)=
+## ExactMultipoles Enum Params
+How multipoles are handled in a Bend element.
+Possible values:
+- ExactMultipoles.OFF - Bend curvature not taken into account.
+- ExactMultipoles.HORIZONTALLY_PURE - Coefficients correspond to horizontally pure multipoles.
+- ExactMultipoles.VERTICALLY_PURE - Coefficients correspond to vertically pure multipoles.
+
+
+%---------------------------------------------------------------------------------------------------
+(s:fiducialpt)=
+## FiducialPt Enum Params
+Fiducial point location with respect to element's branch coordinates.
+Possible values:
+- FiducialPt.ENTRANCE_END - Entrance end of element
+- FiducialPt.CENTER - Center of element
+- FiducialPt.EXIT_END - Exit end of element
+- FiducialPt.NONE - No point chosen
+
+
+%---------------------------------------------------------------------------------------------------
+(s:holy)=
+## Holy Traits
+`Holy traits` (named after Tim Holy) are a design pattern in Julia that behave similarly
+to `enums` ([](#s:enum)). A Holy trait group consists of a base abstract type with a set of values
+(traits) which are abstract types that inherit from the base abstract type.
+
+The advantage of Holy traits is that they can be used with function dispatch. The disadvantage is
+that the same Holy trait value name cannot be used with multiple groups.
+
+There is a convenience function `holy_traits` which will define a traits group, export the names,
+and create a docstring for the group. Values can be added to an existing group by defining a
+new struct that inherits from the group abstract type.
+
+Example: To extend the `EleGeometry` trait group to include the value `HELIX_GEOMETRY` do
+```{code} yaml
+abstract type HELIX_GEOMETRY <: EleGeometry
+```
+
+%---------------------------------------------------------------------------------------------------
+(s:apertureshape)=
+## ApertureShape Holy Trait Params
+The shape of an aperture.
+- RECTANGULAR - Rectangular shape.
+- ELLIPTICAL - Elliptical shape.
+- VERTEX - Shape defined by set of vertices.
+- CUSTOM_SHAPE - Shape defined with custom function.
+
+%---------------------------------------------------------------------------------------------------
+(s:elegeometry)=
+## EleGeometry Holy Trait Params
+The geometry of the reference orbit through an element.
+- STRAIGHT - Straight line geometry.
+- CIRCULAR - Circular "bend-like" geometry.
+- ZERO_LENGTH - Zero longitudinal length geometry.
+- PATCH_GEOMETRY - Patch element like geometry.
+- GIRDER_GEOMETRY - Support girder-like geometry.
+- CRYSTAL_GEOMETRY - Crystal geometry.
+- MIRROR_GEOMETRY - Mirror geometry.
+
+```{footbibliography}
+```
diff --git a/docs/src/figures/alignment-ref.svg b/docs/src/figures/alignment-ref.svg
new file mode 100644
index 0000000..dc3afbe
--- /dev/null
+++ b/docs/src/figures/alignment-ref.svg
@@ -0,0 +1,1350 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/alignment2.svg b/docs/src/figures/alignment2.svg
new file mode 100644
index 0000000..ceddb0d
--- /dev/null
+++ b/docs/src/figures/alignment2.svg
@@ -0,0 +1,1093 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/apertures.svg b/docs/src/figures/apertures.svg
new file mode 100644
index 0000000..e1a3265
--- /dev/null
+++ b/docs/src/figures/apertures.svg
@@ -0,0 +1,1303 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/bend.svg b/docs/src/figures/bend.svg
new file mode 100644
index 0000000..0ee0713
--- /dev/null
+++ b/docs/src/figures/bend.svg
@@ -0,0 +1,2727 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/coordinates.svg b/docs/src/figures/coordinates.svg
new file mode 100644
index 0000000..8807de9
--- /dev/null
+++ b/docs/src/figures/coordinates.svg
@@ -0,0 +1,1340 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/ele-coord-frame.svg b/docs/src/figures/ele-coord-frame.svg
new file mode 100644
index 0000000..4bc728f
--- /dev/null
+++ b/docs/src/figures/ele-coord-frame.svg
@@ -0,0 +1,4000 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/floor-coords.svg b/docs/src/figures/floor-coords.svg
new file mode 100644
index 0000000..811370e
--- /dev/null
+++ b/docs/src/figures/floor-coords.svg
@@ -0,0 +1,1104 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/fork-patch.svg b/docs/src/figures/fork-patch.svg
new file mode 100644
index 0000000..dca6220
--- /dev/null
+++ b/docs/src/figures/fork-patch.svg
@@ -0,0 +1,4733 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/girder.svg b/docs/src/figures/girder.svg
new file mode 100644
index 0000000..84f1212
--- /dev/null
+++ b/docs/src/figures/girder.svg
@@ -0,0 +1,3652 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/mirror.svg b/docs/src/figures/mirror.svg
new file mode 100644
index 0000000..854143f
--- /dev/null
+++ b/docs/src/figures/mirror.svg
@@ -0,0 +1,1899 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/patch-between.svg b/docs/src/figures/patch-between.svg
new file mode 100644
index 0000000..7a1d3cd
--- /dev/null
+++ b/docs/src/figures/patch-between.svg
@@ -0,0 +1,4062 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/patch-problem.svg b/docs/src/figures/patch-problem.svg
new file mode 100644
index 0000000..4aa9dbe
--- /dev/null
+++ b/docs/src/figures/patch-problem.svg
@@ -0,0 +1,3721 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/patch.svg b/docs/src/figures/patch.svg
new file mode 100644
index 0000000..997ebd6
--- /dev/null
+++ b/docs/src/figures/patch.svg
@@ -0,0 +1,3746 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/scibmad.svg b/docs/src/figures/scibmad.svg
new file mode 100644
index 0000000..c90595d
--- /dev/null
+++ b/docs/src/figures/scibmad.svg
@@ -0,0 +1,981 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/superimpose-positioning.svg b/docs/src/figures/superimpose-positioning.svg
new file mode 100644
index 0000000..32de519
--- /dev/null
+++ b/docs/src/figures/superimpose-positioning.svg
@@ -0,0 +1,996 @@
+
+
\ No newline at end of file
diff --git a/docs/src/figures/tilt-bend.svg b/docs/src/figures/tilt-bend.svg
new file mode 100644
index 0000000..caa5df4
--- /dev/null
+++ b/docs/src/figures/tilt-bend.svg
@@ -0,0 +1,1282 @@
+
+
\ No newline at end of file
diff --git a/docs/src/index.md b/docs/src/index.md
index b72cfca..d419712 100644
--- a/docs/src/index.md
+++ b/docs/src/index.md
@@ -1,43 +1,37 @@
-# AcceleratorLattice.jl
+# Particle Accelerator Lattice Standard
+
+This standard is an effort to create a standard to promote lattice information exchange for particle accelerators.
+
+```{toctree}
+:maxdepth: 1
+:caption: Lattice Construction and Manipulation
+
+introduction.md
+ele-anatomy.md
+ele-types.md
+enums.md
+ele-param-groups.md
+construction.md
+multipass.md
+superimpose.md
+custom.md
+utilities.md
+```
+
+```{toctree}
+:maxdepth: 1
+:caption: Conventions and Physics
+
+coordinates.md
+electromagnetic-fields.md
+```
+
+```{toctree}
+:maxdepth: 1
+:caption: Developer's Guide
+
+new-ele.md
+bookkeeping.md
+design.md
+```
-*Lattice instantiation and manipulation for high energy particle accelerators.*
-
-Part of the Bmad-Julia project for simulations of charged-particle and X-rays
-in accelerators and storage rings.
-
-This documentation serves as an introduction and quick reference guide to `AcceleratorLattice.jl`.
-The depth manual can be found the `Tracking Packages` section.
-
-## Overview
-
-With the `AcceleratorLattice.jl` package accelerator lattices can be constructed and manipulated.
-This does not include tracking. Packages that implement tracking are listed in [Tracking Packages]
-
-## Nomenclature
-
-- `Element`: Lattice elements are the basic building block for describing an accelerator. Lattice elements are structs that inherit from the abstract type `Lattice`. Example element structs are `Quadrupole` and `RFCavity`.
-
-- `Branch`: A lattice branch is essentially an array of lattice elements. All branches are of type `Branch`. Branches come in two types: There are "tracking" branches through which particles can be tracked and there are "lord" branches which hold a collection of "lord" elements which are elements can control the parameters of other elements but are not tracked through directly.
-
-- `lattice`: A lattice is an array of branches. All lattices are of type `Lattice`. Tracking branches can be connected together to form an entire accelerator complex. For example, a branch representing an injection line can be connected to a branch representing a storage ring and there can be multiple branches representing extraction lines connected to the storage ring branch.
-
-## Setup
-
-## Basic Usage
-
-## Tracking Packages
-
-Since Bmad-Julia is in the initial stages of development, currently there are no packages for tracking.
-
-## Cheat Sheet
-
-Functions and Structs sorted by functionality.
-
-## Programming conventions
-
-Follow general Julia programming conventions with two spaces per indent.
-
-Non-ASCII characters in code can be problematical in that some of them are hard to decipher and,
-depending upon the editor being used, hard to type. So use of non-ASCII characters should be
-avoided unless the use is clearly beneficial. One example of acceptable use is the notin character "∉" since
-there is no ASCII equivalent.
\ No newline at end of file
diff --git a/docs/src/introduction.md b/docs/src/introduction.md
new file mode 100644
index 0000000..1efd62d
--- /dev/null
+++ b/docs/src/introduction.md
@@ -0,0 +1,295 @@
+(c:introduction)=
+# Introduction and Concepts
+
+%---------------------------------------------------------------------------
+(s:introduction)=
+## Introduction
+
+This chapter is an introduction to the AcceleratorLattice package which is part of the
+greater SciBmad ecosystem of toolkits and programs for accelerator simulations. With AcceleratorLattice,
+lattices can be constructed and manipulated. Essentially, a `lattice` instance contains
+a set of "`branches`" and a branch contains
+an array of lattice `elements` with each element representing an object like a magnet
+or a RF cavity. A branch can be used to describe such
+things as LINACs, storage rings, injection lines, X-ray beam lines, etc. Different branches in a
+lattice can be connected together. For example, an injection line branch can be connected to a storage
+ring branch or the lines of two rings can be connected together to form a colliding beam machine.
+This ability to describe the interconnections between branches means that
+a lattice instance can hold all the information about an entire machine complex from beam creation
+to dump lines enabling a single lattice to be used as the basis of start-to-end simulations.
+
+The sole purpose of the AcceleratorLattice package is to implement methods for lattice construction.
+Other stuff, like tracking and lattice analysis (for example, calculating
+closed orbits and Twiss functions), is left to other packages in the SciBmad ecosystem.
+
+%---------------------------------------------------------------------------
+(s:doc)=
+## Documentation
+
+There are three main sources of documentation of the AcceleratorLattice package.
+One source is this PDF manual which gives in-depth documentationon.
+A second source is the web based introduction and overview guide.
+Finally, functions, structs and other objects are documented in the code files themselves.
+Taking advantage of Julia's built-in documentation system, this code-file documentation
+can be accessed via using Julia's REPL.
+
+%---------------------------------------------------------------------------
+(s:history)=
+## Brief History
+
+AcceleratorLattice has it's origins in the Bmad{footcite:p}`Sagan:Bmad2006` ecosystem of toolkits and programs
+developed over several decades at Cornell University.
+While the development of AcceleratorLattice is heavily influenced by the
+experience --- both good and bad --- of the development and use of Bmad as well as experience
+with other accelerator simulation programs, the code of the two are
+completely separate with Bmad being written in Fortran and AcceleratorLattice being written in Julia.
+
+The Julia language itself is used as the basis for constructing lattices with AcceleratorLattice.
+Other simulation programs
+have similarly utilized the underlying programming language for constructing
+lattices{footcite:p}`Appleby:Merlin2020;Iadarola:Xsuite2023`. This is in marked contrast to many accelerator
+simulation programs such programs as MAD{footcite:p}`Grote:MAD1989`,
+Elegant{footcite:p}`Borland:Elegant2000`, and Bmad.
+By using Julia for the lattice language, the user will automatically have access to such features
+as plotting, optimization packages, linear algebra packages, etc.
+This gives a massive boost to the versatility and usability of any SciBmad simulation program.
+Moreover, maintainability is greatly enhanced due to the reduction in the amount of code that needs
+to be developed.
+
+%---------------------------------------------------------------------------------------------------
+(s:ack)=
+## Acknowledgements
+
+Thanks must go to the people who have contributed to this effort and without
+whom SciBmad would only be a shadow of what it is today:
+
+Etienne Forest (aka Patrice Nishikawa),
+Dan Abell,
+Scott Berg,
+Oleksii Beznosov,
+Alexander Coxe,
+Laurent Deniau,
+Auralee Edelen,
+Ryan Foussel,
+Juan Pablo Gonzalez-Aguilera,
+Georg Hoffstaetter,
+Chris Mayes,
+Matthew Signorelli,
+Hugo Slepicka,
+
+%---------------------------------------------------------------------------
+(s:using)=
+## Using AcceleratorLattice.jl
+
+AcceleratorLattice is hosted on GitHub. The official repository is at
+```{code} yaml
+ github.com/bmad-sim/AcceleratorLattice.jl
+```
+The `README.md` file there has instructions on how to install AcceleratorLattice.
+
+A `using` statement must be given before using AcceleratorLattice in Julia
+```{code} yaml
+ using AcceleratorLattice
+```
+
+%---------------------------------------------------------------------------
+(s:manual.con)=
+## Manual Conventions
+
+This manual has the following conventions:
+%
+- **Type fields:**
+`Fields` of a type are also referred to as `components` or `parameters`.
+A component `c` of a type `S` can be referred to as `S.c`. In the case
+of lattice elements, `Ele` (the abstract type that all elements inherit from) is
+used represent any of the subtypes such as `Quadrupole`, etc. If the component
+is an array, the notation `S.c[]` can be used to emphasize this.
+%
+
+%---------------------------------------------------------------------------
+(s:element.def)=
+## Lattice Elements
+
+The basic building block used to describe an accelerator is the lattice `element`. An
+element is generally something physical like a bending magnet or a
+quadrupole, or a diffracting crystal.
+
+Lattice elements can be divided into two classes.
+One class are the elements that particles are tracked through. These "tracking" elements are
+contained in the "tracking branches" ([](#s:branch.def)) of the lattice. Other elements,
+called "`lord`" elements, are used to
+represent relationships between elements. "`Super-lord`" elements ([](#c:super)) are
+used when elements overlap spatially. "`Multipass_lord`" elements ([](#c:multipass))
+are used when a beam goes through the same elements multiple times like in a recirculating Linac
+or when different beam go through the same elements like in the interaction region of a
+colliding beam machine.
+
+%---------------------------------------------------------------------------
+(s:branch.def)=
+## Lattice Branches
+
+The next level up from lattice `elements` are the `branches`.
+Each branch holds an array of lattice elements.
+A branch is of type `Branch`.
+
+There are two types of `branches`: branches whose `Branch.type` parameter is set to
+a suitable subtype of `LordBranch` holds Lord elements and
+branches whose `Branch.type` parameter is set to `TrackingBranch` holds an ordered
+list of elements that can be tracked through. AcceleratorLattice defines three lord branches named:
+```{code} yaml
+ "super" -- Contains super lord elements.
+ "multipass" -- Contains multipass lord elements.
+ "girder" -- Contains Girder elements.
+```
+Additional lord branches may be added by the user if desired.
+
+A tracking branch can represent a LINAC, X-Ray beam line, storage ring, etc.
+For all tracking branches, the first element in the element array
+must be of type `BeginningEle` ([](#s:begin.ele)).
+Additionally, for all tracking branches,
+the end element must be of type `Marker` ([](#s:mark)).
+
+All tracking branches have a name `Branch.name` inherited from the `BeamLine` that defines
+the branch in the lattice file and branches contains an array of elements `Branch.ele[]`.
+If the `BeamLine` used to instantiate a tracking branch does not have a name, The default name
+is used. The default name is `"Bn"` where `n` is the index of the
+branch in the `Lattice.branch` array. For example, `"B2"` would be the default name of
+`lat.branch[2]` (assuming that this is a tracking branch).
+
+%---------------------------------------------------------------------------
+(s:lattice.def)=
+## Lattices
+
+A `lattice` ([](#s:lattice.def)) is the root structure holding the information about a
+"machine". A machine may be as simple as a line of elements (like the elements of a Linac) or
+as complicated as an entire accelerator complex with multiple storage rings, Linacs, transfer
+lines, etc. All lattices are of type `Lattice`.
+
+Essentially, a `lattice`, has an array `Lattice.branch[]` of `branches` with each branch
+describing part of the machine.
+Branches can be interconnected to form a unified whole.
+Tracking branches can be interconnected using `Fork` elements ([](#s:fork)).
+This is used to simulate forking beam lines such as a connections to a transfer line, dump line, or an
+X-ray beam line. The `branch` from which other `branches` fork but is not forked to by any
+other `branch` is called a `root` branch.
+
+A lattice may contain multiple `root` `branches`. For example, a pair of intersecting storage
+rings will generally have two `root` branches, one for each ring.
+
+Branches can be accessed by name using the overloaded index operator for `Lattice`.
+For example, if `lat` is an instance of a lattice, the super lord branch ([](#s:branch.def)),
+which has the name `"super"`, can be accessed via:
+```{code} yaml
+ lat["super"] # Access by branch name
+ lat.branch[2] # Access by branch index
+```
+Where it is assumed for this example that the super lord branch has index 2.
+
+Similarly, lattice elements can be accessed by name or by index.
+For example, if `lat` is a lattice instance, and `"q1"` is the name of an element or
+elements that are in a branch named "B2", the following are equivalent:
+```{code} yaml
+ elist = lat["q1"]
+ elist = find(lat, "q1")
+ b2 = lat.branch["B2"]; elist = b2["q1"]
+```
+`elist` will be a vector of elements since a name may match to multiple elements.
+
+%---------------------------------------------------------------------------
+(s:conventions)=
+## AcceleratorLattice Conventions
+
+AcceleratorLattice has the following conventions:
+%
+- **Evaluation is at upstream end:**
+For lattice element parameters that are s-dependent, the evaluation location is the
+`upstream` edge of the element ([](#s:ref.construct)). These parameters include the
+element's floor position, the reference energy/momentum, and the s-position.
+%
+
+%---------------------------------------------------------------------------
+(s:min.lat)=
+## Minimal Working Lattice Example
+
+The following is a minimal example of constructing a lattice with a quadrupole, drift, and then
+a bend:
+```{code} yaml
+ using AcceleratorLattice
+ @ele begin_ele = BeginningEle(pc_ref = 1e7, species_ref = species("electron"))
+ @ele q = Quadrupole(L = 0.6, K2 = 0.3)
+ @ele d = Drift(L = 0.4)
+ @ele b = Bend(L = 1.2, angle = 0.001)
+
+ a_line = beamline("simple_line", [begin_ele, q, d, b])
+ lat = Lattice("simple_lat", [a_line])
+```
+
+%---------------------------------------------------------------------------
+(s:X)=
+## Differences From Bmad
+
+There are many differences between AcceleratorLattice and Bmad. Many of of these will be fairly
+obvious. Some differences to be aware of:
+- Bmad is generally case insensitive (except for things like file names). AcceleratorLattice, like
+the Julia language, is case sensitive.
+%
+With Bmad, the branch array within a lattice and the element array within a branch is
+indexed from zero. With SciBmad, indexing of `Lattice.branch[]` and `branch.ele[]` is
+from one conforming to the Julia standard.
+%
+- The Bmad names for the coordinate systems ([](#s:coords)) was somewhat different and not
+always consistent. The `floor` and `element body` names are the same but `machine`
+coordinates are called the `laboratory` in Bmad.
+%
+- Evaluation was at the downstream end ([](#s:conventions)) in Bmad not the upstream end.
+%
+- With Bmad a value for any aperture limits of zero means the limit does not exist.
+with AcceleratorLattice a value of `NaN` means the aperture does not exist. Additionally, with
+Bmad a positive value for `x1_limit` or `y1_limit` meant that the aperture was
+on the negative side of the `x-axis` or `y-axis` respectively. With AcceleratorLattice, a positive
+value for `x_limit[1]` or `y_limit[1]` means the aperture is on the positive side of
+of the `x-axis` or `y-axis` respectively. This makes the notation consistent across
+the different ways to specify apertures (compare with `Mask` element syntax.).
+%
+- AcceleratorLattice defines the reference point for misalignment of a Bend element as the center
+of the chord between the entrance and exit end points.
+With Bmad, the reference point is at the center of the reference trajectory arc between the entrance
+and the exit. An additional difference is that the Bmad `roll` misalignment is called `tilt`
+under AcceleratorLattice.
+%
+- Bmad does not allow redefinition of named variables nor elements. AcceleratorLattice allows this.
+%
+- With Bmad, the beginning and end elements are implicitly inserted into a branch line.
+With AcceleratorLattice, only an end element will be implicitly inserted if the end of the beamline is
+not a marker.
+Also with Bmad the beginning element is always named `Beginning` while with AcceleratorLattice there
+is no restriction on the name.
+%
+- Restrictions on the order of statements used to create a lattice are different.
+For example, in Bmad, a statement defining a lattice element can be placed anywhere
+except if there is an `expand_lattice` statement and the element is not being used
+with superposition in which case the element definition must be before the `expand_lattice`
+statement. With AcceleratorLattice, element definitions must come before the element is used in a line.
+%
+- With Bmad superposition of two non-drift elements, if there existed the appropriate
+combined type, will result in a super-slave of the appropriate combined type. For example,
+a `solenoid` superimposed over a `quadrupole` would give a `sol_quad` super slave with
+`solenoid` and `quadrupole` super lords. The problem here is that calculation of the
+super slave parameters may not be possible. For example if the super lord
+elements are misaligned, in general it is not possible to compute a corresponding super slave
+misalignment. To avoid this, AcceleratorLattice creates a `UnionEle` super slave element
+(which in Bmad is known as a "jumbo" super slave). It is up to the tracking routines to
+figure out how to track though a `UnionEle`
+%
+- In `Bmad` there are two types of bends called `sbend` and `rbend`.
+This organization was inherited from `MAD`. While both `sbends` and `rbends`
+represent the same physical type of bend, the two have different ways to specify the bend parameters.
+This can be confusing since `rbends` and `sbends` use the same names for different parameters.
+For example, the length `l` for an `sbend` is the arc length but for an `rbend` it is the
+chord length. To avoid confusion, AcceleratorLattice combines the two into a single `Bend` type with
+distinct parameter names. For example, `L` is the arc length and `L_chord` is the chord length.
+
+
+
+```{footbibliography}
+```
diff --git a/docs/src/multipass.md b/docs/src/multipass.md
new file mode 100644
index 0000000..6465a03
--- /dev/null
+++ b/docs/src/multipass.md
@@ -0,0 +1,193 @@
+(c:multipass)=
+# Multipassindex{multipass|hyperbf}
+
+%-----------------------------------------------------------------------------
+(s:multipass.fund)=
+## Multipass Fundamentals
+`Multipass` lines are a way to handle the bookkeeping when different elements being tracked
+through represent the same physical element. For example, consider the case where dual ring colliding
+beam machine is to be simulated. In this case the lattice file might look like:
+```{code} yaml
+ring1 = beamline("r1", [..., IR_region, ...])
+ring2 = beamline("r2", [..., reverse(IR_region), ...])
+IR_region = beamline("IR", [Q1, ....])
+lat = Lattice("dual_ring", [ring1, ring2])
+```
+[The `reverse` construct means go through the line backwards ([](#s:ele.reverse))]
+In this case, the `Q1` element in `ring1` and the
+`Q1` element in `ring2` represent the same physical element.
+Thus the parameters
+of both the `Q1`s should be varied in tandem. This can be done automatically using `multipass`.
+The use of multipass simplifies lattice and program development since the bookkeeping details are left
+to the AcceleratorLattice bookkeeping routines.
+
+index{multipass_slave}index{multipass_lord}
+To illustrate how `multipass` works, consider the example of an Energy Recovery Linac (ERL) where
+the beam will recirculate back through the LINAC section to recover the energy in the beam before it
+is dumped. In AcceleratorLattice, this situation can simulated by designating the LINAC section as `multipass`.
+The lattice file might look like:
+```{code} yaml
+@ele RF1 = LCavity(...)
+linac = beamline["linac", [RF1, ...], multipass = true)
+erl_line = beamline("erl", [linac, ..., linac])
+lat = Lattice("erl", [erl_line])
+rf1p2 = find_ele(lat, "RF1!mp1")
+rf1p2.multipass_phase = pi
+```
+The beamline called `linac` is designated as `multipass`. This `linac` line appears twice in
+the line `erl_line` and `erl_line` is the root line for lattice expansion.
+In branch 1 of the
+lattice, which will be a tracking branch, there will be two elements derived from the `RF1` element:
+```{code} yaml
+RF1!mp1, ..., RF1!mp2, ...
+```
+Since the two elements are derived from a `multipass` line, they are given unique names by adding
+an `!mpN` suffix where `N` is an integer.
+These types of elements are known as `multipass_slave` elements. In
+addition to the `multipass_slave` elements there will be a `multipass_lord` element (that doesn't
+get tracked through) called `RF1` in the `multipass_lord` branch of the lattice ([](#s:lord.slave)).
+Changes to the parameters of the lord `RF1` element will be passed to the slave elements by the AcceleratorLattice
+bookkeeping routines. Assuming that the phase of `RF1!mp1` gives acceleration, to make `RF1!mp2`
+decelerate, the `multipass_phase` parameter of `RF1!mp2` is set to pi. This is the one parameter
+that AcceleratorLattice's bookkeeping routines will not touch when transferring parameter values from `RF1` to
+its slaves. Notice that the `multipass_phase` parameter had to be set after the lattice is formed
+using the `expand` function ([](#s:expand)). This is true since
+`RF1!mp2` does not exist before the lattice is expanded. `multipass_phase` is useful with
+relative time tracking [](#s:rf.time). However, `multipass_phase` is "unphysical" and is just
+a convenient way to shift the phase pass-to-pass through a given cavity. To "correctly" simulate
+the recirculating beam, absolute time tracking should be used and the length of the lattice from a
+cavity back to itself needs to be properly adjusted to get the desired phase advance. See the discussion
+in section~[](#s:rf.time).
+
+Multiple elements of the same name in a multipass line are considered
+physically distinct. Example:
+```{code} yaml
+m_line = beamline("m", [A, A, B], multipass = true)
+u_line = beamline("u", [m_line, m_line])
+lat = Lattice("lat", [u_line])
+```
+In this example, branch 1 of the lattice is:
+```{code} yaml
+A!mp1, A!mp1, B!mp1, A!mp2, A!mp2, B!mp2
+```
+In the `multipass_lord` branch of the lattice there will be two multipass lords called `A` and
+one another lord called `B`.
+That is, there are three physically distinct elements in the lattice. The first
+`A` lord controls the 1St and 4Th elements in branch 1 and the second
+`A` lord controls the 2Nd and 5Th elements. If `m_line` was {em not} marked `multipass`,
+branch 1 would have four `A` and two `B` elements and there would be
+no lord elements.
+
+Sublines contained in a multipass line that are themselves not marked multipass act the same as if
+the elements of the subline where substituted directly in place of the subline in the containing
+line. For example:
+```{code} yaml
+a_line = beamline("a", [A])
+m_line = beamline("m", [a_line, a_line], multipass = true)
+u_line = beamline("u", [m_line, m_line])
+lat = Lattice("lat", [u_line])
+```
+In this example, `a_line`, which is a subline of the multipass `m_line`, is {em not}
+designated `multipass` and the result is the same as the previous example where `m_line` was
+defined to be `(A, A, B)`. That is, there will be three physical elements represented by three
+multipass lords.
+
+Multipass lines do not have to be at the same "level" in terms of nesting of lines within
+lines. Additionally, multipass can be used with line reversal ([](#s:ele.reverse)). Example:
+```{code} yaml
+m_line = beamline("m", [A, B], multipass = true)
+m2_line = beamline("m2", m_line)
+@ele P = patch(...) # Reflection patch
+u_line = beamline("u", [m_line, P, reverse(m2_line)])
+lat = Lattice("lat", [u_line])
+```
+Here the tracking part of the lattice is
+```{code} yaml
+A!mp1, B!mp1, ..., B!mp2 (r), A!mp2 (r)
+```
+The "(r)" here just denotes that the element is reversed and is not part of the name. The lattice
+will have a multipass lord `A` that controls the two `A!mp n` elements and similarly with
+`B`. This lattice represents the case where, when tracking,
+a particle goes through the m_line in the "forward"
+direction and, at the reflection patch element `P`, the coordinate system is reversed so that the particle
+is then tracked in the reverse direction through the elements of `m_line` twice.
+While it is possible to use reflection "{math}`-`" ([](#s:lines.wo.arg)) instead
+of reversal ([](#s:ele.reverse)), reflection here does not make physical sense. Needed
+here is a reflection patch `P` ([](#s:patch)) between reversed and unreversed elements.
+
+The procedure for how to group lattice elements into multipass slave groups which represent the same
+physical element is as follows. For any given element in the lattice, this element has some line it
+came from. Call this line {math}`L_0`. The {math}`L_0` line in turn may have been contained in some other line
+{math}`L_1`, etc. The chain of lines {math}`L_0`, {math}`L_1`, ..., {math}`L_n` ends at some point and the last (top) line
+{math}`L_n` will be one of the root lines listed in the `use` statement ([](#s:use)) in the lattice
+file. For any given element in the lattice, starting with {math}`L_0` and proceeding upwards through the
+chain, let {math}`L_m` be the {em first} line in the chain that is marked as `multipass`. If no such
+line exists for a given element, that element will not be a multipass slave. For elements that have
+an associated {math}`L_m` multipass line, all elements that have a common {math}`L_m` line and have the same
+element index when {math}`L_m` is expanded are put into a multipass slave group (for a given line the
+element index with respect to that line is 1 for the first element in the expanded line, the second
+element has index 2, etc.). For example, using the example above, the first element of the lattice,
+`A!mp1`, has the chain:
+```{code} yaml
+m_line, u_line
+```
+The last element in the lattice, (`A!mp2`), has the chain
+```{code} yaml
+m_line, m2_line, u_line
+```
+For both elements the {math}`L_m` line is `m_line` and both elements are derived from the element with
+index 1 with respect to `m_line`. Therefore, the two elements will be slaved together.
+
+As a final example, consider the case where a subline of a multipass line is also marked
+`multipass`:
+```{code} yaml
+a_line = beamline("a", [A], multipass = true)
+m_line = beamline("m", [a_line, a_line, B], multipass = true)
+u_line = beamline("u", [m_line, m_line])
+lat = Lattice("lat", [u_line])
+```
+In this case, branch 1 of the lattice will be:
+```{code} yaml
+A!mp1, A!mp2, B!mp1, A!mp3, A!mp4, B!mp2
+```
+There will be two lord elements representing the two physically distinct elements `A` and `B`.
+The `A` lord element will will control the four `A!mpN` elements in the tracking
+part of the lattice. The `B` lord will control the two `B!mpN` elements in the tracking part
+of the lattice.
+
+To simplify the constructed lattice, if the set of lattice elements to slave together only contains
+one element, a multipass lord is not constructed. For example:
+```{code} yaml
+m_line = beamline("m", [A, A, B], multipass = true)
+u_line = beamline([m_line])
+lat = Lattice("lat", [u_line])
+```
+In this example no multipass lords are constructed and the lattice is simply
+```{code} yaml
+A, A, B
+```
+
+It is important to note that the floor coordinates ([](#s:floor)) of the slaves of a given
+multipass lord are not constrained by AcceleratorLattice to be the same. It is up to the lattice designer to make
+sure that the physical positions of the slaves makes sense (that is, are the same).
+
+%-----------------------------------------------------------------------------
+(s:ref.e.multi)=
+## The Reference Energy in a Multipass Line
+Consider the lattice where the tracking elements are
+```{code} yaml
+A!mp1, C, A!mp2
+```
+where `A!mp1` and `A!mp2` are multipass slaves of element `A` and `C` is a `lcavity`
+element with some finite voltage. In this case, the reference energy calculation ([](#s:energy))
+where the reference energy of an element is inherited from the previous element, assigns differing
+reference energies to `A!mp1` and `A!mp2`. In such a situation, what should be the assigned
+reference energy for the multipass lord element `A`? AcceleratorLattice calculates the lord reference energy
+in one of two ways. If, in the lattice file, `static_energy_ref` is set `true`,
+`e_tot_ref` or `pc_ref` the value set for the multipass lord element by the User will be used.
+If `static_energy_ref` is `false` (the default),
+the reference energy (or reference momentum) the reference energy of the lord is set equal to the
+reference energy of the first pass slave element.
+The setting of `static_energy_ref` for multipass slaves is always `false`.
+```{footbibliography}
+```
diff --git a/docs/src/new-ele.md b/docs/src/new-ele.md
new file mode 100644
index 0000000..0676547
--- /dev/null
+++ b/docs/src/new-ele.md
@@ -0,0 +1,42 @@
+(c:new.ele)=
+# Defining New Lattice Elements
+%---------------------------------------------------------------------------------------------------
+(s:X)=
+## Defining new Element Parameters
+* Bookkeeping
+
+%---------------------------------------------------------------------------------------------------
+(s:new.ele)=
+## Defining a New Element
+To construct a new element type:
+
+* Define a new element type. Example:
+```{code} yaml
+@construct_ele_type NewEleType
+```
+
+* Extend EleGeometry Holy trait group ([](#s:holy)) if a new geometry is needed. Example:
+```{code} yaml
+abstract type CORKSCREW <: EleGeometry end
+```
+
+* If the geometry is not `STRAIGHT`, Extend the `ele_geometry()` function to return the
+correct geometry for the new type of element. Example:
+```{code} yaml
+ele_geometry(ele::NewEleType) = CORKSCREW
+```
+
+* If the element has a new type of geometry, extend the `propagate_ele_geometry()` function
+to handle the new type of geometry. Example:
+```{code} yaml
+function propagate_ele_geometry(::Type{CORKSCREW}, fstart::FloorParams, ele::Ele)
+...
+return floor_end # FloorParams at the downstream end of the element.
+end
+```
+
+
+%---------------------------------------------------------------------------------------------------
+
+```{footbibliography}
+```
diff --git a/docs/src/superimpose.md b/docs/src/superimpose.md
new file mode 100644
index 0000000..0cc06eb
--- /dev/null
+++ b/docs/src/superimpose.md
@@ -0,0 +1,518 @@
+(c:super)=
+# Superposition
+Superposition is the insertion of elements into a lattice after the lattice has been created by the
+`expand` function. Superposition is beneficial for various purposes. A common use of superposition is to
+insert `marker` elements within other elements. For example, placing a marker element in the middle
+of a quadrupole.
+Another use case is when the field in some region is due to the overlap of several
+elements. For example, a quadrupole magnet inside a larger solenoid magnet.
+
+%-----------------------------------------------------------------------------
+(s:super.fund)=
+## Superposition on a Drift
+```{figure} figures/superimpose-positioning.svg
+caption[Superposition Offset.]{
+The superposition `offset` is the longitudinal {math}`s`-distance from the origin point of the
+reference element to the origin point of the element being superimposed.
+}
+:name: f:superimpose
+```
+
+A simple example illustrates how superposition works (also see section [](#s:lord.slave)):
+```{code} yaml
+using AcceleratorLattice
+@ele dd = Drift(L = 12)
+@ele bb = BeginningEle(species_ref = species("proton"), pc_ref = 1e11)
+@ele ss = Solenoid(L = 1)
+zline = beamline("z", [bb, dd])
+lat = Lattice("lat", zline)
+
+ref_ele = find_eles(lat, "dd")
+superimpose!(ss, ref_ele, offset = 0.2)
+```
+Before superposition, branch 1 of lattice `lat` looks like
+```{code} yaml
+Branch 1: "z" geometry => open L s s_downstream
+1 "bb" BeginningEle 0.000000 0.000000 -> 0.000000
+2 "dd" Drift 12.000000 0.000000 -> 12.000000
+3 "end_ele" Marker 0.000000 12.000000 -> 12.000000
+```
+
+The `superimpose!` function has the signature
+```{code} yaml
+function superimpose!(super_ele::Ele, ref::T;
+ele_origin::BodyLocationSwitch = b_center, offset::Real = 0,
+ref_origin::BodyLocationSwitch = b_center, wrap::Bool = true)
+where {E <: Ele, T <: Union{Branch, Ele, Vector{Branch}, Vector{E}}}
+```
+The superimpose
+
+statement inserts a copy of the element `ss` in the lattice.
+
+
+
+
+After insertion, branch 1 looks like:
+```{code} yaml
+Branch 1: "z" geometry => open L s s_downstream
+1 "bb" BeginningEle 0.000000 0.000000 -> 0.000000
+2 "dd!1" Drift 5.700000 0.000000 -> 5.700000
+3 "ss" Solenoid 1.000000 5.700000 -> 6.700000
+4 "dd!2" Drift 5.300000 6.700000 -> 12.000000
+5 "end_ele" Marker 0.000000 12.000000 -> 12.000000
+```
+The insertion of the `ss` copy is within the `drift` named `dd`. The position
+
+With superpositions, `Drift` elements are handled differently from other elements. This is done
+to simplify the bookkeeping code. T
+
+
+
+Rules:
+begin{itemize}
+%
+- The `super_ele` element cannot be a `Drift`.
+%
+- %
+The `bookkeeper!` function must be called after any superpositions or
+%
+end{itemize}
+
+
+Branch 1: "z" geometry => open L s s_downstream
+1 "bb" BeginningEle 0.000000 0.000000 -> 0.000000
+2 "dd" Drift 12.000000 0.000000 -> 12.000000
+3 "end_ele" Marker 0.000000 12.000000 -> 12.000000
+
+
+```{code} yaml
+using AcceleratorLattice
+@ele qq = Quadrupole(L = 4)
+@ele dd = Drift(L = 12)
+@ele ss = Solenoid(L = 1)
+@ele bb = BeginningEle(species_ref = species("proton"), pc_ref = 1e11)
+zline = beamline("z", [bb, qq, dd])
+lat = Lattice("lat", zline)
+
+ref_ele = find_eles (lat, "dd")
+superimpose!(ss, ref_ele, offset = 0.2)
+```
+
+parameter of element `S` superimposes `S` over the lattice vn{(Q,
+D)}. The placement of `S` is such that the beginning of `S` is coincident with the center of
+`Q` (this is is explained in more detail below). Additionally, a marker `M` is superimposed at
+a distance of +1~meter from the center of `S`. The tracking part of the lattice
+([](#s:lord.slave)) looks like:
+```{code} yaml
+Element Key Length Total
+1) Q{#}1 Quadrupole 2 2
+2) Q{B}S Sol_quad 2 4
+3) S{#}1 Solenoid 3 7
+4) M Marker 0
+4) S{#}2 Solenoid 3 10
+5) D{#}2 Drift 4 14
+```
+What Bmad has done is to split the original elements `(Q, D)` at the edges of `S` and then
+`S` was split where `M` is inserted. The first element in the lattice, `Q#1`, is the part
+of `Q` that is outside of `S`. Since this is only part of `Q`, Bmad has put a `#1` in
+the name so that there will be no confusion. (a single `#` has no special meaning other than the
+fact that Bmad uses it for mangling names. This is opposed to a double `##` which is used to
+denote the {math}`N`Th instance of an element ([](#s:ele.match)). The next element, `Q{B`S}, is the
+part of `Q` that is inside `S`. `Q{B`S} is a combination solenoid/quadrupole element as
+one would expect. `S{#`1} is the part of `S` that is outside `Q` but before `M`. This
+element is just a solenoid. Next comes `M`, `S{#`1}, and finally `D#2` is the rest of the
+drift outside `S`.
+
+In the above example, `Q` and `S` will be super lord elements (`s:lord.slave`) and
+four elements in the tracking part of the lattice will be `super_slave` elements. This is
+illustrated in {numref}`f:super.ex`B.
+
+Notice that the name chosen for the `sol_quad` element `Q{B`S} is dependent upon what is
+being superimposed upon what. If `Q` had been superimposed upon `S` then the name would have
+been `S{B`Q}.
+
+When Bmad sets the element class for elements created from superpositions, Bmad will set the class
+of the element to something other than an `em_field` element ([](#s:em.field)) if possible. If
+no other possibilities exist, Bmad will use `em_field`. For example, a `quadrupole`
+superimposed with a `solenoid` will produce a `sol_quad` `super_slave` element but a
+`solenoid` superimposed with a `rfcavity` element will produce an `em_field` element since
+there is no other class of element that can simultaneously handle solenoid and RF fields. An
+`em_field` `super_slave` element will also be created if any of the superimposing elements
+have a non-zero orientation ([](#s:offset)) since it is not, in general, possible to construct a slave
+element that properly mimics the effect of a non-zero orientation.
+
+
+
+With the lattice broken up like this Bmad has constructed something that can be easily
+analyzed. However, the original elements `Q` and `S` still exist within the lord section of
+the lattice. Bmad has bookkeeping routines so that if a change is made to the `Q` or `S`
+elements then these changes can get propagated to the corresponding slaves. It does not matter which
+element is superimposed. Thus, in the above example, `S` could have been put in the Beam Line
+(with a drift before it) and `Q` could then have been superimposed on top and the result would
+have been the same (except that the split elements could have different names).
+
+If an element has zero length (for example, a `marker` element), is superimposed, or is
+superimposed upon, then the element will remain in the tracking part of the lattice and there will
+be no corresponding lord element. See {numref}`f:super.ex`.
+
+Superimpose syntax:
+```{code} yaml
+Q: quad, superimpose, ... ! Superimpose element Q.
+Q: quad, superimpose = T, ... ! Same as above.
+Q: quad, ... ! First define element Q ...
+Q[superimpose] = T ! ... and then superimpose.
+Q[superimpose] = F ! Suppress superposition.
+```
+Superposition happens at the end of parsing so the last set of the `superimpose` for an element
+will override previous settings.
+
+It is also possible to superimpose an element using the `superimpose` command which has the
+syntax:
+```{code} yaml
+superimpose, element = , ...
+```
+With the same optional superposition parameters (`ref`, `offset`, etc.) given below.
+Example:
+```{code} yaml
+superimpose, element = Q1, ref = B12, offset = 1.3,
+ele_origin = beginning, ref_origin = end
+```
+Note: Superposition using the superimpose statement allows superimposing the same element with
+multiple reference elements and/or multiple offsets. The drawback is that superposition using the
+superimpose statement may not be switched off later in the lattice file.
+
+The placement of a superimposed element is illustrated in {numref}`f:superimpose`. The placement of a
+superimposed element is determined by three factors: An origin point on the superimposed element, an
+origin point on the reference element, and an offset between the points. The parameters that
+determine these three quantities are:
+index{ref}index{offset}
+index{ref_origin}index{ele_origin}
+```{code} yaml
+create_jumbo_slave = ! See [](#s:jumbo.slave)
+wrap_superimpose = ! Wrap if element extends past lattice ends?
+ref =
+offset = ! default = 0
+ele_origin = ! Origin pt on element.
+ref_origin = ! Origin pt on ref element.
+```
+`ref` sets the reference element. If `ref` is not present then the start of the lattice is
+used (more precisely, the start of branch 0 ([](#s:branch.def))). Wild card characters
+([](#s:ele.match) can be used with `ref`. If `ref` matches to multiple elements (which may
+also happen without wild card characters if there are multiple elements with the name given by
+`ref`) in the lattice a superposition will be done, one for each match.
+
+The location of the origin points are determined by the setting of `ele_origin` and
+`ref_origin`. The possible settings for these parameters are
+```{code} yaml
+beginning ! Beginning (upstream) edge of element
+center ! Center of element. Default.
+end ! End (downstream) edge of element
+```
+`center` is the default setting. `Offset` is the longitudinal offset of the origin
+of the element being superimposed relative
+to the origin of the reference element. The default offset is zero.
+A positive offset moves the element being superimposed in the `downstream` direction if
+the reference element has a normal longitudinal `orientation` ([](#s:ele.reverse)) and
+vice versa for the reference element has a reversed longitudinal orientation.
+
+Note: There is an old syntax, deprecated but still supported for now, where the origin points were
+specified by the appearance of:
+```{code} yaml
+ele_beginning ! Old syntax. Do not use.
+ele_center ! Old syntax. Do not use.
+ele_end ! Old syntax. Do not use.
+ref_beginning ! Old syntax. Do not use.
+ref_center ! Old syntax. Do not use.
+ref_end ! Old syntax. Do not use.
+```
+For example, "ele_origin = beginning" in the old syntax would be "ele_beginning".
+
+index{drift}
+index{overlay}index{group}index{girder}
+The element begin superimposed may be any type of element except `drift`, `group`,
+`overlay`, and `girder` control elements. The reference element used to position a
+superimposed element may be a `group` or `overlay` element as long as the `group` or
+`overlay` controls the parameters of exactly one element. In this case, the controlled element is
+used as the reference element.
+
+index{geometry}index{open}
+By default, a superimposed element that extends beyond either end of the lattice will be wrapped
+around so part of the element will be at the beginning of the lattice and part of the element will
+be at the end. For consistency's sake, this is done even if the `geometry` is set to `open`
+(for example, it is sometimes convenient to treat a circular lattice as linear). Example:
+```{code} yaml
+d: drift, l = 10
+q: quad, l = 4, superimpose, offset = 1
+machine: line = (d)
+use, machine
+```
+The lattice will have five elements in the tracking section:
+```{code} yaml
+Element Key Length
+0) BEGINNING Beginning_ele 0
+1) Q{#}2 Quadrupole 3 ! Slave representing beginning of Q element
+2) D{#}1 Drift 6
+3) Q{#}1 Quadrupole 1 ! Slave representing end of Q element
+4) END Marker 0
+```
+And the lord section of the lattice will have the element `Q`.
+
+To not wrap an element that is being superimposed, set the `wrap_superimpose` logical to `False`.
+Following the above example, if the definition of`q` is extended by adding `wrap_superimpose`:
+```{code} yaml
+q: quad, l = 4, superimpose, offset = 1, wrap_superimpose = F
+```
+In this instance there are four elements in the tracking section:
+```{code} yaml
+Element Key Length
+0) BEGINNING Beginning_ele 0
+1) Q Quadrupole 4
+2) D{#}1 Drift 7
+4) END Marker 0
+```
+And the lord section of the lattice will not have any elements.
+
+To superimpose a zero length element "`S`" next to a zero length element "`Z`", and to
+make sure that `S` will be on the correct side of `Z`, set the `ref_origin` appropriately.
+For example:
+```{code} yaml
+S1: marker, superimpose, ref = Z, ref_origin = beginning
+S2: marker, superimpose, ref = Z, ref_origin = end
+Z: marker
+```
+The order of the elements in the lattice will be
+```{code} yaml
+S1, Z, S2
+```
+If `ref_origin` is not present or set to `center`, the ordering of the elements will be
+arbitrary.
+
+If a zero length element is being superimposed at a spot where there are other zero length elements,
+the general rule is that the element will be placed as close as possible to the reference element.
+For example:
+```{code} yaml
+S1: marker, superimpose, offset = 1
+S2: marker, superimpose, offset = 1
+```
+In this case, after `S1` is superimposed at {math}`s = 1` meter, the superposition of `S2` will
+place it as close to the reference element, which in this case is the `BEGINNING` elements at {math}`s`
+= 0{math}`, as possible. Thus the final order of the superimposed elements is:`
+```{code} yaml
+S2, S1
+```
+To switch the order while still superimposing `S2` second one possibility is to use:
+```{code} yaml
+S1: marker, superimpose, offset = 1
+S2: marker, superimpose, ref = S1, ref_origin = end
+```
+
+If a superposition uses a reference element, and there are {math}`N` elements in the lattice with the
+reference element name, there will be {math}`N` superpositions. For example, the following will split in
+two all the quadrupoles in a lattice:
+```{code} yaml
+M: null_ele, superimpose, ref = quadrupole::*
+```
+A `null_ele` ([](#s:null.ele)) element is used here so that there is no intervening element
+between split quadrupole halves as there would be if a `marker` element was used.
+
+
+index{drift!superposition}index{pipe!superposition}
+When a superposition is made that overlaps a drift, the drift, not being a "real" element,
+vanishes. That is, it does not get put in the lord section of the lattice. Note that if aperture
+limits ([](#s:limit)) have been assigned to a drift, the aperture limits can "disappear" when
+the superposition is done. Explicitly, if the exit end of a drift has been assigned aperture limits,
+the limits will disappear if the superimposed element overlays the exit end of the drift. A similar
+situation applies to the entrance end of a drift. If this is not desired, use a `pipe` element
+instead.
+
+To simplify bookkeeping, a drift element may not be superimposed. Additionally, since drifts can
+disappear during superposition, to avoid unexpected behavior the superposition reference element may
+not be the {math}`N`Th instance of a drift with a given name. For example, if there are a number of drift
+elements in the lattice named `a_drft`, the following is not allowed:
+```{code} yaml
+my_oct: octupole, ..., superimpose, ref = a_drft##2 ! This is an error
+```
+
+When the parameters of a super_slave are computed from the parameters of its super lords, some types
+of parameters may be "missing". For example, it is, in general, not possible to set appropriate
+aperture parameters ([](#s:limit)) of a super_slave if the lords of the slave have differing
+aperture settings. When doing calculations, Bmad will use the corresponding parameters stored in
+the lord elements to correctly calculate things.
+
+When superposition is done in a line where there is `element reversal` ([](#s:ele.reverse)),
+the calculation of the placement of a superimposed element is also "reversed" to make the relative
+placement of elements independent of any element reversal. An example will make this clear:
+```{code} yaml
+d1: drift, l = 1
+d2: d1
+q1: quad, l = 0.1, superimpose, ref = d1, offset = 0.2,
+ref_origin = beginning, ele_origin = beginning
+q2: q1, ref = d2
+p: patch, x_pitch = pi ! Needed to separate reversed and unreversed.
+this_line: line = (d1, p, --d2)
+use, this_line
+```
+Since the reference element of the `q2` superposition, that is `d2`, is a reversed element,
+`q2` will be reversed and the sense of `offset`, `ref_origin`, and `ele_origin` will be
+reversed so that the position of `q2` with respect to `d2` will be the mirror image of the
+position of `q1` with respect to `d1`. The tracking part of the lattice will be:
+```{code} yaml
+Element: d1{#}1 q1 d1{#}2 d2{#}2 q2 d2{#}1
+Length: 0.2 0.1 0.7 0.7 0.1 0.3
+Reversed element?: No No No Yes Yes Yes
+```
+
+Superposition with `line reflection` ([](#s:lines.wo.arg)) works the same way as line reversal.
+
+The `no_superposition` statement ([](#s:no.sup)) can be used to turn off superpositioning
+
+%-----------------------------------------------------------------------------
+(s:super.sub.line)=
+## Superposition and Sub-Lines
+Sometimes it is convenient to do simulations with only part of a lattice. The rule for how
+superpositions are handled in this case is illustrated in the following example. Consider a lattice
+file which defines a `line` called `full` which is defined by two sublines called `sub1`
+and `sub2`:
+```{code} yaml
+sub1: line = {..., ele1, ...}
+sub2: line = {...}
+full: line = {sub1, sub2}
+m1: marker, superimpose, ref = ele1, offset = 3.7
+use, full
+```
+Now suppose you want to do a simulation using only the `sub2` line. Rather than edit the original
+file, one way to do this would be to create a second file which overrides the used line:
+```{code} yaml
+call, file = "full.bmad"
+use, sub2
+```
+where `full.bmad` is the name of the original file. What happens to the superposition of `m1`
+in this case? Since `m1` uses a reference element, `ele1`, that is not in `sub1`, Bmad
+will ignore the superposition. Even though Bmad will ignore the superposition of `m1` here,
+Bmad will check that `ele1` has been defined. If `ele1` has not been defined, Bmad will
+assume that there is a typographic error and issue an error message.
+
+Notice that in this case it is important for the superposition to have an explicit reference element
+since without an explicit reference element the superposition is referenced to the beginning of the
+lattice. Thus, in the above example, if the superposition were written like:
+```{code} yaml
+m1: marker, superimpose, offset = 11.3
+```
+then when the `full` line is used, the superposition of `m1` is referenced to the beginning of
+`full` (which is the same as the beginning of `sub1`) but when the `sub2` line is used, the
+superposition of `m1` is referenced to the beginning of `sub2` which is not the same as the
+beginning of `full`.
+
+%-----------------------------------------------------------------------------
+(s:jumbo.slave)=
+## Jumbo Super_Slaves
+The problem with the way `super_slave` elements are created as discussed above is that edge
+effects will not be dealt with properly when elements with non-zero fields are misaligned. When this
+is important, especially at low energy, a possible remedy is to instruct Bmad to construct
+"`jumbo`" super_slave elements. The general idea is to create one large `super_slave` for
+any set of overlapping elements. Returning to the superposition example at the start of
+Section~[](#s:super), If the superposition of solenoid `S` is modified to be
+```{code} yaml
+S: solenoid, l = 8, superimpose, ref = Q, ele_origin = beginning,
+create_jumbo_slave = T
+```
+The result is shown in {numref}`f:super.ex`C. The tracking part of the lattice will be
+```{code} yaml
+Element Key Length Total
+1) Q{B}S Sol_quad 2 4
+2) M Marker 0
+3) S{#}2 Solenoid 3 10
+4) D{#}2 Drift 4 14
+```
+index{lord_pad1}index{lord_pad2}
+`Q` and part of `S` have been combined into a jumbo `super_slave` named `Q{B`S}. Since
+the super lord elements of a jumbo `super_slave` may not completely span the slave two
+parameters of each lord will be set to show the position of the lord within the slave. These two
+parameters are
+```{code} yaml
+lord_pad1 ! offset at upstream end
+lord_pad2 ! offset at downstream end
+```
+`lord_pad1` is the distance between the upstream edge of the jumbo `super_slave` and a
+super lord. `lord_pad2` is the distance between the downstream edge of a super lord and
+the downstream edge of the jumbo `super_slave`. With the present example, the lords have the
+following padding:
+```{code} yaml
+lord_pad1 lord_pad2
+Q 0 3
+S 2 0
+```
+The following rule holds for all super lords with and without jumbo slaves:
+```{code} yaml
+Sum of all slave lengths = lord length + lord_pad1 + lord_pad2
+```
+
+One major drawback of jumbo `super_slave` elements is that the `tracking_method`
+([](#s:tkm)) will, by necessity, have to be `runge_kutta`, or `time_runge_kutta` and the
+`mat6_calc_method` ([](#s:xfer)) will be set to `tracking`.
+
+Notice that the problem with edge effects for non-jumbo `super_slave` elements only occurs when
+elements with nonzero fields are superimposed on top of one another. Thus, for example, one does not
+need to use jumbo elements when superimposing a `marker` element.
+
+index{field_overlaps}
+Another possible way to handle overlapping fields is to use the `field_overlaps` element
+parameter as discussed in [](#s:overlap).
+
+%-----------------------------------------------------------------------------
+(s:super.length)=
+## Changing Element Lengths when there is Superposition
+When a program is running, if `group` ([](#s:group)) or `overlay` ([](#s:overlay))
+elements are used to vary the length of elements that are involved in superimposition, the results
+are different from what would have resulted if instead the lengths of the elements where changed in
+the lattice file. There are two reasons for this. First, once the lattice file has been parsed,
+lattices can be "mangled" by adding or removing elements in a myriad of ways. This means that it
+is not possible to devise a general algorithm for adjusting superimposed element lengths that
+mirrors what the effect of changing the lengths in the lattice file.
+
+Second, even if a lattice has not been mangled, an algorithm for varying lengths that is based on
+the superimpose information in the lattice file could lead to unexpected results. To see this
+consider the first example in Section~[](#s:super). If the length of `S` is varied in the
+lattice file, the upstream edge of `S` will remain fixed at the center of `Q` which means that
+the length of the `super_slave` element `Q{#`1} will be invariant. On the other hand, if
+element `S` is defined by
+```{code} yaml
+S: solenoid, l = 8, superimpose, offset = 6
+```
+This new definition of `S` produces exactly the same lattice as before. However, now varying the
+length of `S` will result in the center of `S` remaining fixed and the length of `Q{#`1}
+will not be invariant with changes of the length of `S`. This variation in behavior could be very
+confusing since, while running a program, one could not tell by inspection of the element positions
+what should happen if a length were changed.
+
+To avoid confusion, Bmad uses a simple algorithm for varying the lengths of elements involved in
+superposition: The rule is that the length of the most downstream `super_slave` is varied. With
+the first example in Section~[](#s:super), the `group` `G` varying the length of `Q`
+defined by:
+```{code} yaml
+G: group = {Q}, var = {l}
+```
+would vary the length of `Q{B`S} which would result in an equal variation of the length of
+`S`. To keep the length of `S` invariant while varying `Q` the individual `super_slave`
+lengths can be varied. Example:
+```{code} yaml
+G2: group = {Q{#}1, S{#}1:-1}, var = {l}
+```
+The definition of `G2` must be placed in the lattice file after the superpositions so that the
+super slaves referred to by `G2` have been created.
+
+In the above example there is another, cleaner, way of achieving the same result by varying the
+downstream edge of `Q`:
+```{code} yaml
+G3: group = {Q}, var = {end_edge}
+```
+
+
+*) Difference from Bmad: Superposition is always done after lattice expansion.
+
+*) Superimposing using the same given Drift as a reference element multiple times is not allowed (unlike Bmad).
+Instead, superimpose a Null ele at the beginning or end of the drift and then use that as the reference.
+At the end, remove the Null element
+
+```{footbibliography}
+```
diff --git a/docs/src/utilities.md b/docs/src/utilities.md
new file mode 100644
index 0000000..324d316
--- /dev/null
+++ b/docs/src/utilities.md
@@ -0,0 +1,25 @@
+(c:utilities)=
+# Utilities
+This chapter covers utility functions.
+
+%---------------------------------------------------------------------------------------------------
+(s:iteration)=
+## Iteration Over Elements in a Lattice
+Iteration over a Region (see traversal.jl)
+
+%---------------------------------------------------------------------------------------------------
+(s:search)=
+## Searching for Lattice Elements
+%---------------------------------------------------------------------------------------------------
+(s:conversion)=
+## Particle Properties Conversion Functions
+%---------------------------------------------------------------------------------------------------
+(s:math)=
+## Math Utilities
+%---------------------------------------------------------------------------------------------------
+(s:manipulation)=
+## Lattice Manipulation
+%---------------------------------------------------------------------------------------------------
+(s:misc.utilities)=
+## Miscellaneous Utilities```{footbibliography}
+```
diff --git a/manual/ele-param-groups.tex b/manual/ele-param-groups.tex
index 104a395..ad1d181 100644
--- a/manual/ele-param-groups.tex
+++ b/manual/ele-param-groups.tex
@@ -1,4 +1,4 @@
-\chapter{Element Parameter Paramss}
+\chapter{Element Parameters}
\label{c:ele.groups}
Generally, element parameters are grouped into ``\vn{element} \vn{parameter} \vn{group}''
diff --git a/manual/ele-types.tex b/manual/ele-types.tex
index 820a247..4c4c471 100644
--- a/manual/ele-types.tex
+++ b/manual/ele-types.tex
@@ -161,7 +161,8 @@ \section{Bend}
\begin{figure}[ht]
- \centering \includegraphics{bend.pdf}
+ \centering
+ \includegraphics{bend.pdf}
\caption[Bend geometry]{
Bend geometry. Red dots are the entry and exit points that define the origin for the
coordinate systems at the entry end $(s_1, x_1)$ and exit ends $(s_2, x_2)$ respectively.
@@ -635,8 +636,9 @@ \section{Girder}
\end{example}
Using a small angle approximation to simplify the calculation, the \vn{x_pitch} of \vn{g4} produces
an offset at the center of \vn{q2} of $0.01 = 0.002 * 5$. This, added to the offsets of \vn{g4} and
-\vn{q2}, give the total \vn{x_offset}, denoted \vn{x_offset_tot} of \vn{q2} is $0.06 = 0.01 + 0.03 +
-0.02$. The total \vn{x_pitch}, denoted \vn{x_pitch_tot}, of \vn{q2} is $0.022 = 0.02 + 0.001$.
+\vn{q2}, give the total \vn{x_offset}, denoted \vn{x_offset_tot} of \vn{q2} is
+$0.06 = 0.01 + 0.03 + 0.02$.
+The total \vn{x_pitch}, denoted \vn{x_pitch_tot}, of \vn{q2} is $0.022 = 0.02 + 0.001$.
A \vn{Girder} that has its \vn{is_on} attribute set to False is considered to be unsifted with
respect to it's reference frame.
@@ -737,11 +739,6 @@ \section{Patch}
coordinate system is needed so that the fields or apertures can be unambiguously positioned.
-
-%----
-There
-
-
Generally, if a particle is reasonably near the branch reference curve, there is a one-to-one mapping
between the particle's position and branch $(x, y, s)$ coordinates.
@@ -756,8 +753,8 @@ \section{Patch}
reference curve a distance \vn{L} from point $\gamma$ is labeled $\beta$ in the figure.
In the branch $(x, y, s)$ coordinate system a particle at $\alpha$ will have some value $s = s_0$. A
-particle at point $\beta$ will have the same value $s = s_0$ and a particle at $\gamma$ will have $s
-= s_1 = s_0 + L$. A particle at point $r_a$ in \fig{f:patch.prob} illustrates the problem of
+particle at point $\beta$ will have the same value $s = s_0$ and a particle at $\gamma$ will have
+$s = s_1 = s_0 + L$. A particle at point $r_a$ in \fig{f:patch.prob} illustrates the problem of
assigning $(x, y, s)$ coordinates to a given position. If the particle is considered to be within
the region of \vn{ele_a}, the particle's $s$ position will be $s_{a2}$ which is greater than the
value $s_0$ at the exit end of the element. This contradicts the expectation that particles within
diff --git a/manual/introduction.tex b/manual/introduction.tex
index cab8ad4..decc592 100644
--- a/manual/introduction.tex
+++ b/manual/introduction.tex
@@ -3,7 +3,7 @@ \chapter{Introduction and Concepts}
%---------------------------------------------------------------------------
\section{Introduction}
-This chapter is an introduction to, the \accellat package which is part of the
+This chapter is an introduction to the \accellat package which is part of the
greater \scibmad ecosystem of toolkits and programs for accelerator simulations. With \accellat,
lattices can be constructed and manipulated. Essentially, a \vn{lattice} instance contains
a set of ``\vn{branches}'' and a branch contains
diff --git a/src/core.jl b/src/core.jl
index 7d15770..f428e7c 100644
--- a/src/core.jl
+++ b/src/core.jl
@@ -27,25 +27,6 @@ Example: length(:abc) => 4
Base.length(sym::Symbol) = length(repr(sym))
-#---------------------------------------------------------------------------------------------------
-# index
-
-"""
- index(str::AbstractString, substr::AbstractString)
-
-Index of substring in string. Assumes all characters are ASCII.
-Returns 0 if substring is not found
-""" index
-
-function index(str::AbstractString, substr::AbstractString)
- ns = length(substr)
- for ix in range(1, length(str)-ns+1)
- if str[ix:ix+ns-1] == substr; return ix; end
- end
-
- return 0
-end
-
#---------------------------------------------------------------------------------------------------
# strip_AL