diff --git a/docs/source/_static/css/my_theme.css b/docs/source/_static/css/my_theme.css
new file mode 100644
index 00000000..2c85b2c9
--- /dev/null
+++ b/docs/source/_static/css/my_theme.css
@@ -0,0 +1,27 @@
+@import url("theme.css");
+
+/* Main panel */
+.wy-nav-content {
+ max-width: 80%;
+}
+
+
+/* Maths */
+.MathJax_Display {
+ text-align: left !important;
+}
+
+
+/* Citation tables */
+.wy-table-responsive {
+ margin: 0;
+ border-top: 1px dotted rgba(235,235,235,1) ! important;
+}
+
+table.citation td {
+ padding: 5px ! important;
+}
+
+table.citation td.label {
+ width: 100px ! important;
+}
diff --git a/docs/source/app_source.rst b/docs/source/app_source.rst
new file mode 100644
index 00000000..9b875b97
--- /dev/null
+++ b/docs/source/app_source.rst
@@ -0,0 +1,202 @@
+***********************
+Overview of source code
+***********************
+
+This section provides an overview of the source code modules and describes each of the classes and methods used in the gprMax package. The following licensing information applies to all source files unless otherwise stated::
+
+ Copyright (C) 2015, The University of Edinburgh.
+
+ Authors: Craig Warren and Antonis Giannopoulos
+
+ gprMax is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ gprMax is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with gprMax. If not, see .
+
+
+constants.py
+============
+
+Defines constants:
+
+* Speed of light in vacuum :math:`c=2.9979245 \times 10^8` m/s
+* Permittivity of free space :math:`\epsilon_0=8.854187 \times 10^{-12}` F/m
+* Permeability of free space :math:`\mu_0=1.256637 \times 10^{-6}` H/m
+* Impedance of free space :math:`z_0=376.7303134` Ohms
+
+Defines data types:
+
+* Solid and ID arrays use 32-bit integers (0 to 4294967295)
+* Rigid arrays use 8-bit integers (the smallest available numpy type to store booleans - true/false)
+* Fractal and dispersive coefficient arrays use complex numbers (:code:`complextype`) which are represented as two :code:`floattype`
+* Main field arrays use floats (:code:`floattype`) and complex numbers (:code:`complextype`)
+* :code:`floattype` and :code:`complextype` are set to use 32-bit floats but can be changed to use 64-bit double precision if required.
+
+.. automodule:: gprMax.constants
+
+
+exceptions.py
+=============
+
+.. automodule:: gprMax.exceptions
+
+
+fields_output.py
+================
+
+.. automodule:: gprMax.fields_output
+
+
+fields_update.pyx
+=================
+
+.. automodule:: gprMax.fields_update
+
+
+fractals.py
+===========
+
+.. automodule:: gprMax.fractals
+
+
+geometry_primitives.pyx
+=======================
+
+.. automodule:: gprMax.geometry_primitives
+
+
+geometry_views.py
+=================
+
+.. automodule:: gprMax.geometry_views
+
+
+gprMax.py
+===========
+
+.. automodule:: gprMax.gprMax
+
+grid.py
+=======
+
+.. automodule:: gprMax.grid
+
+
+input_cmds_file.py
+==================
+
+.. automodule:: gprMax.input_cmds_file
+
+
+input_cmds_geometry.py
+======================
+
+.. automodule:: gprMax.input_cmds_geometry
+
+
+input_cmds_multiuse.py
+======================
+
+.. automodule:: gprMax.input_cmds_multiuse
+
+
+input_cmds_singleuse.py
+=======================
+
+.. automodule:: gprMax.input_cmds_singleuse
+
+
+materials.py
+============
+
+.. automodule:: gprMax.materials
+
+
+pml_1order_update.pyx
+=====================
+
+.. automodule:: gprMax.pml_1order_update
+
+
+pml_2order_update.pyx
+=====================
+
+.. automodule:: gprMax.pml_2order_update
+
+
+pml_call_updates.py
+===================
+
+.. automodule:: gprMax.pml_call_updates
+
+
+pml.py
+======
+
+.. automodule:: gprMax.pml
+
+
+receivers.py
+============
+
+.. automodule:: gprMax.receivers
+
+
+snapshots.py
+============
+
+.. automodule:: gprMax.snapshots
+
+
+sources.py
+==========
+
+.. automodule:: gprMax.sources
+
+
+user_libs.antennas.py
+=====================
+
+This module is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License::
+
+ Copyright (C) 2015, Craig Warren
+
+ This module is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
+ To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+
+ Please use the attribution at http://dx.doi.org/10.1190/1.3548506
+
+.. automodule:: user_libs.antennas
+
+
+utilities.py
+============
+
+.. automodule:: gprMax.utilities
+
+
+waveforms.py
+============
+
+.. automodule:: gprMax.waveforms
+
+
+yee_cell_build.pyx
+==================
+
+.. automodule:: gprMax.yee_cell_build
+
+
+yee_cell_setget_rigid.pyx
+=========================
+
+.. automodule:: gprMax.yee_cell_setget_rigid
+
diff --git a/docs/source/app_waveforms.rst b/docs/source/app_waveforms.rst
new file mode 100644
index 00000000..babd1aef
--- /dev/null
+++ b/docs/source/app_waveforms.rst
@@ -0,0 +1,154 @@
+.. _waveforms:
+
+******************
+Built-in waveforms
+******************
+
+This section provides definitions of the functions that are used to create the built-in waveforms. Example plots are shown using the parameters: amplitude of one, frequency of 1GHz, time window of 6ns, and a time step of 1.926ps.
+
+gaussian
+========
+
+A Gaussian waveform.
+
+.. math:: I = e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/gaussian.pdf
+
+ Example of the ``gaussian`` waveform - time domain and power spectrum.
+
+
+gaussiandot
+===========
+
+First derivative of a Gaussian waveform.
+
+.. math:: I = -2 \zeta (t-\chi) e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/gaussiandot.pdf
+
+ Example of the ``gaussiandot`` waveform - time domain and power spectrum.
+
+
+gaussiandotnorm
+===============
+
+Normalised first derivative of a Gaussian waveform.
+
+.. math:: I = -2 \sqrt{\frac{e}{2\zeta}} \zeta (t-\chi) e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/gaussiandotnorm.pdf
+
+ Example of the ``gaussiandotnorm`` waveform - time domain and power spectrum.
+
+
+gaussiandotdot
+==============
+
+Second derivative of a Gaussian waveform.
+
+.. math:: I = 2\zeta \left(2\zeta(t-\chi)^2 - 1 \right) e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/gaussiandotdot.pdf
+
+ Example of the ``gaussiandotdot`` waveform - time domain and power spectrum.
+
+
+gaussiandotdotnorm
+==================
+
+Normalised second derivative of a Gaussian waveform.
+
+.. math:: I = \left( 2\zeta (t-\chi)^2 - 1 \right) e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/gaussiandotdotnorm.pdf
+
+ Example of the ``gaussiandotdotnorm`` waveform - time domain and power spectrum.
+
+
+gaussiandotdotdot
+=================
+
+Third derivative of a Gaussian waveform.
+
+.. math:: I = \zeta^2 \left( 3(t-\chi) - 2\zeta (t-\chi)^3 \right) e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/gaussiandotdotdot.pdf
+
+ Example of the ``gaussiandotdotdot`` waveform - time domain and power spectrum.
+
+
+ricker
+======
+
+A Ricker (or Mexican Hat) waveform which is the negative, normalised second derivative of a Gaussian waveform.
+
+.. math:: I = - \left( 2\zeta (t-\chi)^2 -1 \right) e^{-\zeta(t-\chi)^2}
+
+where :math:`I` is the current, :math:`\zeta = 2\pi^2f^2`, :math:`\chi=\frac{1}{f}` and :math:`f` is the frequency.
+
+.. figure:: images/ricker.pdf
+
+ Example of the ``ricker`` waveform - time domain and power spectrum.
+
+
+sine
+====
+
+A single cycle of a sine waveform.
+
+.. math:: I = R\sin(2\pi ft)
+
+and
+
+.. math::
+
+ R =
+ \begin{cases}
+ 1 &\text{if $ft\leq1$}, \\
+ 0 &\text{if $ft>1$}.
+ \end{cases}
+
+:math:`I` is the current, :math:`t` is time and :math:`f` is the frequency.
+
+.. figure:: images/sine.pdf
+
+ Example of the ``sine`` waveform - time domain and power spectrum.
+
+
+contsine
+========
+
+A continuous sine waveform. In order to avoid introducing noise into the calculation the amplitude of the waveform is modulated for the first cycle of the sine wave (ramp excitation).
+
+.. math:: I = R\sin(2\pi ft)
+
+and
+
+.. math::
+
+ R =
+ \begin{cases}
+ R_cft &\text{if $R\leq 1$}, \\
+ 1 &\text{if $R>1$}.
+ \end{cases}
+
+where :math:`I` is the current, :math:`R_c` is set to :math:`0.25`, :math:`t` is time and :math:`f` is the frequency.
+
+.. figure:: images/contsine.pdf
+
+ Example of the ``contsine`` waveform - time domain and power spectrum.
+
+
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 00000000..cc0ed043
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,371 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# gprMax documentation build configuration file, created by
+# sphinx-quickstart on Fri Jul 17 11:23:46 2015.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import os, re, shlex, sys
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('../../gprMax'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.mathjax', 'sphinx.ext.autodoc', 'sphinx.ext.napoleon'
+]
+
+# Options for autodoc
+autodoc_default_flags = ['members']
+autodoc_member_order = 'bysource'
+autoclass_content = 'both'
+
+# Options for napoleon (which parses googlestyle)
+napoleon_use_param = False
+
+# Figure numbering
+numfig = True
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'gprMax'
+copyright = '2015, The University of Edinburgh. Authors: Craig Warren and Antonis Giannopoulos'
+author = 'Craig Warren and Antonis Giannopoulos'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+# Read version number from gprMax/gprMax.py
+#version = re.search('^__version__\s*=\s*\'(.*)\'',
+# open('../../gprMax/gprMax/gprMax.py').read(),
+# re.M).group(1)
+version = '3.0.0b3'
+# The full version, including alpha/beta/rc tags.
+release = version + '(Bowmore)'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'sphinx_rtd_theme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+html_title = 'gprMax User Guide'
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = 'images/gprMax_FB_logo.png'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+html_style = 'css/my_theme.css'
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'gprMaxdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'gprMax.tex', 'gprMax User Guide',
+ 'Craig Warren and Antonis Giannopoulos', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+latex_logo = 'images/gprMax_logo.png'
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+latex_show_urls = 'inline'
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'gprMax', 'gprMax User Guide',
+ [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'gprMax', 'gprMax User Guide',
+ author, 'gprMax', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The basename for the epub file. It defaults to the project name.
+#epub_basename = project
+
+# The HTML theme for the epub output. Since the default themes are not optimized
+# for small screen space, using the same theme for HTML and epub output is
+# usually not wise. This defaults to 'epub', a theme designed to save visual
+# space.
+#epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or 'en' if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#epub_tocscope = 'default'
+
+# Fix unsupported image types using the Pillow.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#epub_use_index = True
diff --git a/docs/source/examples_2D.rst b/docs/source/examples_2D.rst
new file mode 100644
index 00000000..535d6098
--- /dev/null
+++ b/docs/source/examples_2D.rst
@@ -0,0 +1,180 @@
+***********
+2D Examples
+***********
+
+This section provides some general example models in 2D that demonstrate how to use certain features of gprMax. Each example comes with an input file which you can download and run.
+
+A-scan with a Hertzian dipole source
+====================================
+
+:download:`cylinder_Ascan_2D.in `
+
+This example is the gprMax equivalent of 'Hello World'! It demonstrates how to simulate a single trace (A-scan) from a metal cylinder buried in a dielectric half-space.
+
+.. literalinclude:: models/cylinder_Ascan_2D.in
+ :language: none
+ :linenos:
+
+The geometry of the scenario is straightforward and is shown in :numref:`cylinder_half_space_geo`.
+
+.. _cylinder_half_space_geo:
+
+.. figure:: images/cylinder_half_space_geo.pdf
+ :width: 600 px
+
+ Geometry of a 2D model of a metal cylinder buried in a dielectric half-space.
+
+For this initial example a detailed description of what each command in the input file does and why each command was used is given. The following steps explain the steps taken to build the input file:
+
+Determine the constitutive parameters for the materials
+-------------------------------------------------------
+
+There will be three different materials in the model representing air, the dielectric half-space, and the metal cylinder. Air (free space) already exists as a built-in material in gprMax which can be accessed using the ``free_space`` identifier. The metal cylinder will be modelled as a Perfect Electric Conductor, which again exists as a built-in material in gprMax and can be accessed using the ``pec`` identifier. So the only material which has to be defined is for the dielectric half-space. It is a non-magnetic material, i.e. :math:`\mu_r=1` and :math:`\sigma_*=0` and with a relative permittivity of six, :math:`\epsilon_r=6`, and zero conductivity, :math:`\sigma=0`. The identifier ``half_space`` will be used.
+
+.. code-block:: none
+
+ #material: 6 0 1 0 half_space
+
+Determine the source type and excitation frequency
+--------------------------------------------------
+
+These should generally be known, often based on the GPR system or scenario being modelled. Low frequencies are used where significant penetration depth is important, whereas high frequencies are used where less penetration and better resolution are required. In this case a theoretical Hertzian dipole source fed with a Ricker waveform with a centre frequency of :math:`f_c=1.5~\textrm{GHz}` will be used to simulate the GPR antenna (later examples will demonstrate how to include a model of the actual GPR antenna in the simulation).
+
+.. code-block:: none
+
+ #waveform: ricker 1 1.5e9 my_ricker
+ #hertzian_dipole: z 0.100 0.170 0 my_ricker
+
+The Ricker waveform is created with the ``#waveform`` command, specifying an amplitude of one, centre frequency of 1.5 GHz and picking an arbitrary identifier of ``my_ricker``. The Hertzian dipole source is created using the ``#hertzian_dipole`` command, specifying a z direction polarisation (the survey direction if a B-scan were being created), location on the surface of the slab, and using the Ricker waveform already created.
+
+Calculate a spatial resolution and domain size
+----------------------------------------------
+
+In the :ref:`guidance` section it was stated that a good *rule-of-thumb* was that the spatial resolution should be one tenth of the smallest wavelength present in the model. To determine the smallest wavelength, the highest frequency present in the model is required. This is not the centre frequency of the Ricker waveform! By examining the spectrum of the Ricker waveform it is evident much higher frequencies are present, 2-3 times as high as the centre frequency. So the highest frequency present in the model is likely to be around 4 GHz. The wavelength at 4 GHz in the half-space would be:
+
+.. math:: \lambda = \frac{c}{f \sqrt{\epsilon_r}} = \frac{299792458}{4\times 10^9 \sqrt{6}} = 30.6~\textrm{mm}
+
+This would give a minimum spatial resolution of 3 mm. However, the diameter of the cylinder is 20 mm so would be resolved to 7 cells. Therefore a better choice would be 2 mm which resolves the diameter of the rebar to 10 cells, but since the model is only 2D (and therefore the size of the domain will not be large), a spatial resolution of 1 mm will be used.
+
+.. code-block:: none
+
+ #dx_dy_dz: 0.001 0.001 0.001
+
+The domain size should be enough to enclose the volume of interest, plus allow 10 cells (if using the default value) for the PML absorbing boundary conditions and approximately another 10 cells of between the PML and any objects of interest. In this case the plan is to take a B-scan of the scenario (in the next example) so the domain should be large enough to do that. Although this is a 2D model one cell must be specified in the infinite direction (in this case the z direction) of the domain.
+
+.. code-block:: none
+
+ #domain: 0.240 0.190 0.001
+
+Since this is a 2D model the PML should be switched off for the two faces of the domain in the infinite direction (in this case the z direction). This is achieved using the command:
+
+.. code-block:: none
+
+ #pml_cells: 10 10 0 10 10 0
+
+Choose a time window
+--------------------
+
+It is desired to see the reflection from the cylinder, therefore the time window must be long enough to allow the electromagnetic waves to propagate from the source through the half-space to the cylinder and be reflected back to the receiver, i.e.
+
+.. math:: \frac{0.180}{\frac{c}{\sqrt{6}}} = 1.47~\textrm{ns}
+
+This is the minimum time required, but to allow for the entire pulse wavelet to be reflected back to the receiver an initial time window of 4 ns will be tested.
+
+.. code-block:: none
+
+ #time_window: 4e-9
+
+gprMax will calculate the time step required for the model using the CFL condition in 3D. However, since this is a 2D model the time step can be relaxed to the CFL condition in 2D. This is achieved using the command:
+
+.. code-block:: none
+
+ #time_step_limit_type: 2D
+
+Create the objects
+------------------
+
+Now physical objects can created for the half-space and the cylinder. First the ``#box`` command will be used to create the half-space and then the ``#cylinder`` command will be given which will overwrite the properties of the half-space with those of the cylinder at the location of the cylinder.
+
+.. code-block:: none
+
+ #box: 0 0 0 0.240 0.170 0.001 half_space
+ #cylinder: 0.120 0.080 0 0.120 0.080 0.001 0.010 pec
+
+Run the model
+-------------
+
+You can now run the model:
+
+.. code-block:: none
+
+ python -m gprMax cylinder_Ascan_2D.in
+
+View the results
+----------------
+
+You should have produced an output file ``cylinder_Ascan_2D.out``. You can view the results (see :ref:`output` section) using the command:
+
+.. code-block:: none
+
+ python -m tools.plot_hdf5_Ascan cylinder_Ascan_2D.out
+
+:numref:`cylinder_Ascan_results` shows the time history of the electric and magnetic field components at the receiver location. The :math:`E_z` field component can be converted to voltage which represents the A-scan (trace). The initial part of the signal (<1.5 ns) represents the direct wave from transmitter to receiver. Then comes the reflected wavelet from the metal cylinder.
+
+.. _cylinder_Ascan_results:
+
+.. figure:: images/cylinder_Ascan.pdf
+
+ Field outputs from a model of a metal cylinder buried in a dielectric half-space.
+
+
+B-scan with a Hertzian dipole source
+====================================
+
+:download:`cylinder_Bscan_2D.in `
+
+This example using the same geometry as the previous example but this time a B-scan is created. A B-scan is composed of multiple traces (A-scans) recorded as the source and receiver are moved over the target, in this case the metal cylinder.
+
+.. literalinclude:: models/cylinder_Bscan_2D.in
+ :language: none
+ :linenos:
+
+The differences between this input file and the one from the A-scan are the x coordinates of the source and receiver (lines 11 adnd 12), and the commands needed to move the source and receiver (lines 13 and 14). The source and receiver are offset by 40mm from each other as before. They are now shifted to the starting position for the scan. The ``#src_steps`` command is used to tell gprMax to move every source in the model by specified steps each time the model is run. Similarly, the ``#rx_steps`` command is used to tell gprMax to move every receiver in the model by specified steps each time the model is run. Note, the same functionality could be achieved by using a block of Python code in the input file to move the source and receiver (for further details see the :ref:`Python section `).
+
+To run the model for a B-scan is slightly different than for a single A-scan. You must pass an optional argument to gprMax to specify the number of times the model should be run, which in this case is the number of A-scans (traces) that will comprise the B-scan. For a B-scan over a distance of 160mm with a step of 2mm that is 80 A-scans.
+
+.. code-block:: none
+
+ python -m gprMax cylinder_Bscan_2D.in -n 80
+
+
+Results
+-------
+
+You should have produced 80 output files, one for each A-scan, with names ``cylinder_Bscan_2D1.out``, ``cylinder_Bscan_2D2.out`` etc... These can be combined into a single file using the command:
+
+.. code-block:: none
+
+ python -m tools.outputfiles_mergehdf5 cylinder_Bscan_2D 80
+
+You should see a combined output file ``cylinder_Bscan_2D_all.out``. The tool will ask you if you want to delete the original single A-scan output files or keep them.
+
+You can now view an image of the B-scan using the command:
+
+.. code-block:: none
+
+ python -m tools.plot_hdf5_Bscan cylinder_Bscan_2D_all.out Ez
+
+:numref:`cylinder_Bscan_results` shows the B-scan (image of the Ez field). As expected a hyperbolic response is present from the metal cylinder.
+
+.. _cylinder_Bscan_results:
+
+.. figure:: images/cylinder_Bscan_results.pdf
+
+ B-scan of model of a metal cylinder buried in a dielectric half-space.
+
+
+
+
+
+
diff --git a/docs/source/examples_3D.rst b/docs/source/examples_3D.rst
new file mode 100644
index 00000000..4ce4f4c3
--- /dev/null
+++ b/docs/source/examples_3D.rst
@@ -0,0 +1,110 @@
+***********
+3D Examples
+***********
+
+This section provides some general example models in 3D that demonstrate how to use certain features of gprMax. Each example comes with an input file which you can download and run.
+
+Using an antenna model
+======================
+
+:download:`antenna_MALA_1200_fs.in `
+
+This example demonstrates how to use one of the built-in antenna models in a simulation. Using a model of an antenna rather than a simple source, such as a Hertzian dipole, can improve the accuracy of the results of a simulation for many situations. It is especially important when the target is in the near-field of the antenna and there are complex interactions between the antenna and the environment. The simulation uses the model of an antenna similar to a MALA 1.2GHz antenna.
+
+.. literalinclude:: models/antenna_MALA_1200_fs.in
+ :language: none
+ :linenos:
+
+.. figure:: images/antenna_MALA_1200.png
+ :width: 600 px
+
+ FDTD geometry mesh showing an antenna model similar to a MALA 1.2GHz antenna (skid removed for illustrative purposes).
+
+The antenna model is loaded from a Python module and inserted into the input file just like another geometry command. The arguments for the ``antenna_like_MALA_1200`` function specify its (x, y, z) location as 0.132m, 0.095m, 0.100m using a 1mm spatial resolution. In this example the antenna is the only object in the model, i.e. the antenna is in free space. When the simulation is run two geometry files for the antenna are produced along with an output file which contains a single receiver (the antenna output). The antenna bowties are aligned with the y axis so the output is the y component of the electric field. More information can be found in the :ref:`Python section `.
+
+Results
+-------
+
+:numref:`antenna_MALA_1200_fs_results` shows the time history of the electric and magnetic field components from the receiver bowtie of the antenna model. The antenna bowties are aligned with the y axis so the output will be the Ey component of the electric field.
+
+.. _antenna_MALA_1200_fs_results:
+
+.. figure:: images/antenna_MALA_1200_fs_results.pdf
+
+ Field outputs from the receiver bowtie of a model of an antenna similar to a MALA 1.2GHz antenna.
+
+B-scan with an antenna model
+============================
+
+:download:`GSSI_1500_cylinder_Bscan.in `
+
+This example demonstrates how to create a B-scan with an antenna model. The scenario is purposely simple to illustrate the method. A metal cylinder of diameter 20mm is buried in a dielectric half-space which has a relative permittivity of six. The simulation uses the model of an antenna similar to a GSSI 1.5GHz antenna.
+
+.. literalinclude:: models/GSSI_1500_cylinder_Bscan.in
+ :language: none
+ :linenos:
+
+.. figure:: images/GSSI_1500_cylinder.png
+ :width: 600 px
+
+ FDTD geometry mesh showing a metal cylinder buried in a half-space and an antenna model similar to a GSSI 1.5GHz antenna.
+
+The antenna must be moved to a new position for every single A-scan (trace) in the B-scan. In this example the B-scan distance will be 270mm with a trace every 5mm, so 54 model runs will be required.
+
+.. code-block:: none
+
+ python -m gprMax GSSI_1500_cylinder_Bscan.in -n 54
+
+The total number of runs for a model as well as the number of the current run of the model are stored and can be accessed in Python as ``number_model_runs`` and ``current_model_run``. The ``current_model_run`` can be used to move the position of the antenna for every run of the model as shown in Line 13. The antenna will be moved 5mm in the x direction for every new run of the model.
+
+Results
+-------
+
+:numref:`GSSI_1500_cylinder_Bscan_results` shows the B-scan (image of the Ey field). As expected a hyperbolic response is present from the metal cylinder.
+
+.. _GSSI_1500_cylinder_Bscan_results:
+
+.. figure:: images/GSSI_1500_cylinder_Bscan_results.pdf
+
+ B-scan of model of a metal cylinder buried in a dielectric half-space with a model of an antenna similar to a GSSI 1.5GHz antenna.
+
+Building a heterogeneous soil
+=============================
+
+:download:`heterogeneous_soil.in `
+
+This example demonstrates how to build a more realistic soil model using a stochastic distribution of dielectric properties. A mixing model for soils proposed by Peplinski (http://dx.doi.org/10.1109/36.387598) is used to define a series of dispersive material properties for the soil.
+
+.. literalinclude:: models/heterogeneous_soil.in
+ :language: none
+ :linenos:
+
+.. figure:: images/heterogeneous_soil.png
+ :width: 600 px
+
+ FDTD geometry mesh showing a heterogeneous soil model with a rough surface.
+
+Line 10 defines a series of dispersive materials to represent a soil with sand fraction 0.5, clay fraction 0.5, bulk density :math:`2~g/cm^3`, sand particle density of :math:`2.66~g/cm^3`, and a volumetric water fraction range of 0.001 - 0.25. The volumetric water fraction is given as a range which is what defines a series of dispersive materials.
+
+These materials can then be distributed stochastically over a volume using the ``#fractal_box`` command. Line 11 defines a volume, a fractal dimension, a number of materials, and a mixing model to use. The fractal dimension, 1.5, controls how the materials are stochastically distributed. The fractal weightings, 1, 1, 1, weight the fractal in the x, y, and z directions. The number of materials, 50, specifies how many dispersive materials to create using the mixing model (``my_soil``).
+
+Adding rough surfaces
+---------------------
+
+A rough surface can be added to any side of ``#fractal_box`` using,
+
+.. code-block:: none
+
+ #add_surface_roughness: 0 0 0.070 0.15 0.15 0.070 1.5 1 1 0.065 0.080 my_soil_box
+
+which defines one of the surfaces of the ``#fractal_box``, a fractal dimension, and minimum and maximum values for the height of the roughness (relative to the original ``#fractal_box`` volume). In this example the roughness will be stochastically distributed with troughs up to 5mm deep, and peaks up to 10mm high.
+
+More information, including adding surface water and vegetation, can be found in the :ref:`section on using the fractal box command `.
+
+
+
+
+
+
+
+
diff --git a/docs/source/faqs.rst b/docs/source/faqs.rst
new file mode 100644
index 00000000..8259835b
--- /dev/null
+++ b/docs/source/faqs.rst
@@ -0,0 +1,5 @@
+****
+FAQs
+****
+
+This section will provide answers to frequently asked questions about gprMax and its uses.
\ No newline at end of file
diff --git a/docs/source/features.rst b/docs/source/features.rst
new file mode 100644
index 00000000..f815a502
--- /dev/null
+++ b/docs/source/features.rst
@@ -0,0 +1,163 @@
+.. _capabilities:
+
+*****************
+Software Features
+*****************
+
+This section begins with an overview, primarily for previous users, about what is new, what has changed, and what has been retired in this version of gprMax. It is then followed by more general descriptions some of the key features of gprMax that are useful for GPR modelling as well as more general electromagnetic simulations.
+
+What's new/changed?
+===================
+
+A brief summary of what each input command does is given. Please refer to the :ref:`commands` section for a detailed description of the syntax of each command.
+
+The code has been completely re-written in Python/Cython. In the process a lot of changes have been made to improve efficiency, speed, and usability. Many new features have been implemented, which have been focussed on the following areas:
+
+* Scripting in the input file.
+* Built-in library of antenna models
+* Anisotropic material modelling.
+* Dispersive material modelling using multiple pole Debye, Lorenz or Drude formulations.
+* Building heterogeneous objects using fractal distributions.
+* Building objects with rough surfaces.
+* Modelling soils with realistic dielectric and geometric properties.
+* Improved PML (RIPML) performance.
+
+New commands
+------------
+
+* ``#python`` and ``#end_python`` are used to define blocks of the input file where Python code will be executed. This allows the user to use scripting directly in the input file.
+* ``#material`` replaces ``#medium`` with a new syntax.
+* ``#add_dispersion_debye`` is used to add Debye dispersive properties to a ``#material``.
+* ``#add_dispersion_lorenz`` is used to add Lorenz dispersive properties to a ``#material``.
+* ``#add_dispersion_drude`` is used to add Drude dispersive properties to a ``#material``.
+* ``#soil_peplinski`` is a soil mixing model that can be used with ``#fractal_box`` to generate soil(s) with more realistic dielectric and geometric properties.
+* ``#cylindrical_sector`` (like a slice of pie shape) is a new object building command.
+* ``#geometry_view`` replaces ``#geometry_file`` or ``#geometry_vtk`` and is used to create views of the geometry of the model in open source Visualization ToolKit (VTK) (http://www.vtk.org) format which can be viewed in many free readers, such as Paraview (http://www.paraview.org).
+* ``#fractal_box`` is used to create a volume with a fractal distribution of properties.
+* ``#add_surface_roughness`` is used to add a rough surface to a ``#fractal_box``.
+* ``#add_surface_water`` is used to add surface water to a ``#fractal_box`` that has a rough surface.
+* ``#add_grass`` is used to add grass to a ``#fractal_box``.
+* ``#waveform`` is used to specify a waveform shape, and works in conjunction with the changed source commands.
+* ``#magnetic_dipole`` is used to introduce a magnetic dipole source, i.e. current on a small loop.
+* ``#pml_cfs`` is an advanced command for adjusting the CFS parameters used in the new PML.
+
+
+Changed commands
+----------------
+
+* All object building commands support anisotropy via additional material identifiers, e.g. ``#box: 0.0 0.0 0.0 0.1 0.1 0.1 matX matY matZ``.
+* Dielectric smoothing can be turned on (the default setting) or off for any volumetric object building command by specifying a character ``y`` (on) or ``n`` (off) after the material identifier, e.g. ``#sphere: 0.5 0.5 0.5 0.25 sand n``.
+* ``#triangle`` can now create both triangular patches (2D) and triangular prisms (3D) via a thickness parameter.
+* ``#pml_cells`` replaces ``#pml_layers`` and can now be used to control the number of cells of PML on the six faces of the model domain. The number of cells can be set to zero on any of the faces to turn that PML off if desired. The default behaviour (if this command is not specified) is to use 10 cells.
+* ``#hertzian_dipole`` and ``#voltage_source`` now specify polarisation, location, any additional parameters, and an identifier to link to a ``#waveform`` command.
+* ``#snapshot`` no longer requires a type, as only VTK snapshot files are now produced.
+* ``#num_of_procs`` is now called ``#num_omp_threads``.
+* ``#tx_steps`` is now called ``#src_steps``.
+
+
+Retired commands
+----------------
+
+* ``#analysis`` and ``#end_analysis`` are no longer required as: sources and receivers can be specified anywhere is the input file; the output file automatically has the same name as the input file with a ``.out`` extension; the format of the output file is now HDF5 (https://www.hdfgroup.org/HDF5/); gprMax can be run with the syntax ``gprMax my_input_file -n number_of_runs``, where ``number_of_runs`` can be used to rerun the model for creating scans and/or moving geometry between runs.
+* ``#tx`` is no longer required as the polarisation and position of a source is now specified in the source command, e.g. ``#hertzian_dipole: y 0.05 0.05 0.05 myPulse``.
+* ``#cylinder_new`` has become ``#cylinder``.
+* ``#cylindrical_segment`` was under-used and its effect can be created by cutting a ``#cylinder`` with a ``#box``.
+* ``#bowtie`` can be created using the new behaviour of ``#triangle``.
+* ``#number_of_media`` is not required with the new Python code.
+* ``#nips_number`` is not required with the new Python code.
+* ``#media_file`` was under-used.
+* ``#geometry_file`` has been replaced with the ``#geometry_view`` command.
+* ``#medium`` has been replaced with the ``#material`` command.
+* ``#abc_type``, ``#abc_order``, ``#abc_stability_factors``, ``#abc_optimization_angles``, and ``#abc_mixing_parameters`` are not required as the Higdon ABCs have been removed.
+* ``#huygens_surface`` will become part of the new ``#plane_wave`` command which is yet to be implemented.
+
+
+Commands yet to be implemented
+------------------------------
+
+There are commands from previous versions of gprMax that are planned for this version, but are yet to be implemented. These will be introduced in a future update. They are: ``#thin_wire``, ``#transmission_line``, and ``#plane_wave``.
+
+
+Migrating old input files
+-------------------------
+
+gprMax includes a Python module (in the ``tools`` package) to help you migrate old input files, written for previous versions of gprMax, to the syntax of the new commands. The module will do its best to convert the old file and write a new one, however, you should still carefully check the new file to make sure it is what you intended! Usage (from the top-level gprMax directory) is: ``python -m tools.inputfileold2new my_old_inputfile.in``.
+
+
+Key features
+============
+
+Python scriptable input files
+-----------------------------
+
+The input file has now been made scriptable by permitting blocks of Python code to be specified between ``#python`` and ``#end_python`` commands. The code is executed when the input file is read by gprMax. You don't need any external tools, such as MATLAB, to generate larger, more complex input files for building intricate models. Python scripting means that gprMax now includes :ref:`libraries of more complex objects, such as antennas `, that can be easily inserted into a model. You can also access a number of built-in constants from your Python code. For further details see the :ref:`Python section `.
+
+Dispersive media
+----------------
+
+gprMax has always included the ability to represent dispersive materials using a single-pole Debye model. Many materials can be adequately represented using this approach for the typical frequency ranges associated with GPR. However, multi-pole Debye, Drude and Lorenz functions are often used to simulate the electric susceptibility of materials such as: water [PIE2009]_, human tissue [IRE2013]_, cold plasma [LI2013]_, gold [VIA2005]_, and soils [BER1998]_, [GIAK2012]_, [TEI1998]_. Electric susceptibility relates the polarization density to the electric field, and includes both the real and imaginary parts of the complex electric permittivity variation. In the new version of gprMax a recursive convolution based method is used to express dispersive properties as apparent current density sources [GIA2014]_. A major advantage of this implementation is that it creates an inclusive susceptibility function that holds, as special cases, Debye, Drude and Lorenz materials. For further details see the :ref:`material commands section `.
+
+Realistic soils, heterogeneous objects and rough surfaces
+---------------------------------------------------------
+
+The inclusion of improved models of soils is important for many GPR simulations. gprMax can now be used to create soils with more realistic dielectric and geometrical properties. A semi-empirical model, initially suggested by [DOB1985]_, is used to describe the dielectric properties of the soil. The model relates relative permittivity of the soil to bulk density, sand particle density, sand fraction, clay fraction and water volumetric fraction. Using this approach, a more realistic soil with a stochastic distribution of the aforementioned parameters can be modelled. The real and imaginary parts of this semi-empirical model can be approximated using a multi-pole Debye function plus a conductive term. This can now be achieved in gprMax using the new dispersive material functionality. For further details see the :ref:`material commands section `.
+
+Fractals are scale invariant functions which can express the topography of the earth for a wide range of scales with sufficient detail [TUR1987]_. For this reason fractals have been chosen to represent the topography of soils. Fractals can be generated by the convolution of Gaussian noise with an inverse Fourier transform of :math:`\frac{1}{kb}`, where :math:`k` is the wavenumber and :math:`b` is a constant related to the fractal dimension [TUR1997]_. gprMax can now generate heterogeneous volumes (boxes) with realistic soil properties that can have rough surfaces applied. For further details see the :ref:`fractal object building commands section `.
+
+Fractal correlated noise [TUR1997]_ is used to describe the stochastic distribution of the properties of soils. This approach has been chosen because it has been shown that soil-related environmental properties frequently obey fractal laws [BUR1981]_, [HILL1998]_. For further details see the :ref:`material commands section ` and the :ref:`fractal object building commands section `.
+
+.. _antennas:
+
+Library of antenna models
+-------------------------
+
+gprMax now includes Python modules with pre-defined models of antennas that behave similarly to commercial antennas [WAR2011]_. Currently models of antennas similar to Geophysical Survey Systems, Inc. (GSSI) (http://www.geophysical.com) 1.5 GHz (Model 5100) antenna, and MALA Geoscience (http://www.malags.com/) 1.2 GHz antenna are included. By taking advantage of Python scripting in input files, using such complex structures in a model is straightforward without having to be built step-by-step by the user. For further details see the :ref:`Python section `.
+
+Anisotropy
+----------
+
+It is possible to specify objects that have diagonal anisotropy which allows materials such as wood and fibre-reinforced composites, often imaged with GPR, to be more accurately modelled. Standard isotropic objects specify one material identifier that defines the same properties in x, y, and z directions. However, every volumetric object building command can also be specified with three material identifiers, which allows properties for the x, y, and z directions to be separately defined.
+
+Dielectric smoothing
+--------------------
+
+At the boundaries between different materials in the model there is the question of which material properties to use?
+
+* Should the last object to be defined at that location dictate the properties?
+* Should an average set of properties of the materials of the objects that share that location be used?
+
+This latter option is often referred to as dielectric smoothing. To address this question gprMax includes an option to turn dielectric smoothing on or off for volumetric object building commands. The default behaviour (if no option is specified) is for dielectric smoothing to be on. The option can be specified with a single character ``y`` (on) or ``n`` (off) given after the material identifier in each object command.
+
+Perfectly Matched Layer (PML) boundary conditions
+-------------------------------------------------
+
+With increased research into quantitative information from GPR, it has become necessary for models to be able to have more efficient and better-performing Perfectly Matched Layer (PML) absorbing boundary conditions. Since 2005 gprMax has featured PML absorbing boundary conditions based on the uniaxial PML (UPML) [GED1998]_ formulation. A PML based on a recursive integration approach to the complex frequency shifted (CFS) PML [GIA2012]_ has been adopted in the new version of gprMax. A general formulation of this RIPML, which can be used to develop any order of PML, has been used to implement first and second order CFS stretching functions. One of the attractions of the RIPML is that it is easily applied as a correction to the field quantities after the complete FDTD grid has been updated using the standard FDTD update equations. gprMax now offers the ability (for advanced users) to customise the parameters of the PML which allows its performance to be better optimised for specific applications. Additionally, since the RIPML is media agnostic it can be used without change to problems involving dispersive and anisotropic materials. For further details see the :ref:`PML commands section `.
+
+Open source, robust, file formats
+---------------------------------
+
+Alongside improvements to the input file there is a new output file format – HDF5 (http://www.hdfgroup.org/HDF5/) – to manage the larger and more complex data sets that are being generated. HDF5 is a robust, portable and extensible format with a number of free readers available. For further details see the :ref:`output file section