Repository: calkit/calkit

Issue:
I want to be able to easily start a new publication from a LaTeX template
Design decision: Include templates in the repo, installing with the package, or host them on GitHub and download as needed?

Upsides of shipping with the package:
- Simpler, can copy an entire directory rather than needing to figure out how to download from GitHub or whatever.
- Can work offline.

Downsides:
- Can inflate repo and package size if we have lots of templates someday. The JFM template's necessary files are under 200 kB total. This is quite a bit bigger than the code itself, but not too bad. I suppose someday if things get too crazy, we could always switch to a separate repo and/or package for templates. There could be a combination of both. If a template is registered with the package, we could notate if it's included or needs to be downloaded.

Discussion:

Solution patch:
diff --git a/calkit/__init__.py b/calkit/__init__.py
index 3fba4216..1b361271 100644
--- a/calkit/__init__.py
+++ b/calkit/__init__.py
@@ -1,4 +1,4 @@
-__version__ = "0.3.3"
+__version__ = "0.4.0"
 
 from .core import *
 from . import git
@@ -8,3 +8,4 @@
 from . import config
 from . import models
 from . import office
+from . import templates
diff --git a/calkit/cli/list.py b/calkit/cli/list.py
index 7ec925db..47e261bb 100644
--- a/calkit/cli/list.py
+++ b/calkit/cli/list.py
@@ -77,3 +77,10 @@ def list_environments():
         typer.echo(name + ":")
         for k, v in env.items():
             typer.echo(f"    {k}: {v}")
+
+
+@list_app.command(name="templates")
+def list_templates():
+    for kind, tpl_dict in calkit.templates.TEMPLATES.items():
+        for name in tpl_dict:
+            typer.echo(f"{kind}/{name}")
diff --git a/calkit/cli/main.py b/calkit/cli/main.py
index edf694ea..d75ca825 100644
--- a/calkit/cli/main.py
+++ b/calkit/cli/main.py
@@ -481,11 +481,21 @@ def run_in_env(
             ),
         ),
     ] = None,
+    wdir: Annotated[
+        str,
+        typer.Option(
+            "--wdir",
+            help=(
+                "Working directory. "
+                "By default will run current working directory."
+            ),
+        ),
+    ] = None,
     verbose: Annotated[
         bool, typer.Option("--verbose", "-v", help="Print verbose output.")
     ] = False,
 ):
-    ck_info = calkit.load_calkit_info()
+    ck_info = calkit.load_calkit_info(process_includes=True)
     envs = ck_info.get("environments", {})
     if not envs:
         raise_error("No environments defined in calkit.yaml")
@@ -507,33 +517,42 @@ def run_in_env(
     if env_name is None:
         raise_error("Environment must be specified if there are multiple")
     env = envs[env_name]
-    cwd = os.getcwd()
+    if wdir is not None:
+        cwd = os.path.abspath(wdir)
+    else:
+        cwd = os.getcwd()
     image_name = env.get("image", env_name)
-    wdir = env.get("wdir", "/work")
+    docker_wdir = env.get("wdir", "/work")
+    shell = env.get("shell", "sh")
+    platform = env.get("platform")
     if env["kind"] == "docker":
-        cmd = " ".join(cmd)
-        cmd = [
+        shell_cmd = " ".join(cmd)
+        docker_cmd = [
             "docker",
             "run",
+        ]
+        if platform:
+            docker_cmd += ["--platform", platform]
+        docker_cmd += [
             "-it" if sys.stdin.isatty() else "-i",
             "--rm",
             "-w",
-            wdir,
+            docker_wdir,
             "-v",
-            f"{cwd}:{wdir}",
+            f"{cwd}:{docker_wdir}",
             image_name,
-            "bash",
+            shell,
             "-c",
-            f"{cmd}",
+            f"{shell_cmd}",
         ]
         if verbose:
-            typer.echo(f"Running command: {cmd}")
-        subprocess.call(cmd)
+            typer.echo(f"Running command: {docker_cmd}")
+        subprocess.call(docker_cmd, cwd=wdir)
     elif env["kind"] == "conda":
         cmd = ["conda", "run", "-n", env_name] + cmd
         if verbose:
             typer.echo(f"Running command: {cmd}")
-        subprocess.call(cmd)
+        subprocess.call(cmd, cwd=wdir)
     else:
         raise_error("Environment kind not supported")
 
diff --git a/calkit/cli/new.py b/calkit/cli/new.py
index 3ad1e72f..c98c5882 100644
--- a/calkit/cli/new.py
+++ b/calkit/cli/new.py
@@ -3,6 +3,7 @@
 from __future__ import annotations
 
 import os
+import shutil
 import subprocess
 
 import git
@@ -472,3 +473,189 @@ def new_dataset(
             repo.git.add("dvc.yaml")
         if repo.git.diff("--staged"):
             repo.git.commit(["-m", f"Add dataset {path}"])
+
+
+@new_app.command(name="publication", help="Create a new publication.")
+def new_publication(
+    path: Annotated[
+        str,
+        typer.Argument(
+            help=(
+                "Path for the publication. "
+                "If using a template, this could be a directory."
+            )
+        ),
+    ],
+    title: Annotated[
+        str, typer.Option("--title", help="The title of the publication.")
+    ],
+    description: Annotated[
+        str,
+        typer.Option(
+            "--description", help="A description of the publication."
+        ),
+    ],
+    kind: Annotated[
+        str,
+        typer.Option(
+            "--kind", help="Kind of the publication, e.g., 'journal-article'."
+        ),
+    ],
+    stage_name: Annotated[
+        str,
+        typer.Option(
+            "--stage",
+            help="Name of the pipeline stage to build the output file.",
+        ),
+    ] = None,
+    deps: Annotated[
+        list[str], typer.Option("--dep", help="Path to stage dependency.")
+    ] = [],
+    outs_from_stage: Annotated[
+        str,
+        typer.Option(
+            "--deps-from-stage-outs",
+            help="Stage name from which to add outputs as dependencies.",
+        ),
+    ] = None,
+    template: Annotated[
+        str,
+        typer.Option(
+            "--template",
+            help=(
+                "Template with which to create the source files. "
+                "Should be in the format {type}/{name}."
+            ),
+        ),
+    ] = None,
+    env_name: Annotated[
+        str,
+        typer.Option(
+            "--environment",
+            help="Name of the build environment to create, if desired.",
+        ),
+    ] = None,
+    no_commit: Annotated[
+        bool,
+        typer.Option(
+            "--no-commit", help="Do not commit resulting changes to the repo."
+        ),
+    ] = False,
+    overwrite: Annotated[
+        bool,
+        typer.Option(
+            "--overwrite",
+            "-f",
+            help="Overwrite existing objects if they already exist.",
+        ),
+    ] = False,
+):
+    ck_info = calkit.load_calkit_info(process_includes=False)
+    pubs = ck_info.get("publications", [])
+    envs = ck_info.get("environments", {})
+    pub_paths = [p.get("path") for p in pubs]
+    if template is not None:
+        template_type, _ = template.split("/")
+    else:
+        template_type = None
+    # Check all of our inputs
+    if template_type not in ["latex"]:
+        raise_error(f"Unknown template type '{template_type}'")
+    if env_name is not None and template_type != "latex":
+        raise_error("Environments can only be created for latex templates")
+    if env_name is not None and env_name in envs and not overwrite:
+        raise_error(f"Environment '{env_name}' already exists")
+    if template_type is not None:
+        try:
+            template_obj = calkit.templates.get_template(template)
+        except ValueError:
+            raise_error(f"Template '{template}' does not exist")
+    # Parse outs from stage if specified
+    if outs_from_stage:
+        pipeline = calkit.dvc.read_pipeline()
+        stages = pipeline.get("stages", {})
+        if outs_from_stage not in stages:
+            raise_error(f"Stage {outs_from_stage} does not exist")
+        stage = stages[outs_from_stage]
+        if "foreach" in stage:
+            for val in stage["foreach"]:
+                for out in stage.get("do", {}).get("outs", []):
+                    deps.append(out.replace("${item}", val))
+        else:
+            deps += stage.get("outs", [])
+    # Create publication object
+    if template_type == "latex":
+        pub_fpath = os.path.join(
+            path, template_obj.target.removesuffix(".tex") + ".pdf"
+        )
+    else:
+        pub_fpath = path
+    if not overwrite and pub_fpath in pub_paths:
+        raise_error(f"Publication with path {pub_fpath} already exists")
+    elif overwrite and pub_fpath in pub_paths:
+        pubs = [p for p in pubs if p.get("path") != pub_fpath]
+    pub = dict(
+        path=pub_fpath,
+        kind=kind,
+        title=title,
+        description=description,
+        stage=stage_name,
+    )
+    pubs.append(pub)
+    ck_info["publications"] = pubs
+    repo = git.Repo()
+    # Create environment if applicable
+    if env_name is not None and template_type == "latex":
+        env_path = f".calkit/environments/{env_name}.yaml"
+        os.makedirs(".calkit/environments", exist_ok=True)
+        env = {"_include": env_path}
+        envs[env_name] = env
+        env_remote = dict(
+            kind="docker",
+            image="kjarosh/latex:2024.4",
+            description="TeXlive full from kjarosh.",
+            platform="linux/amd64",
+        )
+        with open(env_path, "w") as f:
+            calkit.ryaml.dump(env_remote, f)
+        ck_info["environments"] = envs
+        repo.git.add(env_path)
+    with open("calkit.yaml", "w") as f:
+        calkit.ryaml.dump(ck_info, f)
+    repo.git.add("calkit.yaml")
+    # Copy in template files if applicable
+    if template_type == "latex":
+        if overwrite and os.path.exists(path):
+            shutil.rmtree(path)
+        calkit.templates.use_template(
+            name=template, dest_dir=path, title=title
+        )
+        repo.git.add(path)
+    # Create stage if applicable
+    if stage_name is not None and template_type == "latex":
+        cmd = f"cd {path} && latexmk -pdf {template_obj.target}"
+        if env_name is not None:
+            cmd = f'calkit runenv -n {env_name} "{cmd}"'
+        target_dep = os.path.join(path, template_obj.target)
+        dvc_cmd = [
+            "dvc",
+            "stage",
+            "add",
+            "-n",
+            stage_name,
+            "-o",
+            pub_fpath,
+            "-d",
+            target_dep,
+        ]
+        if env_name is not None:
+            dvc_cmd += ["-d", env_path]
+        for dep in deps:
+            dvc_cmd += ["-d", dep]
+        if overwrite:
+            dvc_cmd.append("-f")
+        dvc_cmd.append(cmd)
+        subprocess.check_call(dvc_cmd)
+        repo.git.add("dvc.yaml")
+    if not no_commit and repo.git.diff("--staged"):
+        repo.git.commit(["-m", f"Add new publication {pub_fpath}"])
diff --git a/calkit/core.py b/calkit/core.py
index 2ea00b19..330a0eb8 100644
--- a/calkit/core.py
+++ b/calkit/core.py
@@ -46,11 +46,25 @@ def find_project_dirs(relative=False, max_depth=3) -> list[str]:
     return final_res
 
 
-def load_calkit_info(wdir=None) -> dict:
+def load_calkit_info(wdir=None, process_includes=False) -> dict:
+    """Load Calkit project information."""
+    info = {}
     fpath = "calkit.yaml"
     if wdir is not None:
         fpath = os.path.join(wdir, fpath)
     if os.path.isfile(fpath):
         with open(fpath) as f:
-            return ryaml.load(f)
-    return {}
+            info = ryaml.load(f)
+    # Check for any includes, i.e., entities with an _include key, for which
+    # we should merge in another file
+    # Currently this is only supported with environments because they may need
+    # to be tracked as DVC dependencies
+    if process_includes:
+        if "environments" in info:
+            for env_name, env in info["environments"].items():
+                if "_include" in env:
+                    include_fpath = env.pop("_include")
+                    with open(include_fpath) as f:
+                        include_data = ryaml.load(f)
+                    info["environments"][env_name] |= include_data
+    return info
diff --git a/calkit/models.py b/calkit/models.py
index 542a2ce0..690b896d 100644
--- a/calkit/models.py
+++ b/calkit/models.py
@@ -73,6 +73,8 @@ class DockerEnvironment(Environment):
     kind: str = "docker"
     image: str
     layers: list[str] | None = None
+    shell: Literal["bash", "sh"] = "sh"
+    platform: str | None = None
 
 
 class Software(BaseModel):
diff --git a/calkit/templates/__init__.py b/calkit/templates/__init__.py
new file mode 100644
index 00000000..bb67a43f
--- /dev/null
+++ b/calkit/templates/__init__.py
@@ -0,0 +1 @@
+from .core import *
diff --git a/calkit/templates/core.py b/calkit/templates/core.py
new file mode 100644
index 00000000..c47c856d
--- /dev/null
+++ b/calkit/templates/core.py
@@ -0,0 +1,118 @@
+"""Core functionality for working with templates."""
+
+import os
+import shutil
+from typing import Literal
+
+from pydantic import BaseModel
+
+from calkit.templates.latex import GITIGNORE as LATEX_GITIGNORE
+
+
+class Template(BaseModel):
+    """Model for a template.
+
+    Defines what kind of template it is, its name, and if/how we should allow
+    for replacing strings in the template in the process of copying it to a
+    project, e.g., if it's a LaTeX template and we want to automatically
+    set the title.
+
+    Attributes
+    ----------
+    kind : string
+        What kind of template is this.
+    name : string
+        Kebab-case name of the template.
+    loc : string
+        Location of the template. If not provided, will be inferred from the
+        kind and name.
+    files: list of strings
+        Files to copy. If not specified, will copy all in the directory.
+    gitignore : string
+        Content to put into the ``.gitignore`` file.
+    """
+
+    kind: Literal["latex"]
+    name: str
+    loc: str | None = None  # Can be local (auto-detected by path) or URL
+    files: list[str] | None = None  # Which filenames should be copied
+    gitignore: str | None = None
+
+
+class LatexTemplate(Template):
+    kind: str = "latex"
+    target: str = "paper.tex"
+    gitignore: str = LATEX_GITIGNORE
+
+
+# A registry of available templates, keyed by their kind and subkeyed by their
+# name
+TEMPLATES = {
+    "latex": {
+        "article": LatexTemplate(name="article"),
+        "jfm": LatexTemplate(name="jfm"),
+    },
+    "project": {},
+}
+
+
+def get_template(name: str) -> Template:
+    """Get a template by name, which should include its namespace or type."""
+    template_type, template_name = name.split("/")
+    if template_type not in TEMPLATES:
+        raise ValueError(f"Unknown template type '{template_type}'")
+    templates = TEMPLATES[template_type]
+    if template_name not in templates:
+        raise ValueError(f"Unknown template name '{template_name}'")
+    return templates[template_name]
+
+
+def use_template(name: str, dest_dir: str, **kwargs):
+    """Copy template files into ``dest_dir``.
+
+    The destination directory must be empty if it exists.
+    """
+    template = get_template(name)
+    if template.loc is None:
+        loc = os.path.join(
+            os.path.dirname(os.path.abspath(__file__)),
+            template.kind,
+            template.name,
+        )
+        print(loc)
+    else:
+        loc = template.loc
+    if loc.startswith("http://") or loc.startswith("https://"):
+        raise NotImplementedError("Remote template support not implemented")
+    files = template.files
+    if files is None:
+        files = os.listdir(loc)
+    if isinstance(template, LatexTemplate) and template.target not in files:
+        files.append(template.target)
+    if os.path.exists(dest_dir):
+        if os.path.isfile(dest_dir):
+            raise ValueError("Destination directory already exists as a file")
+        if os.listdir(dest_dir):
+            raise ValueError("Destination directory must be empty")
+    else:
+        os.makedirs(dest_dir)
+    # Copy files into destination
+    for fname in files:
+        fpath = os.path.join(loc, fname)
+        shutil.copy(src=fpath, dst=dest_dir)
+    # Write gitignore if applicable
+    if template.gitignore is not None:
+        with open(os.path.join(dest_dir, ".gitignore"), "w") as f:
+            f.write(template.gitignore)
+    # If there's a title in kwargs and we're using a LaTeX template,
+    # replace that line
+    if isinstance(template, LatexTemplate) and "title" in kwargs:
+        with open(os.path.join(dest_dir, template.target)) as f:
+            lines = f.readlines()
+        txt = ""
+        for line in lines:
+            if line.strip().startswith(r"\title{"):
+                line = r"\title{" + kwargs["title"] + "}\n"
+            txt += line
+        with open(os.path.join(dest_dir, template.target), "w") as f:
+            f.write(txt)
diff --git a/calkit/templates/latex/__init__.py b/calkit/templates/latex/__init__.py
new file mode 100644
index 00000000..bb67a43f
--- /dev/null
+++ b/calkit/templates/latex/__init__.py
@@ -0,0 +1 @@
+from .core import *
diff --git a/calkit/templates/latex/article/paper.tex b/calkit/templates/latex/article/paper.tex
new file mode 100644
index 00000000..2a8db0a4
--- /dev/null
+++ b/calkit/templates/latex/article/paper.tex
@@ -0,0 +1,43 @@
+% A generic article template
+\documentclass[11pt]{article}
+
+\usepackage{sectsty}
+\usepackage{graphicx}
+
+% Margins
+\topmargin=-0.45in
+\evensidemargin=0in
+\oddsidemargin=0in
+\textwidth=6.5in
+\textheight=9.0in
+\headsep=0.25in
+
+\title{This is the paper}
+\author{ The Author }
+\date{\today}
+
+\begin{document}
+\maketitle
+\pagebreak
+
+% Optional TOC
+% \tableofcontents
+% \pagebreak
+
+%--Paper--
+
+\section{Section 1}
+
+Lorem Ipsum
+
+% \includegraphics{../figures/my-figure.png}
+
+\pagebreak
+
+\section{Section 2}
+
+Lorem Ipsum \\
+
+%--/Paper--
+
+\end{document}
diff --git a/calkit/templates/latex/core.py b/calkit/templates/latex/core.py
new file mode 100644
index 00000000..cf46ab8b
--- /dev/null
+++ b/calkit/templates/latex/core.py
@@ -0,0 +1,11 @@
+"""Core functionality for working with LaTeX templates."""
+
+GITIGNORE = """
+*.aux
+*.fdb_latexmk
+*.fls
+*.log
+*.pdf
+*.out
+*.DS_Store
+"""
diff --git a/calkit/templates/latex/jfm/jfm.bst b/calkit/templates/latex/jfm/jfm.bst
new file mode 100644
index 00000000..cd345d0e
--- /dev/null
+++ b/calkit/templates/latex/jfm/jfm.bst
@@ -0,0 +1,1659 @@
+%% v1.0 (SGLS) 12/97
+% Stefan Llewellyn Smith, sgls1@damtp.cam.ac.uk
+% See readme in jfm style distribution.
+%%
+%%v1.1 revised 12/2005 to fix second initial problem, as suggested by 
+%%Christian Schoof
+%%
+%% This is file `jfmraw.bst',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% merlin.mbs  (with options: `,ay,nat,vonx,nm-rev,nmft-sc,dt-beg,yr-blk,yrp-x,note-yr,thtit-a,vol-bf,vnum-sp,volp-com,jnm-x,add-pub,pre-edn,edby-par,edbyx,blk-tit,pp,ed,abr,ord,xlab-it,amper,and-xcom,etal-it')
+%% ----------------------------------------
+%% *** JFM basic style ***
+%%
+  %-------------------------------------------------------------------
+  % The original source file contains the following version information:
+  % \ProvidesFile{merlin.mbs}[1997/06/09 3.83 (PWD)]
+  %
+  % NOTICE:
+  % This file may be used for non-profit purposes.
+  % It may not be distributed in exchange for money,
+  %   other than distribution costs.
+  %
+  % The author provides it `as is' and does not guarantee it in any way.
+  %
+  % Copyright (C) 1994-97 Patrick W. Daly
+  %           (C) 1997    Stefan G. Llewellyn Smith
+  %-------------------------------------------------------------------
+  %   For use with BibTeX version 0.99a or later
+  %-------------------------------------------------------------------
+  % This bibliography style file is intended for texts in ENGLISH
+  % This is an author-year citation style bibliography. As such, it is
+  % non-standard LaTeX, and requires a special package file to function properly.
+  % Such a package is    natbib.sty   by Patrick W. Daly
+  % The form of the \bibitem entries is
+  %   \bibitem[Jones et al.(1990)]{key}...
+  %   \bibitem[Jones et al.(1990)Jones, Baker, and Smith]{key}...
+  % The essential feature is that the label (the part in brackets) consists
+  % of the author names, as they should appear in the citation, with the year
+  % in parentheses following. There must be no space before the opening
+  % parenthesis!
+  % With natbib v5.3, a full list of authors may also follow the year.
+  % In natbib.sty, it is possible to define the type of enclosures that is
+  % really wanted (brackets or parentheses), but in either case, there must
+  % be parentheses in the label.
+  % The \cite command functions as follows:
+  %   \cite{key} ==>>                Jones et al. (1990)
+  %   \cite[]{key} ==>>              (Jones et al., 1990)
+  %   \cite[chap. 2]{key} ==>>       (Jones et al., 1990, chap. 2)
+  %   \cite[e.g.][]{key} ==>>        (e.g. Jones et al., 1990)
+  %   \cite[e.g.][p. 32]{key} ==>>   (e.g. Jones et al., p. 32)
+  %   \citeauthor{key}               Jones et al.
+  %   \citefullauthor{key}           Jones, Baker, and Smith
+  %   \citeyear{key}                 1990
+  %---------------------------------------------------------------------
+
+ENTRY
+   { address
+     author
+     booktitle
+     chapter
+     edition
+     editor
+     howpublished
+     institution
+     journal
+     key
+     month
+     note
+     number
+     organization
+     pages
+     publisher
+     school
+     series
+     title
+     type
+     volume
+     year
+     eprint
+   }
+   {}
+   { label extra.label sort.label short.list }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+   #1 'mid.sentence :=
+   #2 'after.sentence :=
+   #3 'after.block :=
+}
+
+STRINGS { s t }
+
+FUNCTION {output.nonnull}
+{ 's :=
+   output.state mid.sentence =
+     { ", " * write$ }
+     { output.state after.block =
+         { add.period$ write$
+           newline$
+           "\newblock " write$
+         }
+         { output.state before.all =
+             'write$
+             { add.period$ " " * write$ }
+           if$
+         }
+       if$
+       mid.sentence 'output.state :=
+     }
+   if$
+   s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+     'pop$
+     'output.nonnull
+   if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+   duplicate$ empty$
+     { pop$ "empty " t * " in " * cite$ * warning$ }
+     'output.nonnull
+   if$
+}
+
+FUNCTION {fin.entry}
+{ add.period$
+   write$
+   newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+     'skip$
+     { after.block 'output.state := }
+   if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+     'skip$
+     { output.state before.all =
+         'skip$
+         { after.sentence 'output.state := }
+       if$
+     }
+   if$
+}
+
+FUNCTION {add.blank}
+{  " " * before.all 'output.state :=
+}
+
+FUNCTION {date.block}
+{
+   add.blank
+}
+
+FUNCTION {not}
+{   { #0 }
+     { #1 }
+   if$
+}
+
+FUNCTION {and}
+{   'skip$
+     { pop$ #0 }
+   if$
+}
+
+FUNCTION {or}
+{   { pop$ #1 }
+     'skip$
+   if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+   swap$ empty$
+   and
+     'skip$
+     'new.block
+   if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+     { pop$ "" }
+     'skip$
+   if$
+}
+
+FUNCTION {emphasize}
+{ duplicate$ empty$
+     { pop$ "" }
+     { "{\em " swap$ * "\/}" * }
+   if$
+}
+
+FUNCTION {cmd@author}
+{ duplicate$ empty$
+     { pop$ "" }
+     { "\au{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@editor}
+{ duplicate$ empty$
+     { pop$ "" }
+     { "\ed{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@year}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \yr{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@atitle}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \at{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@jtitle}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \jt{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@bktitle}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \bt{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@seriestitle}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \st{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@bvolume}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \bvol{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@volume}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \vol{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@pages}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \pg{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@publisher}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \publ{" swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@arxiv}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \arxiv{arXiv: " swap$ * "}" * }
+   if$
+}
+
+FUNCTION {cmd@org}
+{ duplicate$ empty$
+     { pop$ "" }
+     { " \org{" swap$ * "}" * }
+   if$
+}
+
+
+FUNCTION {bolden}
+{ duplicate$ empty$
+     { pop$ "" }
+     { "{\bf " swap$ * "}" * }
+   if$
+}
+
+FUNCTION {scaps}
+{ duplicate$ empty$
+     { pop$ "" }
+     { "{\sc " swap$ * "}" * }
+   if$
+}
+
+FUNCTION {capitalize}
+{ "u" change.case$ "t" change.case$ }
+
+FUNCTION {space.word}
+{ " " swap$ * " " * }
+
+  % Here are the language-specific definitions for explicit words.
+  % Each function has a name bbl.xxx where xxx is the English word.
+  % The language selected here is ENGLISH
+FUNCTION {bbl.and}
+{ "and"}
+
+FUNCTION {bbl.editors}
+{ "ed." }
+
+FUNCTION {bbl.editor}
+{ "ed." }
+
+FUNCTION {bbl.edby}
+{ "edited by" }
+
+FUNCTION {bbl.edition}
+{ "edn." }
+
+FUNCTION {bbl.volume}
+{ "vol." }
+
+FUNCTION {bbl.of}
+{ "of" }
+
+FUNCTION {bbl.number}
+{ "" }
+
+FUNCTION {bbl.nr}
+{ "no." }
+
+FUNCTION {bbl.in}
+{ "in" }
+
+FUNCTION {bbl.pages}
+{ "pp." }
+
+FUNCTION {bbl.page}
+{ "p." }
+
+FUNCTION {bbl.chapter}
+{ "chap." }
+
+FUNCTION {bbl.techrep}
+{ "Tech. Rep." }
+
+FUNCTION {bbl.mthesis}
+{ "Master's thesis" }
+
+FUNCTION {bbl.phdthesis}
+{ "PhD thesis" }
+
+FUNCTION {bbl.first}
+{ "1st" }
+
+FUNCTION {bbl.second}
+{ "2nd" }
+
+FUNCTION {bbl.third}
+{ "3rd" }
+
+FUNCTION {bbl.fourth}
+{ "4th" }
+
+FUNCTION {bbl.fifth}
+{ "5th" }
+
+FUNCTION {bbl.st}
+{ "st" }
+
+FUNCTION {bbl.nd}
+{ "nd" }
+
+FUNCTION {bbl.rd}
+{ "rd" }
+
+FUNCTION {bbl.th}
+{ "th" }
+
+MACRO {jan} {"Jan."}
+
+MACRO {feb} {"Feb."}
+
+MACRO {mar} {"Mar."}
+
+MACRO {apr} {"Apr."}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"Jun."}
+
+MACRO {jul} {"Jul."}
+
+MACRO {aug} {"Aug."}
+
+MACRO {sep} {"Sep."}
+
+MACRO {oct} {"Oct."}
+
+MACRO {nov} {"Nov."}
+
+MACRO {dec} {"Dec."}
+
+FUNCTION {eng.ord}
+{ duplicate$ "1" swap$ *
+   #-2 #1 substring$ "1" =
+      { bbl.th * }
+      { duplicate$ #-1 #1 substring$
+        duplicate$ "1" =
+          { pop$ bbl.st * }
+          { duplicate$ "2" =
+              { pop$ bbl.nd * }
+              { "3" =
+                  { bbl.rd * }
+                  { bbl.th * }
+                if$
+              }
+            if$
+           }
+        if$
+      }
+    if$
+}
+
+MACRO {acmcs} {"ACM Computing Surveys"}
+
+MACRO {acta} {"Acta Informatica"}
+
+MACRO {cacm} {"Communications of the ACM"}
+
+MACRO {ibmjrd} {"IBM Journal of Research and Development"}
+
+MACRO {ibmsj} {"IBM Systems Journal"}
+
+MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
+
+MACRO {ieeetc} {"IEEE Transactions on Computers"}
+
+MACRO {ieeetcad}
+  {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
+
+MACRO {ipl} {"Information Processing Letters"}
+
+MACRO {jacm} {"Journal of the ACM"}
+
+MACRO {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {tocs} {"ACM Transactions on Computer Systems"}
+
+MACRO {tods} {"ACM Transactions on Database Systems"}
+
+MACRO {tog} {"ACM Transactions on Graphics"}
+
+MACRO {toms} {"ACM Transactions on Mathematical Software"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+INTEGERS { nameptr namesleft numnames }
+
+FUNCTION {format.names}
+{ 's :=
+   #1 'nameptr :=
+   s num.names$ 'numnames :=
+   numnames 'namesleft :=
+     { namesleft #0 > }
+     { s nameptr
+       "{vv~}{ll}{, jj}{, ff}" format.name$ cmd@author 't :=
+       nameptr #1 >
+         {
+           namesleft #1 >
+             { ", " * t * }
+             {
+               t "others" =
+                 { " " * "et~al." emphasize * }
+                 { " \& " * t * }
+               if$
+             }
+           if$
+         }
+         't
+       if$
+       nameptr #1 + 'nameptr :=
+       namesleft #1 - 'namesleft :=
+     }
+   while$
+}
+
+FUNCTION {format.names.ed}
+{ 's :=
+   #1 'nameptr :=
+   s num.names$ 'numnames :=
+   numnames 'namesleft :=
+     { namesleft #0 > }
+     { s nameptr
+       "{ff~}{vv~}{ll}{, jj}"
+       format.name$ 't :=
+       nameptr #1 >
+         {
+           namesleft #1 >
+             { ", " * t * }
+             {
+               t "others" =
+                 { " " * "et~al." emphasize * }
+                 { " \& " * t * }
+               if$
+             }
+           if$
+         }
+         't
+       if$
+       nameptr #1 + 'nameptr :=
+       namesleft #1 - 'namesleft :=
+     }
+   while$
+}
+
+FUNCTION {format.key}
+{ empty$
+     { key field.or.null }
+     { "" }
+   if$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+     { "" }
+     {
+      author format.names scaps 
+     }
+   if$
+}
+
+FUNCTION {format.editors}
+{ editor empty$
+     { "" }
+     {
+       editor format.names scaps
+       editor num.names$ #1 >
+         { ", " * bbl.editors * }
+         { ", " * bbl.editor * }
+       if$
+     }
+   if$
+}
+
+FUNCTION {format.in.editors}
+{ editor empty$
+     { "" }
+     { editor format.names.ed cmd@editor
+     }
+   if$
+}
+
+FUNCTION {format.note}
+{ note empty$
+     { "" }
+     { note #1 #1 substring$
+       duplicate$ "{" =
+         'skip$
+         { output.state mid.sentence =
+           { "l" }
+           { "u" }
+         if$
+         change.case$
+         }
+       if$
+       note #2 global.max$ substring$ *
+     }
+   if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+     { "" }
+     { title "t" change.case$
+     }
+   if$
+}
+
+FUNCTION {format.full.names}
+{'s :=
+   #1 'nameptr :=
+   s num.names$ 'numnames :=
+   numnames 'namesleft :=
+     { namesleft #0 > }
+     { s nameptr
+       "{vv~}{ll}" format.name$ 't :=
+       nameptr #1 >
+         {
+           namesleft #1 >
+             { ", " * t * }
+             {
+               t "others" =
+                 { " " * "et~al." emphasize * }
+                 { " \& " * t * }
+               if$
+             }
+           if$
+         }
+         't
+       if$
+       nameptr #1 + 'nameptr :=
+       namesleft #1 - 'namesleft :=
+     }
+   while$
+}
+
+FUNCTION {author.editor.key.full}
+{ author empty$
+     { editor empty$
+         { key empty$
+             { cite$ #1 #3 substring$ }
+             'key
+           if$
+         }
+         { editor format.full.names }
+       if$
+     }
+     { author format.full.names }
+   if$
+}
+
+FUNCTION {author.key.full}
+{ author empty$
+     { key empty$
+          { cite$ #1 #3 substring$ }
+           'key
+       if$
+     }
+     { author format.full.names }
+   if$
+}
+
+FUNCTION {editor.key.full}
+{ editor empty$
+     { key empty$
+          { cite$ #1 #3 substring$ }
+           'key
+       if$
+     }
+     { editor format.full.names }
+   if$
+}
+
+FUNCTION {make.full.names}
+{ type$ "book" =
+   type$ "inbook" =
+   or
+     'author.editor.key.full
+     { type$ "proceedings" =
+         'editor.key.full
+         'author.key.full
+       if$
+     }
+   if$
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+   "\bibitem[" write$
+   label write$
+   ")" make.full.names duplicate$ short.list =
+      { pop$ }
+      { * }
+    if$
+   "]{" * write$
+   cite$ write$
+   "}" write$
+   newline$
+   ""
+   before.all 'output.state :=
+}
+
+FUNCTION {n.dashify}
+{ 't :=
+   ""
+     { t empty$ not }
+     { t #1 #1 substring$ "-" =
+         { t #1 #2 substring$ "--" = not
+             { "--" *
+               t #2 global.max$ substring$ 't :=
+             }
+             {   { t #1 #1 substring$ "-" = }
+                 { "-" *
+                   t #2 global.max$ substring$ 't :=
+                 }
+               while$
+             }
+           if$
+         }
+         { t #1 #1 substring$ *
+           t #2 global.max$ substring$ 't :=
+         }
+       if$
+     }
+   while$
+}
+
+FUNCTION {word.in}
+{ bbl.in capitalize
+   " " * }
+
+FUNCTION {format.date}
+{ year duplicate$ empty$
+     { "empty year in " cite$ * "; set to ????" * warning$
+        pop$ "????" }
+     'skip$
+   if$
+   extra.label *
+   before.all 'output.state :=
+   "" swap$ * cmd@year
+}
+
+FUNCTION {format.btitle}
+{ title emphasize
+}
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+     { "~" }
+     { " " }
+   if$
+   swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+     'pop$
+     { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+   if$
+}
+
+FUNCTION {format.bvolume}
+% Changed (SGLS)
+% Notes swap$ fudge
+{ volume empty$
+     { "" }
+     { series empty$
+        { "" }
+        { series cmd@seriestitle }
+      if$
+      swap$ bbl.volume volume tie.or.space.connect output cmd@volume
+     }
+   if$
+}
+%{ volume empty$
+%    { "" }
+%    { bbl.volume volume tie.or.space.connect
+%      series empty$
+%        'skip$
+%        { bbl.of space.word * series emphasize * }
+%      if$
+%      "volume and number" number either.or.check
+%    }
+%  if$
+%}
+
+FUNCTION {format.number.series}
+% Changed (SGLS)
+{
+  volume empty$
+     { series empty$
+         { ""
+           number empty$
+             'skip$
+             { "there's a number but no series in " cite$ * warning$ }
+           if$
+         }
+         { series emphasize " " * number *}
+       if$
+     }
+     { "" }
+   if$
+}
+%{ volume empty$
+%    { number empty$
+%        { series field.or.null }
+%        { output.state mid.sentence =
+%            { bbl.number }
+%            { bbl.number capitalize }
+%          if$
+%          number tie.or.space.connect
+%          series empty$
+%            { "there's a number but no series in " cite$ * warning$ }
+%            { bbl.in space.word * series * }
+%          if$
+%        }
+%      if$
+%    }
+%    { "" }
+%  if$
+%}
+
+FUNCTION {is.num}
+{ chr.to.int$
+   duplicate$ "0" chr.to.int$ < not
+   swap$ "9" chr.to.int$ > not and
+}
+
+FUNCTION {extract.num}
+{ duplicate$ 't :=
+   "" 's :=
+   { t empty$ not }
+   { t #1 #1 substring$
+     t #2 global.max$ substring$ 't :=
+     duplicate$ is.num
+       { s swap$ * 's := }
+       { pop$ "" 't := }
+     if$
+   }
+   while$
+   s empty$
+     'skip$
+     { pop$ s }
+   if$
+}
+
+FUNCTION {convert.edition}
+{ edition extract.num "l" change.case$ 's :=
+   s "first" = s "1" = or
+     { bbl.first 't := }
+     { s "second" = s "2" = or
+         { bbl.second 't := }
+         { s "third" = s "3" = or
+             { bbl.third 't := }
+             { s "fourth" = s "4" = or
+                 { bbl.fourth 't := }
+                 { s "fifth" = s "5" = or
+                     { bbl.fifth 't := }
+                     { s #1 #1 substring$ is.num
+                         { s eng.ord 't := }
+                         { edition 't := }
+                       if$
+                     }
+                   if$
+                 }
+               if$
+             }
+           if$
+         }
+       if$
+     }
+   if$
+   t
+}
+
+FUNCTION {format.edition}
+{ edition empty$
+     { "" }
+     { output.state mid.sentence =
+         { convert.edition "l" change.case$ " " * bbl.edition * }
+         { convert.edition "t" change.case$ " " * bbl.edition * }
+       if$
+     }
+   if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+   #0 'multiresult :=
+     { multiresult not
+       t empty$ not
+       and
+     }
+     { t #1 #1 substring$
+       duplicate$ "-" =
+       swap$ duplicate$ "," =
+       swap$ "+" =
+       or or
+         { #1 'multiresult := }
+         { t #2 global.max$ substring$ 't := }
+       if$
+     }
+   while$
+   multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+     { "" }
+     { pages multi.page.check
+         { bbl.pages pages n.dashify tie.or.space.connect }
+         { bbl.page pages tie.or.space.connect }
+       if$
+       cmd@pages
+     }
+   if$
+}
+
+FUNCTION {format.journal.pages}
+{
+   pages empty$
+     'skip$
+     { duplicate$ empty$
+         { pop$ format.pages }
+         { ", " * pages n.dashify cmd@pages * }
+       if$
+     }
+   if$
+}
+
+FUNCTION {format.vol.num.pages}
+{ volume field.or.null
+%   bolden 
+   cmd@bvolume
+   number empty$
+     'skip$
+     {
+       "~(" number * ")" * *
+       volume empty$
+         { "there's a number but no volume in " cite$ * warning$ }
+         'skip$
+       if$
+     }
+   if$
+   format.journal.pages
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+     'format.pages
+     { type empty$
+         { bbl.chapter }
+         { type "l" change.case$ }
+       if$
+       chapter tie.or.space.connect
+       pages empty$
+         'skip$
+         { ", " * format.pages * }
+       if$
+     }
+   if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+% Changed to get edition after booktitle (SGLS)
+% Notes swap$ fudge
+{ booktitle empty$
+     { "" }
+     { word.in booktitle emphasize *
+       edition empty$
+	'skip$
+         { swap$ format.edition output }
+       if$
+       editor empty$
+         { "" * }
+         {" (" * 
+           editor num.names$ #1 >
+             { bbl.editors }
+             { bbl.editor }
+           if$
+           *
+           " " *
+           format.in.editors * 
+           ")" *
+         }
+       if$
+     }
+   if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+     'skip$
+     { pop$
+       type "t" change.case$
+     }
+   if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+     { bbl.techrep emphasize }
+     'type
+   if$
+   number empty$
+     { "t" change.case$ }
+     { number tie.or.space.connect }
+   if$
+}
+
+FUNCTION {format.article.crossref}
+{
+   word.in
+   " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+     { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+       word.in
+     }
+     { bbl.volume capitalize
+       volume tie.or.space.connect
+       bbl.of space.word *
+     }
+   if$
+   " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{
+   word.in
+   " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.publisher}
+{ publisher empty$
+     { "empty publisher in " cite$ * warning$ }
+     'skip$
+   if$
+   ""
+   address empty$ publisher empty$ and
+     'skip$
+     {
+       address empty$
+         'skip$
+         { address * }
+       if$
+       publisher empty$
+         'skip$
+         { address empty$
+             'skip$
+             { ": " * }
+           if$
+           publisher *
+         }
+       if$
+       cmd@publisher
+     }
+   if$
+   output
+}
+
+FUNCTION {format.eprint}
+{ eprint empty$
+     { "" }
+     { ", " * eprint cmd@arxiv * ""}
+   if$
+}
+
+FUNCTION {article}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check  cmd@atitle
+   new.sentence
+   crossref missing$
+     { journal cmd@jtitle
+%       emphasize
+       "journal" output.check
+       add.blank
+       format.vol.num.pages output
+     }
+     { format.article.crossref output.nonnull
+     }
+   if$
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+   author empty$
+     { format.editors "author and editor" output.check
+       editor format.key output
+     }
+     { format.authors output.nonnull
+       crossref missing$
+         { "author and editor" editor either.or.check }
+         'skip$
+       if$
+     }
+   if$
+   format.date "year" output.check
+   date.block
+   format.btitle "title" output.check
+% Added edition after title (SGLS)
+   format.edition output
+   crossref missing$
+     { format.bvolume output
+   new.sentence
+       format.number.series output
+%      format.edition output
+   new.sentence
+       format.publisher
+     }
+     {
+   new.sentence
+       format.book.crossref output.nonnull
+     }
+   if$
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+   format.authors output
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check
+   new.sentence
+   howpublished output
+   address output
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+   author empty$
+     { format.editors "author and editor" output.check
+       editor format.key output
+     }
+     { format.authors output.nonnull
+       crossref missing$
+         { "author and editor" editor either.or.check }
+         'skip$
+       if$
+     }
+   if$
+   format.date "year" output.check
+   date.block
+   format.btitle "title" output.check
+% Added edition after title (SGLS)
+   format.edition output
+   crossref missing$
+     {
+       format.bvolume output
+       format.chapter.pages "chapter and pages" output.check
+   new.sentence
+       format.number.series output
+%      format.edition output
+   new.sentence
+       format.publisher
+     }
+     {
+       format.chapter.pages "chapter and pages" output.check
+   new.sentence
+       format.book.crossref output.nonnull
+     }
+   if$
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check cmd@atitle
+   new.sentence
+   crossref missing$
+     { format.in.ed.booktitle "booktitle" output.check cmd@bktitle
+       format.bvolume output
+       format.number.series output
+%      format.edition output
+       format.chapter.pages output
+   new.sentence
+       format.publisher
+     }
+     { format.incoll.inproc.crossref output.nonnull
+       format.chapter.pages output
+     }
+   if$
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check
+   new.sentence
+   crossref missing$
+     { format.in.ed.booktitle "booktitle" output.check cmd@bktitle
+       format.bvolume output
+       format.number.series output
+       format.pages output
+    new.sentence
+       publisher empty$
+         { organization output
+           address output
+         }
+         { organization output
+           format.publisher
+         }
+       if$
+     }
+     { format.incoll.inproc.crossref output.nonnull
+       format.pages output
+     }
+   if$
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+   format.authors output
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.btitle "title" output.check
+% Added edition after title (SGLS)
+   format.edition output
+   new.sentence
+   organization output
+   address output
+%  format.edition output
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check
+   new.sentence
+   bbl.mthesis format.thesis.type output.nonnull
+   school "school" output.check
+   address output
+   format.note output
+   fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+   format.authors output
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title output
+   new.sentence
+   howpublished output
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check cmd@atitle
+   new.sentence
+   bbl.phdthesis format.thesis.type output.nonnull
+   school "school" output.check
+   address output
+   format.note output
+   fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+   format.editors output
+   editor format.key output
+   format.date "year" output.check
+   date.block
+   format.btitle "title" output.check
+   format.bvolume output
+   format.number.series output
+   address output
+   organization output
+   new.sentence
+   publisher output
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check cmd@bktitle
+   new.sentence
+   format.tr.number output.nonnull
+   new.sentence
+   institution "institution" output.check cmd@org
+   address output
+   format.note output
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+   format.authors "author" output.check
+   author format.key output
+   format.date "year" output.check
+   date.block
+   format.title "title" output.check
+   new.sentence
+   format.note "note" output.check
+   format.eprint output
+   fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+   "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+   'len :=
+   s #1 len substring$ =
+     { s len #1 + global.max$ substring$ }
+     's
+   if$
+}
+
+FUNCTION {format.lab.names}
+{ 's :=
+   s #1 "{vv~}{ll}" format.name$
+   s num.names$ duplicate$
+   #2 >
+     { pop$ " " * "et~al." emphasize * }
+     { #2 <
+         'skip$
+         { s #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+             { " " * "et~al." emphasize * }
+             { " \& " * s #2 "{vv~}{ll}" format.name$ * }
+           if$
+         }
+       if$
+     }
+   if$
+}
+
+FUNCTION {author.key.label}
+{ author empty$
+     { key empty$
+         { cite$ #1 #3 substring$ }
+         'key
+       if$
+     }
+     { author format.lab.names }
+   if$
+}
+
+FUNCTION {author.editor.key.label}
+{ author empty$
+     { editor empty$
+         { key empty$
+             { cite$ #1 #3 substring$ }
+             'key
+           if$
+         }
+         { editor format.lab.names }
+       if$
+     }
+     { author format.lab.names }
+   if$
+}
+
+FUNCTION {editor.key.label}
+{ editor empty$
+     { key empty$
+         { cite$ #1 #3 substring$ }
+         'key
+       if$
+     }
+     { editor format.lab.names }
+   if$
+}
+
+FUNCTION {calc.short.authors}
+{ type$ "book" =
+   type$ "inbook" =
+   or
+     'author.editor.key.label
+     { type$ "proceedings" =
+         'editor.key.label
+         'author.key.label
+       if$
+     }
+   if$
+   'short.list :=
+}
+
+FUNCTION {calc.label}
+{ calc.short.authors
+   short.list
+   "("
+   *
+   year duplicate$ empty$
+      { pop$ "????" }
+      'skip$
+   if$
+   *
+   'label :=
+}
+
+FUNCTION {sort.format.names}
+{ 's :=
+   #1 'nameptr :=
+   ""
+   s num.names$ 'numnames :=
+   numnames 'namesleft :=
+     { namesleft #0 > }
+     { s nameptr
+       "{ll{ }}{  f{ }}{  jj{ }}"
+       format.name$ 't :=
+       nameptr #1 >
+         {
+           "   "  *
+           namesleft #1 = t "others" = and
+             { "zzzzz" * }
+             { t sortify * }
+           if$
+         }
+         { t sortify * }
+       if$
+       nameptr #1 + 'nameptr :=
+       namesleft #1 - 'namesleft :=
+     }
+   while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+   "A " #2
+     "An " #3
+       "The " #4 t chop.word
+     chop.word
+   chop.word
+   sortify
+   #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+     { key empty$
+         { "to sort, need author or key in " cite$ * warning$
+           ""
+         }
+         { key sortify }
+       if$
+     }
+     { author sort.format.names }
+   if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+     { editor empty$
+         { key empty$
+             { "to sort, need author, editor, or key in " cite$ * warning$
+               ""
+             }
+             { key sortify }
+           if$
+         }
+         { editor sort.format.names }
+       if$
+     }
+     { author sort.format.names }
+   if$
+}
+
+FUNCTION {editor.sort}
+{ editor empty$
+     { key empty$
+         { "to sort, need editor or key in " cite$ * warning$
+           ""
+         }
+         { key sortify }
+       if$
+     }
+     { editor sort.format.names }
+   if$
+}
+
+FUNCTION {presort}
+{ calc.label
+   label sortify
+   "    "
+   *
+   type$ "book" =
+   type$ "inbook" =
+   or
+     'author.editor.sort
+     { type$ "proceedings" =
+         'editor.sort
+         'author.sort
+       if$
+     }
+   if$
+   #1 entry.max$ substring$
+   'sort.label :=
+   sort.label
+   *
+   "    "
+   *
+   title field.or.null
+   sort.format.title
+   *
+   #1 entry.max$ substring$
+   'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT
+
+STRINGS { last.label next.extra }
+
+INTEGERS { last.extra.num number.label }
+
+FUNCTION {initialize.extra.label.stuff}
+{ #0 int.to.chr$ 'last.label :=
+   "" 'next.extra :=
+   #0 'last.extra.num :=
+   #0 'number.label :=
+}
+
+FUNCTION {forward.pass}
+{ last.label label =
+     { last.extra.num #1 + 'last.extra.num :=
+       last.extra.num int.to.chr$ 'extra.label :=
+     }
+     { "a" chr.to.int$ 'last.extra.num :=
+       "" 'extra.label :=
+       label 'last.label :=
+     }
+   if$
+   number.label #1 + 'number.label :=
+}
+
+FUNCTION {reverse.pass}
+{ next.extra "b" =
+     { "a" 'extra.label := }
+     'skip$
+   if$
+   extra.label 'next.extra :=
+   extra.label
+   emphasize
+   duplicate$ empty$
+     'skip$
+     { "{\natexlab{" swap$ * "}}" * }
+   if$
+   'extra.label :=
+   label extra.label * 'label :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+
+ITERATE {forward.pass}
+
+REVERSE {reverse.pass}
+
+FUNCTION {bib.sort.order}
+{ sort.label
+   "    "
+   *
+   year field.or.null sortify
+   *
+   "    "
+   *
+   title field.or.null
+   sort.format.title
+   *
+   #1 entry.max$ substring$
+   'sort.key$ :=
+}
+
+ITERATE {bib.sort.order}
+
+SORT
+
+FUNCTION {begin.bib}
+{ preamble$ empty$
+     'skip$
+     { preamble$ write$ newline$ }
+   if$
+   "\begin{thebibliography}{" number.label int.to.str$ * "}" *
+   write$ newline$
+"\expandafter\ifx\csname natexlab\endcsname\relax\def\natexlab#1{#1}\fi"
+  write$ newline$
+ "\def\au#1{#1} \def\ed#1{#1} \def\yr#1{#1}\def\at#1{#1}\def\jt#1{\textit{#1}} \def\bt#1{#1}\def\bvol#1{\textbf{#1}} \def\vol#1{#1} \def\pg#1{#1} \def\publ#1{#1}\def\arxiv#1{#1}\def\org#1{#1}\def\st#1{\textit{#1}}"
+  write$ newline$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+   "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib}
+%% End of customized bst file
+%%
+%% End of file `jfmraw.bst'.
diff --git a/calkit/templates/latex/jfm/jfm.cls b/calkit/templates/latex/jfm/jfm.cls
new file mode 100644
index 00000000..cc55fc6e
--- /dev/null
+++ b/calkit/templates/latex/jfm/jfm.cls
@@ -0,0 +1,1518 @@
+%%http://www.jfm.damtp.cam.ac.uk/online_submission.html%%
+%% This is file `jfm.cls'
+%%
+%% CUP Journal of Fluid Mechanics document class
+%% Copyright (1996, 1997) Cambridge University Press
+%%
+%% by Mark A. Reed
+%%   based on JFM.sty v1.3.
+%% v1.25 8 Aug 2001 revised by Alison Woollatt to include DOI reference
+%% v1.26 released 27th July 2004
+%% v1.27 13 Nov 2006 modified by TeX Support to remove "By" from authors
+%% v1.28 13 Mar 2007 modified by TeX Support to change \floatpagefraction
+%% from {.95} to {.9}
+%%
+%% Incorporating parts of authordate.sty, by David Rhead.
+%% Incorporating subeqn.sty, by Stephen Gildea.
+%% Incorporating subeqnarray.sty, by Johannes Braams.
+%%
+%% Bugs (in the case of unchanged files) should be reported to
+%% texsupport@aptaracorp.com
+%%
+%% This software may only be used in the preparation of journal articles
+%% or books or parts of books to be published by Cambridge University Press.
+%% Any other use constitutes an infringement of copyright.
+%%
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+
+\NeedsTeXFormat{LaTeX2e}[1996/06/01]
+\ProvidesClass{jfm}[2006/11/13 v1.27 Journal of Fluid Mechanics document class]
+
+\usepackage{graphicx}
+
+\newif\ifNAT@numbers\NAT@numbersfalse
+\AtBeginDocument{\usepackage{natbib}}
+
+\newif\if@index
+\newif\if@referee
+\newif\ifCUPmtlplainloaded
+\newif\ifflm@rapids
+\newif\iflineno% 3-8-20
+\DeclareOption{lineno}{\linenotrue}% 3-8-20
+
+\DeclareOption{oneside}{\relax}
+\DeclareOption{twoside}{\@twosidetrue \@mparswitchtrue}
+\DeclareOption{draft}{\setlength\overfullrule{5\p@}}
+\DeclareOption{final}{\setlength\overfullrule{\z@}}
+\DeclareOption{onecolumn}{\@twocolumnfalse}
+\DeclareOption{twocolumn}{\relax}
+\DeclareOption{titlepage}{\relax}
+\DeclareOption{notitlepage}{\relax}
+\DeclareOption{leqno}{\relax}
+\DeclareOption{fleqn}{\relax}
+\DeclareOption{index}{\@indextrue}
+\DeclareOption{prodtf}{\CUPmtlplainloadedtrue}
+\DeclareOption{referee}{\@refereetrue}
+\DeclareOption{rapids}{\global\flm@rapidstrue}
+
+\ExecuteOptions{twoside,final,onecolumn}
+\ProcessOptions\relax
+
+\ifCUPmtlplainloaded \RequirePackage{CUPTimes,jfm2esym}\fi
+
+\setlength\lineskip{1\p@}
+\setlength\normallineskip{1\p@}
+\renewcommand\baselinestretch{}
+
+\edef\t@xtsize{10.5}% 8-8-20 %\edef\t@xtsize{\ifCUPmtlplainloaded 10.5\else 10\fi}
+
+
+\renewcommand\normalsize{%
+  \@setfontsize\normalsize{\t@xtsize}\@xiipt
+  \abovedisplayskip 6.5\p@ \@plus 1\p@ \@minus 1\p@
+  \belowdisplayskip \abovedisplayskip
+  \abovedisplayshortskip 3\p@ \@plus 1\p@
+  \belowdisplayshortskip \abovedisplayshortskip
+}
+
+\normalsize
+
+
+
+\let\fontswitch=\relax
+\let\realbf=\relax
+
+\AtBeginDocument{%
+  \ifuseAMSsubequ \else
+    \global\let\subequations\CUPsubequations
+    \global\let\endsubequations\endCUPsubequations
+  \fi
+}
+
+\AtBeginDocument{%
+  \@ifpackageloaded{natbib}
+    {\bibpunct{(}{)}{;}{a}{}{,}%
+     \global\let\thebibliography\JFMthebib
+     \global\let\endthebibliography\JFMendthebib}
+    {\relax}%
+}
+
+\ifCUPmtlplainloaded
+  \AtBeginDocument{%
+    \DeclareMathSizes{10.5}{10.5}{7}{5}%
+    \DeclareFontShape{OT1}{mtr}{sb}{n}{<-> xmntsm}{}%
+    \DeclareMathAlphabet{\sbmath}{OT1}{mtr}{sb}{n}%
+    \newcommand\realbf{\def\bfdefault{bx}\bfseries}%
+    \newcommand\fontswitch{\def\bfdefault{sb}}%
+  }
+\fi
+
+\newcommand\small{%
+  \@setfontsize\small\@ixpt\@xpt
+  \abovedisplayskip 6\p@ \@plus 1\p@ \@minus 1\p@
+  \belowdisplayskip \abovedisplayskip
+  \abovedisplayshortskip 3\p@ \@plus 1\p@
+  \belowdisplayshortskip \abovedisplayshortskip
+}
+
+\newcommand\footnotesize{\small}
+\newcommand\indexsize{\@setfontsize\indexsize\@viiipt\@ixpt}
+\newcommand\scriptsize{\@setfontsize\scriptsize\@viipt\@viiipt}
+\newcommand\tiny{\@setfontsize\tiny\@vpt\@vipt}
+\newcommand\large{\@setfontsize\large\@xipt{13}}
+\newcommand\Large{\@setfontsize\Large\@xivpt{18}}
+\newcommand\LARGE{\@setfontsize\LARGE\@xviipt{19}}
+\newcommand\huge{\@setfontsize\huge\@xxpt{25}}
+\newcommand\Huge{\@setfontsize\Huge\@xxvpt{30}}
+
+\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
+\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
+\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
+\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
+\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
+\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
+\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
+\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal}
+\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal}
+
+\edef\r@{\ifCUPmtlplainloaded mtr\else cmr\fi}
+\edef\s@{\ifCUPmtlplainloaded mtss\else cmss\fi}
+
+\newcommand\qsmall{%
+  \usefont{OT1}{\r@}{m}{n}\fontsize{9.75}{\f@baselineskip}\selectfont}
+\newcommand\qsmit{%
+  \usefont{OT1}{\r@}{m}{it}\fontsize{9.75}{\f@baselineskip}\selectfont}
+\newcommand\qsbf{%
+  \usefont{OT1}{\r@}{bx}{n}\fontsize{9.75}{\f@baselineskip}\selectfont}
+\newcommand\qssf{%
+  \usefont{OT1}{\s@}{m}{n}\fontsize{9.75}{\f@baselineskip}\selectfont}
+\newcommand\boldit{%
+  \usefont{OT1}{\r@}{bx}{it}\fontsize{10}{\f@baselineskip}\selectfont}
+
+\newcommand\qit{\qsmit \fontsize{\f@size}{10.75}\selectfont}
+\newcommand\qbf{\qsbf  \fontsize{\f@size}{10.75}\selectfont}
+\newcommand\qsf{\qssf  \fontsize{\f@size}{10.75}\selectfont}
+\newcommand\qrm{\qsmall\fontsize{\f@size}{10.75}\selectfont}
+
+\ifCUPmtlplainloaded\else
+  \DeclareTextFontCommand\textsfi{\usefont{OT1}{cmss}{m}{sl}}
+  \DeclareMathAlphabet\mathsfi            {OT1}{cmss}{m}{sl}
+  \DeclareTextFontCommand\textsfb{\usefont{OT1}{cmss}{bx}{n}}
+  \DeclareMathAlphabet\mathsfb            {OT1}{cmss}{bx}{n}
+  \DeclareTextFontCommand\textsfbi{\usefont{OT1}{cmss}{m}{sl}}
+  \DeclareMathAlphabet\mathsfbi            {OT1}{cmss}{m}{sl}
+  \IfFileExists{t1phv.fd}
+  {\DeclareTextFontCommand\textsfbi{\usefont{T1}{phv}{b}{it}}
+  \DeclareMathAlphabet\mathsfbi            {T1}{phv}{b}{it}
+  }{}
+  \IfFileExists{ot1phv.fd}
+  {\DeclareTextFontCommand\textsfbi{\usefont{OT1}{phv}{b}{it}}
+  \DeclareMathAlphabet\mathsfbi            {OT1}{phv}{b}{it}
+  }{}
+\fi
+
+%\DeclareMathAlphabet{\cup@mathbisf}{T1}{phv}{b}{it}
+
+\DeclareMathSymbol{\varGamma}{\mathord}{letters}{"00}
+\DeclareMathSymbol{\varDelta}{\mathord}{letters}{"01}
+\DeclareMathSymbol{\varTheta}{\mathord}{letters}{"02}
+\DeclareMathSymbol{\varLambda}{\mathord}{letters}{"03}
+\DeclareMathSymbol{\varXi}{\mathord}{letters}{"04}
+\DeclareMathSymbol{\varPi}{\mathord}{letters}{"05}
+\DeclareMathSymbol{\varSigma}{\mathord}{letters}{"06}
+\DeclareMathSymbol{\varUpsilon}{\mathord}{letters}{"07}
+\DeclareMathSymbol{\varPhi}{\mathord}{letters}{"08}
+\DeclareMathSymbol{\varPsi}{\mathord}{letters}{"09}
+\DeclareMathSymbol{\varOmega}{\mathord}{letters}{"0A}
+
+
+\setlength\oddsidemargin{2pc}
+\setlength\evensidemargin{2pc}
+\setlength\marginparwidth{2.0cm}
+\setlength\marginparsep{10\p@}
+
+\setlength\topmargin{2.5pc}
+\setlength\headheight{12\p@}
+\setlength\headsep{6\p@}
+\setlength\topskip{12\p@}
+\setlength\footskip{28pt}
+
+\newlength\halflineskip
+\setlength\halflineskip{6\p@ \@plus .5\p@ \@minus .5\p@}
+\newlength\affilskip
+\setlength\affilskip{3\p@}
+
+\setlength\textheight{49\baselineskip}
+\addtolength\textheight{\topskip}
+\setlength\textwidth{32pc}
+\setlength\columnsep{10\p@}
+\setlength\columnseprule{\z@}
+
+\special{papersize=174mm,247mm}
+\pdfpagewidth 174mm
+\pdfpageheight 247mm
+
+\setlength\oddsidemargin{-1pc}
+\setlength\evensidemargin{-1pc}
+\setlength\topmargin{-2.7pc}
+
+
+\setlength\footnotesep{\z@}
+\setlength{\skip\footins}{9\p@ \@plus 3\p@}
+
+\setlength\floatsep{10\p@ \@plus 2\p@ \@minus 1\p@}
+\setlength\textfloatsep{12\p@ \@plus 6\p@}
+\setlength\intextsep{\floatsep}
+\setlength\dblfloatsep{\floatsep}
+\setlength\dbltextfloatsep{\floatsep}
+\setlength\@fptop{\z@ \@plus 0fil}
+\setlength\@fpsep{10\p@ \@plus 0fil}
+\setlength\@fpbot{\z@ \@plus 3fil}
+\setlength\@dblfptop{\z@ \@plus 0fil}
+\setlength\@dblfpsep{10\p@ \@plus 0fil}
+\setlength\@dblfpbot{\z@ \@plus 3fil}
+\setlength\marginparpush{5\p@}
+
+\setlength\parskip{\z@ \@plus .3\p@}
+\setlength\parindent{10pt}
+\setlength\partopsep{\z@ \@plus 1\p@}
+\@lowpenalty   51
+\@medpenalty  151
+\@highpenalty 301
+\@beginparpenalty -\@lowpenalty
+\@endparpenalty -\@lowpenalty
+\@itempenalty -\@lowpenalty
+\clubpenalty\z@
+\widowpenalty\@M
+
+\newcommand\partname{Part}
+\newcommand\part{\par\addvspace{4ex}\@afterindentfalse \secdef\@part\@spart}
+
+\def\@part[#1]#2{%
+  \ifnum \c@secnumdepth >\m@ne
+    \refstepcounter{part}%
+    \addcontentsline{toc}{part}{\partname\ \thepart: #1}%
+  \else
+    \addcontentsline{toc}{part}{#1}%
+  \fi
+  {\parindent \z@ \centering
+   \ifnum \c@secnumdepth >\m@ne
+     \normalfont\large\rmfamily \MakeUppercase{\partname}\ %
+     \ifcase\thepart \or ONE \or TWO \or THREE \or FOUR \or FIVE
+       \or SIX \or SEVEN \or EIGHT \or NINE \or TEN \else \fi
+   \par \nobreak
+   \fi
+   \normalfont\LARGE\rmfamily #2 \markboth{}{}\par}%
+  \nobreak \vskip 3ex \@afterheading
+}
+
+\def\@spart#1{%
+  {\parindent \z@ \centering\normalfont\LARGE\rmfamily #1\par}%
+  \nobreak \vskip 3ex \@afterheading
+}
+
+\newcommand\@raggedright{\rightskip=\@flushglue \let\\=\@centercr
+  \parindent\z@}
+\newcommand\@raggedcenter{\centering\rightskip=\@flushglue
+  \let\\=\@centercr}
+
+\newif\ifno@eqnreset
+\newcommand\nosectioneqnreset{\global\no@eqnresettrue
+  \renewcommand\theequation{\@arabic\c@equation}%
+}
+
+\newcommand\section{%
+  \ifno@eqnreset
+  %\ifappendix\setcounter{section}{0}
+    \ifappendix \setcounter{equation}\z@\fi
+  \else
+ % \setcounter{equation}{0}
+   \setcounter{equation}\z@
+  \fi
+  \@startsection {section}{1}{\z@}
+    {\ifflm@rapids 12\p@ \@plus 6\p@ \@minus 2\p@\else
+     20\p@ \@plus 6\p@ \@minus 2\p@\fi}
+    {3\p@}
+    {\normalfont\large\ifflm@rapids\normalsize\fi\fontswitch\bfseries\@raggedright}%
+}
+
+\newcommand\subsection{%
+  \@startsection{subsection}{2}{\z@}
+    {12\p@ \@plus 3\p@ \@minus 3\p@}
+    {3\p@}
+    {\normalfont\normalsize\itshape\@raggedcenter}%
+}
+
+\newcommand\subsubsection{%
+  \@startsection{subsubsection}{3}{\z@}
+    {9\p@ \@plus 3\p@ \@minus 3\p@}
+    {3\p@}
+    {\raggedright\normalfont\normalsize\itshape}%
+}
+
+
+%\newcommand\paragraph{}
+\newcommand\subparagraph{}
+
+\def\@seccntformat#1{% FROM LATEX.LTX
+  \normalfont\rmfamily\csname the#1\endcsname.\enskip
+}
+
+\def\@secappcntformat#1{%
+  \ifappendix \appendixname\ifoneappendix\else~\fi\fi
+  \ifoneappendix\else \csname the#1\endcsname\relax\fi
+  \ifx\apphe@d\@empty \else .\fi\enskip
+}
+
+\def\@sect#1#2#3#4#5#6[#7]#8{% FROM LATEX.LTX
+  \ifnum #2>\c@secnumdepth
+    \let\@svsec\@empty
+  \else
+    \refstepcounter{#1}%
+    \ifnum #2>\@ne
+      \protected@edef\@svsec{\@seccntformat{#1}\relax}%
+    \else
+      \def\apphe@d{#8}%
+      \protected@edef\@svsec{\@secappcntformat{#1}\relax}%
+    \fi
+  \fi
+  \@tempskipa #5\relax
+  \ifdim \@tempskipa>\z@
+    \begingroup
+    #6{%
+       \@hangfrom{\hskip #3\relax\@svsec}%
+         \interlinepenalty \@M #8\@@par}%
+    \endgroup
+    \csname #1mark\endcsname{#7}%
+    \ifnum #2=\@ne
+      \addcontentsline{toc}{#1}{%
+        \ifnum #2>\c@secnumdepth \else
+        \ifappendix \appendixname~\csname the#1\endcsname
+        \else \protect\numberline{\csname the#1\endcsname.}#7\fi
+        \fi}%
+    \else
+      \addcontentsline{toc}{#1}{%
+        \ifnum #2>\c@secnumdepth \else
+        \protect\numberline{\csname the#1\endcsname.}#7\fi}%
+    \fi
+  \else
+    \def\@svsechd{%
+      #6{\hskip #3\relax
+      \@svsec #8}%
+      \csname #1mark\endcsname{#7}%
+      \addcontentsline{toc}{#1}{%
+        \ifnum #2>\c@secnumdepth \else
+          \protect\numberline{\csname the#1\endcsname.}%
+        \fi
+        #7}}%
+  \fi
+  \@xsect{#5}\@afterindentfalse\@afterheading}%%% 3-8-20
+
+%%%%%%% 3-8-20 %%%%
+\def\@ssect#1#2#3#4#5{%
+  \@tempskipa #3\relax
+  \ifdim \@tempskipa>\z@
+    \begingroup
+      #4{%
+        \@hangfrom{\hskip #1}%
+          \interlinepenalty \@M #5\@@par}%
+    \endgroup
+  \else
+    \def\@svsechd{#4{\hskip #1\relax #5}}%
+  \fi
+  \@xsect{#3}\@afterindentfalse\@afterheading}
+%%%%%%%%%%%%%%%%
+
+\newif\ifappendix
+\newif\ifoneappendix
+\newcommand\appendixname{Appendix}
+
+\newcommand\oneappendix{\global\oneappendixtrue \appendix}
+\newcommand\appendix{\par
+\setcounter{section}{0}
+ % \setcounter{section}\z@
+ \setcounter{equation}{0}
+  %\setcounter{equation}\z@
+  \renewcommand\thesection{\@Alph\c@section}%
+  \renewcommand\thesubsection{\thesection.\@arabic\c@subsection}%
+  \renewcommand\thesubsubsection{\thesubsection.\@arabic\c@subsubsection}%
+  \renewcommand\theequation{\thesection\,\@arabic\c@equation}%
+  \global\appendixtrue
+}
+
+\setcounter{secnumdepth}{3}
+
+\newcounter{part}
+\newcounter {section}
+\newcounter {subsection}[section]
+\newcounter {subsubsection}[subsection]
+\newcounter {paragraph}[subsubsection]
+\newcounter{refsection}[section]
+\renewcommand\thepart          {\@arabic\c@part}
+\renewcommand\thesection       {\@arabic\c@section}
+\renewcommand\thesubsection    {\thesection.\@arabic\c@subsection}
+\renewcommand\thesubsubsection {\thesubsection.\@arabic\c@subsubsection}
+\renewcommand\theparagraph     {\thesubsubsection.\@arabic\c@paragraph}
+
+\newlength\@indentskip
+\newlength\smallindent
+\newlength\@footindent
+\newlength\@leftskip
+\setlength\@indentskip{2.5em}
+\setlength\smallindent{1em}
+\setlength\@footindent{\smallindent}
+\setlength\@leftskip{\z@}
+
+\setlength\leftmargini{\z@}
+\setlength\labelsep{\z@}
+\setlength\labelwidth{\z@}
+
+\newcommand\makeitemlabel[1]{\hspace\labelwidth\hspace\labelsep\hfill#1}
+
+\def\@listI{\parsep\z@ \topsep\z@ \partopsep\z@ \itemsep\z@ \rightmargin\z@
+  \leftmargin\labelwidth \advance\leftmargin\labelsep
+  }
+
+\def\@listi{\@listI \leftmargin\leftmargini \itemindent 1em}
+\def\@listii{\@listI \advance\leftmargin .5em}
+\def\@listiii{\@listI}
+\def\@listiv{\@listI}
+\def\@listv{\@listI}
+\def\@listvi{\@listI}
+\@listi
+
+\def\itemize{% FROM LATEX.LTX
+  \ifnum \@itemdepth >\thr@@ \@toodeep\else
+    \advance\@itemdepth\@ne
+    \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}%
+    \expandafter
+    \list
+      \csname\@itemitem\endcsname
+      {\labelsep .5em\settowidth{\labelwidth}{\csname\@itemitem\endcsname}%
+       \let\makelabel\makeitemlabel}%
+  \fi
+}
+
+\newcommand\labelitemi{$\m@th\bullet$}
+\newcommand\labelitemii{$\m@th\circ$}
+\newcommand\labelitemiii{\normalfont\bfseries ---}
+\newcommand\labelitemiv{\normalfont\bfseries --}
+
+\def\enumerate{% FROM LATEX.LTX
+  \ifnum \@enumdepth >\thr@@ \@toodeep\else
+    \advance\@enumdepth\@ne
+    \edef\@enumctr{enum\romannumeral\the\@enumdepth}%
+  \fi
+  \@ifnextchar [{\@enumeratetwo}{\@enumeratetwo[i]}%
+}
+
+\def\@enumeratetwo[#1]{%
+  \expandafter
+  \list
+    \csname label\@enumctr\endcsname
+    {\settowidth\labelwidth{#1}
+    \labelwidth 1.5pc
+    \labelsep .5em%
+%     \advance\itemindent\labelsep
+     \advance\itemindent\labelwidth
+     \usecounter\@enumctr\relax}%
+}
+
+\newcommand\labelenumi  {{\normalfont\rmfamily(\theenumi)}}
+\newcommand\labelenumii {{\normalfont\rmfamily(\theenumii)}}
+\newcommand\labelenumiii{\theenumiii.}
+\newcommand\labelenumiv {\theenumiv}
+
+\renewcommand\theenumi{{\normalfont\@roman\c@enumi}}
+\renewcommand\theenumii{{\normalfont\itshape\@alph\c@enumii}}
+\renewcommand\theenumiii{\@roman\c@enumiii}
+\renewcommand\theenumiv{\@roman\c@enumiv}
+
+\renewcommand\p@enumii{\theenumi.}
+\renewcommand\p@enumiii{\p@enumii\theenumii.}
+\renewcommand\p@enumiv{\p@enumiii\theenumiii.}
+
+\newcommand*\descriptionlabel[1]{\hspace\labelsep \normalfont\bfseries #1}
+
+\newenvironment{description}
+  {\list{}{\labelwidth\z@
+  \ifnum\@listdepth=\@ne \else \advance\leftmargin 1em\fi
+  \let\makelabel\descriptionlabel}}
+  {\endlist}
+
+\newenvironment{verse}
+  {\let\\=\@centercr
+   \list{}{\itemsep\z@
+   \itemindent -\@indentskip
+   \listparindent \itemindent
+   \rightmargin\leftmargin
+   \advance\leftmargin \@indentskip}\item[]}
+  {\endlist}
+
+\newenvironment{quotation}
+  {\list{}{\listparindent\smallindent
+   \itemindent\listparindent
+   \leftmargin 1pc\rightmargin\leftmargin
+   \topsep\halflineskip
+   \parsep \z@ \@plus 1\p@}\item[]\qsmall\baselineskip 10.75\p@}
+  {\endlist}
+
+\newenvironment{quote}
+  {\par\list{}{\leftmargin 1pc\rightmargin\leftmargin
+   \listparindent\smallindent}\item[]%
+   \qsmall\baselineskip 10.75\p@\rule{\z@}{10\p@}\ignorespaces}
+  {\endlist}
+
+\def\@begintheorem#1#2{% FROM LATEX.LTX
+  \par\vskip\halflineskip {\normalfont\scshape #1\ #2.}%
+  \enskip\normalfont\itshape}
+\def\@opargbegintheorem#1#2#3{% FROM LATEX.LTX
+  \par\vskip\halflineskip {\normalfont\scshape #1\ #2\ (#3).}%
+  \enskip\normalfont\itshape}
+\def\@endtheorem{\vskip\halflineskip\par}% FROM LATEX.LTX
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% theorem* code from psp
+
+\newif\ifrembrks
+\newcommand\removebrackets{\rembrkstrue}
+
+\def\@xnthm#1#2[#3]{% FROM LATEX.LTX
+\expandafter\@ifdefinable\csname #1\endcsname
+  {\@definecounter{#1}\@newctr{#1}[#3]%
+   \expandafter\xdef\csname the#1\endcsname{\expandafter\noexpand
+   \csname the#3\endcsname \@thmcountersep \@thmcounter{#1}}%
+   \global\@namedef{#1}{\@thm{#1}{#2}}%
+   \global\@namedef{#1*}{\@thmstar{#1}{#2}}%
+   \global\@namedef{end#1}{\@endtheorem}%
+   \global\@namedef{end#1*}{\@endthmstar}}%
+}
+
+\def\@ynthm#1#2{% FROM LATEX.LTX
+\expandafter\@ifdefinable\csname #1\endcsname
+  {\@definecounter{#1}%
+   \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}%
+   \global\@namedef{#1}{\@thm{#1}{#2}}%
+   \global\@namedef{#1*}{\@thmstar{#1}{#2}}%
+   \global\@namedef{end#1}{\@endtheorem}%
+   \global\@namedef{end#1*}{\@endthmstar}}%
+}
+
+\def\@othm#1[#2]#3{% FROM LATEX.LTX
+  \@ifundefined{c@#2}{\@nocounterr{#2}}%
+    {\expandafter\@ifdefinable\csname #1\endcsname
+    {\global\@namedef{the#1}{\@nameuse{the#2}}%
+     \global\@namedef{#1}{\@thm{#2}{#3}}%
+     \global\@namedef{#1*}{\@thmstar{#2}{#3}}%
+     \global\@namedef{end#1}{\@endtheorem}%
+     \global\@namedef{end#1*}{\@endthmstar}}}%
+}
+
+\def\@thmstar#1#2{\@ifnextchar[{\@ythmstar{#1}{#2}}{\@xthmstar{#1}{#2}}}
+\def\@xthmstar#1#2{\@beginthmstar{#2}{\csname the#1\endcsname}\ignorespaces}
+\def\@ythmstar#1#2[#3]{\@opargbeginthmstar{#2}{\csname the#1\endcsname}{#3}%
+  \ignorespaces}
+
+\def\@thmstarcounter#1{{}}
+\def\@thmstarcountersep{{}}
+
+\def\@beginthmstar#1#2{%
+  \par\vskip\halflineskip {\normalfont\scshape #1.}%
+  \enskip\normalfont\itshape}
+
+\def\@opargbeginthmstar#1#2#3{%
+  \par\vskip\halflineskip {\normalfont\scshape #1\ {\normalfont\rmfamily
+  \ifrembrks #3\global\rembrksfalse\else (#3)\fi.}}%
+  \normalfont\itshape\enskip}
+
+\def\@endthmstar{\vskip\halflineskip\par}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newsavebox{\proofbox}
+\sbox{\proofbox}{\unitlength 1\p@\begin{picture}(7,7)%
+  \put(0,0){\framebox(7,7){}}\end{picture}}
+
+\newlength\rpbdim
+\newcommand\raiseproofboxby[1]{\setlength\rpbdim{#1}}
+\def\raiseproofb@x{\llap{\vbox to\z@{\hsize=\wd\proofbox\vss
+  \hbox{\usebox\proofbox}\vskip\rpbdim}}%
+  \setlength\rpbdim{\z@}%
+}
+
+\newenvironment{proof}
+  {\par\vskip\halflineskip {\normalfont\itshape Proof.}\enskip}
+  {\hspace*{\fill}\ifdim\rpbdim=\z@ \usebox\proofbox\else \raiseproofb@x\fi
+   \vskip\halflineskip\par}
+
+\newenvironment{proof*}{\proof}{\vskip\halflineskip\par}
+
+\newcommand\newremark[2]{%
+  \newenvironment{#1}{\list{}{\topsep\halflineskip \labelwidth\z@
+    \labelsep .5em \let\makelabel\makeitemlabel}%
+  \item[{\normalfont\itshape #2.}]}{\endlist}%
+}
+
+\renewcommand\theequation{\thesection.\@arabic\c@equation}
+
+% subeqn.sty follows
+% Copyright (c) 1990 by Stephen Gildea
+% Permission to copy all or part of this work is granted, provided
+% that the copies are not made or distributed for resale, and that
+% the copyright notice and this notice are retained.
+% Modified for use with JFM/LaTeX2e.
+
+\newif\ifuseAMSsubequ
+\newcommand\useAMSsubequations{\global\useAMSsubequtrue}
+
+\newtoks\@stequation
+
+\newenvironment{CUPsubequations}
+  {\refstepcounter{equation}%
+   \edef\@savedequation{\the\c@equation}%
+   \@stequation=\expandafter{\theequation}%
+   \edef\@savedtheequation{\the\@stequation}%
+   \edef\oldtheequation{\theequation}%
+   \setcounter{equation}\z@
+   \def\theequation{\oldtheequation{\itshape\alph{equation}}}}
+  {\setcounter{equation}{\@savedequation}%
+   \@stequation=\expandafter{\@savedtheequation}%
+   \edef\theequation{\the\@stequation}\global\@ignoretrue}
+
+\newcommand\returnthesubequation{%
+  \gdef\thesubequation{\theequation{\itshape\@alph\c@subequation}}}
+
+% subeqnarray.sty
+% Copyright (C) 1988 by Johannes Braams, Dr Neher Laboratories
+% Modified for use with JFM/LaTeX2e.
+
+\newcounter{subequation}[equation]
+\renewcommand\thesubequation{\theequation{\itshape\@alph\c@subequation}}
+\def\@subeqnnum{{\normalfont\rmfamily (\thesubequation)}}
+
+\newcommand\slabel[1]{\@bsphack % MODIFIED IN LINE WITH LATEX.LTX
+  \protected@write\@auxout{}%
+    {\string\newlabel{#1}{{\thesubequation}{\thepage}}}%
+  \@esphack}
+
+\newenvironment{subeqnarray} % MODIFIED IN LINE WITH LATEX.LTX
+  {\stepcounter{equation}%
+   \let\@currentlabel=\theequation
+   \global\c@subequation\@ne
+   \global\@eqnswtrue
+   \m@th
+   \global\@eqcnt\z@
+   \tabskip\@centering
+   \let\\\@subeqncr
+   $$\everycr{}\halign to\displaywidth\bgroup
+     \hskip\@centering$\displaystyle\tabskip\z@skip{##}$\@eqnsel
+    &\global\@eqcnt\@ne \hfil${\;##\;}$\hfil
+    &\global\@eqcnt\tw@
+     $\displaystyle\tabskip\z@skip{##}$\hfil\tabskip\@centering
+    &\hb@xt@\z@\bgroup\hss##\egroup
+      \tabskip\z@skip \cr}
+  {\@@subeqncr\egroup $$\global\@ignoretrue}
+
+\def\@subeqncr{{\ifnum0=`}\fi\@ifstar{\global\@eqpen\@M
+    \@ysubeqncr}{\global\@eqpen\interdisplaylinepenalty \@ysubeqncr}}
+
+\def\@ysubeqncr{\@ifnextchar [{\@xsubeqncr}{\@xsubeqncr[\z@]}}
+
+
+\def\@xsubeqncr[#1]{\ifnum0=`{\fi}\@@subeqncr
+   \noalign{\penalty\@eqpen\vskip\jot\vskip #1\relax}}
+
+\def\@@subeqncr{\let\@tempa\relax
+    \ifcase\@eqcnt \def\@tempa{& & &}\or \def\@tempa{& &}
+      \else \def\@tempa{&}\fi
+     \@tempa \if@eqnsw\@subeqnnum\refstepcounter{subequation}\fi
+     \global\@eqnswtrue\global\@eqcnt\z@\cr}
+
+\let\@ssubeqncr=\@subeqncr
+\newenvironment{subeqnarray*}
+  {\def\@subeqncr{\nonumber\@ssubeqncr}\subeqnarray}
+  {\global\advance\c@equation\m@ne \nonumber\endsubeqnarray}
+
+\renewenvironment{eqnarray} % MODIFIED IN LINE WITH LATEX.LTX
+  {\stepcounter{equation}%
+   \let\@currentlabel=\theequation
+   \global\@eqnswtrue
+   \m@th
+   \global\@eqcnt\z@
+   \tabskip\@centering
+   \let\\\@eqncr
+   $$\everycr{}\halign to \displaywidth\bgroup
+     \hskip\@centering$\displaystyle\tabskip\z@skip{##}$\@eqnsel
+   &\global\@eqcnt\@ne \hfil${\;##\;}$\hfil
+   &\global\@eqcnt\tw@
+     $\displaystyle\tabskip\z@skip{##}$\hfil \tabskip\@centering
+   &\hb@xt@\z@\bgroup\hss##\egroup
+     \tabskip\z@skip \cr}
+  {\@@eqncr\egroup\global\advance\c@equation\m@ne
+   $$\global\@ignoretrue}
+
+\newenvironment{titlepage}
+  {\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn
+   \else \newpage \fi \thispagestyle{empty}\c@page\z@}
+  {\if@restonecol\twocolumn \else \newpage \fi}
+
+\setlength\arraycolsep{5\p@}
+\setlength\tabcolsep{3\p@}
+\setlength\arrayrulewidth{.5\p@}
+\setlength\doublerulesep{1.5\p@}
+\setlength\tabbingsep{\labelsep}
+\setlength{\skip\@mpfootins}{5\p@ \@plus .4\p@ \@minus .4\p@}
+\setlength\fboxsep{3\p@}
+\setlength\fboxrule{.5\p@}
+
+\newcommand\affiliation[1]{\gdef\@affiliation{\let\aff\aff@inst#1}}
+\gdef\@affiliation{}
+
+\newcommand\maketitle{\appendixfalse \iflineno\relax\nolinenumbers\fi%% 3-8-20
+  \@ifnextchar [{\m@ketitleone}{\m@ketitletwo}}%
+\def\m@ketitletwo{\m@ketitleone[n]}
+
+\newif\iffofootnote
+\newcommand\fulloutfootnote{\global\fofootnotetrue}
+
+\def\m@ketitleone[#1]{\par\iflineno\relax\runninglinenumbers\fi% 3-8-20
+  \begingroup \iflineno\relax\runninglinenumbers\fi%% 3-8-20
+  \bgroup
+    \def\@makefntext##1{%
+      \iffofootnote
+        \enskip\@thefnmark \ ##1\global\fofootnotefalse
+      \else
+        \setbox\@tempboxa\hbox{\quad\@thefnmark\enskip ##1}%
+        \ifdim\wd\@tempboxa>\hsize \unhbox\@tempboxa\else
+        \centerline{\unhbox\@tempboxa\quad}\fi
+      \fi}%
+    \newpage \global\@topnum\z@
+    \@maketitle{#1}\thispagestyle{titlepage}\@thanks
+  \egroup
+  \endgroup
+  \setcounter{footnote}\z@
+  \global\let\@maketitle\relax
+  \global\let\@thanks\@empty
+  \global\let\@title\@empty
+  \global\let\@author\@empty
+  \global\let\@affiliation\@empty
+  \global\let\maketitle\relax
+  \global\let\thanks\relax
+}
+
+\renewcommand\and{{\normalfont
+  \ifCUPmtlplainloaded
+    \fontseries{sb}\fontshape{n}\fontsize{8}{12}\selectfont
+  \else
+    \indexsize\bfseries
+  \fi
+  and}%
+}
+
+\def\put@rapidsHead{\ifflm@rapids
+ \noindent\minipage[t]{\linewidth}
+ \vskip-25pt
+ \hrule width \linewidth height 1.5pt
+ \par\vskip 26pt
+ \fontsize{30pt}{35pt}\sffamily\bfseries JFM RAPIDS\\
+ \fontsize{12pt}{12pt}\sffamily\bfseries journals.cambridge.org/rapids\\[-3pt]
+ \hrule width \linewidth height 1pt
+ \endminipage\par\vskip 24pt\fi}
+
+\def\put@absrule{\ifflm@rapids\par\vskip1pc\hrule\fi}
+
+\def\@title@alignment{\ifflm@rapids\raggedright\fi}
+\def\@author@alignment{\ifflm@rapids\raggedright\fi}
+\def\@aff@alignment{\ifflm@rapids\raggedright\fi}
+\def\@history@alignment{\ifflm@rapids\raggedright\fi}
+
+
+\def\@maketitle#1{%
+ \newpage
+ \vspace*{10\p@}\addvspace{5pc}%
+ {\flushleft
+  {\normalfont\LARGE\fontswitch\bfseries
+  \put@rapidsHead%
+  \@title@alignment%
+  \@title \par}%
+  \vskip 14\p@ \@plus 2\p@ \@minus 1\p@
+  {\normalfont\large\fontswitch\bfseries\baselineskip=12\p@
+     \@author@alignment%
+     \lowercase{\@author}\par}%
+  \vskip 4\p@ \@plus 1\p@
+  {\normalfont\small
+  \@aff@alignment%
+  \@affiliation \par}%
+  \vskip 8\p@ \@plus 2\p@ \@minus 1\p@
+  %{\normalfont\small (Received \@date)}% x@rem
+  \normalfont\small
+  \@history@alignment%
+  (Received xx; revised xx; accepted xx)\hfill% x@add
+  \put@absrule
+ \par}%
+ \vskip 8\p@ \@plus 2\p@ \@minus 1\p@
+}
+
+\newenvironment{abstract}
+  {\par\normalfont\normalsize\noindent\ignorespaces}
+  {\par\vskip 9\p@ \@plus 1\p@ \@minus 1\p@
+%   \vbox{\centerline{\rule[4\p@]{30pc}{.4\p@}}}
+}
+
+\newenvironment{keywords}
+  {\par\noindent{\bf Key words:}\ \normalfont\normalsize\noindent\ignorespaces}
+  {\par\vskip 9\p@ \@plus 1\p@ \@minus 1\p@
+   \ifflm@rapids\vskip-1pc\put@absrule\else%
+   \vbox{\centerline{\rule[4\p@]{30pc}{.4\p@}}}
+   \vskip 30pt
+   \fi%
+   }
+
+\mark{{}{}}
+\renewcommand\author{\@ifnextchar [{\@authortwo}{\@authorone}}
+\def\@authortwo[#1]#2{\gdef\@author{#2}\gdef\@shortauthor{#1}}
+\def\@authorone#1{\gdef\@author{\def\and{and }#1}%
+ \begingroup\def\and{and}%\gdef\@shortauthor{#1}
+ \endgroup}
+\gdef\@author{\mbox{}}
+
+\newcommand\shortauthor[1]{\edef\@tempx{#1}%
+  \ifx\@tempx\@empty\gdef\@shortauthor{Short author list is empty!!}
+  \else\gdef\@shortauthor{#1}\fi}
+\gdef\@shortauthor{}
+
+\renewcommand\title{\@ifnextchar [{\@titletwo}{\@titleone}}
+\def\@titletwo[#1]#2{\gdef\@title{#2}\gdef\@shorttitle{#1}}
+\def\@titleone#1{\gdef\@title{#1}%\gdef\@shorttitle{#1}
+}
+\gdef\@title{\mbox{}}
+
+\newcommand\shorttitle[1]{\edef\@tempx{#1}%
+ \ifx\@tempx\@empty\gdef\@shorttitle{Short title is empty!!}%
+ \else\gdef\@shorttitle{#1}\fi}
+\gdef\@shorttitle{}
+
+\newcommand\volume[1]{\gdef\@volume{#1}}
+\gdef\@volume{11}
+
+\newcommand\pagerange[1]{\gdef\@pagerange{#1}}
+\gdef\@pagerange{1--000}
+
+\newcommand\pubyear[1]{\def\@pubyear{#1}}
+\edef\@pubyear{\number\year}
+
+\newcommand\journal[1]{\gdef\@journal{#1}}
+
+\newcommand\doi[1]{\gdef\@doi{10.1017/#1}}
+\gdef\@doi{10.1017/S000000000000000X}
+
+\gdef\@journal{%
+  \vbox to 5.5\p@{\noindent
+    \parbox[t]{4.5in}{\normalfont\indexsize\baselineskip 9\p@
+      {\itshape J.\ Fluid\ Mech.} (\@pubyear), {\itshape vol.} \@volume,
+      {\itshape pp.} \@pagerange.\quad \copyright\ \@pubyear\ Cambridge University
+        Press\\[2.5\p@]
+      DOI: \@doi\quad {Printed in the United Kingdom}}%
+  \vss}%
+}
+\gdef\@underjournal{%
+  \vbox to 5.5\p@{\noindent
+    \parbox[t]{4.5in}{\normalfont\indexsize{\itshape Under consideration
+      for publication in J.\ Fluid\ Mech.}\\[2.5\p@]
+      {\ \ }}%
+  \vss}%
+}
+
+\def\footerflagdefns#1{\hbox to \hsize{\hfill\colorbox{mycol}{\color{white}\fontsize{14}{16}\bfseries\selectfont#1}\hfill}}%
+
+\def\absfooterflag{\footerflagdefns{Abstract must not spill onto p.2}}%
+
+\def\pagelimitfooter{\bgroup%
+\ifnum\c@page=4\relax%
+\footerflagdefns{Focus on Fluids articles must not exceed this page length}%
+\else%
+\ifnum\c@page=10\relax%
+\footerflagdefns{Rapids articles must not exceed this page length}%
+\fi\fi%
+\egroup}%
+
+\def\ps@headings{\let\@mkboth\markboth
+  \def\@oddhead{\hfil{\itshape\@shorttitle}\hfil\llap{\thepage}}%
+  \def\@evenhead{\rlap{\thepage}\hfil\itshape\@shortauthor\hfil}%
+  \def\@oddfoot{}%
+  \def\@evenfoot{\pagelimitfooter}%
+  \def\sectionmark##1{\markboth{##1}{}}%
+  \def\subsectionmark##1{\markright{##1}}%
+}
+
+\usepackage{color}
+\definecolor{mycol}{cmyk}{0,1,0,0}
+
+\def\flmspecialinstruction#1{#1}
+\def\ps@spheadings{\let\@mkboth\markboth
+  \def\@oddhead{\hfil{\itshape\@shorttitle}\hfil\llap{\thepage}}%
+  \def\@evenhead{\rlap{\thepage}\hfil\itshape\@shortauthor\hfil}%
+  \def\@oddfoot{\vbox{\vskip10pt\colorbox{mycol}{\textcolor{white}{\fontseries{b}\fontsize{14}{16}\selectfont \flmspecialinstruction}}}}%
+  \def\@evenfoot{\vbox{\vskip10pt\colorbox{mycol}{\textcolor{white}{\fontseries{b}\fontsize{14}{16}\selectfont \flmspecialinstruction}}}}%
+  \def\sectionmark##1{\markboth{##1}{}}%
+  \def\subsectionmark##1{\markright{##1}}%
+}
+
+\def\ps@myheadings{\let\@mkboth\@gobbletwo
+  \def\@oddhead{\hfil{\itshape\rightmark}\hfil\llap{\thepage}}%
+  \def\@evenhead{\rlap{\thepage}\hfil\itshape\leftmark\hfil}%
+  \def\@oddfoot{}%
+  \def\@evenfoot{}%
+  \def\sectionmark##1{}%
+  \def\subsectionmark##1{}%
+}
+
+\ifCUPmtlplainloaded
+  \def\@j@urnal{\@journal}
+\else
+  \def\@j@urnal{\@underjournal}
+\fi
+
+\def\ps@titlepage{\leftskip\z@\let\@mkboth\@gobbletwo\vfuzz=5\p@
+  \def\@oddhead{\vbox{\vspace*{-1pc}\hbox to \textwidth{\@j@urnal \hfil\llap{\thepage}}\par\vskip4pt%
+\hbox to \textwidth{{\fboxsep0pt\fbox{\parbox{\textwidth}{\par\vskip2.7pc\centerline{Banner appropriate to article type will appear here in typeset article}\par\vskip2.7pc}}}}
+}}
+  \def\@evenhead{\@j@urnal \hfil\llap{\thepage}}%
+  \def\@oddfoot{\absfooterflag}%
+  \def\@evenfoot{\absfooterflag}%
+  \def\sectionmark##1{}%
+  \def\subsectionmark##1{}%
+}
+
+\newcommand\@pnumwidth{1.55em}
+\newcommand\@tocrmarg {2.55em}
+\newcommand\@dotsep{4.5}
+\setcounter{tocdepth}{2}
+
+\def\@dottedtocline#1#2#3#4#5{% FROM LATEX.LTX
+  \ifnum #1>\c@tocdepth \else
+    \vskip \z@ \@plus.2\p@
+    {\leftskip #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip
+     \parindent #2\relax\@afterindenttrue
+     \interlinepenalty\@M
+     \leavevmode
+     \@tempdima #3\relax
+     \advance\leftskip \@tempdima \null\hskip -\leftskip
+     {#4}\nobreak
+     \leaders\hbox{$\m@th
+        \mkern \@dotsep mu\hbox{\phantom{.}}\mkern \@dotsep
+        mu$}\hfill
+     \nobreak
+     \hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor #5}%
+     \par}%
+  \fi}
+
+\newcommand\contentsname{CONTENTS}
+
+\newcommand\tableofcontents{%
+  \@restonecolfalse
+  \if@twocolumn\@restonecoltrue\onecolumn\fi
+  \vskip 4\p@ \@plus .5\p@
+  \centerline{\normalfont\scshape \contentsname}%
+  \vskip 3\p@
+  \@starttoc{toc}%
+  \if@restonecol\twocolumn\fi \par\vspace{12\p@}%
+}
+
+\newcommand*\l@section[2]{%
+  \ifnum \c@tocdepth >\z@
+    \addpenalty{\@secpenalty}%
+    \@tempdima 1.5em%
+    \begingroup
+      \parindent \z@ \rightskip \@pnumwidth
+      \parfillskip -\@pnumwidth \normalfont\rmfamily \leavevmode
+      \advance\leftskip\@tempdima \hskip -\leftskip
+      {\normalfont\bfseries #1}\nobreak\hfil
+      \nobreak\hb@xt@\@pnumwidth{\hss #2}\par
+    \endgroup
+  \fi
+}
+
+\newcommand*\l@subsection{\@dottedtocline{2}{2.5em}{2.3em}}
+\newcommand*\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}}
+
+\newif\if@restonecol
+\newcommand\indexname{Index}
+
+\newenvironment{theindex}
+  {\section*{\indexname}%
+   \addcontentsline{toc}{section}{\indexname}%
+   \normalfont\footnotesize \parindent\z@ \parskip\z@ \@plus .1\p@\relax
+   \let\item\@idxitem}
+  {\if@restonecol\onecolumn\else\clearpage\fi}
+
+\newcommand\@idxitem{\par\hangindent 1em\relax}
+\newcommand\subitem{\@idxitem\hspace*{1em}}
+\newcommand\subsubitem{\subitem}
+\newcommand\indexspace{\par\vskip\baselineskip \relax}
+
+\renewcommand\footnoterule{\setcounter{footnote}\z@}
+\newcommand\@makempfntext[1]{\strut\@thefnmark\enskip #1}
+
+\newcommand\@makefntext[1]{%
+  \setbox\@tempboxa\hbox{\quad\@thefnmark\enskip #1}%
+  \ifdim\wd\@tempboxa>\hsize
+    \unhbox\@tempboxa
+  \else
+    \centerline{\unhbox\@tempboxa}%
+  \fi
+}
+
+\long\def\@mpfootnotetext#1{% FROM LATEX.LTX
+  \global\setbox\@mpfootins\vbox{%
+    \unvbox\@mpfootins
+    \reset@font\footnotesize
+    \hsize\columnwidth
+    \@parboxrestore
+    \protected@edef\@currentlabel
+         {\csname p@mpfootnote\endcsname\@thefnmark}%
+    \color@begingroup \centering
+      \@makempfntext{%
+        \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+    \color@endgroup}%
+}
+
+\def\@fnsymbol#1{% MODIFIED IN LINE WITH LATEX.LTX
+  \ensuremath{\ifcase#1\or \dag\or \ddag\or \P\or \|\or
+    \dag\dag\or \ddag\ddag\or \P\P\or \|\| \else\@ctrerr\fi}%
+}
+
+\renewcommand\@makefnmark{\hbox{\@thefnmark}}
+\renewcommand\thempfootnote{\hbox{$\@fnsymbol\c@mpfootnote$}}
+
+\setcounter{topnumber}{3}
+\renewcommand\topfraction{.9}
+\setcounter{bottomnumber}{0}
+\renewcommand\bottomfraction{.9}
+\setcounter{totalnumber}{3}
+\renewcommand\textfraction{.05}
+\renewcommand\floatpagefraction{.9}
+\setcounter{dbltopnumber}{3}
+\renewcommand\dbltopfraction{.9}
+\renewcommand\dblfloatpagefraction{.5}
+
+\newif\ifrem@fullpt
+\newcommand\removefullpoint{\global\rem@fullpttrue}
+
+\newif\ifbot@fig
+\newenvironment{bottomfigure}{\def\fps@figure{b}%
+  \setcounter{bottomnumber}{1}%
+  \global\bot@figtrue
+  \@float{figure}\fstyle@figure}
+  {\end@float}
+
+\usepackage[hang,small,center]{caption}
+\setlength{\captionmargin}{30pt}
+
+%\long\def\@makecaption\normalfont%{%
+ % \ifbot@fig \rule{\textwidth}{.25pt}\fi
+%  \vskip 5\p@ \@plus .4\p@ \@minus .4\p@
+ % \begingroup
+   % \small\setbox\@tempboxa\hbox{{\normalfont\scshape
+    % #1\ifrem@fullpt\else .\fi} #2}%
+    %\ifdim \wd\@tempboxa >\tw@\hsize
+     % \unhbox\@tempboxa\par
+  %  \else
+      %{\centering \unhbox\@tempboxa\par}%
+    %\fi
+ % \endgroup
+  %\global\rem@fullptfalse
+ % \global\bot@figfalse
+%}
+
+\newcounter{table}
+\renewcommand\thetable{\@arabic\c@table}
+\def\fps@table{tp}
+\def\ftype@table{1}
+\def\ext@table{lot}
+\newcommand\tablename{Table}
+\def\fnum@table{\tablename~\thetable}
+
+\newif\iffollowon
+\newif\ifrmrule
+
+\newcommand\followon{\global\followontrue}
+\newcommand\norule{\global\rmruletrue}
+
+\newenvironment{table}
+  {\@float{table}\fstyle@table
+   \iffollowon \else \vspace*{9.5\p@}\fi
+   \global\followonfalse
+   \rule{\textwidth}{.5\p@}\vskip\floatsep\relax}
+  {\ifrmrule \global\rmrulefalse \else \rule{\textwidth}{.5\p@}\fi
+   \end@float}
+
+\newenvironment{table*}{\@dblfloat{table}\fstyle@table}{\end@dblfloat}
+\newenvironment{plaintable}{\@float{table}\fstyle@table}{\end@float}
+
+\def\fstyle@table{\normalfont\small\rmfamily}
+\def\fjust@table{\centering}
+\def\fcapjust@table{\centering}
+\def\fcapsize@table{\normalfont\small\scshape}
+\def\fcapstyle@table{\normalfont\small\rmfamily}
+
+\newcounter{figure}
+\renewcommand\thefigure{\@arabic\c@figure}
+\def\fps@figure{tp}
+\def\ftype@figure{2}
+\def\ext@figure{lof}
+\newcommand\figurename{Figure}
+\def\fnum@figure{\figurename~\thefigure}
+
+\newenvironment{figure}{\@float{figure}\fstyle@figure}{\end@float}
+\newenvironment{figure*}{\@dblfloat{figure}\fstyle@figure}{\end@dblfloat}
+
+\def\fstyle@figure{\normalfont\small\rmfamily}
+\def\fjust@figure{\centering}
+\def\fcapjust@figure{\centering}
+\def\fcapsize@figure{\normalfont\small\scshape}
+\def\fcapstyle@figure{\normalfont\small\rmfamily}
+
+\newcommand\smallls{\kern.12em\relax}
+\newcommand\ls{\kern.15em\relax}
+\newcommand\ns{\kern.5em\relax}
+
+\renewcommand{\thefootnote}{\mbox{$\@fnsymbol\c@footnote$}}
+
+\renewcommand\hline{%
+  \noalign{\ifnum0=`}\fi \vskip 6\p@
+  \hrule \@height \arrayrulewidth \vskip 6\p@
+  \futurelet \@tempa\@xhline
+}
+
+\renewcommand\@xhline{%
+  \ifx\@tempa\hline \vskip -12\p@ \vskip\doublerulesep\fi \ifnum0=`{\fi}%
+}
+
+\newenvironment{acknowledgments}
+  {\par\vskip 10\p@ \@plus 1\p@ \@minus 1\p@}{\par}
+\let\acknowledgements\acknowledgments
+\let\endacknowledgements\endacknowledgments
+
+\newcommand\today{}
+\edef\today{\number\day\ \ifcase\month\or
+  January\or February\or March\or April\or May\or June\or
+  July\or August\or September\or October\or November\or December
+ \fi \ \number\year}
+
+\newif\if@altcite
+\renewcommand\@biblabel[1]{}% FROM LATEX.LTX
+\newcommand\newblock{\hskip .11em \@plus .33em \@minus .07em\relax}
+\newcommand\bibls{\kern.065em\relax}
+
+\newenvironment{thebibliography}[1]{%
+  \par\vskip 20\p@ \@plus 1\p@ \@minus 1\p@
+  \ifflm@rapids\section*{References}\else
+  \centerline{\normalfont\small\scshape R\bibls E\bibls F\bibls E\bibls
+             R\bibls E\bibls N\bibls C\bibls E\bibls S}\fi%
+ \nobreak
+ \vskip 4\p@ \@plus .5\p@ \@minus .5\p@
+ \nobreak
+ \list{}{\labelwidth\z@ \leftmargin 2.5em \itemindent -2.5em \itemsep 1\p@}%
+ \normalfont\small\parindent\z@
+ \parskip\z@ \@plus .1\p@\relax
+ \sloppy\clubpenalty\z@ \widowpenalty\@M
+ \sfcode`\.\@m\relax}
+ {\endlist}
+
+
+\let\JFMthebib\thebibliography
+\let\JFMendthebib\endthebibliography
+
+\DeclareRobustCommand\cite{% FROM LATEX.LTX
+  \@ifnextchar [{\@tempswatrue\global\@altcitetrue\@citex}
+    {\@tempswafalse\global\@altcitefalse\@citex[]}}
+
+\def\@citex[#1]#2{% FROM LATEX.LTX
+  \let\@citea\@empty
+  \@cite{\@for\@citeb:=#2\do
+    {\@citea\def\@citea{,\penalty\@m\ }%
+     \edef\@citeb{\expandafter\@firstofone\@citeb}%
+     \if@filesw\immediate\write\@auxout{\string\citation{\@citeb}}\fi
+     \@ifundefined{b@\@citeb}{\mbox{\reset@font\bfseries ?}%
+       \G@refundefinedtrue
+       \@latex@warning
+         {Citation `\@citeb' on page \thepage \space undefined}}%
+       {{\csname b@\@citeb\endcsname}}}}{#1}}
+
+\renewcommand\@cite[2]{% FROM LATEX.LTX
+  {\if@altcite #2\else #1\fi}\global\@altcitefalse}
+
+\newif\iffontfound
+\newcommand\checkfont[1]{%
+  \batchmode
+  \font\test=#1\relax
+  \errorstopmode
+  \fontfoundfalse
+  \ifx\test\nullfont \else \fontfoundtrue\fi
+}
+
+\pagestyle{headings}
+\pagenumbering{arabic}
+\frenchspacing
+\ifCUPmtlplainloaded
+  \setlength\oddsidemargin\z@
+  \setlength\evensidemargin\z@
+  \setlength\topmargin\z@
+\fi
+\if@referee
+  \renewcommand\baselinestretch{2}\raggedbottom
+\else
+  \flushbottom
+\fi
+
+\if@index
+  \newcommand\indextitlesize{\@setfontsize\indextitlesize\@xiipt{18}}
+
+  \renewcommand\ls{\kern.10em\relax}%.15
+  \renewcommand\ns{\kern.44em\relax}% .5
+
+  \def\@maketitle#1{%
+    \newpage
+    \vspace*{8\p@}%
+    {\centering \sloppy
+      {\normalfont\indextitlesize\fontswitch\bfseries \@title \par}%
+      \vskip 14\p@ \@plus 2\p@ \@minus 1\p@
+        {\normalfont\large\fontswitch\bfseries\baselineskip=12\p@
+%       By\ns \uppercase{\@author}
+        \par}%
+      \vskip 4\p@ \@plus 1\p@
+        {\normalfont\small \@affiliation \par}%
+      \vskip 8\p@ \@plus 2\p@ \@minus 1\p@
+%       {\normalfont\small (Received \@date)}%
+        \par}%
+    \vspace*{-14\p@ \@plus 2\p@ \@minus 1\p@}
+  }
+  \renewcommand\journal[1]{\gdef\@journal{#1}}
+  \gdef\@journal{%
+    \vbox to 5.5\p@{\noindent
+      \parbox[t]{4.5in}{\normalfont\indexsize\baselineskip 9\p@
+        \textsc{Journal of Fluid Mechanics}\hfill\textsc{Volume 423\quad\date}\\%[2.5\p@]
+        {}
+    }\vss}%
+  }
+
+  \def\ps@titlepage{\leftskip\z@\let\@mkboth\@gobbletwo\vfuzz=5\p@
+    \def\@oddhead{\small\textsc{J\ls o\ls u\ls r\ls n\ls a\ls l\ns
+      o\ls f\ns
+      F\ls l\ls u\ls i\ls d\ns
+      M\ls e\ls c\ls h\ls a\ls n\ls i\ls c\ls s}%
+      \hfill\textsc{V\ls o\ls l\ls u\ls m\ls e\ns \@volume\quad 25\ns N\ls o\ls v\ls e\ls m\ls b\ls e\ls r\ns 2000}}%
+    \def\@evenhead{\@j@urnal}%
+    \def\@oddfoot{}%
+    \def\@evenfoot{}%
+    \def\sectionmark##1{}%
+    \def\subsectionmark##1{}%
+  }
+
+  \renewcommand*\descriptionlabel[1]{\hspace\labelsep \normalfont\fontswitch\bfseries #1}
+  \renewenvironment{description}
+    {\list{}{\parsep 4pt\small\labelwidth\z@\labelsep 0.5em
+    \leftmargin 18pt\itemindent-\leftmargin
+    \let\makelabel\descriptionlabel}}
+    {\endlist}
+
+  \renewcommand\title{\@ifnextchar [{\@titletwo}{\@titleone}}
+  \def\@titletwo[#1]#2{\gdef\@title{#2}\gdef\@shorttitle{#1}}
+  \def\@titleone#1{\gdef\@title{#1}\gdef\@shorttitle{#1}}
+  \gdef\@title{\mbox{}}
+\fi% end of \if@index
+
+
+%% Extracted from old version of jfm-instructions.tex
+% For units of measure
+\newcommand\dynpercm{\nobreak\mbox{$\;$dyn\,cm$^{-1}$}}
+\newcommand\cmpermin{\nobreak\mbox{$\;$cm\,min$^{-1}$}}
+
+% Various bold symbols
+\providecommand\bnabla{\boldsymbol{\nabla}}
+\providecommand\bcdot{\boldsymbol{\cdot}}
+\newcommand\biS{\boldsymbol{S}}
+\newcommand\etb{\boldsymbol{\eta}}
+
+% For multiletter symbols
+\newcommand\Real{\mbox{Re}}          % cf plain TeX's \Re and Reynolds number
+\newcommand\Imag{\mbox{Im}}           % cf plain TeX's \Im
+\newcommand\Rey{\mbox{\textit{Re}}}  % Reynolds number
+\newcommand\Pran{\mbox{\textit{Pr}}} % Prandtl number, cf TeX's \Pr product
+\newcommand\Pen{\mbox{\textit{Pe}}}  % Peclet number
+\newcommand\Ai{\mbox{Ai}}            % Airy function
+\newcommand\Bi{\mbox{Bi}}            % Airy function
+
+%Bessel function
+\newcommand\rmJ{{\rm J}}
+\newcommand\rmY{{\rm Y}}
+\newcommand\rmK{{\rm K}}
+\newcommand\rmI{{\rm I}}
+
+\newcommand\ssC{\mathsf{C}}    % for sans serif C
+\newcommand\sfsP{\mathsfi{P}}  % for sans serif sloping P
+\newcommand\slsQ{\mathsfbi{Q}} % for sans serif bold-sloping Q
+
+% Hat position
+\newcommand\hatp{\skew3\hat{p}}      % p with hat
+\newcommand\hatR{\skew3\hat{R}}      % R with hat
+\newcommand\hatRR{\skew3\hat{\hatR}} % R with 2 hats
+\newcommand\doubletildesigma{\skew2\tilde{\skew2\tilde{\Sigma}}}
+%       italic Sigma with double tilde
+
+% array strut to make delimiters come out right size both ends
+\newsavebox{\astrutbox}
+\sbox{\astrutbox}{\rule[-5pt]{0pt}{20pt}}
+\newcommand{\astrut}{\usebox{\astrutbox}}
+
+\newcommand\GaPQ{\ensuremath{G_a(P,Q)}}
+\newcommand\GsPQ{\ensuremath{G_s(P,Q)}}
+\newcommand\p{\ensuremath{\partial}}
+\newcommand\tti{\ensuremath{\rightarrow\infty}}
+\newcommand\kgd{\ensuremath{k\gamma d}}
+\newcommand\shalf{\ensuremath{{\scriptstyle\frac{1}{2}}}}
+\newcommand\sh{\ensuremath{^{\shalf}}}
+\newcommand\smh{\ensuremath{^{-\shalf}}}
+\newcommand\squart{\ensuremath{{\textstyle\frac{1}{4}}}}
+\newcommand\thalf{\ensuremath{{\textstyle\frac{1}{2}}}}
+\newcommand\Gat{\ensuremath{\widetilde{G_a}}}
+\newcommand\ttz{\ensuremath{\rightarrow 0}}
+\newcommand\ndq{\ensuremath{\frac{\mbox{$\partial$}}{\mbox{$\partial$} n_q}}}
+\newcommand\sumjm{\ensuremath{\sum_{j=1}^{M}}}
+\newcommand\pvi{\ensuremath{\int_0^{\infty}%
+  \mskip \ifCUPmtlplainloaded -30mu\else -33mu\fi -\quad}}
+
+\newcommand\etal{\mbox{\textit{et al.}}}
+\newcommand\etc{etc.\ }
+\newcommand\eg{e.g.\ }
+
+
+% See if the author has the AMS 'amsbsy' package installed: If they have,
+% use it to provide better bold math support (with \boldsymbol).
+
+\ifCUPmtlplainloaded \else
+  \IfFileExists{amsbsy.sty}
+    {\typeout{^^JFound the 'amsbsy' package on the system, using it.^^J}%
+     \usepackage{amsbsy}}
+    {\providecommand\boldsymbol[1]{\mbox{\boldmath $##1$}}}
+\fi
+
+% See if the author has AMS Euler fonts installed: If they have, attempt
+% to use the 'upmath' package to provide upright math.
+\ifCUPmtlplainloaded \else
+  \checkfont{eurm10}
+  \iffontfound
+    \IfFileExists{upmath.sty}
+      {\typeout{^^JFound AMS Euler Roman fonts on the system,
+                   using the 'upmath' package.^^J}%
+       \usepackage{upmath}}
+      {\typeout{^^JFound AMS Euler Roman fonts on the system, but you
+                   dont seem to have the}%
+       \typeout{'upmath' package installed. JFM.cls can take advantage
+                 of these fonts,^^Jif you use 'upmath' package.^^J}%
+       \providecommand\upi{\pi}%
+      }
+  \else
+    \providecommand\upi{\pi}%
+  \fi
+\fi
+
+
+
+% See if the author has AMS symbol fonts installed: If they have, attempt
+% to use the 'amssymb' package to provide the AMS symbol characters.
+
+\ifCUPmtlplainloaded \else
+  \checkfont{msam10}
+  \iffontfound
+    \IfFileExists{amssymb.sty}
+      {\typeout{^^JFound AMS Symbol fonts on the system, using the
+                'amssymb' package.^^J}%
+       \usepackage{amssymb}%
+       \let\le=\leqslant  \let\leq=\leqslant
+       \let\ge=\geqslant  \let\geq=\geqslant
+      }{}
+  \fi
+\fi
+
+% Extras
+
+\hyphenpenalty 9500
+\emergencystretch 20pt
+\tolerance=300
+
+\def\aff#1{\ignorespaces\textsuperscript{#1}}
+\def\aff@inst#1{\par\vskip3pt\textsuperscript{#1}\unskip\ignorespaces}
+\def\email#1{Email address for correspondence: #1}
+
+\def\corresp#1{\unskip\thanks{#1}}
+\def\aunote#1{\unskip\thanks{#1}}
+
+% Figure caption legends:
+\newcommand{\opensquare}{\mbox{$\square$}}
+\newcommand{\opentriangle}{\mbox{$\vartriangle$}}
+\newcommand{\opentriangledown}{\mbox{$\triangledown$}}
+\newcommand{\opendiamond}{\mbox{$\lozenge$}}
+\newcommand{\fullsquare}{\mbox{$\blacksquare$}}
+\newcommand{\fulldiamond}{\mbox{$\blacklozenge$}}
+\newcommand{\fullstar}{\mbox{$\bigstar$}}
+\newcommand{\fulltriangle}{\mbox{$\blacktriangle$}}
+\let\fulltri=\fulltriangle
+\newcommand{\fulltriangledown}{\mbox{$\blacktriangledown$}}
+\let\fulltridown=\fulltriangledown
+\newcommand{\opencirc}{\mbox{\Large$\circ$}}
+\newcommand{\opensqr}{\mbox{$\square$}}
+\newcommand{\opentri}{\mbox{$\triangle$}}
+\newcommand{\opentridown}{\mbox{$\bigtriangledown$}}
+%\newcommand{\opendiamond}{\mbox{$\diamondsuit$}}
+\newcommand{\fullcirc}{\mbox{{\Large$\bullet$}}}
+\newcommand{\fullsqr}{\,\vrule height5pt depth0pt width5pt}
+\newcommand{\dotted}{\protect\mbox{${\mathinner{\cdotp\cdotp\cdotp\cdotp\cdotp\cdotp}}$}}
+\newcommand{\dashed}{\protect\mbox{-\ -\ -\ -}}
+\newcommand{\broken}{\protect\mbox{-- -- --}}
+\newcommand{\longbroken}{\protect\mbox{--- --- ---}}
+\newcommand{\chain}{\protect\mbox{--- $\cdot$ ---}}
+\newcommand{\dashddot}{\protect\mbox{--- $\cdot$ $\cdot$ ---}}
+\newcommand{\full}{\protect\mbox{------}}
+
+% For sans serif characters:
+% The following macros are setup in JFM.cls for sans-serif fonts in text
+% and math.  If you use these macros in your article, the required fonts
+% will be substitued when your article is typeset by the typesetter.
+%
+% \textsfi, \mathsfi   : sans-serif slanted
+% \textsfb, \mathsfb   : sans-serif bold
+% \textsfbi, \mathsfbi : sans-serif bold slanted (doesnt exist in CM fonts)
+%
+% For san-serif roman use \textsf and \mathsf as normal.
+\iflineno\AtBeginDocument{\usepackage{lineno-FLM}}\fi% 3-8-20
+% Greek letters
+\let\rmGamma  \Gamma
+\let\rmDelta  \Delta
+\let\rmTheta  \Theta
+\let\rmLambda \Lambda
+\let\rmXi     \Xi
+\let\rmPi     \Pi
+\let\rmSigma  \Sigma
+\let\rmUpsilon\Upsilon
+\let\rmPhi    \Phi
+\let\rmPsi    \Psi
+\let\rmOmega  \Omega
+
+\def\Gamma  {\varGamma}
+\def\Delta  {\varDelta}
+\def\Theta  {\varTheta}
+\def\Lambda {\varLambda}
+\def\Xi     {\varXi}
+\def\Pi     {\varPi}
+\def\Sigma  {\varSigma}
+\def\Upsilon{\varUpsilon}
+\def\Phi    {\varPhi}
+\def\Psi    {\varPsi}
+\def\Omega  {\varOmega}
+
+\let\mathbi\boldsymbol
+
+%%%%%% 8-8-20 %% Introduced for back section with small font size
+\newcounter{savesecnumdepth}
+\providecommand{\backsectionname}{Acknowledgements}
+\newcommand{\backsection}[2][\backsectionname]{\begingroup\par%
+  \small%
+  \setcounter{savesecnumdepth}{\value{secnumdepth}}%
+  \setcounter{secnumdepth}{0}%
+\vskip6pt
+\noindent \textbf{#1.} #2\par%
+  \setcounter{secnumdepth}{\value{savesecnumdepth}}%
+  \endgroup}
+%%%%%%
+
+\endinput
+
+%%% Date: 3-8-20 
+%%% Updated the template to get the line numbers using lineno.sty
+%%% Inserted \@afterindentfalse\@afterheading to avoid indentation after headings
+
+%%% Date 8-8-20
+%%% Changed the default point size as 10.5 for FLM new style \edef\t@xtsize{\ifCUPmtlplainloaded 10.5\else 10\fi}
+%%% Introduced \backsection tag to make the heading run on style with small font size as like references.
+
+% end of file jfm.cls
diff --git a/calkit/templates/latex/jfm/lineno-FLM.sty b/calkit/templates/latex/jfm/lineno-FLM.sty
new file mode 100644
index 00000000..cdc2abf4
--- /dev/null
+++ b/calkit/templates/latex/jfm/lineno-FLM.sty
@@ -0,0 +1,113 @@
+%\usepackage[switch]{lineno}
+%\newcounter{lasttextlineno}
+\usepackage[pagewise,mathlines]{lineno}
+\runninglinenumbers %% for continous line numbering regardless of box and minipage but only on left side in single/double column
+%\linenumbers %% properly in single/double column but boxes and minipage linenos not getting continuous
+%\pagewiselinenumbers%%
+\newif \ifLineNumbers%
+\linenumberdisplaymath
+
+\def\linenumberfont{\normalfont\fontsize{8}{10}\selectfont}
+\if@twocolumn
+\setlength\marginparwidth{.75cm}
+\setlength\marginparsep{19.5\p@}
+\else
+\setlength\marginparwidth{3.0cm}
+\setlength\marginparsep{24\p@}
+\fi
+\newcommand\linenomathWithnumbersforams{%
+  \ifLineNumbers
+  %\ifx\@@par\@@@par\else
+    \ifnum\interlinepenalty>-\linenopenaltypar
+      \global\holdinginserts\thr@@
+      \advance\interlinepenalty \linenopenalty
+     \ifhmode                                   % v4.3
+      \advance\predisplaypenalty \linenopenalty
+     \fi
+      %\advance\postdisplaypenalty \linenopenalty
+      \advance\interdisplaylinepenalty \linenopenalty
+    \fi
+  \fi
+  \ignorespaces
+  }
+
+\newcommand\linenomathWithnumbersformultline{%
+  \ifLineNumbers
+  %\ifx\@@par\@@@par\else
+    \ifnum\interlinepenalty>-\linenopenaltypar
+      \global\holdinginserts\thr@@
+      \advance\interlinepenalty \linenopenalty
+     \ifhmode                                   % v4.3
+      %\advance\predisplaypenalty \linenopenalty
+     \fi
+      %\advance\postdisplaypenalty \linenopenalty
+      \advance\interdisplaylinepenalty \linenopenalty
+    \fi
+  \fi
+  \ignorespaces
+  }
+
+
+
+\newcommand*\patchAmsMathEnvironmentForLineno[1]{%
+\expandafter\let\csname old#1\expandafter\endcsname\csname #1\endcsname
+\expandafter\let\csname oldend#1\expandafter\endcsname\csname end#1\endcsname
+\renewenvironment{#1}%
+{\def\linenomath{\linenomathWithnumbersforams}%added
+ \@namedef{linenomath*}{\linenomathNonumbers}%added
+\linenomath\csname old#1\endcsname}%
+{\csname oldend#1\endcsname\endlinenomath}}%
+\newcommand*\patchBothAmsMathEnvironmentsForLineno[1]{%
+\patchAmsMathEnvironmentForLineno{#1}%
+\patchAmsMathEnvironmentForLineno{#1*}%
+}%
+
+\AtBeginDocument{%
+%\patchBothAmsMathEnvironmentsForLineno{equation}% deleted
+%\patchBothAmsMathEnvironmentsForLineno{align}%
+\patchBothAmsMathEnvironmentsForLineno{flalign}%
+\patchBothAmsMathEnvironmentsForLineno{alignat}%
+\patchBothAmsMathEnvironmentsForLineno{gather}%
+%\patchBothAmsMathEnvironmentsForLineno{multline}%
+%\patchBothAmsMathEnvironmentsForLineno{split}%
+\patchAmsMathEnvironmentForLineno{array}%
+%\patchAmsMathEnvironmentForLineno{split}%
+}
+
+%%\AtBeginDocument{%
+  \let\LN@align\align
+  \let\LN@endalign\endalign
+  \renewenvironment{align}%
+     {\linenomath\LN@align}%
+     {\LN@endalign\endlinenomath}%
+%%}
+
+
+\renewenvironment{multline}{\linenomathWithnumbersformultline%
+  \start@multline\st@rredfalse
+}{%
+  \iftagsleft@ \@xp\lendmultline@ \else \@xp\rendmultline@ \fi
+  \ignorespacesafterend
+\endlinenomath}
+\renewenvironment{multline*}{\linenomathWithnumbersformultline\start@multline\st@rredtrue}{\endmultline\endlinenomath}
+
+\def\insplit@{%
+  \global\setbox\z@\vbox\bgroup
+    \Let@ \chardef\dspbrk@context\@ne \restore@math@cr
+    \default@tag % disallow use of \tag here
+    \ialign\bgroup
+      \hfil%
+      \strut@
+       $\m@th\displaystyle{##}$% 
+     &$\m@th\displaystyle{{}##}$%
+      \hfill % Why not \hfil?---dmj, 1994/12/28
+      \crcr\noalign{\global\advance\c@linenumber\@ne}%
+}
+
+\makeatletter
+\setlength\marginparsep{12\p@}
+\setlength\marginparpush{0\p@}
+\setlength\marginparwidth{2.6pc}
+\makeatother
+
+\endinput
diff --git a/calkit/templates/latex/jfm/paper.tex b/calkit/templates/latex/jfm/paper.tex
new file mode 100644
index 00000000..cbcaba68
--- /dev/null
+++ b/calkit/templates/latex/jfm/paper.tex
@@ -0,0 +1,468 @@
+%% Downloaded from JFM website 2024-11-17
+\documentclass[lineno]{jfm}
+
+\usepackage{graphicx}
+%\usepackage{epstopdf,epsfig}
+\usepackage{newtxtext}
+\usepackage{newtxmath}
+\usepackage{natbib}
+\usepackage{hyperref}
+\hypersetup{
+    colorlinks = true,
+    urlcolor   = blue,
+    citecolor  = black,
+}
+\newtheorem{lemma}{Lemma}
+\newtheorem{corollary}{Corollary}
+\newcommand{\RomanNumeralCaps}[1]
+\linenumbers
+
+
+% {\MakeUppercase{\romannumeral #1}}
+
+\title{JFM {\LaTeX} submission template}
+
+\author{Alan N. Jones\aff{1}
+  \corresp{\email{JFMEditorial@cambridge.org}},
+  H.-C. Smith\aff{1}
+ \and J.Q. Long\aff{2}}
+
+\affiliation{\aff{1}STM Journals, Cambridge University Press, The Printing House, Shaftesbury Road, Cambridge CB2 8BS, UK
+\aff{2}DAMTP, Centre for Mathematical Sciences, Wilberforce Road, Cambridge CB3 0WA, UK}
+
+\begin{document}
+\maketitle
+
+\begin{abstract}
+This file contains information for authors planning to submit a paper to the {\it Journal of Fluid Mechanics}. The document was generated in {\LaTeX} using the JFM class file and supporting files provided on the JFM website \href{https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/information/author-instructions/preparing-your-materials}{here}, and the source files can be used as a template for submissions (please note that this is mandatory for {\it JFM Rapids}). Full author instructions can be found on the \href{https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/information/author-instructions}{JFM website}. The present paragraph appears in the \verb}abstract} environment. All papers should feature a single-paragraph abstract of no more than 250 words which must not spill onto the seond page of the manuscript. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract. Dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract dummy text of abstract.
+\end{abstract}
+
+\begin{keywords}
+Authors should not enter keywords on the manuscript, as these must be chosen by the author during the online submission process and will then be added during the typesetting process (see \href{https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/information/list-of-keywords}{Keyword PDF} for the full list).  Other classifications will be added at the same time.
+\end{keywords}
+
+{\bf MSC Codes }  {\it(Optional)} Please enter your MSC Codes here
+
+\section{First-order heading}
+\label{sec:headings}
+
+ This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+
+\subsection {Second-order Heading}
+ This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.  This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+
+ \subsubsection {Third-order Heading}
+ This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+\section{Figures and Tables}\label{sec:Figures_Tables}
+
+\begin{figure}
+%   \centerline{\includegraphics{../figures/figure-1}} % Images in 100% size
+  \caption{Trapped-mode wavenumbers, $kd$, plotted against $a/d$ for
+    three ellipses:\protect\\
+    ---$\!$---,
+    $b/a=1$; $\cdots$\,$\cdots$, $b/a=1.5$.}
+\label{fig:ka}
+\end{figure}
+
+\subsection{Figures}
+ Each figure should be accompanied by a single caption, to appear beneath, and must be cited in the text. Figures should appear in the order in which they are first mentioned in the text. For example see figures \ref{fig:ka} and \ref{fig:kd}.
+
+ This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+
+\begin{figure}
+%   \centerline{\includegraphics{../figures/figure-2}}
+  \caption{The features of the four possible modes corresponding to
+  (\textit{a}) periodic\protect\\ and (\textit{b}) half-periodic solutions.}
+\label{fig:kd}
+\end{figure}
+
+\subsection{Tables}
+ Tables, however small, must be numbered sequentially in the order in which they are mentioned in the text. Words \textit {table 1, table 2} should be lower case throughout.
+ See table \ref{tab:kd} for an example.
+
+ This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+
+\begin{table}
+  \begin{center}
+\def~{\hphantom{0}}
+  \begin{tabular}{lccc}
+      $a/d$  & $M=4$   &   $M=8$ & Callan \etal \\[3pt]
+       0.1   & 1.56905 & ~~1.56~ & 1.56904\\
+       0.3   & 1.50484 & ~~1.504 & 1.50484\\
+       0.55  & 1.39128 & ~~1.391 & 1.39131\\
+       0.7   & 1.32281 & ~10.322 & 1.32288\\
+       0.913 & 1.34479 & 100.351 & 1.35185\\
+  \end{tabular}
+  \caption{Values of $kd$ at which trapped modes occur when $\rho(\theta)=a$.}
+  \label{tab:kd}
+  \end{center}
+\end{table}
+
+\section{Notation and style}\label{notstyle}
+ Generally any queries concerning notation and journal style can be answered by viewing recent pages in the Journal. However, the following guide provides the key points to note. It is expected that Journal style and mathematical notation will be followed, and authors should take care to define all variables or entities upon first use. Also note that footnotes are not normally accepted.  Abbreviations must be defined at first use, glossaries or lists/tables of abbreviations are not permitted.
+
+\subsection{Mathematical notation}
+\subsubsection{Setting variables, functions, vectors, matrices etc}
+\begin{itemize} \label{sec:MathNot}
+\item {\bf Italic font} should be used for denoting variables, with multiple-letter symbols avoided except in the case of dimensionless numbers such as $\Rey$, $\Pran$ and $\Pen$ (Reynolds, Prandtl, and P\'eclet numbers respectively, which are defined as \verb}\Rey}, \verb}\Pran} and \verb}\Pen} in the template).\\
+\item {\bf Upright Roman font} (or upright Greek where appropriate) should be used for:\\
+\begin {enumerate}
+\item (vI) label, e.g.  T. t (transpose)\\
+\item Fixed operators: sin, log, d, $\Delta$, exp etc.\\
+\item Constants: i ($\sqrt{-1}$), $\upi$ (defined as \verb}\upi}),e  etc.\\
+\item Special Functions: $\Ai$, $\Bi$ (Airy functions, defined as \verb}\Ai} and \verb}\Bi}), $\Real$ (real part, defined as \verb}\Real}), $\Imag$ (imaginary part, defined as \verb}\Imag}), etc.\\[-4pt]
+\item Physical units: cm, s, etc.\\[-4pt]
+\item Abbreviations: c.c. (complex conjugate), h.o.t. (higher-order terms), DNS, etc.\\[-4pt]
+\end {enumerate}
+\item {\bf Bold italic font} (or bold sloping Greek) should be used for vectors (with the centred dot for a scalar product also in bold): $\boldsymbol{i \cdot j}$\\[-4pt]
+\item {\bf Bold sloping sans serif font}, defined by the \verb}\mathsfbi} macro, should be used for tensors and matrices: $\mathsfbi{D}$ \\[-4pt]
+\item {\bf Calligraphic font} (for example $\mathcal{G}$, $\mathcal{R}$) can be used as an alternative to italic when the same letter denotes a different quantity use \verb}\mathcal} in \LaTeX)
+\end{itemize}
+
+\subsubsection{Other symbols}  Large numbers  that are not scientific powers should not include commas, but should use a non-breaking space, and use the form 1600 or 16 000 or 160 000.
+Use \textit{O} to denote `of the order of', not the \LaTeX\ $\mathcal{O}$.
+
+The product symbol ($\times$) should only be used to denote multiplication where an equation is broken over more than one line, to denote a cross product, or between numbers . The $\boldsymbol {\cdot}$ symbol should not be used, except to denote a scalar product of vectors specifically.
+
+\subsubsection{Example Equations}
+ This section contains sample equations in the JFM style. Please refer to the {\LaTeX} source file for examples of how to display such equations in your manuscript.
+
+\begin{equation}
+  (\nabla^2+k^2)G_s=(\nabla^2+k^2)G_a=0
+  \label{Helm}
+\end{equation}
+
+\begin{equation}
+  \bnabla\bcdot\boldsymbol{v} = 0,\quad \nabla^{2}P=
+    \bnabla\bcdot(\boldsymbol{v}\times \boldsymbol{w}).
+\end{equation}
+
+\begin{equation}
+  G_s,G_a\sim 1 / (2\upi)\ln r
+  \quad \mbox{as\ }\quad r\equiv|P-Q|\rightarrow 0,
+  \label{singular}
+\end{equation}
+
+\begin{equation}
+\left. \begin{array}{ll}
+\displaystyle\frac{\p G_s}{\p y}=0
+  \quad \mbox{on\ }\quad y=0,\\[8pt]
+\displaystyle  G_a=0
+  \quad \mbox{on\ }\quad y=0,
+ \end{array}\right\}
+  \label{symbc}
+\end{equation}
+
+
+\begin{equation}
+  -\frac{1}{2\upi} \int_0^{\infty} \gamma^{-1}[\mathrm exp(-k\gamma|y-\eta|)
+   + \mathrm exp(-k\gamma(2d-y-\eta))] \cos k(x-\xi)t\:\mathrm{d} t,
+   \qquad 0<y,\quad \eta<d,
+\end{equation}
+
+\begin{equation}
+  \gamma(t) = \left\{
+    \begin{array}{ll}
+      -\mathrm{i}(1-t^2)^{1/2}, & t\le 1 \\[2pt]
+      (t^2-1)^{1/2},         & t>1.
+    \end{array} \right.
+\end{equation}
+
+\[
+  -\frac{1}{2\upi}
+   \pvi B(t)\frac{\cosh k\gamma(d-y)}{\gamma\sinh k\gamma d}
+   \cos k(x-\xi)t\:\mathrm{d} t
+\]
+
+\begin{equation}
+  G = -\frac{1}{4}\mathrm{i} (H_0(kr)+H_0(kr_1))
+    - \frac{1}{\upi} \pvi\frac{\mathrm{e}^{-\kgd}}%
+    {\gamma\sinh\kgd} \cosh k\gamma(d-y) \cosh k\gamma(d-\eta)
+\end{equation}
+
+Note that when equations are included in definitions, it may be suitable to render them in line, rather than in the equation environment: $\boldsymbol{n}_q=(-y^{\prime}(\theta),
+x^{\prime}(\theta))/w(\theta)$.
+Now $G_a=\squart Y_0(kr)+\Gat$ where
+$r=\{[x(\theta)-x(\psi)]^2 + [y(\theta)-y(\psi)]^2\}^{1/2}$ and $\Gat$ is
+regular as $kr\ttz$. However, any fractions displayed like this, other than $\thalf$ or $\squart$, must be written on the line, and not stacked (ie 1/3).
+
+\begin{eqnarray}
+  \ndq\left(\frac{1}{4} Y_0(kr)\right) & \sim &
+    \frac{1}{4\upi w^3(\theta)}
+    [x^{\prime\prime}(\theta)y^{\prime}(\theta)-
+    y^{\prime\prime}(\theta)x^{\prime}(\theta)] \nonumber\\
+  & = & \frac{1}{4\upi w^3(\theta)}
+    [\rho^{\prime}(\theta)\rho^{\prime\prime}(\theta)
+    - \rho^2(\theta)-2\rho^{\prime 2}(\theta)]
+    \quad \mbox{as\ }\quad kr\ttz . \label{inteqpt}
+\end{eqnarray}
+
+\begin{equation}
+  \frac{1}{2}\phi_i = \frac{\upi}{M} \sumjm\phi_j K_{ij}^a w_j,
+  \qquad i=1,\,\ldots,\,M,
+\end{equation}
+where
+\begin{equation}
+  K_{ij}^a = \left\{
+    \begin{array}{ll}
+      \p G_a(\theta_i,\theta_j)/\p n_q, & i\neq j \\[2pt]
+      \p\Gat(\theta_i,\theta_i)/\p n_q
+      + [\rho_i^{\prime}\rho_i^{\prime\prime}-\rho_i^2-2\rho_i^{\prime 2}]
+      / 4\upi w_i^3, & i=j.
+  \end{array} \right.
+\end{equation}
+
+
+\refstepcounter{equation}
+$$
+  \rho_l = \lim_{\zeta \rightarrow Z^-_l(x)} \rho(x,\zeta), \quad
+  \rho_{u} = \lim_{\zeta \rightarrow Z^{+}_u(x)} \rho(x,\zeta)
+  \eqno{(\theequation{\mathit{a},\mathit{b}})}\label{eq35}
+$$
+
+\begin{equation}
+  (\rho(x,\zeta),\phi_{\zeta\zeta}(x,\zeta))=(\rho_0,N_0)
+  \quad \mbox{for}\quad Z_l(x) < \zeta < Z_u(x).
+\end{equation}
+
+
+\begin{subeqnarray}
+  \tau_{ij} & = &
+    (\overline{\overline{u}_i \overline{u}_j}
+    - \overline{u}_i\overline{u}_j)
+    + (\overline{\overline{u}_iu^{SGS}_j
+    + u^{SGS}_i\overline{u}_j})
+    + \overline{u^{SGS}_iu^{SGS}_j},\\[3pt]
+  \tau^\theta_j & = &
+    (\overline{\overline{u}_j\overline{\theta}}
+    - \overline{u}_j \overline{\theta})
+    + (\overline{\overline{u}_j\theta^{SGS}
+    + u^{SGS}_j \overline{\theta}})
+    + \overline{u^{SGS}_j\theta^{SGS}}.
+\end{subeqnarray}
+
+\begin{equation}
+\setlength{\arraycolsep}{0pt}
+\renewcommand{\arraystretch}{1.3}
+\slsQ_C = \left[
+\begin{array}{ccccc}
+  -\omega^{-2}V'_w  &  -(\alpha^t\omega)^{-1}  &  0  &  0  &  0  \\
+  \displaystyle
+  \frac{\beta}{\alpha\omega^2}V'_w  &  0  &  0  &  0  &  \mathrm{i}\omega^{-1} \\
+  \mathrm{i}\omega^{-1}  &  0  &  0  &  0  &  0  \\
+  \displaystyle
+  \mathrm{i} R^{-1}_{\delta}(\alpha^t+\omega^{-1}V''_w)  &  0
+    & -(\mathrm{i}\alpha^tR_\delta)^{-1}  &  0  &  0  \\
+  \displaystyle
+  \frac{\mathrm{i}\beta}{\alpha\omega}R^{-1}_\delta V''_w  &  0  &  0
+    &  0  & 0 \\
+  (\mathrm{i}\alpha^t)^{-1}V'_w  &  (3R^{-1}_{\delta}+c^t(\mathrm{i}\alpha^t)^{-1})
+    &  0  &  -(\alpha^t)^{-2}R^{-1}_{\delta}  &  0  \\
+\end{array}  \right] .
+\label{defQc}
+\end{equation}
+
+\begin{equation}
+\etb^t = \skew2\hat{\etb}^t \exp [\mathrm{i} (\alpha^tx^t_1-\omega t)],
+\end{equation}
+where $\skew2\hat{\etb}^t=\boldsymbol{b}\exp (\mathrm{i}\gamma x^t_3)$.
+\begin{equation}
+\mbox{Det}[\rho\omega^2\delta_{ps}-C^t_{pqrs}k^t_qk^t_r]=0,
+\end{equation}
+
+\begin{equation}
+ \langle k^t_1,k^t_2,k^t_3\rangle = \langle
+\alpha^t,0,\gamma\rangle
+\end{equation}
+
+\begin{equation}
+\boldsymbol{f}(\theta,\psi) = (g(\psi)\cos \theta,g(\psi) \sin \theta,f(\psi)).
+\label{eq41}
+\end{equation}
+
+\begin{eqnarray}
+f(\psi_1) = \frac{3b}{\upi[2(a+b \cos \psi_1)]^{{3}/{2}}}
+  \int^{2\upi}_0 \frac{(\sin \psi_1 - \sin \psi)(a+b \cos \psi)^{1/2}}%
+  {[1 - \cos (\psi_1 - \psi)](2+\alpha)^{1/2}}\mathrm{d}x,
+\label{eq42}
+\end{eqnarray}
+\begin{eqnarray}
+g(\psi_1) & = & \frac{3}{\upi[2(a+b \cos \psi_1)]^{{3}/{2}}}
+  \int^{2\upi}_0 \left(\frac{a+b \cos \psi}{2+\alpha}\right)^{1/2}
+  \left\{ \astrut f(\psi)[(\cos \psi_1 - b \beta_1)S + \beta_1P]
+  \right. \nonumber\\
+&& \mbox{}\times \frac{\sin \psi_1 - \sin \psi}{1-\cos(\psi_1 - \psi)}
+  + g(\psi) \left[\left(2+\alpha - \frac{(\sin \psi_1 - \sin \psi)^2}
+  {1- \cos (\psi - \psi_1)} - b^2 \gamma \right) S \right.\nonumber\\
+&& \left.\left.\mbox{} + \left( b^2 \cos \psi_1\gamma -
+  \frac{a}{b}\alpha \right) F(\frac{1}{2}\upi, \delta) - (2+\alpha)
+  \cos\psi_1 E(\frac{1}{2}\upi, \delta)\right] \astrut\right\} \mathrm{d} \psi,
+\label{eq43}
+\end{eqnarray}
+\begin{equation}
+\alpha = \alpha(\psi,\psi_1) = \frac{b^2[1-\cos(\psi-\psi_1)]}%
+  {(a+b\cos\psi) (a+b\cos\psi_1)},
+  \quad
+  \beta - \beta(\psi,\psi_1) = \frac{1-\cos(\psi-\psi_1)}{a+b\cos\psi}.
+\end{equation}
+
+
+\begin{equation}
+\left. \begin{array}{l}
+\displaystyle
+H(0) = \frac{\epsilon \overline{C}_v}{\tilde{v}^{{1}/{2}}_T
+(1- \beta)},\quad H'(0) = -1+\epsilon^{{2}/{3}} \overline{C}_u
++ \epsilon \skew5\hat{C}_u'; \\[16pt]
+\displaystyle
+H''(0) = \frac{\epsilon u^2_{\ast}}{\tilde{v}^{{1}/{2}}
+_T u^2_P},\quad H' (\infty) = 0.
+\end{array} \right\}
+\end{equation}
+
+\begin{lemma}
+Let $f(z)$ be a trial \citet[][pp.~231--232]{Batchelor59} function defined on $[0,1]$.  Let $\varLambda_1$ denote
+the ground-state eigenvalue for $-\mathrm{d}^2g/\mathrm{d} z^2=\varLambda g$,
+where $g$ must satisfy $\pm\mathrm{d} g/\mathrm{d} z+\alpha g=0$ at $z=0,1$
+for some non-negative constant~$\alpha$.  Then for any $f$ that is not
+identically zero we have
+\begin{equation}
+\frac{\displaystyle
+  \alpha(f^2(0)+f^2(1)) + \int_0^1 \left(
+  \frac{\mathrm{d} f}{\mathrm{d} z} \right)^2 \mathrm{d} z}%
+  {\displaystyle \int_0^1 f^2\mathrm{d} z}
+\ge \varLambda_1 \ge
+\left( \frac{-\alpha+(\alpha^2+8\upi^2\alpha)^{1/2}}{4\upi} \right)^2.
+\end{equation}
+\end{lemma}
+
+\begin{corollary}
+Any non-zero trial function $f$ which satisfies the boundary condition
+$f(0)=f(1)=0$ always satisfies
+\begin{equation}
+  \int_0^1 \left( \frac{\mathrm{d} f}{\mathrm{d} z} \right)^2 \mathrm{d} z.
+\end{equation}
+\end{corollary}
+
+\section{Citations and references}
+All papers included in the References section must be cited in the article, and vice versa. Citations should be included as, for example ``It has been shown \citep{Rogallo81} that...'' (using the {\verb}\citep}} command, part of the natbib package) ``recent work by \citet{Dennis85}...'' (using {\verb}\citet}}).
+The natbib package can be used to generate citation variations, as shown below.\\
+\verb#\citet[pp. 2-4]{Hwang70}#:\\
+\citet[pp. 2-4]{Hwang70} \\
+\verb#\citep[p. 6]{Worster92}#:\\
+\citep[p. 6]{Worster92}\\
+\verb#\citep[see][]{Koch83, Lee71, Linton92}#:\\
+\citep[see][]{Koch83, Lee71, Linton92}\\
+\verb#\citep[see][p. 18]{Martin80}#:\\
+\citep[see][p. 18]{Martin80}\\
+\verb#\citep{Brownell04,Brownell07,Ursell50,Wijngaarden68,Miller91}#:\\
+\citep{Brownell04,Brownell07,Ursell50,Wijngaarden68,Miller91}\\
+\citep{Briukhanovetal1967}\\
+\cite{Bouguet01}\\
+\citep{JosephSaut1990}\\
+
+The References section can either be built from individual \verb#\bibitem# commands, or can be built using BibTex. The BibTex files used to generate the references in this document can be found in the JFM {\LaTeX} template files folder provided on the website \href{https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/information/author-instructions/preparing-your-materials}{here}.
+
+Where there are up to ten authors, all authors' names should be given in the reference list. Where there are more than ten authors, only the first name should appear, followed by {\it {et al.}}
+
+
+\backsection[Supplementary data]{\label{SupMat}Supplementary material and movies are available at \\https://doi.org/10.1017/jfm.2019...}
+
+\backsection[Acknowledgements]{Acknowledgements may be included at the end of the paper, before the References section or any appendices. Several anonymous individuals are thanked for contributions to these instructions.}
+
+\backsection[Funding]{Please provide details of the sources of financial support for all authors, including grant numbers. Where no specific funding has been provided for research, please provide the following statement: "This research received no specific grant from any funding agency, commercial or not-for-profit sectors." }
+
+\backsection[Declaration of interests]{A Competing Interests statement is now mandatory in the manuscript PDF. Please note that if there are no conflicts of interest, the declaration in your PDF should read as follows: {\bf Declaration of Interests}. The authors report no conflict of interest.}
+
+\backsection[Data availability statement]{The data that support the findings of this study are openly available in [repository name] at http://doi.org/[doi], reference number [reference number]. See JFM's \href{https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/information/journal-policies/research-transparency}{research transparency policy} for more information}
+
+\backsection[Author ORCIDs]{Authors may include the ORCID identifers as follows.  F. Smith, https://orcid.org/0000-0001-2345-6789; B. Jones, https://orcid.org/0000-0009-8765-4321}
+
+\backsection[Author contributions]{Authors may include details of the contributions made by each author to the manuscript'}
+
+\appendix
+
+\section{}\label{appA}
+ In order not to disrupt the narrative flow, purely technical material may be included in the appendices. This material should corroborate or add to the main result and be essential for the understanding of the paper. It should be a small proportion of the paper and must not be longer than the paper itself.
+
+This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+
+This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text. This is an example of dummy text.
+
+%\bibliographystyle{jfm}
+%\bibliography{jfm}
+%Use of the above commands will create a bibliography using the .bib file. Shown below is a bibliography built from individual items.
+
+\bibliographystyle{jfm}
+%\bibliography{jfm2esam}
+
+\begin{thebibliography}{99}
+
+\expandafter\ifx\csname natexlab\endcsname\relax
+\def\natexlab#1{#1}\fi
+\expandafter\ifx\csname selectlanguage\endcsname\relax
+\def\selectlanguage#1{\relax}\fi
+
+\bibitem[Batchelor (1971)]{Batchelor59}
+{\sc Batchelor, G.K.} 1971 {Small-scale variation of convected quantities like temperature in turbulent fluid part1, general discussion and the case of small conductivity}, {\it J. Fluid Mech.}, {\bf 5}, pp. 3-113-133.
+
+\bibitem [Bouguet (2008)]{Bouguet01}
+{\sc Bouguet, J.-Y} 2008 Camera Calibration Toolbox for Matlab {\url{http://www.vision.caltech.edu/bouguetj/calib_doc/}}.
+
+ \bibitem[Briukhanovetal et al (1967)] {Briukhanovetal1967}
+{\sc Briukhanov, A. V.,   Grigorian, S. S., Miagkov,  S. M., Plam, M. Y.,   I. E. Shurova, I. E.,   Eglit, M. E. and Yakimov, Y. L.} 1967
+{On some new approaches to the dynamics of snow avalanches},
+{\it Physics of Snow and Ice,  Proceedings of the International Conference on Low Temperature Science}
+{Vol 1} pp. 1221--1241 {Institute of Low Temperature Science, Hokkaido University, Sapporo, Hokkaido, Japan}.
+
+\bibitem[Brownell (2004)]{Brownell04}
+ {\sc Brownell,  C.J.  and Su,  L.K.} 2004  {Planar measurements of differential diffusion in turbulent jets}, {\it AIAA Paper},  pp. 2004-2335.
+
+\bibitem[Brownell and Su (2007)] {Brownell07}
+  {\sc Brownell, C.J. and  Su, L.K.} 2007 {Scale relations and spatial spectra in a differentially diffusing jet}, {\it AIAA Paper}, pp 2007-1314.
+
+\bibitem [Dennis (1985)] {Dennis85}
+ {\sc  Dennis, S.C.R.} 1985 {Compact explicit finite difference approximations to the Navier--Stokes equation},  { In \it Ninth Intl Conf. on Numerical Methods in Fluid Dynamics},  {ed Soubbaramayer and J.P. Boujot},  {Vol 218}, {\it Lecture Notes in Physics}, pp. 23-51. Springer.
+
+\bibitem [Edwards et al. (2017)]{EdwardsVirouletKokelaarGray2017}
+{\sc Edwards, A. N., Viroulet, S., Kokelaar, B. P. and Gray, J. M. N. T.} 2017 Formation of levees, troughs and elevated channels by avalanches on erodible slopes {\it J. Fluid Mech.}, {\bf 823}, pp. 278-315.
+
+\bibitem[Hwang et al (1970)] {Hwang70}
+ {\sc Hwang,  L.-S.  and  Tuck, E.O.} 1970 On the oscillations of harbours of arbitrary shape {\it J.~Fluid Mech.}, {\bf42}, pp 447-464.
+
+\bibitem[Josep and Saut (1990)] {JosephSaut1990}
+ {\sc Joseph, Daniel D. and Saut, Jean Claude} 1990 Short-wave instabilities and ill-posed initial-value problems {\it Theoretical and Computational Fluid Dynamics}, {\bf 1},  pp.191--227,  {\url{http://dx.doi.org/10.1007/BF00418002}}.
+
+\bibitem[Worster (1992)] {Worster92}
+{ \sc  Worster, M.G.} 1992 The dynamics of mushy layers {\it Interactive dynamics of convection and solidification},
+{(ed. S.H. Davis and H.E. Huppert and W. Muller and M.G. Worster)}, pp. 113--138 {Kluwer}.
+
+\bibitem[Koch(1983)] {Koch83}
+{\sc Koch, W.} 1983 Resonant acoustic frequencies of flat plate cascades {\it J.~Sound Vib.}, {\bf 88}, pp. 233-242.
+
+\bibitem[Lee(1971)] {Lee71}
+{\sc Lee,  J.-J.}  1971 Wave-induced oscillations in harbours of arbitrary geometry {\it J.~Fluid Mech.}, {\bf 45}, pp. 375-394.
+
+\bibitem[Linton and  Evans (1992)] {Linton92}
+ {\sc  Linton, C.M. and  Evans, D.V.} 1992 The radiation and scattering of surface waves by a vertical circular cylinder in a channel {\it Phil.\ Trans.\ R. Soc.\ Lond.}, {\bf 338}, pp. 325-357.
+
+\bibitem [Martin(1980] {Martin80}
+ {\sc  Martin, P.A.} 1980 On the null-field equations for the exterior problems of acoustics {\it Q.~J. Mech.\ Appl.\ Maths},{\bf 33}, pp. 385--396.
+
+\bibitem [Rogallo(1981)] {Rogallo81}
+ {\sc Rogallo,  R.S.} 1981 Numerical experiments in homogeneous turbulence  { {\it Tech. Rep.} 81835}  {NASA Tech.\ Mem}.
+
+\bibitem[Ursell(1950)] {Ursell50}
+{\sc  Ursell, F.} 1950 Surface waves on deep water in the presence of a submerged cylinder i {\it Proc.\ Camb.\ Phil.\ Soc.}, {\bf 46}, pp.141--152.
+
+\bibitem[Wijngaarden (1968)]{Wijngaarden68}
+{\sc van Wijngaarden, L.} 1968 On the oscillations Near and at resonance in open pipes {\it J.~Engng Maths},{\bf 2}, pp. 225--240.
+
+\bibitem[Miller (1991)]{Miller91}
+{ \sc  Miller, P.L.} 1991 Mixing in high Schmidt number turbulent jets {school {PhD thesis}} {California Institute of Technology}.
+
+\end{thebibliography}
+
+%% End of file `jfm2esam.bib'.
+
+
+\end{document}
diff --git a/calkit/templates/latex/jfm/upmath.sty b/calkit/templates/latex/jfm/upmath.sty
new file mode 100644
index 00000000..f5647369
--- /dev/null
+++ b/calkit/templates/latex/jfm/upmath.sty
@@ -0,0 +1,158 @@
+%%
+%% This is file `upmath.sty'
+%%
+%% Copyright (1996) Cambridge University Press
+%%
+%% by Mark A. Reed
+%%
+%% This package provides 'upright' math (lower-case Greek, A-Z, a-z,
+%% punctuation, < >, \ell, \partial) from the AMS Euler fonts EURM/B.
+%% When used internaly at CUP, this package substitutes the correct
+%% Monotype Times MTMR/B math fonts.
+%%
+%% Requires the amsbsy.sty and amsgen.sty packages.
+%%
+%% Bugs (in the case of unchanged files) should be reported to
+%% texline@cup.cam.ac.uk
+%%
+%% This software may only be used in the preparation of journal articles
+%% or books or parts of books to be published by Cambridge University Press.
+%% Any other use constitutes an infringement of copyright.
+%%
+%% This file 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.
+%%
+\ProvidesPackage{upmath}[1996/10/20 v1.0 CUP LaTeX2e package]
+
+\RequirePackage{amsbsy}[1995/01/20] % also includes amsgen.sty
+
+% Macro for changing \mathversion's
+\providecommand{\mathch}[2]{% Derived from AMSBSY.STY
+  \begingroup
+  \let\@nomath\@gobble \mathversion{#1}%
+  \math@atom{#2}{%
+  \mathchoice%
+    {\hbox{$\m@th\displaystyle#2$}}%
+    {\hbox{$\m@th\textstyle#2$}}%
+    {\hbox{$\m@th\scriptstyle#2$}}%
+    {\hbox{$\m@th\scriptscriptstyle#2$}}}%
+  \endgroup}
+
+\ifCUPmtlplainloaded \else
+%
+% The following is from Ueur.fd: changed encoding from U to OML.
+% This allows to use eurm/b as (more or less) a math italic font.
+%
+\DeclareFontFamily{OML}{eur}{\skewchar\font'177}
+\DeclareFontShape{OML}{eur}{m}{n}{
+  <5> <6> <7> <8> <9> gen * eurm
+  <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88> eurm10
+  }{}
+\DeclareFontShape{OML}{eur}{b}{n}{
+  <5> <6> <7> <8> <9> gen * eurb
+  <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88> eurb10
+  }{}
+%
+\fi
+
+\DeclareMathVersion{upright}
+\DeclareMathVersion{boldupright}
+\ifCUPmtlplainloaded
+  \SetSymbolFont{letters}{upright}    {OML}{mtm}{m}{n}
+  \SetSymbolFont{letters}{boldupright}{OML}{mtm}{b}{n}
+\else
+  \SetSymbolFont{letters}{upright}    {OML}{eur}{m}{n}
+  \SetSymbolFont{letters}{boldupright}{OML}{eur}{b}{n}
+\fi
+
+\ifCUPmtlplainloaded
+% we want mtr(bx)/mt(b)sy in \mathversion upright/boldupright
+  \SetSymbolFont{operators}{upright}{OT1}{mtr}{m}{n}
+  \SetSymbolFont{symbols}{upright}{OMS}{mtsy}{m}{n}
+  \SetSymbolFont{operators}{boldupright}{OT1}{mtr}{bx}{n}
+  \SetSymbolFont{symbols}{boldupright}{OMS}{mtsy}{b}{n}
+\fi
+
+\DeclareRobustCommand{\mathup}[1]{\mathch{upright}{#1}}
+\DeclareRobustCommand{\mathbup}[1]{\mathch{boldupright}{#1}}
+
+% lower-case Greek
+\newcommand\ualpha{\mathup{\alpha}}
+\newcommand\ubeta{\mathup{\beta}}
+\newcommand\ugamma{\mathup{\gamma}}
+\newcommand\udelta{\mathup{\delta}}
+\newcommand\uepsilon{\mathup{\epsilon}}
+\newcommand\uzeta{\mathup{\zeta}}
+\newcommand\ueta{\mathup{\eta}}
+\newcommand\utheta{\mathup{\theta}}
+\newcommand\uiota{\mathup{\iota}}
+\newcommand\ukappa{\mathup{\kappa}}
+\newcommand\ulambda{\mathup{\lambda}}
+\newcommand\umu{\mathup{\mu}}
+\newcommand\unu{\mathup{\nu}}
+\newcommand\uxi{\mathup{\xi}}
+\newcommand\upi{\mathup{\pi}}
+\newcommand\urho{\mathup{\rho}}
+\newcommand\usigma{\mathup{\sigma}}
+\newcommand\utau{\mathup{\tau}}
+\newcommand\uupsilon{\mathup{\upsilon}}
+\newcommand\uphi{\mathup{\phi}}
+\newcommand\uchi{\mathup{\chi}}
+\newcommand\upsi{\mathup{\psi}}
+\newcommand\uomega{\mathup{\omega}}
+\newcommand\uvarepsilon{\mathup{\varepsilon}}
+\newcommand\uvartheta{\mathup{\vartheta}}
+\newcommand\uvarpi{\mathup{\varpi}}
+\ifCUPmtlplainloaded
+  \newcommand\uvarrho{\mathup{\varrho}}
+  \newcommand\uvarsigma{\mathup{\varsigma}}
+\else
+  \let\uvarrho\varrho % don't exist in eurm.
+  \let\uvarsigma\varsigma
+\fi
+\newcommand\uvarphi{\mathup{\varphi}}
+
+\newcommand\ubalpha{\mathbup{\alpha}}
+\newcommand\ubbeta{\mathbup{\beta}}
+\newcommand\ubgamma{\mathbup{\gamma}}
+\newcommand\ubdelta{\mathbup{\delta}}
+\newcommand\ubepsilon{\mathbup{\epsilon}}
+\newcommand\ubzeta{\mathbup{\zeta}}
+\newcommand\uboldeta{\mathbup{\eta}}
+\newcommand\ubtheta{\mathbup{\theta}}
+\newcommand\ubiota{\mathbup{\iota}}
+\newcommand\ubkappa{\mathbup{\kappa}}
+\newcommand\ublambda{\mathbup{\lambda}}
+\newcommand\ubmu{\mathbup{\mu}}
+\newcommand\ubnu{\mathbup{\nu}}
+\newcommand\ubxi{\mathbup{\xi}}
+\newcommand\ubpi{\mathbup{\pi}}
+\newcommand\ubrho{\mathbup{\rho}}
+\newcommand\ubsigma{\mathbup{\sigma}}
+\newcommand\ubtau{\mathbup{\tau}}
+\newcommand\ubupsilon{\mathbup{\upsilon}}
+\newcommand\ubphi{\mathbup{\phi}}
+\newcommand\ubchi{\mathbup{\chi}}
+\newcommand\ubpsi{\mathbup{\psi}}
+\newcommand\ubomega{\mathbup{\omega}}
+\newcommand\ubvarepsilon{\mathbup{\varepsilon}}
+\newcommand\ubvartheta{\mathbup{\vartheta}}
+\newcommand\ubvarpi{\mathbup{\varpi}}
+\ifCUPmtlplainloaded
+  \newcommand\ubvarrho{\mathbup{\varrho}}
+  \newcommand\ubvarsigma{\mathbup{\varsigma}}
+\else
+  \newcommand\ubvarrho{\boldsymbol{\varrho}} % don't exist in eurb.
+  \newcommand\ubvarsigma{\boldsymbol{\varsigma}}
+\fi
+\newcommand\ubvarphi{\mathbup{\varphi}}
+
+% A few other upright symbols
+\newcommand\upartial {\mathup{\partial}}
+\newcommand\ubpartial{\mathbup{\partial}}
+
+\endinput
+
+% End of file `upmath.sty'
+
diff --git a/docs/tutorials/adding-latex-pub-docker.md b/docs/tutorials/adding-latex-pub-docker.md
new file mode 100644
index 00000000..3067bf69
--- /dev/null
+++ b/docs/tutorials/adding-latex-pub-docker.md
@@ -0,0 +1,47 @@
+# Adding a new LaTeX-based publication with its own Docker build environment
+
+Have you ever wanted to collaborate with a team on a LaTeX article,
+but have ran into roadblocks getting everyone on the team to install the
+correct dependencies?
+This can be especially difficult if different team members are using different
+operating systems.
+However, this is a perfect use case for building the paper with a Docker
+container.
+Here's how to do that by creating a publication in your project
+and specifying a LaTeX template and Docker environment in which to build it,
+all with one command:
+
+```sh
+calkit new publication \
+    --title "This is the title" \
+    --description "This is the description of the paper." \
+    --kind journal-article \
+    --template latex/article \
+    --environment latex \
+    --stage build-paper \
+    ./paper
+```
+
+What happens when we do this:
+
+1. A new publication is added to `calkit.yaml`.
+1. A new Docker environment called `latex` is added to `calkit.yaml`.
+   This environment uses an `_include` key so the details can be written to
+   a different file, `.calkit/environments/latex.yaml`.
+   This will allow us to use that environment specification as an input
+   dependency for a DVC pipeline stage,
+   such that if our environment changes, that stage will be rerun.
+1. Files from a LaTeX template called "article" are copied into the `./paper`
+   directory.
+1. A new stage called `build-paper` is added to the DVC pipeline in `dvc.yaml`.
+   It will have dependencies based on source files in `./paper`
+   and an output based on the template's target file.
+   Note that you can add more dependencies to the resulting pipeline stage
+   with the `--dep` and `--deps-from-stage-outs` commands.
+1. A Git commit is made automatically to add all of these files to the repo.
+   Note this can be disabled with the `--no-commit` option.
+
+If you need to add more dependencies to the stage later,
+e.g., if you have a `.bib` file for references,
+or add more figures,
+you can add these by editing `dvc.yaml` directly.


Test patch:
diff --git a/calkit/tests/cli/test_list.py b/calkit/tests/cli/test_list.py
index d4df39df..55681a22 100644
--- a/calkit/tests/cli/test_list.py
+++ b/calkit/tests/cli/test_list.py
@@ -6,3 +6,7 @@
 def test_list_environments(tmp_dir):
     subprocess.check_call("calkit list environments", shell=True)
     # TODO: Create some environments
+
+
+def test_list_templates():
+    subprocess.check_call("calkit list templates", shell=True)
diff --git a/calkit/tests/cli/test_new.py b/calkit/tests/cli/test_new.py
index aeafa9cf..8bde3e62 100644
--- a/calkit/tests/cli/test_new.py
+++ b/calkit/tests/cli/test_new.py
@@ -130,3 +130,42 @@ def test_new_figure(tmp_dir):
     )
     pipeline = calkit.dvc.read_pipeline()
     assert pipeline["stages"]["create-figure3"]["deps"] == ["myfigure2.png"]
+
+
+def test_new_publication(tmp_dir):
+    subprocess.check_call(["git", "init"])
+    subprocess.check_call(["dvc", "init"])
+    subprocess.check_call(
+        [
+            "calkit",
+            "new",
+            "publication",
+            "my-paper",
+            "--template",
+            "latex/article",
+            "--kind",
+            "journal-article",
+            "--title",
+            "This is a cool title",
+            "--description",
+            "This is a cool description.",
+            "--stage",
+            "build-latex-article",
+            "--environment",
+            "my-latex-env",
+        ]
+    )
+    ck_info = calkit.load_calkit_info()
+    print(ck_info)
+    assert ck_info["environments"]["my-latex-env"] == {
+        "_include": ".calkit/environments/my-latex-env.yaml"
+    }
+    assert ck_info["publications"][0]["path"] == "my-paper/paper.pdf"
+    with open("dvc.yaml") as f:
+        dvc_pipeline = calkit.ryaml.load(f)
+    print(dvc_pipeline)
+    stage = dvc_pipeline["stages"]["build-latex-article"]
+    assert stage["cmd"] == (
+        "calkit runenv -n my-latex-env "
+        '"cd my-paper && latexmk -pdf paper.tex"'
+    )
diff --git a/calkit/tests/test_templates.py b/calkit/tests/test_templates.py
new file mode 100644
index 00000000..a743a8b1
--- /dev/null
+++ b/calkit/tests/test_templates.py
@@ -0,0 +1,14 @@
+"""Tests for ``calkit.templates``."""
+
+import calkit
+from calkit.templates.latex import GITIGNORE as LATEX_GITIGNORE
+
+
+def test_use_template(tmp_dir):
+    calkit.templates.use_template("latex/article", "paper", title="Cool title")
+    with open("paper/paper.tex") as f:
+        txt = f.read()
+    assert r"\title{Cool title}" in txt
+    with open("paper/.gitignore") as f:
+        txt = f.read()
+    assert txt == LATEX_GITIGNORE