diff --git a/.gitignore b/.gitignore
index 9fb1fa18de02b1394d1789b88dd33624f1df193e..f888394c0c21cc5552b0be1f4d3bb945249691ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,8 +45,7 @@ examples/*/restart/*
 examples/*/*/used_parameters.yml
 examples/*/err_file*
 examples/*/out_file*
-examples/*/stf_output*
-examples/*/stf_ouput*
+examples/*/stf_*
 examples/*/log*
 examples/*/*/unused_parameters.yml
 examples/*/*.mpg
diff --git a/Makefile.am b/Makefile.am
index b98b855f9902c55782924888aeafa2185f19dc8a..77c9b8e2292aa6da8d40bbcef00ae0dc1da13e07 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@
 ACLOCAL_AMFLAGS = -I m4
 
 # Show the way...
-SUBDIRS = src examples doc tests tools
+SUBDIRS = src argparse examples doc tests tools
 
 # Non-standard files that should be part of the distribution.
 EXTRA_DIST = INSTALL.swift .clang-format format.sh
diff --git a/README b/README
index 747fe6da4766ca6b7ce272f3d4e15ff105a4b04a..97d096ef1804a4348e88dfaf67c22b2c427a3ad8 100644
--- a/README
+++ b/README
@@ -1,49 +1,69 @@
  Welcome to the cosmological hydrodynamical code
     ______       _________________
    / ___/ |     / /  _/ ___/_  __/
-   \__ \| | /| / // // /_   / /   
-  ___/ /| |/ |/ // // __/  / /    
- /____/ |__/|__/___/_/    /_/     
+   \__ \| | /| / // // /_   / /
+  ___/ /| |/ |/ // // __/  / /
+ /____/ |__/|__/___/_/    /_/
  SPH With Inter-dependent Fine-grained Tasking
 
- Website: www.swiftsim.com
+Website: www.swiftsim.com
  Twitter: @SwiftSimulation
 
 See INSTALL.swift for install instructions.
 
-Usage: swift [OPTION]... PARAMFILE
-       swift_mpi [OPTION]... PARAMFILE
-
-Valid options are:
-  -a                Pin runners using processor affinity.
-  -c                Run with cosmological time integration.
-  -C                Run with cooling.
-  -d                Dry run. Read the parameter file, allocate memory but does not read
-                    the particles from ICs and exit before the start of time integration.
-                    Allows user to check validity of parameter and IC files as well as memory limits.
-  -D                Always drift all particles even the ones far from active particles. This emulates
-                    Gadget-[23] and GIZMO's default behaviours.
-  -e                Enable floating-point exceptions (debugging mode).
-  -f          {int} Overwrite the CPU frequency (Hz) to be used for time measurements.
-  -g                Run with an external gravitational potential.
-  -G                Run with self-gravity.
-  -M                Reconstruct the multipoles every time-step.
-  -n          {int} Execute a fixed number of time steps. When unset use the time_end parameter to stop.
-  -o          {str} Generate a default output parameter file.
-  -P  {sec:par:val} Set parameter value and overwrites values read from the parameters file. Can be used more than once.
-  -r                Continue using restart files.
-  -s                Run with hydrodynamics.
-  -S                Run with stars.
-  -b                Run with stars feedback.
-  -t          {int} The number of threads to use on each MPI rank. Defaults to 1 if not specified.
-  -T                Print timers every time-step.
-  -v           [12] Increase the level of verbosity:
-                    1: MPI-rank 0 writes,
-                    2: All MPI-ranks write.
-  -x                Run with structure finding.
-  -y          {int} Time-step frequency at which task graphs are dumped.
-  -Y          {int} Time-step frequency at which threadpool tasks are dumped.
-  -h                Print this help message and exit.
-
-See the file parameter_example.yml for an example of parameter file.
+Usage: swift [options] [[--] param-file]
+   or: swift [options] param-file
+   or: swift_mpi [options] [[--] param-file]
+   or: swift_mpi [options] param-file
 
+Parameters:
+
+    -h, --help                        show this help message and exit
+
+  Simulation options:
+    -b, --feedback                    Run with stars feedback
+    -c, --cosmology                   Run with cosmological time integration.
+    -C, --cooling                     Run with cooling
+    -D, --drift-all                   Always drift all particles even the ones
+                                      far from active particles. This emulates
+                                      Gadget-[23] and GIZMO's default behaviours.
+    -F, --sourceterms
+    -g, --external-gravity            Run with an external gravitational potential.
+    -G, --self-gravity                Run with self-gravity.
+    -M, --multipole-reconstruction    Reconstruct the multipoles every time-step.
+    -s, --hydro                       Run with hydrodynamics.
+    -S, --stars                       Run with stars
+    -x, --velociraptor                Run with structure finding
+
+  Control options:
+    -a, --pin                         Pin runners using processor affinity.
+    -d, --dry-run                     Dry run. Read the parameter file, allocates
+                                      memory but does not read the particles
+                                      from ICs. Exits before the start of time
+                                      integration. Checks the validity of
+                                      parameters and IC files as well as memory
+                                      limits.
+    -e, --fpe                         Enable floating-point exceptions (debugging
+                                      mode).
+    -f, --cpu-frequency=<str>         Overwrite the CPU frequency (Hz) to be
+                                      used for time measurements.
+    -n, --steps=<int>                 Execute a fixed number of time steps.
+                                      When unset use the time_end parameter
+                                      to stop.
+    -o, --output-params=<str>         Generate a default output parameter
+                                      file.
+    -P, --param=<str>                 Set parameter value, overiding the value
+                                      read from the parameter file. Can be used
+                                      more than once {sec:par:value}.
+    -r, --restart                     Continue using restart files.
+    -t, --threads=<int>               The number of threads to use on each MPI
+                                      rank. Defaults to 1 if not specified.
+    -T, --timers=<int>                Print timers every time-step.
+    -v, --verbose=<int>               Run in verbose mode, in MPI mode 2 outputs
+                                      from all ranks.
+    -y, --task-dumps=<int>            Time-step frequency at which task graphs
+                                      are dumped.
+    -Y, --threadpool-dumps=<int>      Time-step frequency at which threadpool
+                                      tasks are dumped.
+
+See the file examples/parameter_example.yml for an example of parameter file.
diff --git a/README.md b/README.md
index 25f8e14b5b881149270a7e7b8a14ffe9535149ef..94e95776cd80c1bb822f0f68290c2add9d2bb58b 100644
--- a/README.md
+++ b/README.md
@@ -49,9 +49,9 @@ are highly encouraged.
  Welcome to the cosmological hydrodynamical code
     ______       _________________
    / ___/ |     / /  _/ ___/_  __/
-   \__ \| | /| / // // /_   / /   
-  ___/ /| |/ |/ // // __/  / /    
- /____/ |__/|__/___/_/    /_/     
+   \__ \| | /| / // // /_   / /
+  ___/ /| |/ |/ // // __/  / /
+ /____/ |__/|__/___/_/    /_/
  SPH With Inter-dependent Fine-grained Tasking
 
  Website: www.swiftsim.com
@@ -59,38 +59,59 @@ are highly encouraged.
 
 See INSTALL.swift for install instructions.
 
-Usage: swift [OPTION]... PARAMFILE
-       swift_mpi [OPTION]... PARAMFILE
-
-Valid options are:
-  -a                Pin runners using processor affinity.
-  -c                Run with cosmological time integration.
-  -C                Run with cooling.
-  -d                Dry run. Read the parameter file, allocate memory but does not read
-                    the particles from ICs and exit before the start of time integration.
-                    Allows user to check validity of parameter and IC files as well as memory limits.
-  -D                Always drift all particles even the ones far from active particles. This emulates
-                    Gadget-[23] and GIZMO's default behaviours.
-  -e                Enable floating-point exceptions (debugging mode).
-  -f          {int} Overwrite the CPU frequency (Hz) to be used for time measurements.
-  -g                Run with an external gravitational potential.
-  -G                Run with self-gravity.
-  -M                Reconstruct the multipoles every time-step.
-  -n          {int} Execute a fixed number of time steps. When unset use the time_end parameter to stop.
-  -o          {str} Generate a default output parameter file.
-  -P  {sec:par:val} Set parameter value and overwrites values read from the parameters file. Can be used more than once.
-  -r                Continue using restart files.
-  -s                Run with hydrodynamics.
-  -S                Run with stars.
-  -t          {int} The number of threads to use on each MPI rank. Defaults to 1 if not specified.
-  -T                Print timers every time-step.
-  -v           [12] Increase the level of verbosity:
-                    1: MPI-rank 0 writes,
-                    2: All MPI-ranks write.
-  -x                Run with structure finding.
-  -y          {int} Time-step frequency at which task graphs are dumped.
-  -Y          {int} Time-step frequency at which threadpool tasks are dumped.
-  -h                Print this help message and exit.
+Usage: swift [options] [[--] param-file]
+   or: swift [options] param-file
+   or: swift_mpi [options] [[--] param-file]
+   or: swift_mpi [options] param-file
+
+Parameters:
+
+    -h, --help                        show this help message and exit
+
+  Simulation options:
+    -b, --feedback                    Run with stars feedback
+    -c, --cosmology                   Run with cosmological time integration.
+    -C, --cooling                     Run with cooling
+    -D, --drift-all                   Always drift all particles even the ones
+                                      far from active particles. This emulates
+                                      Gadget-[23] and GIZMO's default behaviours.
+    -F, --sourceterms
+    -g, --external-gravity            Run with an external gravitational potential.
+    -G, --self-gravity                Run with self-gravity.
+    -M, --multipole-reconstruction    Reconstruct the multipoles every time-step.
+    -s, --hydro                       Run with hydrodynamics.
+    -S, --stars                       Run with stars
+    -x, --velociraptor                Run with structure finding
+
+  Control options:
+    -a, --pin                         Pin runners using processor affinity.
+    -d, --dry-run                     Dry run. Read the parameter file, allocates
+                                      memory but does not read the particles
+                                      from ICs. Exits before the start of time
+                                      integration. Checks the validity of
+                                      parameters and IC files as well as memory
+                                      limits.
+    -e, --fpe                         Enable floating-point exceptions (debugging
+                                      mode).
+    -f, --cpu-frequency=<str>         Overwrite the CPU frequency (Hz) to be
+                                      used for time measurements.
+    -n, --steps=<int>                 Execute a fixed number of time steps.
+                                      When unset use the time_end parameter
+                                      to stop.
+    -o, --output-params=<str>         Generate a default output parameter
+                                      file.
+    -P, --param=<str>                 Set parameter value, overiding the value
+                                      read from the parameter file. Can be used
+                                      more than once {sec:par:value}.
+    -r, --restart                     Continue using restart files.
+    -t, --threads=<int>               The number of threads to use on each MPI
+                                      rank. Defaults to 1 if not specified.
+    -T, --timers=<int>                Print timers every time-step.
+    -v, --verbose=<int>               Run in verbose mode, in MPI mode 2 outputs
+                                      from all ranks.
+    -y, --task-dumps=<int>            Time-step frequency at which task graphs
+                                      are dumped.
+    -Y, --threadpool-dumps=<int>      Time-step frequency at which threadpool
+                                      tasks are dumped.
 
 See the file examples/parameter_example.yml for an example of parameter file.
-```
diff --git a/argparse/FAQs.md b/argparse/FAQs.md
new file mode 100644
index 0000000000000000000000000000000000000000..c760807070b192c33e624e3f98af4cd24fe16fca
--- /dev/null
+++ b/argparse/FAQs.md
@@ -0,0 +1,36 @@
+# FAQs
+
+## Why removing parsed command-line switches/options?
+
+It destroys the original `argv` array, not compatible with other arguments parsing
+library.
+
+This is because this library is used for short-lived programs, e.g. cli tools
+at beginning. It's very convenient to process remain arguments if we remove
+parsed command-line arguments,  e.g. `<comamnd> [-[s]|--switch]... arguments`.
+
+If you want keep original `argc/argv`, you can make a copy, then pass them to
+`argparse_parse`, e.g.
+
+```c
+int copy_argc          = argc;
+const char **copy_argv = argv;
+copy_argv  = malloc(copy_argc * sizeof(char *));
+for (int i = 0; i < argc; i++) {
+	copy_argv[i] = (char *)argv[i];
+}   
+argparse_parse(&argparse, copy_argc, copy_argv);
+```
+
+Issues:
+
+- https://github.com/cofyc/argparse/issues/3
+- https://github.com/cofyc/argparse/issues/9
+
+## Why using `intptr_t` to hold associated data? Why not `void *`?
+
+I choose `intptr_t` because it's a integer type which also can be used to hold
+a pointer value.  Most of the time, we only need a integer to hold
+user-provided value, see `OPT_BIT` as example. If you want to provide a pointer
+which points to a large amount of data, you can cast it to `intptr_t` and cast
+it back to original pointer in callback function.
diff --git a/argparse/LICENSE b/argparse/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..3c777497645ca9998899db5d8a8041e9831a4604
--- /dev/null
+++ b/argparse/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2012-2013 Yecheng Fu <cofyc.jackson@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/argparse/Makefile.am b/argparse/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..2fa6fb9e9ef4c014697a2c434cd86741cc74d79c
--- /dev/null
+++ b/argparse/Makefile.am
@@ -0,0 +1,28 @@
+# This file is part of SWIFT.
+# Copyright (c) 2018 Peter W. Draper (p.w.draper@durham.ac.uk)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+lib_LTLIBRARIES = libargparse.la
+
+include_HEADERS = argparse.h
+
+AM_SOURCES = argparse.c
+
+# Sources and flags for regular library
+libargparse_la_SOURCES = $(AM_SOURCES)
+libargparse_la_CFLAGS = $(AM_CFLAGS)
+libargparse_la_LDFLAGS = $(AM_LDFLAGS)
+
+EXTRA_DIST = LICENSE README.md
diff --git a/argparse/OWNERS b/argparse/OWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..8cad69dd488010bcaa66ed80d5e3d425f647064c
--- /dev/null
+++ b/argparse/OWNERS
@@ -0,0 +1,2 @@
+approvers:
+- cofyc
diff --git a/argparse/README.md b/argparse/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ddf66b4777e9baaf68be270df3e8994cb96a2998
--- /dev/null
+++ b/argparse/README.md
@@ -0,0 +1,103 @@
+# argparse [![Build Status](https://travis-ci.org/cofyc/argparse.png)](https://travis-ci.org/cofyc/argparse)
+
+argparse - A command line arguments parsing library in C (compatible with C++).
+
+## Description
+
+This module is inspired by parse-options.c (git) and python's argparse
+module.
+
+Arguments parsing is common task in cli program, but traditional `getopt`
+libraries are not easy to use. This library provides high-level arguments
+parsing solutions.
+
+The program defines what arguments it requires, and `argparse` will figure
+out how to parse those out of `argc` and `argv`, it also automatically
+generates help and usage messages and issues errors when users give the
+program invalid arguments.
+
+## Features
+
+ - handles both optional and positional arguments
+ - produces highly informative usage messages
+ - issues errors when given invalid arguments
+
+There are basically three types of options:
+
+ - boolean options
+ - options with mandatory argument
+ - options with optional argument
+
+There are basically two forms of options:
+
+ - short option consist of one dash (`-`) and one alphanumeric character.
+ - long option begin with two dashes (`--`) and some alphanumeric characters.
+
+Short options may be bundled, e.g. `-a -b` can be specified as `-ab`.
+
+Options are case-sensitive.
+
+Options and non-option arguments can clearly be separated using the `--` option.
+
+## Examples
+
+```c
+#include "argparse.h"
+
+static const char *const usage[] = {
+    "test_argparse [options] [[--] args]",
+    "test_argparse [options]",
+    NULL,
+};
+
+#define PERM_READ  (1<<0)
+#define PERM_WRITE (1<<1)
+#define PERM_EXEC  (1<<2)
+
+int
+main(int argc, const char **argv)
+{
+    int force = 0;
+    int test = 0;
+    int num = 0;
+    const char *path = NULL;
+    int perms = 0;
+    struct argparse_option options[] = {
+        OPT_HELP(),
+        OPT_GROUP("Basic options"),
+        OPT_BOOLEAN('f', "force", &force, "force to do"),
+        OPT_BOOLEAN('t', "test", &test, "test only"),
+        OPT_STRING('p', "path", &path, "path to read"),
+        OPT_INTEGER('n', "num", &num, "selected num"),
+        OPT_GROUP("Bits options"),
+        OPT_BIT(0, "read", &perms, "read perm", NULL, PERM_READ, OPT_NONEG),
+        OPT_BIT(0, "write", &perms, "write perm", NULL, PERM_WRITE),
+        OPT_BIT(0, "exec", &perms, "exec perm", NULL, PERM_EXEC),
+        OPT_END(),
+    };
+
+    struct argparse argparse;
+    argparse_init(&argparse, options, usage, 0);
+    argparse_describe(&argparse, "\nA brief description of what the program does and how it works.", "\nAdditional description of the program after the description of the arguments.");
+    argc = argparse_parse(&argparse, argc, argv);
+    if (force != 0)
+        printf("force: %d\n", force);
+    if (test != 0)
+        printf("test: %d\n", test);
+    if (path != NULL)
+        printf("path: %s\n", path);
+    if (num != 0)
+        printf("num: %d\n", num);
+    if (argc != 0) {
+        printf("argc: %d\n", argc);
+        int i;
+        for (i = 0; i < argc; i++) {
+            printf("argv[%d]: %s\n", i, *(argv + i));
+        }
+    }
+    if (perms) {
+        printf("perms: %d\n", perms);
+    }
+    return 0;
+}
+```
diff --git a/argparse/argparse.c b/argparse/argparse.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb6c8c0c0012964090ff3676bcb02d0f5139d22a
--- /dev/null
+++ b/argparse/argparse.c
@@ -0,0 +1,379 @@
+/**
+ * Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
+ * All rights reserved.
+ *
+ * Use of this source code is governed by a MIT-style license that can be found
+ * in the LICENSE file.
+ */
+#include "argparse.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define OPT_UNSET 1
+#define OPT_LONG (1 << 1)
+
+static const char *prefix_skip(const char *str, const char *prefix) {
+  size_t len = strlen(prefix);
+  return strncmp(str, prefix, len) ? NULL : str + len;
+}
+
+static int prefix_cmp(const char *str, const char *prefix) {
+  for (;; str++, prefix++)
+    if (!*prefix) {
+      return 0;
+    } else if (*str != *prefix) {
+      return (unsigned char)*prefix - (unsigned char)*str;
+    }
+}
+
+static void argparse_error(struct argparse *self,
+                           const struct argparse_option *opt,
+                           const char *reason, int flags) {
+  (void)self;
+  if (flags & OPT_LONG) {
+    fprintf(stderr, "error: option `--%s` %s\n", opt->long_name, reason);
+  } else {
+    fprintf(stderr, "error: option `-%c` %s\n", opt->short_name, reason);
+  }
+  exit(1);
+}
+
+static int argparse_getvalue(struct argparse *self,
+                             const struct argparse_option *opt, int flags) {
+  const char *s = NULL;
+  if (!opt->value) goto skipped;
+  switch (opt->type) {
+    case ARGPARSE_OPT_BOOLEAN:
+      if (flags & OPT_UNSET) {
+        *(int *)opt->value = *(int *)opt->value - 1;
+      } else {
+        *(int *)opt->value = *(int *)opt->value + 1;
+      }
+      if (*(int *)opt->value < 0) {
+        *(int *)opt->value = 0;
+      }
+      break;
+    case ARGPARSE_OPT_BIT:
+      if (flags & OPT_UNSET) {
+        *(int *)opt->value &= ~opt->data;
+      } else {
+        *(int *)opt->value |= opt->data;
+      }
+      break;
+    case ARGPARSE_OPT_STRING:
+      if (self->optvalue) {
+        *(const char **)opt->value = self->optvalue;
+        self->optvalue = NULL;
+      } else if (self->argc > 1) {
+        self->argc--;
+        *(const char **)opt->value = *++self->argv;
+      } else {
+        argparse_error(self, opt, "requires a value", flags);
+      }
+      break;
+    case ARGPARSE_OPT_INTEGER:
+      errno = 0;
+      if (self->optvalue) {
+        *(int *)opt->value = strtol(self->optvalue, (char **)&s, 0);
+        self->optvalue = NULL;
+      } else if (self->argc > 1) {
+        self->argc--;
+        *(int *)opt->value = strtol(*++self->argv, (char **)&s, 0);
+      } else {
+        argparse_error(self, opt, "requires a value", flags);
+      }
+      if (errno) argparse_error(self, opt, strerror(errno), flags);
+      if (s[0] != '\0')
+        argparse_error(self, opt, "expects an integer value", flags);
+      break;
+    case ARGPARSE_OPT_FLOAT:
+      errno = 0;
+      if (self->optvalue) {
+        *(float *)opt->value = strtof(self->optvalue, (char **)&s);
+        self->optvalue = NULL;
+      } else if (self->argc > 1) {
+        self->argc--;
+        *(float *)opt->value = strtof(*++self->argv, (char **)&s);
+      } else {
+        argparse_error(self, opt, "requires a value", flags);
+      }
+      if (errno) argparse_error(self, opt, strerror(errno), flags);
+      if (s[0] != '\0')
+        argparse_error(self, opt, "expects a numerical value", flags);
+      break;
+    default:
+      assert(0);
+  }
+
+skipped:
+  if (opt->callback) {
+    return opt->callback(self, opt);
+  }
+
+  return 0;
+}
+
+static void argparse_options_check(const struct argparse_option *options) {
+  for (; options->type != ARGPARSE_OPT_END; options++) {
+    switch (options->type) {
+      case ARGPARSE_OPT_END:
+      case ARGPARSE_OPT_BOOLEAN:
+      case ARGPARSE_OPT_BIT:
+      case ARGPARSE_OPT_INTEGER:
+      case ARGPARSE_OPT_FLOAT:
+      case ARGPARSE_OPT_STRING:
+      case ARGPARSE_OPT_GROUP:
+        continue;
+      default:
+        fprintf(stderr, "wrong option type: %d", options->type);
+        break;
+    }
+  }
+}
+
+static int argparse_short_opt(struct argparse *self,
+                              const struct argparse_option *options) {
+  for (; options->type != ARGPARSE_OPT_END; options++) {
+    if (options->short_name == *self->optvalue) {
+      self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL;
+      return argparse_getvalue(self, options, 0);
+    }
+  }
+  return -2;
+}
+
+static int argparse_long_opt(struct argparse *self,
+                             const struct argparse_option *options) {
+  for (; options->type != ARGPARSE_OPT_END; options++) {
+    const char *rest;
+    int opt_flags = 0;
+    if (!options->long_name) continue;
+
+    rest = prefix_skip(self->argv[0] + 2, options->long_name);
+    if (!rest) {
+      // negation disabled?
+      if (options->flags & OPT_NONEG) {
+        continue;
+      }
+      // only OPT_BOOLEAN/OPT_BIT supports negation
+      if (options->type != ARGPARSE_OPT_BOOLEAN &&
+          options->type != ARGPARSE_OPT_BIT) {
+        continue;
+      }
+
+      if (prefix_cmp(self->argv[0] + 2, "no-")) {
+        continue;
+      }
+      rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name);
+      if (!rest) continue;
+      opt_flags |= OPT_UNSET;
+    }
+    if (*rest) {
+      if (*rest != '=') continue;
+      self->optvalue = rest + 1;
+    }
+    return argparse_getvalue(self, options, opt_flags | OPT_LONG);
+  }
+  return -2;
+}
+
+int argparse_init(struct argparse *self, struct argparse_option *options,
+                  const char *const *usages, int flags) {
+  memset(self, 0, sizeof(*self));
+  self->options = options;
+  self->usages = usages;
+  self->flags = flags;
+  self->description = NULL;
+  self->epilog = NULL;
+  return 0;
+}
+
+void argparse_describe(struct argparse *self, const char *description,
+                       const char *epilog) {
+  self->description = description;
+  self->epilog = epilog;
+}
+
+int argparse_parse(struct argparse *self, int argc, const char **argv) {
+  self->argc = argc - 1;
+  self->argv = argv + 1;
+  self->out = argv;
+
+  argparse_options_check(self->options);
+
+  for (; self->argc; self->argc--, self->argv++) {
+    const char *arg = self->argv[0];
+    if (arg[0] != '-' || !arg[1]) {
+      if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) {
+        goto end;
+      }
+      // if it's not option or is a single char '-', copy verbatim
+      self->out[self->cpidx++] = self->argv[0];
+      continue;
+    }
+    // short option
+    if (arg[1] != '-') {
+      self->optvalue = arg + 1;
+      switch (argparse_short_opt(self, self->options)) {
+        case -1:
+          break;
+        case -2:
+          goto unknown;
+      }
+      while (self->optvalue) {
+        switch (argparse_short_opt(self, self->options)) {
+          case -1:
+            break;
+          case -2:
+            goto unknown;
+        }
+      }
+      continue;
+    }
+    // if '--' presents
+    if (!arg[2]) {
+      self->argc--;
+      self->argv++;
+      break;
+    }
+    // long option
+    switch (argparse_long_opt(self, self->options)) {
+      case -1:
+        break;
+      case -2:
+        goto unknown;
+    }
+    continue;
+
+  unknown:
+    fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]);
+    argparse_usage(self);
+    exit(1);
+  }
+
+end:
+  memmove(self->out + self->cpidx, self->argv, self->argc * sizeof(*self->out));
+  self->out[self->cpidx + self->argc] = NULL;
+
+  return self->cpidx + self->argc;
+}
+
+void argparse_usage(struct argparse *self) {
+  if (self->usages) {
+    fprintf(stdout, "Usage: %s\n", *self->usages++);
+    while (*self->usages && **self->usages)
+      fprintf(stdout, "   or: %s\n", *self->usages++);
+  } else {
+    fprintf(stdout, "Usage:\n");
+  }
+
+  // print description
+  if (self->description) fprintf(stdout, "%s\n", self->description);
+
+  fputc('\n', stdout);
+
+  const struct argparse_option *options;
+
+  // figure out best width
+  size_t usage_opts_width = 0;
+  size_t len;
+  options = self->options;
+  for (; options->type != ARGPARSE_OPT_END; options++) {
+    len = 0;
+    if ((options)->short_name) {
+      len += 2;
+    }
+    if ((options)->short_name && (options)->long_name) {
+      len += 2;  // separator ", "
+    }
+    if ((options)->long_name) {
+      len += strlen((options)->long_name) + 2;
+    }
+    if (options->type == ARGPARSE_OPT_INTEGER) {
+      len += strlen("=<int>");
+    }
+    if (options->type == ARGPARSE_OPT_FLOAT) {
+      len += strlen("=<flt>");
+    } else if (options->type == ARGPARSE_OPT_STRING) {
+      len += strlen("=<str>");
+    }
+    len = (len + 3) - ((len + 3) & 3);
+    if (usage_opts_width < len) {
+      usage_opts_width = len;
+    }
+  }
+  usage_opts_width += 4;  // 4 spaces prefix
+
+  options = self->options;
+  for (; options->type != ARGPARSE_OPT_END; options++) {
+    size_t pos = 0;
+    int pad = 0;
+    if (options->type == ARGPARSE_OPT_GROUP) {
+      fputc('\n', stdout);
+      fprintf(stdout, "%s", options->help);
+      fputc('\n', stdout);
+      continue;
+    }
+    pos = fprintf(stdout, "    ");
+    if (options->short_name) {
+      pos += fprintf(stdout, "-%c", options->short_name);
+    }
+    if (options->long_name && options->short_name) {
+      pos += fprintf(stdout, ", ");
+    }
+    if (options->long_name) {
+      pos += fprintf(stdout, "--%s", options->long_name);
+    }
+    if (options->type == ARGPARSE_OPT_INTEGER) {
+      pos += fprintf(stdout, "=<int>");
+    }
+    if (options->type == ARGPARSE_OPT_FLOAT) {
+      pos += fprintf(stdout, "=<flt>");
+    } else if (options->type == ARGPARSE_OPT_STRING) {
+      pos += fprintf(stdout, "=<str>");
+    }
+    if (pos <= usage_opts_width) {
+      pad = usage_opts_width - pos;
+    } else {
+      fputc('\n', stdout);
+      pad = usage_opts_width;
+    }
+    if (options->help != NULL && strlen(options->help) > 0) {
+      char *str = strdup(options->help);
+      char *token = strtok(str, " ");
+      fprintf(stdout, "%*s%s ", pad + 2, "", token);
+      int count = strlen(token);
+      int dangling = 1;
+      while ((token = strtok(NULL, " ")) != NULL) {
+        if (count == 0) {
+          fprintf(stdout, "%*s", (int)pos + pad + 2, "");
+          dangling = 1;
+        }
+        printf("%s ", token);
+        count += strlen(token);
+        if (count > 30) {
+          count = 0;
+          fprintf(stdout, "\n");
+          dangling = 0;
+        }
+      }
+      if (dangling) fprintf(stdout, "\n");
+      free(str);
+    } else {
+      fprintf(stdout, "\n");
+    }
+  }
+
+  // print epilog
+  if (self->epilog) fprintf(stdout, "%s\n", self->epilog);
+}
+
+int argparse_help_cb(struct argparse *self,
+                     const struct argparse_option *option) {
+  (void)option;
+  argparse_usage(self);
+  exit(0);
+}
diff --git a/argparse/argparse.h b/argparse/argparse.h
new file mode 100644
index 0000000000000000000000000000000000000000..186214b4bc90cea90ef141380bf0017cc50af128
--- /dev/null
+++ b/argparse/argparse.h
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
+ * All rights reserved.
+ *
+ * Use of this source code is governed by a MIT-style license that can be found
+ * in the LICENSE file.
+ */
+#ifndef ARGPARSE_H
+#define ARGPARSE_H
+
+/* For c++ compatibility */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+struct argparse;
+struct argparse_option;
+
+typedef int argparse_callback(struct argparse *self,
+                              const struct argparse_option *option);
+
+enum argparse_flag {
+  ARGPARSE_STOP_AT_NON_OPTION = 1,
+};
+
+enum argparse_option_type {
+  /* special */
+  ARGPARSE_OPT_END,
+  ARGPARSE_OPT_GROUP,
+  /* options with no arguments */
+  ARGPARSE_OPT_BOOLEAN,
+  ARGPARSE_OPT_BIT,
+  /* options with arguments (optional or required) */
+  ARGPARSE_OPT_INTEGER,
+  ARGPARSE_OPT_FLOAT,
+  ARGPARSE_OPT_STRING,
+};
+
+enum argparse_option_flags {
+  OPT_NONEG = 1, /* disable negation */
+};
+
+/**
+ *  argparse option
+ *
+ *  `type`:
+ *    holds the type of the option, you must have an ARGPARSE_OPT_END last in
+ * your array.
+ *
+ *  `short_name`:
+ *    the character to use as a short option name, '\0' if none.
+ *
+ *  `long_name`:
+ *    the long option name, without the leading dash, NULL if none.
+ *
+ *  `value`:
+ *    stores pointer to the value to be filled.
+ *
+ *  `help`:
+ *    the short help message associated to what the option does.
+ *    Must never be NULL (except for ARGPARSE_OPT_END).
+ *
+ *  `callback`:
+ *    function is called when corresponding argument is parsed.
+ *
+ *  `data`:
+ *    associated data. Callbacks can use it like they want.
+ *
+ *  `flags`:
+ *    option flags.
+ */
+struct argparse_option {
+  enum argparse_option_type type;
+  const char short_name;
+  const char *long_name;
+  void *value;
+  const char *help;
+  argparse_callback *callback;
+  intptr_t data;
+  int flags;
+};
+
+/**
+ * argpparse
+ */
+struct argparse {
+  // user supplied
+  const struct argparse_option *options;
+  const char *const *usages;
+  int flags;
+  const char *description;  // a description after usage
+  const char *epilog;       // a description at the end
+  // internal context
+  int argc;
+  const char **argv;
+  const char **out;
+  int cpidx;
+  const char *optvalue;  // current option value
+};
+
+// built-in callbacks
+int argparse_help_cb(struct argparse *self,
+                     const struct argparse_option *option);
+
+// built-in option macros
+#define OPT_END() \
+  { ARGPARSE_OPT_END, 0, NULL, NULL, 0, NULL, 0, 0 }
+#define OPT_BOOLEAN(...) \
+  { ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ }
+#define OPT_BIT(...) \
+  { ARGPARSE_OPT_BIT, __VA_ARGS__ }
+#define OPT_INTEGER(...) \
+  { ARGPARSE_OPT_INTEGER, __VA_ARGS__ }
+#define OPT_FLOAT(...) \
+  { ARGPARSE_OPT_FLOAT, __VA_ARGS__ }
+#define OPT_STRING(...) \
+  { ARGPARSE_OPT_STRING, __VA_ARGS__ }
+#define OPT_GROUP(h) \
+  { ARGPARSE_OPT_GROUP, 0, NULL, NULL, h, NULL, 0, 0 }
+#define OPT_HELP()                                                  \
+  OPT_BOOLEAN('h', "help", NULL, "show this help message and exit", \
+              argparse_help_cb, 0, 0)
+
+int argparse_init(struct argparse *self, struct argparse_option *options,
+                  const char *const *usages, int flags);
+void argparse_describe(struct argparse *self, const char *description,
+                       const char *epilog);
+int argparse_parse(struct argparse *self, int argc, const char **argv);
+void argparse_usage(struct argparse *self);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/argparse/tap-functions b/argparse/tap-functions
new file mode 100644
index 0000000000000000000000000000000000000000..84f700e644c0c09246ca747ce5c22cc884dfff6c
--- /dev/null
+++ b/argparse/tap-functions
@@ -0,0 +1,445 @@
+#!/bin/bash 
+
+
+_version='1.02'
+	
+_plan_set=0
+_no_plan=0
+_skip_all=0
+_test_died=0
+_expected_tests=0 
+_executed_tests=0 
+_failed_tests=0
+TODO=
+
+
+usage(){
+	cat <<'USAGE'
+tap-functions: A TAP-producing BASH library
+
+PLAN:
+  plan_no_plan
+  plan_skip_all [REASON]
+  plan_tests NB_TESTS
+
+TEST:
+  ok RESULT [NAME]
+  okx COMMAND
+  is RESULT EXPECTED [NAME]
+  isnt RESULT EXPECTED [NAME]
+  like RESULT PATTERN [NAME]
+  unlike RESULT PATTERN [NAME]
+  pass [NAME]
+  fail [NAME]
+
+SKIP:
+  skip [CONDITION] [REASON] [NB_TESTS=1]
+
+  skip $feature_not_present "feature not present" 2 || {
+      is $a "a"
+      is $b "b"
+  }
+
+TODO:
+  Specify TODO mode by setting $TODO:
+    TODO="not implemented yet"
+    ok $result "some not implemented test"
+    unset TODO
+
+OTHER:
+  diag MSG
+
+EXAMPLE:
+  #!/bin/bash
+
+  . tap-functions
+
+  plan_tests 7
+
+  me=$USER
+  is $USER $me "I am myself"
+  like $HOME $me "My home is mine"
+  like "`id`" $me "My id matches myself"
+
+  /bin/ls $HOME 1>&2
+  ok $? "/bin/ls $HOME"
+  # Same thing using okx shortcut
+  okx /bin/ls $HOME
+
+  [[ "`id -u`" != "0" ]]
+  i_am_not_root=$?
+  skip $i_am_not_root "Must be root" || {
+    okx ls /root
+  }
+
+  TODO="figure out how to become root..."
+  okx [ "$HOME" == "/root" ]
+  unset TODO
+USAGE
+	exit
+}
+
+opt=
+set_u=
+while getopts ":sx" opt ; do
+	case $_opt in
+        u) set_u=1 ;;
+        *) usage ;;
+    esac
+done
+shift $(( OPTIND - 1 ))
+# Don't allow uninitialized variables if requested
+[[ -n "$set_u" ]] && set -u
+unset opt set_u
+
+# Used to call _cleanup on shell exit
+trap _exit EXIT
+
+
+
+plan_no_plan(){
+	(( _plan_set != 0 )) && "You tried to plan twice!"
+
+	_plan_set=1
+	_no_plan=1
+
+	return 0
+}
+
+
+plan_skip_all(){
+	local reason=${1:-''}
+
+	(( _plan_set != 0 )) && _die "You tried to plan twice!"
+
+	_print_plan 0 "Skip $reason"
+
+	_skip_all=1
+	_plan_set=1
+	_exit 0
+
+	return 0
+}
+
+
+plan_tests(){
+	local tests=${1:?}
+
+	(( _plan_set != 0 )) && _die "You tried to plan twice!"
+	(( tests == 0 )) && _die "You said to run 0 tests!  You've got to run something."
+
+	_print_plan $tests
+	_expected_tests=$tests
+	_plan_set=1
+
+	return $tests
+}
+
+
+_print_plan(){
+	local tests=${1:?}
+	local directive=${2:-''}
+
+	echo -n "1..$tests"
+	[[ -n "$directive" ]] && echo -n " # $directive"
+	echo
+}
+
+
+pass(){
+	local name=$1
+	ok 0 "$name"
+}
+
+
+fail(){
+	local name=$1
+	ok 1 "$name"
+}
+
+
+# This is the workhorse method that actually
+# prints the tests result.
+ok(){
+	local result=${1:?}
+	local name=${2:-''}
+
+	(( _plan_set == 0 )) && _die "You tried to run a test without a plan!  Gotta have a plan."
+
+	_executed_tests=$(( $_executed_tests + 1 ))
+
+	if [[ -n "$name" ]] ; then
+		if _matches "$name" "^[0-9]+$" ; then
+			diag "    You named your test '$name'.  You shouldn't use numbers for your test names."
+			diag "    Very confusing."
+		fi
+	fi
+
+	if (( result != 0 )) ; then
+		echo -n "not "
+		_failed_tests=$(( _failed_tests + 1 ))
+	fi
+	echo -n "ok $_executed_tests"
+
+	if [[ -n "$name" ]] ; then
+		local ename=${name//\#/\\#}
+		echo -n " - $ename"
+	fi
+
+	if [[ -n "$TODO" ]] ; then
+		echo -n " # TODO $TODO" ;
+		if (( result != 0 )) ; then
+			_failed_tests=$(( _failed_tests - 1 ))
+		fi
+	fi
+
+	echo
+	if (( result != 0 )) ; then
+		local file='tap-functions'
+		local func=
+		local line=
+
+		local i=0
+		local bt=$(caller $i)
+		while _matches "$bt" "tap-functions$" ; do
+			i=$(( $i + 1 ))
+			bt=$(caller $i)
+		done
+		local backtrace=
+		eval $(caller $i | (read line func file ; echo "backtrace=\"$file:$func() at line $line.\""))
+			
+		local t=
+		[[ -n "$TODO" ]] && t="(TODO) "
+
+		if [[ -n "$name" ]] ; then
+			diag "  Failed ${t}test '$name'"
+			diag "  in $backtrace"
+		else
+			diag "  Failed ${t}test in $backtrace"
+		fi
+	fi
+
+	return $result
+}
+
+
+okx(){
+	local command="$@"
+
+	local line=
+	diag "Output of '$command':"
+	$command | while read line ; do
+		diag "$line"
+	done
+	ok ${PIPESTATUS[0]} "$command"
+}
+
+
+_equals(){
+	local result=${1:?}
+	local expected=${2:?}
+
+	if [[ "$result" == "$expected" ]] ; then
+		return 0
+	else 
+		return 1
+	fi
+}
+
+
+# Thanks to Aaron Kangas for the patch to allow regexp matching
+# under bash < 3.
+ _bash_major_version=${BASH_VERSION%%.*}
+_matches(){
+	local result=${1:?}
+	local pattern=${2:?}
+
+	if [[ -z "$result" || -z "$pattern" ]] ; then
+		return 1
+	else
+		if (( _bash_major_version >= 3 )) ; then
+			eval '[[ "$result" =~ "$pattern" ]]'
+		else
+			echo "$result" | egrep -q "$pattern"
+		fi
+	fi
+}
+
+
+_is_diag(){
+	local result=${1:?}
+	local expected=${2:?}
+
+	diag "         got: '$result'" 
+	diag "    expected: '$expected'"
+}
+
+
+is(){
+	local result=${1:?}
+	local expected=${2:?}
+	local name=${3:-''}
+
+	_equals "$result" "$expected"
+	(( $? == 0 ))
+	ok $? "$name"
+	local r=$?
+	(( r != 0 )) && _is_diag "$result" "$expected"
+	return $r 
+}
+
+
+isnt(){
+	local result=${1:?}
+	local expected=${2:?}
+	local name=${3:-''}
+
+	_equals "$result" "$expected"
+	(( $? != 0 ))
+	ok $? "$name"
+	local r=$?
+	(( r != 0 )) && _is_diag "$result" "$expected"
+	return $r 
+}
+
+
+like(){
+	local result=${1:?}
+	local pattern=${2:?}
+	local name=${3:-''}
+
+	_matches "$result" "$pattern"
+	(( $? == 0 ))
+	ok $? "$name"
+	local r=$?
+	(( r != 0 )) && diag "    '$result' doesn't match '$pattern'"
+	return $r
+}
+
+
+unlike(){
+	local result=${1:?}
+	local pattern=${2:?}
+	local name=${3:-''}
+
+	_matches "$result" "$pattern"
+	(( $? != 0 ))
+	ok $? "$name"
+	local r=$?
+	(( r != 0 )) && diag "    '$result' matches '$pattern'"
+	return $r
+}
+
+
+skip(){
+	local condition=${1:?}
+	local reason=${2:-''}
+	local n=${3:-1}
+
+	if (( condition == 0 )) ; then
+		local i=
+		for (( i=0 ; i<$n ; i++ )) ; do
+			_executed_tests=$(( _executed_tests + 1 ))
+			echo "ok $_executed_tests # skip: $reason" 
+		done
+		return 0
+	else
+		return
+	fi
+}
+
+
+diag(){
+	local msg=${1:?}
+
+	if [[ -n "$msg" ]] ; then
+		echo "# $msg"
+	fi
+	
+	return 1
+}
+
+	
+_die(){
+	local reason=${1:-'<unspecified error>'}
+
+	echo "$reason" >&2
+	_test_died=1
+	_exit 255
+}
+
+
+BAIL_OUT(){
+	local reason=${1:-''}
+
+	echo "Bail out! $reason" >&2
+	_exit 255
+}
+
+
+_cleanup(){
+	local rc=0
+
+	if (( _plan_set == 0 )) ; then
+		diag "Looks like your test died before it could output anything."
+		return $rc
+	fi
+
+	if (( _test_died != 0 )) ; then
+		diag "Looks like your test died just after $_executed_tests."
+		return $rc
+	fi
+
+	if (( _skip_all == 0 && _no_plan != 0 )) ; then
+		_print_plan $_executed_tests
+	fi
+
+	local s=
+	if (( _no_plan == 0 && _expected_tests < _executed_tests )) ; then
+		s= ; (( _expected_tests > 1 )) && s=s
+		local extra=$(( _executed_tests - _expected_tests ))
+		diag "Looks like you planned $_expected_tests test$s but ran $extra extra."
+		rc=-1 ;
+	fi
+
+	if (( _no_plan == 0 && _expected_tests > _executed_tests )) ; then
+		s= ; (( _expected_tests > 1 )) && s=s
+		diag "Looks like you planned $_expected_tests test$s but only ran $_executed_tests."
+	fi
+
+	if (( _failed_tests > 0 )) ; then
+		s= ; (( _failed_tests > 1 )) && s=s
+		diag "Looks like you failed $_failed_tests test$s of $_executed_tests."
+	fi
+
+	return $rc
+}
+
+
+_exit_status(){
+	if (( _no_plan != 0 || _plan_set == 0 )) ; then
+		return $_failed_tests
+	fi
+
+	if (( _expected_tests < _executed_tests )) ; then
+		return $(( _executed_tests - _expected_tests  ))
+	fi
+
+	return $(( _failed_tests + ( _expected_tests - _executed_tests )))
+}
+
+
+_exit(){
+	local rc=${1:-''}
+	if [[ -z "$rc" ]] ; then
+		_exit_status
+		rc=$?
+	fi
+
+	_cleanup
+	local alt_rc=$?
+	(( alt_rc != 0 )) && rc=$alt_rc
+	trap - EXIT
+	exit $rc
+}
+
diff --git a/argparse/test.sh b/argparse/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..192357d3cc43947593b1db50f2ff46b3092340e6
--- /dev/null
+++ b/argparse/test.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. tap-functions
+plan_no_plan
+
+is "$(./test_argparse -f --path=/path/to/file a 2>&1)" 'force: 1
+path: /path/to/file
+argc: 1
+argv[0]: a'
+
+is "$(./test_argparse -f -f --force --no-force 2>&1)" 'force: 2'
+
+is "$(./test_argparse -i 2>&1)" 'error: option `-i` requires a value'
+
+is "$(./test_argparse -i 2 2>&1)" 'int_num: 2'
+
+is "$(./test_argparse -i2 2>&1)" 'int_num: 2'
+
+is "$(./test_argparse -ia 2>&1)" 'error: option `-i` expects an integer value'
+
+is "$(./test_argparse -i 0xFFFFFFFFFFFFFFFFF 2>&1)" \
+   'error: option `-i` Numerical result out of range'
+
+is "$(./test_argparse -s 2.4 2>&1)" 'flt_num: 2.4'
+
+is "$(./test_argparse -s2.4 2>&1)" 'flt_num: 2.4'
+
+is "$(./test_argparse -sa 2>&1)" 'error: option `-s` expects a numerical value'
+
+is "$(./test_argparse -s 1e999 2>&1)" \
+   'error: option `-s` Numerical result out of range'
+
+is "$(./test_argparse -f -- do -f -h 2>&1)" 'force: 1
+argc: 3
+argv[0]: do
+argv[1]: -f
+argv[2]: -h'
+
+is "$(./test_argparse -tf 2>&1)" 'force: 1
+test: 1'
+
+is "$(./test_argparse --read --write 2>&1)" 'perms: 3'
+
+is "$(./test_argparse -h)" 'Usage: test_argparse [options] [[--] args]
+   or: test_argparse [options]
+
+A brief description of what the program does and how it works.
+
+    -h, --help            show this help message and exit
+
+Basic options
+    -f, --force           force to do
+    -t, --test            test only
+    -p, --path=<str>      path to read
+    -i, --int=<int>       selected integer
+    -s, --float=<flt>     selected float
+
+Bits options
+    --read                read perm
+    --write               write perm
+    --exec                exec perm
+
+Additional description of the program after the description of the arguments.'
diff --git a/argparse/test_argparse.c b/argparse/test_argparse.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f411833aafa603d085258f11b8bbb35ff1c6d39
--- /dev/null
+++ b/argparse/test_argparse.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "argparse.h"
+
+static const char *const usages[] = {
+    "test_argparse [options] [[--] args]",
+    "test_argparse [options]",
+    NULL,
+};
+
+#define PERM_READ (1 << 0)
+#define PERM_WRITE (1 << 1)
+#define PERM_EXEC (1 << 2)
+
+struct stuff {
+  const char *path[10];
+  int npath;
+};
+
+static int callback(struct argparse *self, const struct argparse_option *opt) {
+  printf("Called back... %s\n", *(char **)opt->value);
+  struct stuff *data = (struct stuff *)opt->data;
+  data->path[data->npath] = *(char **)opt->value;
+  data->npath++;
+  return 1;
+}
+
+int main(int argc, const char **argv) {
+  int force = 0;
+  int self_gravity = 0;
+  int int_num = 0;
+  float flt_num = 0.f;
+  struct stuff data;
+  data.npath = 0;
+  data.path[0] = NULL;
+  const char *buffer;
+  int perms = 0;
+  int npath;
+
+  struct argparse_option options[] = {
+      OPT_HELP(),
+      OPT_GROUP("Basic options"),
+      OPT_BOOLEAN('f', "force", &force, "force to do", NULL, 0, 0),
+      OPT_BOOLEAN(0, "self-gravity", &self_gravity, "use self gravity", NULL, 0,
+                  0),
+      OPT_STRING('P', "path", &buffer, "path to read", &callback,
+                 (intptr_t)&data, 0),
+      OPT_INTEGER('i', "int", &int_num, "selected integer", NULL, 0, 0),
+      OPT_FLOAT('s', "float", &flt_num, "selected float", NULL, 0, 0),
+      OPT_END(),
+  };
+
+  struct argparse argparse;
+  argparse_init(&argparse, options, usages, 0);
+  argparse_describe(
+      &argparse,
+      "\nA brief description of what the program does and how it works.",
+      "\nAdditional description of the program after the description of the "
+      "arguments.");
+  argc = argparse_parse(&argparse, argc, argv);
+  if (force != 0) printf("force: %d\n", force);
+  if (self_gravity != 0) printf("self_gravity: %d\n", self_gravity);
+  if (data.npath > 0) {
+    for (int i = 0; i < data.npath; i++) printf("path: %s\n", data.path[i]);
+  }
+  if (int_num != 0) printf("int_num: %d\n", int_num);
+  if (flt_num != 0) printf("flt_num: %g\n", flt_num);
+  if (argc != 0) {
+    printf("argc: %d\n", argc);
+    int i;
+    for (i = 0; i < argc; i++) {
+      printf("argv[%d]: %s\n", i, *(argv + i));
+    }
+  }
+  if (perms) {
+    printf("perms: %d\n", perms);
+  }
+  return 0;
+}
diff --git a/configure.ac b/configure.ac
index c12ea7a51973e4aa495a5809d2687961bacda585..6f1412c04dc4a67bd1beb8c35c1975ae6b3920f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1579,7 +1579,7 @@ AM_CONDITIONAL([HAVE_DOXYGEN], [test "$ac_cv_path_ac_pt_DX_DOXYGEN" != ""])
 
 # Handle .in files.
 AC_CONFIG_FILES([Makefile src/Makefile examples/Makefile doc/Makefile doc/Doxyfile tests/Makefile])
-AC_CONFIG_FILES([tools/Makefile])
+AC_CONFIG_FILES([argparse/Makefile tools/Makefile])
 AC_CONFIG_FILES([tests/testReading.sh], [chmod +x tests/testReading.sh])
 AC_CONFIG_FILES([tests/testActivePair.sh], [chmod +x tests/testActivePair.sh])
 AC_CONFIG_FILES([tests/test27cells.sh], [chmod +x tests/test27cells.sh])
diff --git a/doc/RTD/source/CommandLineOptions/index.rst b/doc/RTD/source/CommandLineOptions/index.rst
index a8ce7af082fd7b2bf3ec285b5bb0b2b5bb509401..9fb9d784d6057e4d9aa4a923143d622e577f142c 100644
--- a/doc/RTD/source/CommandLineOptions/index.rst
+++ b/doc/RTD/source/CommandLineOptions/index.rst
@@ -11,33 +11,52 @@ For instance, just running the ``swift`` binary will not use any SPH or gravity;
 the particles will just sit still!
 
 Below is a list of the command line options and when they should be used. The same list
-can be found by typing ``./swift -h``.
+can be found by typing ``./swift -h``::
 
-+ ``-a``: Pin runners using processor affinity.
-+ ``-c``: Run with cosmological time integration.
-+ ``-C``: Run with cooling.
-+ ``-d``: Dry run. Read the parameter file, allocate memory but does not read
-  the particles from ICs and exit before the start of time integration. Allows
-  user to check validity of parameter and IC files as well as memory limits.
-+ ``-D``: Always drift all particles even the ones far from active particles.
-  This emulates Gadget-[23] and GIZMO's default behaviours.
-+ ``-e``: Enable floating-point exceptions (debugging mode).
-+ ``-f``: {int} Overwrite the CPU frequency (Hz) to be used for time measurements.
-+ ``-g``: Run with an external gravitational potential.
-+ ``-G``: Run with self-gravity.
-+ ``-M``: Reconstruct the multipoles every time-step.
-+ ``-n``: {int} Execute a fixed number of time steps. When unset use the
-  time_end parameter to stop.
-+ ``-o``: {str} Generate a default output parameter file.
-+ ``-P``: {sec:par:val} Set parameter value and overwrites values read from the
-  parameters file. Can be used more than once.
-+ ``-s``: Run with hydrodynamics.
-+ ``-S``: Run with stars.
-+ ``-t``: {int} The number of threads to use on each MPI rank. Defaults to 1 if
-  not specified.
-+ ``-T``: Print timers every time-step.
-+ ``-v``: [12] Increase the level of verbosity: 1, MPI-rank 0 writes, 2, All
-  MPI-ranks write.
-+ ``-y``: {int} Time-step frequency at which task graphs are dumped.
-+ ``-Y``: {int} Time-step frequency at which threadpool tasks are dumped.
-+ ``-h``: Print a help message and exit.
+    -h, --help                        show this help message and exit
+
+  Simulation options:
+    -b, --feedback                    Run with stars feedback
+    -c, --cosmology                   Run with cosmological time integration.
+    -C, --cooling                     Run with cooling
+    -D, --drift-all                   Always drift all particles even the ones
+                                      far from active particles. This emulates
+                                      Gadget-[23] and GIZMO's default behaviours.
+    -F, --sourceterms
+    -g, --external-gravity            Run with an external gravitational potential.
+    -G, --self-gravity                Run with self-gravity.
+    -M, --multipole-reconstruction    Reconstruct the multipoles every time-step.
+    -s, --hydro                       Run with hydrodynamics.
+    -S, --stars                       Run with stars
+    -x, --velociraptor                Run with structure finding
+
+  Control options:
+    -a, --pin                         Pin runners using processor affinity.
+    -d, --dry-run                     Dry run. Read the parameter file, allocates
+                                      memory but does not read the particles
+                                      from ICs. Exits before the start of time
+                                      integration. Checks the validity of
+                                      parameters and IC files as well as memory
+                                      limits.
+    -e, --fpe                         Enable floating-point exceptions (debugging
+                                      mode).
+    -f, --cpu-frequency=<str>         Overwrite the CPU frequency (Hz) to be
+                                      used for time measurements.
+    -n, --steps=<int>                 Execute a fixed number of time steps.
+                                      When unset use the time_end parameter
+                                      to stop.
+    -o, --output-params=<str>         Generate a default output parameter
+                                      file.
+    -P, --param=<str>                 Set parameter value, overiding the value
+                                      read from the parameter file. Can be used
+                                      more than once {sec:par:value}.
+    -r, --restart                     Continue using restart files.
+    -t, --threads=<int>               The number of threads to use on each MPI
+                                      rank. Defaults to 1 if not specified.
+    -T, --timers=<int>                Print timers every time-step.
+    -v, --verbose=<int>               Run in verbose mode, in MPI mode 2 outputs
+                                      from all ranks.
+    -y, --task-dumps=<int>            Time-step frequency at which task graphs
+                                      are dumped.
+    -Y, --threadpool-dumps=<int>      Time-step frequency at which threadpool
+                                      tasks are dumped.
diff --git a/doc/RTD/source/Cooling/index.rst b/doc/RTD/source/Cooling/index.rst
index d9462b5233334769f163883ffd9e859cc7b69767..00b84489c647bbca4948714a95b3d5cd5fb3cce1 100644
--- a/doc/RTD/source/Cooling/index.rst
+++ b/doc/RTD/source/Cooling/index.rst
@@ -66,7 +66,7 @@ TODO
 How to Implement a New Cooling
 ------------------------------
 
-The developper should provide at least one function for:
+The developer should provide at least one function for:
  * writing the cooling name in HDF5
  * cooling a particle
  * the maximal time step possible
diff --git a/doc/RTD/source/ExternalPotentials/index.rst b/doc/RTD/source/ExternalPotentials/index.rst
index e3138162465c200ec71d7d31b02c575e3e663416..ca33eb8189eea216863feb02579344aa22916696 100644
--- a/doc/RTD/source/ExternalPotentials/index.rst
+++ b/doc/RTD/source/ExternalPotentials/index.rst
@@ -17,7 +17,7 @@ give a short overview of the potentials that are implemented in the code:
 1. No potential (none)
 2. Point mass potential (point-mass): classical point mass, can be placed at
    a position with a mass.
-3. Plummer potential (point-mass-softened): in the code a softended point mass 
+3. Plummer potential (point-mass-softened): in the code a softened point mass 
    corresponds to a Plummer potential, can be placed at a position with a mass.
 4. Isothermal potential (isothermal): An isothermal potential which corresponds 
    to a density profile which is :math:`\propto r^{-2}` and a potential which is 
@@ -28,7 +28,7 @@ give a short overview of the potentials that are implemented in the code:
    
    :math:`\Phi(r) = - \frac{GM}{r+a}.`
 
-   The free paramters of Hernquist potential are mass, scale length,
+   The free parameters of Hernquist potential are mass, scale length,
    and softening. The potential can be set at any position in the box.
 6. NFW potential (nfw): The most used potential to describe dark matter halos, the  
    potential is given by:
@@ -36,7 +36,7 @@ give a short overview of the potentials that are implemented in the code:
    :math:`\Phi(r) = - \frac{4\pi G \rho_0 R_s^3}{r} \ln \left( 1+ 
    \frac{r}{R_s} \right).`
 
-   This potential has as free paramters the concentration of the DM halo, the
+   This potential has as free parameters the concentration of the DM halo, the
    virial mass (:math:`M_{200}`) and the critical density.
 7. Sine wave (sine-wave)
 8. Point mass ring (point-mass-ring)
diff --git a/doc/RTD/source/GettingStarted/configuration_options.rst b/doc/RTD/source/GettingStarted/configuration_options.rst
index e37384cfd1c29cb1df82cc180a763f4859650b2e..7dca5cddb0012b9a2146640b9373cfbe81c8dbdd 100644
--- a/doc/RTD/source/GettingStarted/configuration_options.rst
+++ b/doc/RTD/source/GettingStarted/configuration_options.rst
@@ -45,6 +45,6 @@ Several cooling implementations (including GRACKLE) are available.
 Many external potentials are available for use with SWIFT. You can choose
 between them at compile time. Some examples include a central potential, a
 softened central potential, and a sinusoidal potential. You will need to
-configure, for example, the mass in your parameterfile at runtime.
+configure, for example, the mass in your parameter file at runtime.
 
 
diff --git a/doc/RTD/source/GettingStarted/running_example.rst b/doc/RTD/source/GettingStarted/running_example.rst
index 7c9e333ca971ec73f3c2e25b56cc8e1381385567..9dfbdd8c8ec98ea59892a551691aa5f230052e2e 100644
--- a/doc/RTD/source/GettingStarted/running_example.rst
+++ b/doc/RTD/source/GettingStarted/running_example.rst
@@ -14,7 +14,7 @@ as ``wget`` for grabbing the glass).
    cd examples/SodShock_3D
    ./getGlass.sh
    python makeIC.py
-   ../swift -s -t 4 sodShock.yml
+   ../swift --hydro --threads=4 sodShock.yml
    python plotSolution.py 1
 
 
diff --git a/doc/RTD/source/GettingStarted/running_on_large_systems.rst b/doc/RTD/source/GettingStarted/running_on_large_systems.rst
index 55eb812cef21474045931490591b3978841a4085..8bd3a76985e9181bae1a715564e58d2052dd15fc 100644
--- a/doc/RTD/source/GettingStarted/running_on_large_systems.rst
+++ b/doc/RTD/source/GettingStarted/running_on_large_systems.rst
@@ -38,5 +38,5 @@ each with 2x16 core processors for a total of 512 cores):
    #SBATCH -N 16  # Number of nodes to run on
    #SBATCH --tasks-per-node=2  # This system has 2 chips per node
    
-   mpirun -np 32 swift_mpi -t 16 -a parameter.yml
+   mpirun -np 32 swift_mpi --threads=16 --pin parameter.yml
 
diff --git a/doc/RTD/source/GettingStarted/what_about_mpi.rst b/doc/RTD/source/GettingStarted/what_about_mpi.rst
index 098fd35d80d71866cb86d2342d5d54710cd73a82..98141049f3e36506d6033259e7f5bb9394daf997 100644
--- a/doc/RTD/source/GettingStarted/what_about_mpi.rst
+++ b/doc/RTD/source/GettingStarted/what_about_mpi.rst
@@ -9,4 +9,4 @@ and the other ``swift_mpi``. Current wisdom is to run ``swift`` if you are only
 using one node (i.e. without any interconnect), and one MPI rank per NUMA
 region using ``swift_mpi`` for anything larger. You will need some GADGET-2
 HDF5 initial conditions to run SWIFT, as well as a compatible yaml
-parameterfile.
+parameter file.
diff --git a/doc/RTD/source/HydroSchemes/adding_your_own.rst b/doc/RTD/source/HydroSchemes/adding_your_own.rst
index 2d7e640f66153a17e19f4e4c456cd37eed19a95a..549a7a42a22e7f755ad342b86b24c28f67118838 100644
--- a/doc/RTD/source/HydroSchemes/adding_your_own.rst
+++ b/doc/RTD/source/HydroSchemes/adding_your_own.rst
@@ -13,7 +13,7 @@ Adding Hydro Schemes
 SWIFT is engineered to enable you to add your own hydrodynamics schemes easily.
 We enable this through the use of header files to encapsulate each scheme.
 
-Note that it's unlikely you will ever have to consider paralellism or 'loops over
+Note that it's unlikely you will ever have to consider parallelism or 'loops over
 neighbours' for SWIFT; all of this is handled by the tasking system. All we ask
 for is the interaction functions that tell us how to a) compute the density
 and b) compute forces.
@@ -69,7 +69,7 @@ will need to 'fill out' the following:
 + ``hydro_compute_timestep(p, xp, hydro_props, cosmo)`` returns the timestep for 
   the hydrodynamics particles.
 + ``hydro_timestep_extra(p, dt)`` does some extra hydro operations once the
-  physical timestel for the particle is known.
+  physical timestep for the particle is known.
 + ``hydro_init_part(p, hydro_space)`` initialises the particle in preparation for
   the density calculation. This essentially sets properties, such as the density,
   to zero.
diff --git a/doc/RTD/source/HydroSchemes/gizmo.rst b/doc/RTD/source/HydroSchemes/gizmo.rst
index 365e1dc41c27f7c92bfb33859bedad2d96f35248..bbfcae04e1abac57b1476e4533bf92e051e6769d 100644
--- a/doc/RTD/source/HydroSchemes/gizmo.rst
+++ b/doc/RTD/source/HydroSchemes/gizmo.rst
@@ -10,7 +10,7 @@ GIZMO-Like Scheme
    :caption: Contents:
 
 
-There is a meshless finite volume (MFV) GIZMO-like scheme implemented in SWIFT
+There is a mesh-less finite volume (MFV) GIZMO-like scheme implemented in SWIFT
 (see Hopkins 2015 for more information). You will need a Riemann solver to run
 this, and configure as follows:
 
@@ -19,7 +19,7 @@ this, and configure as follows:
    ./configure --with-hydro="gizmo-mfv" --with-riemann-solver="hllc"
 
 
-We also have the meshless finite mass (MFM) GIZMO-like scheme. You can select
+We also have the mesh-less finite mass (MFM) GIZMO-like scheme. You can select
 this at compile-time with the following configuration flags:
 
 .. code-block:: bash
diff --git a/doc/RTD/source/InitialConditions/index.rst b/doc/RTD/source/InitialConditions/index.rst
index 00e7b98c5916a29b31d9396c317dfc2851d7389b..e585c9aa55f269ebbbf9b2d83034b96a688a99f4 100644
--- a/doc/RTD/source/InitialConditions/index.rst
+++ b/doc/RTD/source/InitialConditions/index.rst
@@ -11,17 +11,21 @@ conditions format as the popular `GADGET-2
 its type 3 format. Note that we do not support the GADGET-2 types 1 and 2
 formats.
 
+One crucial difference is that whilst GADGET-2 can have initial conditions split
+over many files SWIFT only supports initial conditions in one single file. **ICs
+split over multiple files cannot be read by SWIFT**. See the
+":ref:`multiple_files_ICs`" section below for possible solutions. In GADGET-2
+having multiple files allows multiple ones to be read in parallel and is the
+only way the code can handle more than 2^31 particles. This limitation is not in
+place in SWIFT. A single file can contain any number of particles (well... up to
+2^64...)  and the file is read in parallel by HDF5 when running on more than one
+compute node.
+
 The original GADGET-2 file format only contains 2 types of particles: gas
-particles and 5 sorts of collisionless particles that allow users to run with 5
+particles and 5 sorts of collision-less particles that allow users to run with 5
 separate particle masses and softenings. In SWIFT, we expand on this by using
 two of these types for stars and black holes.
 
-GADGET-2 can have initial conditions split over many files. This allow multiple
-ones to be read in parallel and is the only way the code can handle more than
-2^31 particles. This limitation is not in place in SWIFT. A single file can
-contain any number of particles (well... up to 2^64...) and the file is read in
-parallel by HDF5 when running on more than one compute node.
-
 As the original documentation for the GADGET-2 initial conditions format is
 quite sparse, we lay out here all of the necessary components. If you are
 generating your initial conditions from python, we recommend you use the h5py
@@ -35,7 +39,7 @@ You can find out more about the HDF5 format on their `webpages
 Structure of the File
 ---------------------
 
-There are several groups that contain 'auxilliary' information, such as
+There are several groups that contain 'auxiliary' information, such as
 ``Header``.  Particle data is placed in separate groups depending of the type of
 the particles. Some types are currently ignored by SWIFT but are kept in the
 file format for compatibility reasons.
@@ -98,7 +102,7 @@ In the ``/Header/`` group, the following attributes are required:
   ``NumPart_Total`` to be >2^31, the use of ``NumPart_Total_HighWord`` is only
   here for compatibility reasons.
 + ``Flag_Entropy_ICs``, a historical value that tells the code if you have
-  included entropy or internal energy values in your intial conditions files.
+  included entropy or internal energy values in your initial conditions files.
   Acceptable values are 0 or 1. We recommend using internal energies over
   entropy in the ICs and hence have this flag set to 0.
 
@@ -113,7 +117,9 @@ GADGET-2 based analysis programs:
   exactly the same as the ``NumPart_Total`` array. As SWIFT only uses ICs
   contained in a single file, this is not necessary for SWIFT-only ICs.
 + ``NumFilesPerSnapshot``, again a historical integer value that tells the code
-  how many files there are per snapshot. You will probably want to set this to 1.
+  how many files there are per snapshot. You will probably want to set
+  this to 1. If this field is present in a SWIFT IC file and has a
+  value different from 1, the code will return an error message.
 + ``Time``, time of the start of the simulation in internal units or expressed
   as a scale-factor for cosmological runs. SWIFT ignores this and reads it from
   the parameter file.
@@ -141,7 +147,7 @@ individual particle type (e.g. ``/PartType0/``) that have the following *dataset
 + ``Masses``, an array of length N that gives the masses of the particles.
 
 For ``PartType0`` (i.e. particles that interact through hydro-dynamics), you will
-need the following auxilliary items:
+need the following auxiliary items:
 
 + ``SmoothingLength``, the smoothing lengths of the particles. These will be
   tidied up a bit, but it is best if you provide accurate numbers. In
@@ -163,7 +169,7 @@ h-free quantities. Switching this parameter on will also affect the box size
 read from the ``/Header/`` group (see above).
 
 Similarly, GADGET cosmological ICs have traditionally used velocities expressed
-as peculiar velocities divided by ``sqrt(a)``. This can be undone by swicthing
+as peculiar velocities divided by ``sqrt(a)``. This can be undone by switching
 on the parameter ``InitialConditions:cleanup_velocity_factors`` in the
 :ref:`Parameter_File_label`.
 
@@ -226,4 +232,27 @@ You should have an HDF5 file with the following structure:
      ParticleIDs=[...]
      Masses=[...]
 
+.. _multiple_files_ICs:
+     
+ICs split over multiple files
+-----------------------------
+
+A basic script ``tools/combine_ics.py`` is provided to merge basic GADGET-2
+initial conditions split into multiple files into one single valid file. This
+script can handle simple HDF5 files (GADGET-2 type 3 ICs) that follow the format
+described above but split over multiple files.
+
+The script can also convert ICs using a ``MassTable`` and create the
+corresponding particle fields. Note that additional fields present in ICs beyond
+the simple GADGET-2 specification will not be merged.
+
+One additional option is to compress the fields in the files using HDF5's gzip
+compression. This is very effective for the fields such as masses or particle
+IDs which are very similar. A checksum filter is also applied in all cases to
+help with data curation.
+
+**We caution that this script is very basic and should only be used with great
+caution.** 
+
+
 
diff --git a/doc/RTD/source/ParameterFiles/index.rst b/doc/RTD/source/ParameterFiles/index.rst
index ec938c6062056e1c1e081c10813ed61b8bfc936f..93cf9b6e86895f9f20c8d644d8d24ccab5df93d6 100644
--- a/doc/RTD/source/ParameterFiles/index.rst
+++ b/doc/RTD/source/ParameterFiles/index.rst
@@ -24,7 +24,7 @@ Comments can be inserted anywhere and start with a hash:
 
 .. code:: YAML
 
-   # Descrption of the physics
+   # Description of the physics
    viscosity_alpha:     2.0
    dt_max:              1.5     # seconds
 
@@ -72,11 +72,11 @@ section. A list of all the possible parameters is kept in the file
 Internal Unit System
 --------------------
 
-This section describes the units used internally by the code. This is
-the system of units in which all the equations are solved. All
-physical constants are converted to this system and if the ICs use a
-different system (see :ref:`ICs_units_label`) the particle quantities
-will be converted when read in.
+The ``InternalUnitSystem`` section describes the units used internally by the
+code. This is the system of units in which all the equations are solved. All
+physical constants are converted to this system and if the ICs use a different
+system (see :ref:`ICs_units_label`) the particle quantities will be converted
+when read in.
 
 The system of units is described using the value of the 5 basic units
 of any system with respect to the CGS system. Instead of using a unit
@@ -113,7 +113,7 @@ schemes that make use of the unit of electric current. There is also
 no incentive to use anything else than Kelvin but that makes the whole
 system consistent with any possible unit system.
 
-If one is interested in using the more humourous `FFF unit
+If one is interested in using the more humorous `FFF unit
 system <https://en.wikipedia.org/wiki/FFF_system>`_ one would use
 
 .. code:: YAML
@@ -132,9 +132,9 @@ exercise for the reader [#f1]_.
 Cosmology
 ---------
 
-When running a cosmological simulation, this section set the values of the
-cosmological model. The epanded :math:`\Lambda\rm{CDM}` parameters governing the
-background evolution of the Univese need to be specified here. These are:
+When running a cosmological simulation, the section ``Cosmology`` sets the values of the
+cosmological model. The expanded :math:`\Lambda\rm{CDM}` parameters governing the
+background evolution of the Universe need to be specified here. These are:
 
 * The reduced Hubble constant: :math:`h`: ``h``,
 * The matter density parameter :math:`\Omega_m`: ``Omega_m``,
@@ -146,7 +146,7 @@ The last parameter can be omitted and will default to :math:`\Omega_r = 0`. Note
 that SWIFT will verify on start-up that the matter content of the initial conditions
 matches the cosmology specified in this section.
 
-This section als specifies the start and end of the simulation expressed in
+This section also specifies the start and end of the simulation expressed in
 terms of scale-factors. The two parameters are:
 
 * Initial scale-factor: ``a_begin``,
@@ -157,7 +157,7 @@ state of dark energy :math:`w(a)`. We use the evolution law :math:`w(a) =
 w_0 + w_a (1 - a)`. The two parameters in the YAML file are:
 
 * The :math:`z=0` dark energy equation of state parameter :math:`w_0`: ``w_0``
-* The dark energy equation of state evolutio parameter :math:`w_a`: ``w_a``
+* The dark energy equation of state evolution parameter :math:`w_a`: ``w_a``
 
 If unspecified these parameters default to the default
 :math:`\Lambda\rm{CDM}` values of :math:`w_0 = -1` and :math:`w_a = 0`.
@@ -179,14 +179,14 @@ use the following parameters:
      w_0:            -1.0          # (Optional)
      w_a:            0.            # (Optional)
 
-When running a non-cosmological simulation (i.e. without the ``-c`` runtime
+When running a non-cosmological simulation (i.e. without the ``-c`` run-time
 flag) this section of the YAML file is entirely ignored.
      
 Gravity
 -------
 
-The behaviour of the self-gravity solver can be modifed by the parameters
-provided in this section. The theory document puts these parameters into the
+The behaviour of the self-gravity solver can be modified by the parameters
+provided in the ``Gravity`` section. The theory document puts these parameters into the
 context of the equations being solved. We give a brief overview here.
 
 * The Plummer-equivalent co-moving softening length used for all particles :math:`\epsilon_{com}`: ``comoving_softening``,
@@ -206,7 +206,7 @@ The last tree-related parameter is
 
 * The tree rebuild frequency: ``rebuild_frequency``.
 
-Thqe tree rebuild frequency is an optional parameter defaulting to
+The tree rebuild frequency is an optional parameter defaulting to
 :math:`0.01`. It is used to trigger the re-construction of the tree every time a
 fraction of the particles have been integrated (kicked) forward in time.
 
@@ -219,12 +219,12 @@ Particle-Mesh part of the calculation. The last three are optional:
 * The scale above which the short-range forces are assumed to be 0 (in units of
   the mesh cell-size multiplied by :math:`a_{\rm smooth}`) :math:`r_{\rm
   cut,max}`: ``r_cut_max`` (default: ``4.5``),
-* The scale bewlo which the short-range forces are assumed to be exactly Newtonian (in units of
+* The scale below which the short-range forces are assumed to be exactly Newtonian (in units of
   the mesh cell-size multiplied by :math:`a_{\rm smooth}`) :math:`r_{\rm
   cut,min}`: ``r_cut_min`` (default: ``0.1``),
   
 For most runs, the default values can be used. Only the number of cells along
-each axis needs to be sepcified. The remaining three values are best described
+each axis needs to be specified. The remaining three values are best described
 in the context of the full set of equations in the theory documents.
   
 As a summary, here are the values used for the EAGLE :math:`100^3~{\rm Mpc}^3`
@@ -251,10 +251,64 @@ SPH
 Time Integration
 ----------------
 
+The ``TimeIntegration`` section is used to set some general parameters related to time
+integration. In all cases, users have to provide a minimal and maximal time-step
+size:
+
+* Maximal time-step size: ``dt_max``
+* Minimal time-step size: ``dt_min``
+
+These quantities are expressed in internal units. All particles will have their
+time-step limited by the maximal value on top of all the other criteria that may
+apply to them (gravity acceleration, Courant condition, etc.). If a particle
+demands a time-step size smaller than the minimum, SWIFT will abort with an
+error message. This is a safe-guard against simulations that would never
+complete due to the number of steps to run being too large.
+
+When running a non-cosmological simulation, the user also has to provide the
+time of the start and the time of the end of the simulation:
+
+* Start time: ``time_begin``
+* End time: ``time_end``
+
+Both are expressed in internal units. The start time is typically set to ``0``
+but SWIFT can handle any value here. For cosmological runs, these values are
+ignored and the start- and end-points of the runs are specified by the start and
+end scale-factors in the cosmology section of the parameter file.
+
+Additionally, when running a cosmological volume, advanced users can specify the
+value of the dimensionless pre-factor entering the time-step condition linked
+with the motion of particles with respect to the background expansion and mesh
+size. See the theory document for the exact equations.
+
+* Dimensionless pre-factor of the maximal allowed displacement:
+  ``max_dt_RMS_factor`` (default: ``0.25``)
+
+This value rarely needs altering.
+
+A full time-step section for a non-cosmological run would be:
+
+.. code:: YAML
+
+  TimeIntegration:
+    time_begin:   0    # Start time in internal units.
+    time_end:     10.  # End time in internal units.
+    dt_max:       1e-2
+    dt_min:       1e-6
+
+Whilst for a cosmological run, one would need:
+
+.. code:: YAML
+
+  TimeIntegration:
+    dt_max:            1e-4
+    dt_min:            1e-10
+    max_dt_RMS_factor: 0.25     # Default optional value
+
 Initial Conditions
 ------------------
 
-This section of the parameter file contains all the options related to
+This ``InitialConditions`` section of the parameter file contains all the options related to
 the initial conditions. The main two parameters are
 
 * The name of the initial conditions file: ``file_name``,
@@ -306,9 +360,9 @@ be:
    InitialConditions:
      file_name:  my_ics.hdf5
      periodic:                    1
-     cleanup_h_factors:           1
-     cleanup_velocity_factors:    1
-     generate_gas_in_ics:         1  
+     cleanup_h_factors:           1     
+     cleanup_velocity_factors:    1     
+     generate_gas_in_ics:         1     
      cleanup_smoothing_lengths:   1  
 
   
@@ -352,19 +406,19 @@ Restarts
 --------
 
 SWIFT can write check-pointing files and restart from them. The behaviour of
-this mechanism is driven by the options int he `Restarts` section of the YAML
+this mechanism is driven by the options in the ``Restarts`` section of the YAML
 parameter file. All the parameters are optional but default to values that
 ensure a reasonable behaviour. 
 
-* Wether or not to enable the dump of restart files: ``enable`` (default:
+* Whether or not to enable the dump of restart files: ``enable`` (default:
   ``1``).
 
 This parameter acts a master-switch for the check-pointing capabilities. All the
 other options require the ``enable`` parameter to be set to ``1``.
   
-* Wether or not to save a copy of the previous set of check-pointing files:
+* Whether or not to save a copy of the previous set of check-pointing files:
   ``save`` (default: ``1``),
-* Wether or not to dump a set of restart file on regular exit: ``onexit``
+* Whether or not to dump a set of restart file on regular exit: ``onexit``
   (default: ``0``),
 * The wall-clock time in hours between two sets of restart files:
   ``delta_hours`` (default: ``6.0``).
@@ -379,7 +433,7 @@ smaller value to allow for enough time to safely dump the check-point files.
 
 If the directory does not exist, SWIFT will create it.  When resuming a run,
 SWIFT, will look for files with the name provided in the sub-directory specified
-here. The files themselves are named ``basename_000001.rst`` where the basenme
+here. The files themselves are named ``basename_000001.rst`` where the basename
 is replaced by the user-specified name and the 6-digits number corresponds to
 the MPI-rank. SWIFT writes one file per MPI rank. If the ``save`` option has
 been activated, the previous set of restart files will be named
@@ -436,7 +490,7 @@ Scheduler
 Domain Decomposition
 --------------------
 
-.. [#f1] The thorough reader (or overly keen SWIFT tester) would find  that the speed of light is :math:`c=1.8026\times10^{12}\,\rm{fur}\,\rm{ftn}^{-1}`, Newton's contant becomes :math:`G_N=4.896735\times10^{-4}~\rm{fur}^3\,\rm{fir}^{-1}\,\rm{ftn}^{-2}` and Planck's constant turns into :math:`h=4.851453\times 10^{-34}~\rm{fur}^2\,\rm{fir}\,\rm{ftn}^{-1}`.
+.. [#f1] The thorough reader (or overly keen SWIFT tester) would find  that the speed of light is :math:`c=1.8026\times10^{12}\,\rm{fur}\,\rm{ftn}^{-1}`, Newton's constant becomes :math:`G_N=4.896735\times10^{-4}~\rm{fur}^3\,\rm{fir}^{-1}\,\rm{ftn}^{-2}` and Planck's constant turns into :math:`h=4.851453\times 10^{-34}~\rm{fur}^2\,\rm{fir}\,\rm{ftn}^{-1}`.
 
 
 .. [#f2] which would translate into a constant :math:`G_N=1.5517771\times10^{-9}~cm^{3}\,g^{-1}\,s^{-2}` if expressed in the CGS system.
diff --git a/doc/RTD/source/ParameterFiles/output_selection.rst b/doc/RTD/source/ParameterFiles/output_selection.rst
index ca905c5e613082cdf9de9db718bdd16c4a3c8951..90ab0f9a7c738c28832bc36de83c4034141d4b21 100644
--- a/doc/RTD/source/ParameterFiles/output_selection.rst
+++ b/doc/RTD/source/ParameterFiles/output_selection.rst
@@ -1,5 +1,5 @@
 .. Parameter File
-   Loic Hausammann, 1 june 2018
+   Loic Hausammann, 1 June 2018
 
 .. _Output_list_label:
 
@@ -37,7 +37,7 @@ Example of file with redshift::
   5
 
 .. _Output_selection_label:
-  
+
 Output Selection
 ~~~~~~~~~~~~~~~~
 
@@ -53,13 +53,13 @@ default all fields are written.
 
 This field is mostly used to remove unnecessary output by listing them
 with 0's. A classic use-case for this feature is a DM-only simulation
-(pure n-body) where all particles have the same mass. Outputing the
+(pure n-body) where all particles have the same mass. Outputting the
 mass field in the snapshots results in extra i/o time and unnecessary
 waste of disk space. The corresponding section of the ``yaml``
 parameter file would look like this::
 
   SelectOutput:
-    Masses_DM:   0 
+    Masses_DM:   0
 
 You can generate a ``yaml`` file containing all the possible fields
-available for a given configuration of SWIFT by running ``./swift -o output.yml``. 
+available for a given configuration of SWIFT by running ``./swift --output-params output.yml``.
diff --git a/doc/RTD/source/VELOCIraptorInterface/output.rst b/doc/RTD/source/VELOCIraptorInterface/output.rst
index 2b0b88eea07df607b71018bdd9bc76d046e76477..946841fbece0207430846725b6a995cbc3f12613 100644
--- a/doc/RTD/source/VELOCIraptorInterface/output.rst
+++ b/doc/RTD/source/VELOCIraptorInterface/output.rst
@@ -67,7 +67,7 @@ wish to extract. The python snippet below should give you an idea of how to
 go about doing this for the bound particles.
 
 First, we need to extract the offset from the ``.catalog_group`` file, and
-work out how many _bound_ partices are in our halo. We can do this by
+work out how many _bound_ particles are in our halo. We can do this by
 looking at the next offset. Then, we can ID match those with the snapshot
 file, and get the mask for the _positions_ in the file that correspond
 to our bound particles. (Note this requires ``numpy > 1.15.0``).
@@ -97,7 +97,7 @@ to our bound particles. (Note this requires ``numpy > 1.15.0``).
    # Again, we're done with that file.
    particles_file.close()
 
-   # Now, the tricky bit. We need to create the correspondance between the
+   # Now, the tricky bit. We need to create the correspondence between the
    # positions in the snapshot file, and the ids.
 
    # Let's look for the dark matter particles in that halo.
@@ -166,7 +166,7 @@ Mean Density related:
   :math:`\Delta=200` based on the mean density of the Universe 
   (:math:`M_{200}`).
 + ``R_200mean``: The :math:`R_{200}` radius of the halo based on the 
-  mean density ofthe Universe.
+  mean density of the Universe.
 
 Virial properties:
 """"""""""""""""""
@@ -190,7 +190,7 @@ properties.
 + ``M_gas``: The gas mass in the halo.
 + ``Mass_tot``: The total mass of the halo
 + ``M_gas_30kpc``: The gas mass within 30 kpc of the halo centre.
-+ ``M_gas_500c``: The gas mass of the overdensity of 500 times the critical
++ ``M_gas_500c``: The gas mass of the over-density of 500 times the critical
   density
 + ``M_gas_Rvmax``: The gas mass within the maximum rotation velocity.
 
@@ -232,7 +232,7 @@ NFW profile properties:
 + ``VXc_gas``, ``VYc_gas`` and ``VZc_gas`` are the velocities of the gas  in
   the centre of the halo [#check]_.
 
-Intertia Tensor properties:
+Inertia Tensor properties:
 """""""""""""""""""""""""""
 
 + ``eig_ij``: Are the normalized eigenvectors of the inertia tensor.
diff --git a/doc/RTD/source/VELOCIraptorInterface/stfalone.rst b/doc/RTD/source/VELOCIraptorInterface/stfalone.rst
index 113cff53a51e446d321f6a912222c565f2bdb38e..191d990c3d485bbc548c435d9b548686b9446397 100644
--- a/doc/RTD/source/VELOCIraptorInterface/stfalone.rst
+++ b/doc/RTD/source/VELOCIraptorInterface/stfalone.rst
@@ -45,7 +45,7 @@ version of the code, so change ``SWIFTINTERFACE="on"`` to
 Compiling VELOCIraptor
 ----------------------
 
-Compoling goes completely different as compared to the on the fly halo finder
+Compiling goes completely different as compared to the on the fly halo finder
 configuration with SWIFT. In this case we can compile the code as::
 
   make 
diff --git a/doc/RTD/source/VELOCIraptorInterface/stfwithswift.rst b/doc/RTD/source/VELOCIraptorInterface/stfwithswift.rst
index ac8dcc5b0b3c4b6b77dbd5dc79be2613eae0edc6..245b455d583d3ccdca02463e2afc6100e14dfb31 100644
--- a/doc/RTD/source/VELOCIraptorInterface/stfwithswift.rst
+++ b/doc/RTD/source/VELOCIraptorInterface/stfwithswift.rst
@@ -85,10 +85,9 @@ the Small Cosmological Volume DMO example we can run a simulation with halo
 finder as::
 
   cd examples/SmallCosmoVolume_DM 
-  ../swift -c -s -G -x -t 8 small_cosmo_volume_dm.yml
+  ../swift --cosmology --hydro --self-gravity --velociraptor --threads=8 small_cosmo_volume_dm.yml
 
-In which there is an additional ``-x`` option which activates the VELOCIraptor
-interface.
+Which activates the VELOCIraptor interface.
 
 
 .. _GitHub: https://github.com/pelahi/VELOCIraptor-STF
diff --git a/doc/RTD/source/VELOCIraptorInterface/whatis.rst b/doc/RTD/source/VELOCIraptorInterface/whatis.rst
index bc14e0925a288315c311972d97951abfc91426a6..a0a2a7441c52c188cc603910b43c112b3e24029e 100644
--- a/doc/RTD/source/VELOCIraptorInterface/whatis.rst
+++ b/doc/RTD/source/VELOCIraptorInterface/whatis.rst
@@ -55,7 +55,7 @@ The VELOCIraptor algorithm consists basically of the following steps [#ref]_:
 
 .. 1. The algorithm is mostly sensitive to substructures that are on the tail
    of the Gaussian velocity density function, this means that VELOCIraptor
-   is most sensitive for subhalos which are cold (slow ratating) but have 
+   is most sensitive for subhalos which are cold (slow rotating) but have 
    a large bulk velocity
 
 
diff --git a/doc/RTD/source/conf.py b/doc/RTD/source/conf.py
index 031687ea5228252e2d2e44ec0bd6f53b1b64d732..46cff147efff3e7f23ff3f618898a17da3f85459 100644
--- a/doc/RTD/source/conf.py
+++ b/doc/RTD/source/conf.py
@@ -23,9 +23,9 @@ copyright = '2018, SWIFT Collaboration'
 author = 'SWIFT Team'
 
 # The short X.Y version
-version = '0.7'
+version = '0.8'
 # The full version, including alpha/beta/rc tags
-release = '0.7.0'
+release = '0.8.0'
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/examples/AgoraDisk/run.sh b/examples/AgoraDisk/run.sh
index d7e284db52c2e6750fd713b3607a7f423bac7769..6bf9a98342b4b1977579761da79e06226c6ded40 100755
--- a/examples/AgoraDisk/run.sh
+++ b/examples/AgoraDisk/run.sh
@@ -38,7 +38,7 @@ cp $sim.hdf5 agora_disk.hdf5
 python3 changeType.py agora_disk.hdf5
 
 # Run SWIFT
-#../swift $flag -s -G -t 4 agora_disk.yml 2>&1 | tee output.log
+#../swift $flag --hydro --self-gravity --threads=4 agora_disk.yml 2>&1 | tee output.log
 
 
 echo "Changing smoothing length to be Gadget compatible"
diff --git a/examples/ConstantCosmoVolume/run.sh b/examples/ConstantCosmoVolume/run.sh
index a2d9cdc63fbef6208caa44e05f91e94a27c4ff20..c7180b5232428a25c253e6f59726497c363eb1f4 100755
--- a/examples/ConstantCosmoVolume/run.sh
+++ b/examples/ConstantCosmoVolume/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -c -G -t 8 constant_volume.yml 2>&1 | tee output.log
+../swift --hydro --cosmology --self-gravity --threads=8 constant_volume.yml 2>&1 | tee output.log
 
 # Plot the result
 python plotSolution.py $i
diff --git a/examples/CoolingBox/run.sh b/examples/CoolingBox/run.sh
index 30b2177a6e8bb95a20146397f8b6a5021161b27f..685836375b8f731d15e82fe1d0459879101ad713 100755
--- a/examples/CoolingBox/run.sh
+++ b/examples/CoolingBox/run.sh
@@ -21,7 +21,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -C -t 1 coolingBox.yml
+../swift --hydro --cooling --threads=1 coolingBox.yml
 
 # Check energy conservation and cooling rate
 python energy_plot.py
diff --git a/examples/CoolingHalo/run.sh b/examples/CoolingHalo/run.sh
index 60ceae649d183dce3a7e5019a1ff94ce7bc4f08d..c7c00fe81c960925fe490cd3d65fbc49d331f2d0 100755
--- a/examples/CoolingHalo/run.sh
+++ b/examples/CoolingHalo/run.sh
@@ -4,7 +4,7 @@
 echo "Generating initial conditions for the isothermal potential box example..."
 python makeIC.py 10000 
 
-../swift -g -s -C -t 16 cooling_halo.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --cooling --threads=16 cooling_halo.yml 2>&1 | tee output.log
 
 python radial_profile.py 2. 200 100
 
diff --git a/examples/CoolingHaloWithSpin/run.sh b/examples/CoolingHaloWithSpin/run.sh
index 131fbf3cb10d2014546683b5f43194840544fd55..90d0cc84e78858e8d163ff51e25375b03c6818e5 100755
--- a/examples/CoolingHaloWithSpin/run.sh
+++ b/examples/CoolingHaloWithSpin/run.sh
@@ -5,7 +5,7 @@ echo "Generating initial conditions for the isothermal potential box example..."
 python makeIC.py 10000 
 
 # Run SWIFT with external potential, SPH and cooling
-../swift -g -s -C -t 1 cooling_halo.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --cooling --threads=1 cooling_halo.yml 2>&1 | tee output.log
 
 # python radial_profile.py 10
 
diff --git a/examples/DiscPatch/GravityOnly/run.sh b/examples/DiscPatch/GravityOnly/run.sh
index 9af1011ee653253f0d1b2cd26db0ac13cf11adc0..999ffa120f809ffe5aa0a3f104e53f8148cfe1c2 100755
--- a/examples/DiscPatch/GravityOnly/run.sh
+++ b/examples/DiscPatch/GravityOnly/run.sh
@@ -7,4 +7,4 @@ then
     python makeIC.py 1000
 fi
 
-../../swift -g -t 2 disc-patch.yml
+../../swift --external-gravity --threads=2 disc-patch.yml
diff --git a/examples/DiscPatch/HydroStatic/run.sh b/examples/DiscPatch/HydroStatic/run.sh
index e1f47ecad54e7e171d78b7da080d56579e985d1e..2dccc93f0445e03750bd090be073b7219b2cd353 100755
--- a/examples/DiscPatch/HydroStatic/run.sh
+++ b/examples/DiscPatch/HydroStatic/run.sh
@@ -13,6 +13,6 @@ then
 fi
 
 # Run SWIFT
-../../swift -g -s -t 4 disc-patch-icc.yml 2>&1 | tee output.log
+../../swift --external-gravity --hydro --threads=4 disc-patch-icc.yml 2>&1 | tee output.log
 
 python plotSolution.py
diff --git a/examples/DiscPatch/HydroStatic_1D/run.sh b/examples/DiscPatch/HydroStatic_1D/run.sh
index e9d073a6cc7a06ec9ebd9fdb556c44778d32c7f4..3e22727adab274a58110e43f127343b9bdcb0c82 100755
--- a/examples/DiscPatch/HydroStatic_1D/run.sh
+++ b/examples/DiscPatch/HydroStatic_1D/run.sh
@@ -8,6 +8,6 @@ then
 fi
 
 # Run SWIFT
-../../swift -g -s -t 4 disc-patch-icc.yml 2>&1 | tee output.log
+../../swift --external-gravity --hydro --threads=4 disc-patch-icc.yml 2>&1 | tee output.log
 
 python plotSolution.py
diff --git a/examples/DwarfGalaxy/run.sh b/examples/DwarfGalaxy/run.sh
index ced1959de34882937a5aa37df4facc294db26050..17c0ac0c7e3456c3b43ade953ed94052edb37ac8 100755
--- a/examples/DwarfGalaxy/run.sh
+++ b/examples/DwarfGalaxy/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -b -G -s -S -t 8 $@ dwarf_galaxy.yml 2>&1 | tee output.log
+../swift --feedback --self-gravity --hydro --stars --threads=8 $@ dwarf_galaxy.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_100/run.sh b/examples/EAGLE_100/run.sh
index 9c990a902a6350eff348aad40c482723d1ba954c..12b6ff2a6e3486f45a9a66a4cca3346336160a3d 100755
--- a/examples/EAGLE_100/run.sh
+++ b/examples/EAGLE_100/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -s -G -S -t 16 eagle_100.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --stars --threads=16 eagle_100.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_12/run.sh b/examples/EAGLE_12/run.sh
index 67f1c24a1ead927823b9240cdeb718b35580d573..90128c4f6c291a86f90e794d452641b08248fbdc 100755
--- a/examples/EAGLE_12/run.sh
+++ b/examples/EAGLE_12/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -s -G -S -t 16 eagle_12.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --stars --threads=16 eagle_12.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_25/run.sh b/examples/EAGLE_25/run.sh
index 0b6cf77d7b2461864fc24055811ee00c7dd00613..af1218f70729663d8efe337c312f6ef2fe8d6620 100755
--- a/examples/EAGLE_25/run.sh
+++ b/examples/EAGLE_25/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -s -G -S -t 16 eagle_25.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --stars--threads=16 eagle_25.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_50/run.sh b/examples/EAGLE_50/run.sh
index a0d5dee11dc58e8d19d4d0e551c5ad8eceb90548..a08e3125b1a8c1d65013ebd537f033abf6de5c3e 100755
--- a/examples/EAGLE_50/run.sh
+++ b/examples/EAGLE_50/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -s -G -S -t 16 eagle_50.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --stars --threads=16 eagle_50.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_6/run.sh b/examples/EAGLE_6/run.sh
index 7ef3fc2abdd1bb3fed1a228bf993bf09fb13f42c..6df5902a057434ad1e7b5145b235655fa981e40e 100755
--- a/examples/EAGLE_6/run.sh
+++ b/examples/EAGLE_6/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -s -G -S -t 16 eagle_6.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --stars --threads=16 eagle_6.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_6/testVELOCIraptor.sh b/examples/EAGLE_6/testVELOCIraptor.sh
index 14ec30487006f0b7e86356837c9a801950c15c83..3f0ae1d6f0da9736b867f53b898752efbfd50324 100755
--- a/examples/EAGLE_6/testVELOCIraptor.sh
+++ b/examples/EAGLE_6/testVELOCIraptor.sh
@@ -36,8 +36,8 @@ if [ "$RUN_DM" = "1" ]; then
     rm $VEL_OUTPUT/vel_$TEST*
 
     # Run test using SWIFT + VELOCIraptor
-    echo "Running: mpirun -np $NUM_MPI_PROC ../swift_mpi -G -t 8 eagle_6.yml -x -n 5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_dmonly"
-    mpirun -np $NUM_MPI_PROC ../swift_mpi -G -t 8 eagle_6.yml -x -n 5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_dmonly
+    echo "Running: mpirun -np $NUM_MPI_PROC ../swift_mpi --self-gravity --threads=8 eagle_6.yml --velociraptor --steps=5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_dmonly"
+    mpirun -np $NUM_MPI_PROC ../swift_mpi --self-gravity --threads=8 eagle_6.yml --velociraptor --steps=5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_dmonly
 
     # Run test using VELOCIraptor
     echo "Running: mpirun -np $NUM_MPI_PROC $VELOCIRAPTOR_PATH/bin/stf-gas -I 2 -i eagle_dmonly_0000 -C $VELOCIRAPTOR_PATH/stf_input_$TEST.cfg -o ./$VEL_OUTPUT/vel_$TEST"
@@ -80,8 +80,8 @@ if [ "$RUN_GAS" = "1" ]; then
     rm $VEL_OUTPUT/vel_$TEST*
 
     # Run test using SWIFT + VELOCIraptor
-    echo "Running: mpirun -np $NUM_MPI_PROC ../swift_mpi -s -G -t 8 eagle_6.yml -x -n 5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_gas"
-    mpirun -np $NUM_MPI_PROC ../swift_mpi -s -G -t 8 eagle_6.yml -x -n 5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_gas
+    echo "Running: mpirun -np $NUM_MPI_PROC ../swift_mpi --hydro --self-gravity --threads=8 eagle_6.yml --velociraptor --steps=5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_gas"
+    mpirun -np $NUM_MPI_PROC ../swift_mpi --hydro --self-gravity --threads=8 eagle_6.yml --velociraptor --steps=5 -P StructureFinding:basename:./$OUTPUT/stf -P StructureFinding:config_file_name:./stf_input_$TEST.cfg -P Snapshots:basename:./eagle_gas
 
     # Run test using VELOCIraptor
     echo "Running: mpirun -np $NUM_MPI_PROC $VELOCIRAPTOR_PATH/bin/stf-gas -I 2 -i eagle_gas_0000 -C ./stf_input_$TEST.cfg -o ./$VEL_OUTPUT/vel_$TEST"
diff --git a/examples/EAGLE_DMO_100/run.sh b/examples/EAGLE_DMO_100/run.sh
index 642c9247cf4aefa299e8f11c9674d737f4770296..6a3b3a00d69c6f3ff78159290d3e41c7d534b8ae 100755
--- a/examples/EAGLE_DMO_100/run.sh
+++ b/examples/EAGLE_DMO_100/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -G -t 16 eagle_100.yml 2>&1 | tee output.log
+../swift --cosmology --self-gravity --threads=16 eagle_100.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_DMO_12/run.sh b/examples/EAGLE_DMO_12/run.sh
index ebf24ee6a5c873d595c58e74a31838eb2d013d92..f5e7e729470d632aab9a539f50d3bb922b7ae88f 100755
--- a/examples/EAGLE_DMO_12/run.sh
+++ b/examples/EAGLE_DMO_12/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -G -t 16 eagle_12.yml 2>&1 | tee output.log
+../swift --cosmology --self-gravity --threads=16 eagle_12.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_DMO_25/run.sh b/examples/EAGLE_DMO_25/run.sh
index ae0a6d3c49b89239da973c7417530204b4751729..6387472050b46d84932d27739b9490b727d4d31f 100755
--- a/examples/EAGLE_DMO_25/run.sh
+++ b/examples/EAGLE_DMO_25/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -G -t 16 eagle_25.yml 2>&1 | tee output.log
+../swift --cosmology --self-gravity --threads=16 eagle_25.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_DMO_50/run.sh b/examples/EAGLE_DMO_50/run.sh
index 31980a5a883e62c972b27a41bbdebe06c7c71539..486f7f33f7a2062563d63873e823c8623f10cf0d 100755
--- a/examples/EAGLE_DMO_50/run.sh
+++ b/examples/EAGLE_DMO_50/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -c -G -t 16 eagle_50.yml 2>&1 | tee output.log
+../swift --cosmology --self-gravity --threads=16 eagle_50.yml 2>&1 | tee output.log
 
diff --git a/examples/EvrardCollapse_3D/run.sh b/examples/EvrardCollapse_3D/run.sh
index abb7614f66fc877aa670db9b0e1335fbfe2e85d2..d9005a7214e297fc79053b5c2ca97b2cafc856a6 100755
--- a/examples/EvrardCollapse_3D/run.sh
+++ b/examples/EvrardCollapse_3D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -G -t 4 evrard.yml 2>&1 | tee output.log
+../swift --hydro --self-gravity --threads=4 evrard.yml 2>&1 | tee output.log
 
 # Get the high resolution 1D reference result if not present.
 if [ ! -e evrardCollapse3D_exact.txt ]
diff --git a/examples/ExternalPointMass/run.sh b/examples/ExternalPointMass/run.sh
index e074c384c4e002a161c7d8258e9068663204099f..fa3a40e20c8101a3b5cdb5f0a443ac937cd680c7 100755
--- a/examples/ExternalPointMass/run.sh
+++ b/examples/ExternalPointMass/run.sh
@@ -8,6 +8,6 @@ then
 fi
 
 rm -rf pointMass_*.hdf5
-../swift -g -t 1 externalPointMass.yml 2>&1 | tee output.log
+../swift --external-gravity --threads=1 externalPointMass.yml 2>&1 | tee output.log
 
 python energy_plot.py
diff --git a/examples/Gradients/run.sh b/examples/Gradients/run.sh
index 44c25ac5695175c40483d9f8b3bbd160b2fcbc0a..4a0a80a3aef3a37c54108d1489abe80cb0fd3f10 100755
--- a/examples/Gradients/run.sh
+++ b/examples/Gradients/run.sh
@@ -1,13 +1,13 @@
 #! /bin/bash
 
 python makeICs.py stretched
-../swift -s -t 2 gradientsStretched.yml
+../swift --hydro --threads=2 gradientsStretched.yml
 python plot.py gradients_stretched_0001.hdf5 stretched
 
 python makeICs.py cartesian
-../swift -s -t 2 gradientsCartesian.yml
+../swift --hydro --threads=2 gradientsCartesian.yml
 python plot.py gradients_cartesian_0001.hdf5 cartesian
 
 python makeICs.py random
-../swift -s -t 2 gradientsRandom.yml
+../swift --hydro --threads=2 gradientsRandom.yml
 python plot.py gradients_random_0001.hdf5 random
diff --git a/examples/GreshoVortex_2D/run.sh b/examples/GreshoVortex_2D/run.sh
index 6d537bcc96c68385434f685bd551a2d423f469e0..855d528bdff2351cebb0602115f48a23bf4f1bc5 100755
--- a/examples/GreshoVortex_2D/run.sh
+++ b/examples/GreshoVortex_2D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 gresho.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 gresho.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 11
diff --git a/examples/GreshoVortex_3D/run.sh b/examples/GreshoVortex_3D/run.sh
index da7d6cee111aebcfd2fcb0f3508af80ef73cbeb0..1967a77ba70bfb30191df8fef6e1e5e7bd68e4eb 100755
--- a/examples/GreshoVortex_3D/run.sh
+++ b/examples/GreshoVortex_3D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 gresho.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 gresho.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 11
diff --git a/examples/Hernquist_circularorbit/plotprog.py b/examples/Hernquist_circularorbit/plotprog.py
index 849ae4e365e0712faac7436a9b01a4e51c9794f0..a19c66e7f30e0e4012a23a4d38dd23045deea6e2 100755
--- a/examples/Hernquist_circularorbit/plotprog.py
+++ b/examples/Hernquist_circularorbit/plotprog.py
@@ -49,7 +49,6 @@ for i in range(0, lengthrun):
     zz[:, i] = positions[:, 2] - 500.0
 
 col = ["b", "r", "c", "y", "k"]
-print(np.shape(xx), np.shape(yy), np.shape(zz))
 
 for i in range(0, numbpar):
     plt.plot(xx[i, :], yy[i, :], col[i])
diff --git a/examples/Hernquist_circularorbit/run.sh b/examples/Hernquist_circularorbit/run.sh
index a2fedd0914edece43995d20776e048fd85e33963..fe2eb0bd0780c3aa66d2b52b10e76b146fb9dde2 100755
--- a/examples/Hernquist_circularorbit/run.sh
+++ b/examples/Hernquist_circularorbit/run.sh
@@ -12,7 +12,7 @@ then
 fi
 
 # self gravity G, external potential g, hydro s, threads t and high verbosity v
-../swift -g -t 6 hernquistcirc.yml 2>&1 | tee output.log
+../swift --external-gravity --threads=6 hernquistcirc.yml 2>&1 | tee output.log
 
 
 echo "Save plots of the circular orbits"
diff --git a/examples/Hernquist_radialinfall/run.sh b/examples/Hernquist_radialinfall/run.sh
index b2bcd99f9e7b0e571cffcd18b0fc29e50cad8b06..0ad64e2dd2c3c0bfd66f2da3d8bee1edb30fb5f2 100755
--- a/examples/Hernquist_radialinfall/run.sh
+++ b/examples/Hernquist_radialinfall/run.sh
@@ -12,7 +12,7 @@ then
 fi
 
 rm -rf hernquist_*.hdf5
-../swift -g -t 1 hernquist.yml 2>&1 | tee output.log
+../swift --external-gravity --threads=1 hernquist.yml 2>&1 | tee output.log
 
 
 
diff --git a/examples/HydrostaticHalo/run.sh b/examples/HydrostaticHalo/run.sh
index 82584282559c1fceb0492aada671ff83fb74c924..cb67be62aa014627c021ef784e68495cc48f637b 100755
--- a/examples/HydrostaticHalo/run.sh
+++ b/examples/HydrostaticHalo/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run for 10 dynamical times
-../swift -g -s -t 1 hydrostatic.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --threads=1 hydrostatic.yml 2>&1 | tee output.log
 
 echo "Plotting density profiles"
 mkdir plots
diff --git a/examples/InteractingBlastWaves_1D/run.sh b/examples/InteractingBlastWaves_1D/run.sh
index 31717bd806ddd6c98c24dfc1def6f79dddff42ff..cb8519e7f924357c19271dfb8edd902f629a4649 100755
--- a/examples/InteractingBlastWaves_1D/run.sh
+++ b/examples/InteractingBlastWaves_1D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 interactingBlastWaves.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 interactingBlastWaves.yml 2>&1 | tee output.log
 
 # Get the high resolution reference solution if not present.
 if [ ! -e interactingBlastWaves1D_exact.txt ]
diff --git a/examples/IsolatedGalaxy_dmparticles/angularmomentum.py b/examples/IsolatedGalaxy_dmparticles/angularmomentum.py
new file mode 100755
index 0000000000000000000000000000000000000000..4398dfeb8b079143886c5565e7667f72fc0bdcef
--- /dev/null
+++ b/examples/IsolatedGalaxy_dmparticles/angularmomentum.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+###############################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+import numpy as np
+import h5py
+import matplotlib.pyplot as plt
+import scipy.optimize as sco
+
+
+Nmax = 2001
+steps = 10
+angmomcomp = False
+
+iterarray = np.arange(0, Nmax + 1, steps)
+Lxtot = np.zeros(len(iterarray))
+Lytot = np.zeros(len(iterarray))
+Lztot = np.zeros(len(iterarray))
+Ltot = np.zeros(len(iterarray))
+time_array = np.zeros(len(iterarray))
+
+
+for i in iterarray:
+    f = h5py.File("output_%04d.hdf5" % i, "r")
+
+    boxsize = f["Header"].attrs["BoxSize"] / 2.0
+
+    time_array[int(i / steps)] = f["Header"].attrs["Time"]
+
+    particles = f["PartType4"]
+    coordinates = particles["Coordinates"][:, :]
+    velocities = particles["Velocities"][:, :]
+    masses = particles["Masses"][:]
+
+    R = (
+        (coordinates[:, 0] - boxsize[0]) ** 2 + (coordinates[:, 1] - boxsize[1]) ** 2
+    ) ** 0.5
+    X = np.abs(coordinates[:, 0] - boxsize[0])
+    Y = np.abs(coordinates[:, 1] - boxsize[1])
+    Z = np.abs(coordinates[:, 2] - boxsize[2])
+
+    vx = velocities[:, 0]
+    vy = velocities[:, 1]
+    vz = velocities[:, 2]
+
+    Lx = (Y * vz - Z * vy) * masses
+    Ly = (Z * vx - X * vz) * masses
+    Lz = (X * vy - Y * vx) * masses
+
+    L = (Lx ** 2 + Ly ** 2 + Lz ** 2) ** 0.5
+
+    Lxtot[int(i / steps)] = np.sum(Lx)
+    Lytot[int(i / steps)] = np.sum(Ly)
+    Lztot[int(i / steps)] = np.sum(Lz)
+    Ltot[int(i / steps)] = np.sum(L)
+
+time_array[-1] = 2.0
+if angmomcomp:
+    plt.plot(time_array, Lxtot / Lxtot[0] - 1, label="Lx total")
+    plt.plot(time_array, Lytot / Lytot[0] - 1, label="Ly total")
+    plt.plot(time_array, Lztot / Lztot[0] - 1, label="Lz total")
+plt.plot(time_array, Ltot / Ltot[0] - 1, label="L total")
+plt.xlabel("Time")
+plt.ylabel("ratio between current and zero angular momentum")
+plt.legend()
+plt.show()
+
+plt.semilogy(time_array, np.absolute(Ltot / Ltot[0] - 1))
+plt.xlabel("Time (Gyr)")
+plt.ylabel("Fractional change of total angular momentum")
+plt.savefig("Total_angular_momentum.png")
+plt.show()
+plt.close()
diff --git a/examples/IsolatedGalaxy_dmparticles/getIC.sh b/examples/IsolatedGalaxy_dmparticles/getIC.sh
new file mode 100755
index 0000000000000000000000000000000000000000..39e62d6fc3b7c83648aa66541c9cba2cdf758ac3
--- /dev/null
+++ b/examples/IsolatedGalaxy_dmparticles/getIC.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+wget https://home.strw.leidenuniv.nl/~nobels/data/3e11-star-only-DM-halo-galaxy.hdf5 
diff --git a/examples/IsolatedGalaxy_dmparticles/isolated_galaxy.yml b/examples/IsolatedGalaxy_dmparticles/isolated_galaxy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..dccfb28a3f1c888d2a83b5e28b759a30a6928754
--- /dev/null
+++ b/examples/IsolatedGalaxy_dmparticles/isolated_galaxy.yml
@@ -0,0 +1,43 @@
+# Define the system of units to use internally.
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.9891E43   # 10^10 solar masses 
+  UnitLength_in_cgs:   3.08567758E21   # 1 kpc 
+  UnitVelocity_in_cgs: 1E5   # km/s
+  UnitCurrent_in_cgs:  1   # Amperes
+  UnitTemp_in_cgs:     1   # Kelvin
+
+# Parameters for the self-gravity scheme
+Gravity:
+  mesh_side_length:       32        # Number of cells along each axis for the periodic gravity mesh.
+  eta:          0.025               # Constant dimensionless multiplier for time integration.
+  theta:        0.7                 # Opening angle (Multipole acceptance criterion).
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
+
+# Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.)
+TimeIntegration:
+  time_begin:        0.    # The starting time of the simulation (in internal units).
+  time_end:          1.    # The end time of the simulation (in internal units).
+  dt_min:            1e-6  # The minimal time-step size of the simulation (in internal units).
+  dt_max:            1e-2  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:   output      # Common part of the name of output files
+  time_first: 0.          # (Optional) Time of the first output if non-cosmological time-integration (in internal units)
+  delta_time: 0.001        # Time difference between consecutive outputs (in internal units)
+
+Scheduler:
+  max_top_level_cells:  96
+  
+# Parameters governing the conserved quantities statistics
+Statistics:
+  delta_time:           1e-2     # Time between statistics output
+  time_first:             0.     # (Optional) Time of the first stats output if non-cosmological time-integration (in internal units)
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  3e11-star-only-DM-halo-galaxy.hdf5  # The file to read
+  periodic:                    0    # Are we running with periodic ICs?
+
+ 
diff --git a/examples/IsolatedGalaxy_dmparticles/profilefit.py b/examples/IsolatedGalaxy_dmparticles/profilefit.py
new file mode 100755
index 0000000000000000000000000000000000000000..e7755062ea45de4f42716b14c5896b0da676f001
--- /dev/null
+++ b/examples/IsolatedGalaxy_dmparticles/profilefit.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+###############################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+import numpy as np
+import h5py
+import matplotlib.pyplot as plt
+from matplotlib.colors import BoundaryNorm
+from matplotlib.ticker import MaxNLocator
+import scipy.optimize as sco
+import os
+
+
+def linearfunc(x, a, b):
+    return a * x + b
+
+
+def radialfunc(r, h, A):
+    return A * np.exp(-r / h) * r
+
+
+def verticalfunc(z, A, z0, zoff):
+    return 2 * A * np.exp(-(z - zoff) / z0)
+
+
+def verticalfunc2(z, A, z0):
+    return 2 * A * np.exp(-(z) / z0)
+
+
+def verticalfunc3(z, A, z0, zoff, b):
+    return 2 * A * np.exp(-(z - zoff) / z0) + b
+
+
+Nmax = 2001
+steps = 10
+storefits = False
+logfit = True
+normalfit = False
+
+# if the user wants to store the indivudal fits
+if storefits:
+    if not os.path.exists("radial"):
+        os.mkdir("radial")
+        os.mkdir("vertical")
+        os.mkdir("histsnap")
+
+
+# Initialize the arrays
+R_ideal = np.linspace(0, 40, 100)
+Z_ideal = np.linspace(0, 10, 100)
+
+iterarray = np.arange(0, Nmax + 1, steps)
+
+Z0t = np.zeros(len(iterarray))
+Z0terr = np.zeros(len(iterarray))
+h0t = np.zeros(len(iterarray))
+h0terr = np.zeros(len(iterarray))
+Ar = np.zeros(len(iterarray))
+Arerr = np.zeros(len(iterarray))
+Az = np.zeros(len(iterarray))
+Azerr = np.zeros(len(iterarray))
+time_array = np.zeros(len(iterarray))
+
+ar = np.zeros(len(iterarray))
+arerr = np.zeros(len(iterarray))
+br = np.zeros(len(iterarray))
+brerr = np.zeros(len(iterarray))
+az = np.zeros(len(iterarray))
+azerr = np.zeros(len(iterarray))
+bz = np.zeros(len(iterarray))
+bzerr = np.zeros(len(iterarray))
+eps = 1e-6
+
+
+for i in iterarray:
+    # Getting the data from the snapshots
+    f = h5py.File("output_%04d.hdf5" % i, "r")
+
+    boxsize = f["Header"].attrs["BoxSize"] / 2.0
+
+    time_array[int(i / steps)] = f["Header"].attrs["Time"]
+
+    particles = f["PartType4"]
+    coordinates = particles["Coordinates"][:, :]
+    masses = particles["Masses"][:]
+
+    R = (
+        (coordinates[:, 0] - boxsize[0]) ** 2 + (coordinates[:, 1] - boxsize[1]) ** 2
+    ) ** 0.5
+    Z = np.abs(coordinates[:, 1] - boxsize[1])
+
+    # Bin the coordinates to make them suitable for fitting
+    Rhist = np.histogram(R, bins=100, range=[0, 40], normed=True)
+    Zhist = np.histogram(Z, bins=100, range=[0, 10.0], normed=True)
+
+    # Create correct variables for fitting
+    Ry = Rhist[0]
+    Rx = (Rhist[1][1:] + Rhist[1][: len(Rhist[0])]) / 2.0
+
+    Zy = Zhist[0]
+    Zx = (Zhist[1][1:] + Zhist[1][: len(Zhist[0])]) / 2.0
+
+    # Fit with two methods: non-linear LSQ and linear LSQ in log space
+    bestsolR = sco.curve_fit(radialfunc, Rx[10:], Ry[10:], p0=[2.0, 0.2])
+    bestsolZ = sco.curve_fit(verticalfunc, Zx[40:], Zy[40:])
+    bestsolRlog = sco.curve_fit(linearfunc, Rx[10:], np.log10(Ry[10:] + eps))
+    bestsolZlog = sco.curve_fit(linearfunc, Zx[40:], np.log10(Zy[40:] + eps))
+
+    # Store variables
+    h0t[int(i / steps)] = bestsolR[0][0]
+    Z0t[int(i / steps)] = bestsolZ[0][1]
+    Ar[int(i / steps)] = bestsolR[0][1]
+    Az[int(i / steps)] = bestsolZ[0][0]
+    Z0terr[int(i / steps)] = (bestsolZ[1][1, 1]) ** 0.5
+    h0terr[int(i / steps)] = (bestsolR[1][0, 0]) ** 0.5
+    Arerr[int(i / steps)] = (bestsolR[1][1, 1]) ** 0.5
+    Azerr[int(i / steps)] = (bestsolZ[1][0, 0]) ** 0.5
+
+    ar[int(i / steps)] = bestsolRlog[0][0]
+    arerr[int(i / steps)] = (bestsolRlog[1][0, 0]) ** 0.5
+    br[int(i / steps)] = bestsolRlog[0][1]
+    brerr[int(i / steps)] = (bestsolRlog[1][1, 1]) ** 0.5
+    az[int(i / steps)] = bestsolZlog[0][0]
+    azerr[int(i / steps)] = (bestsolZlog[1][0, 0]) ** 0.5
+    bz[int(i / steps)] = bestsolZlog[0][1]
+    bzerr[int(i / steps)] = (bestsolZlog[1][1, 1]) ** 0.5
+
+    if storefits:
+        plt.step(Rx, Ry)
+        plt.plot(
+            R_ideal,
+            radialfunc(R_ideal, bestsolR[0][0], bestsolR[0][1]),
+            label="Non linear LSQ",
+        )
+        plt.plot(
+            R_ideal,
+            10 ** (linearfunc(R_ideal, bestsolRlog[0][0], bestsolRlog[0][1])),
+            label="Linear LSQ",
+        )
+        plt.xlim(0, 40)
+        plt.ylim(0, 0.25)
+        plt.xlabel("R (kpc)")
+        plt.ylabel("Probability")
+        plt.savefig("./radial/radialsnap%04d.png" % i)
+        plt.close()
+
+        plt.step(Zx, Zy)
+        plt.plot(
+            Z_ideal,
+            verticalfunc(Z_ideal, bestsolZ[0][0], bestsolZ[0][1], bestsolZ[0][2]),
+            label="Non linear LSQ",
+        )
+        plt.plot(
+            Z_ideal,
+            10 ** (linearfunc(Z_ideal, bestsolZlog[0][0], bestsolZlog[0][1])),
+            label="Linear LSQ",
+        )
+        plt.xlim(0, 10.0)
+        plt.ylim(0, 0.6)
+        plt.xlabel("z (kpc)")
+        plt.ylabel("Probability")
+        plt.savefig("./vertical/verticalsnap%04d.png" % i)
+        plt.close()
+
+time_array[-1] = 2.0
+
+ax = plt.subplot(111)
+ax.set_yscale("log")
+if logfit:
+    plt.errorbar(
+        time_array,
+        np.absolute(az / (az[0]) - 1),
+        yerr=azerr / (az[0]),
+        label="z0 scale height (Log space)",
+    )
+    plt.errorbar(
+        time_array,
+        np.absolute(ar / (ar[0]) - 1),
+        yerr=arerr / (ar[0]),
+        label="h scale lenght (Log space)",
+    )
+if normalfit:
+    plt.errorbar(
+        time_array,
+        np.absolute(Z0t / (Z0t[0]) - 1),
+        yerr=Z0terr / (Z0t[0]),
+        label="z0 scale height (normal space)",
+    )
+    plt.errorbar(
+        time_array,
+        np.absolute(h0t / (h0t[0]) - 1),
+        yerr=h0terr / (h0t[0]),
+        label="h scale height (normal space)",
+    )
+ax.set_xlabel("Time (Gyr)")
+ax.set_ylabel("Fractional difference")
+plt.legend()
+plt.savefig("Fitdifference-witherror.pdf")
+plt.close()
+
+
+ax = plt.subplot(111)
+ax.set_yscale("log")
+if logfit:
+    plt.plot(
+        time_array, np.absolute(az / (az[0]) - 1), label="z0 scale height (Log space)"
+    )
+    plt.plot(
+        time_array, np.absolute(ar / (ar[0]) - 1), label="h scale lenght (Log space)"
+    )
+if normalfit:
+    plt.plot(
+        time_array,
+        np.absolute(Z0t / (Z0t[0]) - 1),
+        label="z0 scale height (normal space)",
+    )
+    plt.plot(
+        time_array,
+        np.absolute(h0t / (h0t[0]) - 1),
+        label="h scale height (normal space)",
+    )
+ax.set_xlabel("Time (Gyr)")
+ax.set_ylabel("Fractional difference")
+plt.legend()
+plt.savefig("Fitdifference.pdf")
+plt.show()
diff --git a/examples/IsolatedGalaxy_dmparticles/run.sh b/examples/IsolatedGalaxy_dmparticles/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5a4d5b6ce44150983fda6daf62cf0c77854e1845
--- /dev/null
+++ b/examples/IsolatedGalaxy_dmparticles/run.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+if [ ! -e reddeathgalaxywithDM.hdf5 ]
+then
+    echo "Fetching initial conditons for the isolated galaxy with an external potential ..."
+    ./getIC.sh
+fi 
+
+../swift --external-gravity --self-gravity --stars --threads=16 isolated_galaxy.yml 2>&1 | tee output.log
+
+
+echo "Make plots of conservation of total angular momentum" 
+if command -v python3 &>/dev/null; then
+    python3 angularmomentum.py 
+else
+    python angularmomentum.py 
+fi
+
+echo "Make plots of change of vertical and radial profile"
+if command -v python3 &>/dev/null; then
+    python3 profilefit.py 
+else
+    python profilefit.py 
+fi
diff --git a/examples/IsolatedGalaxy_potential/angularmomentum.py b/examples/IsolatedGalaxy_potential/angularmomentum.py
new file mode 100755
index 0000000000000000000000000000000000000000..4398dfeb8b079143886c5565e7667f72fc0bdcef
--- /dev/null
+++ b/examples/IsolatedGalaxy_potential/angularmomentum.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+###############################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+import numpy as np
+import h5py
+import matplotlib.pyplot as plt
+import scipy.optimize as sco
+
+
+Nmax = 2001
+steps = 10
+angmomcomp = False
+
+iterarray = np.arange(0, Nmax + 1, steps)
+Lxtot = np.zeros(len(iterarray))
+Lytot = np.zeros(len(iterarray))
+Lztot = np.zeros(len(iterarray))
+Ltot = np.zeros(len(iterarray))
+time_array = np.zeros(len(iterarray))
+
+
+for i in iterarray:
+    f = h5py.File("output_%04d.hdf5" % i, "r")
+
+    boxsize = f["Header"].attrs["BoxSize"] / 2.0
+
+    time_array[int(i / steps)] = f["Header"].attrs["Time"]
+
+    particles = f["PartType4"]
+    coordinates = particles["Coordinates"][:, :]
+    velocities = particles["Velocities"][:, :]
+    masses = particles["Masses"][:]
+
+    R = (
+        (coordinates[:, 0] - boxsize[0]) ** 2 + (coordinates[:, 1] - boxsize[1]) ** 2
+    ) ** 0.5
+    X = np.abs(coordinates[:, 0] - boxsize[0])
+    Y = np.abs(coordinates[:, 1] - boxsize[1])
+    Z = np.abs(coordinates[:, 2] - boxsize[2])
+
+    vx = velocities[:, 0]
+    vy = velocities[:, 1]
+    vz = velocities[:, 2]
+
+    Lx = (Y * vz - Z * vy) * masses
+    Ly = (Z * vx - X * vz) * masses
+    Lz = (X * vy - Y * vx) * masses
+
+    L = (Lx ** 2 + Ly ** 2 + Lz ** 2) ** 0.5
+
+    Lxtot[int(i / steps)] = np.sum(Lx)
+    Lytot[int(i / steps)] = np.sum(Ly)
+    Lztot[int(i / steps)] = np.sum(Lz)
+    Ltot[int(i / steps)] = np.sum(L)
+
+time_array[-1] = 2.0
+if angmomcomp:
+    plt.plot(time_array, Lxtot / Lxtot[0] - 1, label="Lx total")
+    plt.plot(time_array, Lytot / Lytot[0] - 1, label="Ly total")
+    plt.plot(time_array, Lztot / Lztot[0] - 1, label="Lz total")
+plt.plot(time_array, Ltot / Ltot[0] - 1, label="L total")
+plt.xlabel("Time")
+plt.ylabel("ratio between current and zero angular momentum")
+plt.legend()
+plt.show()
+
+plt.semilogy(time_array, np.absolute(Ltot / Ltot[0] - 1))
+plt.xlabel("Time (Gyr)")
+plt.ylabel("Fractional change of total angular momentum")
+plt.savefig("Total_angular_momentum.png")
+plt.show()
+plt.close()
diff --git a/examples/IsolatedGalaxy_potential/getIC.sh b/examples/IsolatedGalaxy_potential/getIC.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0e621c990792d5ee86c75c91141457f402319b72
--- /dev/null
+++ b/examples/IsolatedGalaxy_potential/getIC.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+wget https://home.strw.leidenuniv.nl/~nobels/data/3e11-star-only-static-potential-galaxy.hdf5 
+
diff --git a/examples/IsolatedGalaxy_potential/isolated_galaxy.yml b/examples/IsolatedGalaxy_potential/isolated_galaxy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..deee132ee38ae5e04397839a21a677f4851e6bac
--- /dev/null
+++ b/examples/IsolatedGalaxy_potential/isolated_galaxy.yml
@@ -0,0 +1,56 @@
+# Define the system of units to use internally.
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.9891E43   # 10^10 solar masses 
+  UnitLength_in_cgs:   3.08567758E21   # 1 kpc 
+  UnitVelocity_in_cgs: 1E5   # km/s
+  UnitCurrent_in_cgs:  1   # Amperes
+  UnitTemp_in_cgs:     1   # Kelvin
+
+# Parameters for the self-gravity scheme
+Gravity:
+  mesh_side_length:       32        # Number of cells along each axis for the periodic gravity mesh.
+  eta:          0.025               # Constant dimensionless multiplier for time integration.
+  theta:        0.7                 # Opening angle (Multipole acceptance criterion).
+  comoving_softening:     0.0300 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0300    # Physical softening length (in internal units).
+
+# Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.)
+TimeIntegration:
+  time_begin:        0.    # The starting time of the simulation (in internal units).
+  time_end:          2.    # The end time of the simulation (in internal units).
+  dt_min:            1e-6  # The minimal time-step size of the simulation (in internal units).
+  dt_max:            1e-2  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:   output      # Common part of the name of output files
+  time_first: 0.          # (Optional) Time of the first output if non-cosmological time-integration (in internal units)
+  delta_time: 0.001        # Time difference between consecutive outputs (in internal units)
+
+  
+# Parameters governing the conserved quantities statistics
+Statistics:
+  delta_time:           1e-2     # Time between statistics output
+  time_first:             0.     # (Optional) Time of the first stats output if non-cosmological time-integration (in internal units)
+
+Scheduler:
+  max_top_level_cells:   96
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  3e11-star-only-static-potential-galaxy.hdf5  # The file to read
+  periodic:                    0    # Are we running with periodic ICs?
+
+# Hernquist potential parameters
+HernquistPotential:
+  useabspos:       0        # 0 -> positions based on centre, 1 -> absolute positions 
+  position:        [0.,0.,0.]    # Location of centre of isothermal potential with respect to centre of the box (if 0) otherwise absolute (if 1) (internal units)
+  idealizeddisk:   1        # Run with an idealized galaxy disk
+  M200:            30.0   # M200 of the galaxy disk
+  h:               0.704    # reduced Hubble constant (value does not specify the used units!)
+  concentration:   7.1      # concentration of the Halo
+  diskfraction:              0.0434370991372   # Disk mass fraction
+  bulgefraction:              0.00705852860979  # Bulge mass fraction
+  timestep_mult:   0.01     # Dimensionless pre-factor for the time-step condition, basically determines the fraction of the orbital time we use to do the time integration
+  epsilon:         0.030      # Softening size (internal units)
+ 
diff --git a/examples/IsolatedGalaxy_potential/profilefit.py b/examples/IsolatedGalaxy_potential/profilefit.py
new file mode 100755
index 0000000000000000000000000000000000000000..e7755062ea45de4f42716b14c5896b0da676f001
--- /dev/null
+++ b/examples/IsolatedGalaxy_potential/profilefit.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+###############################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+import numpy as np
+import h5py
+import matplotlib.pyplot as plt
+from matplotlib.colors import BoundaryNorm
+from matplotlib.ticker import MaxNLocator
+import scipy.optimize as sco
+import os
+
+
+def linearfunc(x, a, b):
+    return a * x + b
+
+
+def radialfunc(r, h, A):
+    return A * np.exp(-r / h) * r
+
+
+def verticalfunc(z, A, z0, zoff):
+    return 2 * A * np.exp(-(z - zoff) / z0)
+
+
+def verticalfunc2(z, A, z0):
+    return 2 * A * np.exp(-(z) / z0)
+
+
+def verticalfunc3(z, A, z0, zoff, b):
+    return 2 * A * np.exp(-(z - zoff) / z0) + b
+
+
+Nmax = 2001
+steps = 10
+storefits = False
+logfit = True
+normalfit = False
+
+# if the user wants to store the indivudal fits
+if storefits:
+    if not os.path.exists("radial"):
+        os.mkdir("radial")
+        os.mkdir("vertical")
+        os.mkdir("histsnap")
+
+
+# Initialize the arrays
+R_ideal = np.linspace(0, 40, 100)
+Z_ideal = np.linspace(0, 10, 100)
+
+iterarray = np.arange(0, Nmax + 1, steps)
+
+Z0t = np.zeros(len(iterarray))
+Z0terr = np.zeros(len(iterarray))
+h0t = np.zeros(len(iterarray))
+h0terr = np.zeros(len(iterarray))
+Ar = np.zeros(len(iterarray))
+Arerr = np.zeros(len(iterarray))
+Az = np.zeros(len(iterarray))
+Azerr = np.zeros(len(iterarray))
+time_array = np.zeros(len(iterarray))
+
+ar = np.zeros(len(iterarray))
+arerr = np.zeros(len(iterarray))
+br = np.zeros(len(iterarray))
+brerr = np.zeros(len(iterarray))
+az = np.zeros(len(iterarray))
+azerr = np.zeros(len(iterarray))
+bz = np.zeros(len(iterarray))
+bzerr = np.zeros(len(iterarray))
+eps = 1e-6
+
+
+for i in iterarray:
+    # Getting the data from the snapshots
+    f = h5py.File("output_%04d.hdf5" % i, "r")
+
+    boxsize = f["Header"].attrs["BoxSize"] / 2.0
+
+    time_array[int(i / steps)] = f["Header"].attrs["Time"]
+
+    particles = f["PartType4"]
+    coordinates = particles["Coordinates"][:, :]
+    masses = particles["Masses"][:]
+
+    R = (
+        (coordinates[:, 0] - boxsize[0]) ** 2 + (coordinates[:, 1] - boxsize[1]) ** 2
+    ) ** 0.5
+    Z = np.abs(coordinates[:, 1] - boxsize[1])
+
+    # Bin the coordinates to make them suitable for fitting
+    Rhist = np.histogram(R, bins=100, range=[0, 40], normed=True)
+    Zhist = np.histogram(Z, bins=100, range=[0, 10.0], normed=True)
+
+    # Create correct variables for fitting
+    Ry = Rhist[0]
+    Rx = (Rhist[1][1:] + Rhist[1][: len(Rhist[0])]) / 2.0
+
+    Zy = Zhist[0]
+    Zx = (Zhist[1][1:] + Zhist[1][: len(Zhist[0])]) / 2.0
+
+    # Fit with two methods: non-linear LSQ and linear LSQ in log space
+    bestsolR = sco.curve_fit(radialfunc, Rx[10:], Ry[10:], p0=[2.0, 0.2])
+    bestsolZ = sco.curve_fit(verticalfunc, Zx[40:], Zy[40:])
+    bestsolRlog = sco.curve_fit(linearfunc, Rx[10:], np.log10(Ry[10:] + eps))
+    bestsolZlog = sco.curve_fit(linearfunc, Zx[40:], np.log10(Zy[40:] + eps))
+
+    # Store variables
+    h0t[int(i / steps)] = bestsolR[0][0]
+    Z0t[int(i / steps)] = bestsolZ[0][1]
+    Ar[int(i / steps)] = bestsolR[0][1]
+    Az[int(i / steps)] = bestsolZ[0][0]
+    Z0terr[int(i / steps)] = (bestsolZ[1][1, 1]) ** 0.5
+    h0terr[int(i / steps)] = (bestsolR[1][0, 0]) ** 0.5
+    Arerr[int(i / steps)] = (bestsolR[1][1, 1]) ** 0.5
+    Azerr[int(i / steps)] = (bestsolZ[1][0, 0]) ** 0.5
+
+    ar[int(i / steps)] = bestsolRlog[0][0]
+    arerr[int(i / steps)] = (bestsolRlog[1][0, 0]) ** 0.5
+    br[int(i / steps)] = bestsolRlog[0][1]
+    brerr[int(i / steps)] = (bestsolRlog[1][1, 1]) ** 0.5
+    az[int(i / steps)] = bestsolZlog[0][0]
+    azerr[int(i / steps)] = (bestsolZlog[1][0, 0]) ** 0.5
+    bz[int(i / steps)] = bestsolZlog[0][1]
+    bzerr[int(i / steps)] = (bestsolZlog[1][1, 1]) ** 0.5
+
+    if storefits:
+        plt.step(Rx, Ry)
+        plt.plot(
+            R_ideal,
+            radialfunc(R_ideal, bestsolR[0][0], bestsolR[0][1]),
+            label="Non linear LSQ",
+        )
+        plt.plot(
+            R_ideal,
+            10 ** (linearfunc(R_ideal, bestsolRlog[0][0], bestsolRlog[0][1])),
+            label="Linear LSQ",
+        )
+        plt.xlim(0, 40)
+        plt.ylim(0, 0.25)
+        plt.xlabel("R (kpc)")
+        plt.ylabel("Probability")
+        plt.savefig("./radial/radialsnap%04d.png" % i)
+        plt.close()
+
+        plt.step(Zx, Zy)
+        plt.plot(
+            Z_ideal,
+            verticalfunc(Z_ideal, bestsolZ[0][0], bestsolZ[0][1], bestsolZ[0][2]),
+            label="Non linear LSQ",
+        )
+        plt.plot(
+            Z_ideal,
+            10 ** (linearfunc(Z_ideal, bestsolZlog[0][0], bestsolZlog[0][1])),
+            label="Linear LSQ",
+        )
+        plt.xlim(0, 10.0)
+        plt.ylim(0, 0.6)
+        plt.xlabel("z (kpc)")
+        plt.ylabel("Probability")
+        plt.savefig("./vertical/verticalsnap%04d.png" % i)
+        plt.close()
+
+time_array[-1] = 2.0
+
+ax = plt.subplot(111)
+ax.set_yscale("log")
+if logfit:
+    plt.errorbar(
+        time_array,
+        np.absolute(az / (az[0]) - 1),
+        yerr=azerr / (az[0]),
+        label="z0 scale height (Log space)",
+    )
+    plt.errorbar(
+        time_array,
+        np.absolute(ar / (ar[0]) - 1),
+        yerr=arerr / (ar[0]),
+        label="h scale lenght (Log space)",
+    )
+if normalfit:
+    plt.errorbar(
+        time_array,
+        np.absolute(Z0t / (Z0t[0]) - 1),
+        yerr=Z0terr / (Z0t[0]),
+        label="z0 scale height (normal space)",
+    )
+    plt.errorbar(
+        time_array,
+        np.absolute(h0t / (h0t[0]) - 1),
+        yerr=h0terr / (h0t[0]),
+        label="h scale height (normal space)",
+    )
+ax.set_xlabel("Time (Gyr)")
+ax.set_ylabel("Fractional difference")
+plt.legend()
+plt.savefig("Fitdifference-witherror.pdf")
+plt.close()
+
+
+ax = plt.subplot(111)
+ax.set_yscale("log")
+if logfit:
+    plt.plot(
+        time_array, np.absolute(az / (az[0]) - 1), label="z0 scale height (Log space)"
+    )
+    plt.plot(
+        time_array, np.absolute(ar / (ar[0]) - 1), label="h scale lenght (Log space)"
+    )
+if normalfit:
+    plt.plot(
+        time_array,
+        np.absolute(Z0t / (Z0t[0]) - 1),
+        label="z0 scale height (normal space)",
+    )
+    plt.plot(
+        time_array,
+        np.absolute(h0t / (h0t[0]) - 1),
+        label="h scale height (normal space)",
+    )
+ax.set_xlabel("Time (Gyr)")
+ax.set_ylabel("Fractional difference")
+plt.legend()
+plt.savefig("Fitdifference.pdf")
+plt.show()
diff --git a/examples/IsolatedGalaxy_potential/run.sh b/examples/IsolatedGalaxy_potential/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e93b43b55bdb233282da05fb5098347969279f13
--- /dev/null
+++ b/examples/IsolatedGalaxy_potential/run.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+if [ ! -e reddeathgalaxy.hdf5 ]
+then
+    echo "Fetching initial conditons for the isolated galaxy with an external potential ..."
+    ./getIC.sh
+fi 
+
+../swift --external-gravity --self-gravity --stars --threads=16 isolated_galaxy.yml 2>&1 | tee output.log
+
+
+echo "Make plots of conservation of total angular momentum" 
+if command -v python3 &>/dev/null; then
+    python3 angularmomentum.py 
+else
+    python angularmomentum.py 
+fi
+
+echo "Make plots of change of vertical and radial profile"
+if command -v python3 &>/dev/null; then
+    python3 profilefit.py 
+else
+    python profilefit.py 
+fi
diff --git a/examples/IsothermalPotential/run.sh b/examples/IsothermalPotential/run.sh
index a5f03f32f82e27660d0a950335d731cf0ff7401d..bc44b2bd1f05b84354f171801b9c2d6c28ea3641 100755
--- a/examples/IsothermalPotential/run.sh
+++ b/examples/IsothermalPotential/run.sh
@@ -8,6 +8,6 @@ then
 fi
 
 rm -rf Isothermal_*.hdf5
-../swift -g -t 1 isothermal.yml 2>&1 | tee output.log
+../swift --external-gravity --threads=1 isothermal.yml 2>&1 | tee output.log
 
 python energy_plot.py
diff --git a/examples/KelvinHelmholtzGrowthRate_2D/run.sh b/examples/KelvinHelmholtzGrowthRate_2D/run.sh
index 3e6e026f66b14846a5c6e8e9daf99797dc3ff87a..505d64498463bfa414ed30b25abb91ccd1b7f0df 100755
--- a/examples/KelvinHelmholtzGrowthRate_2D/run.sh
+++ b/examples/KelvinHelmholtzGrowthRate_2D/run.sh
@@ -9,7 +9,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 kelvinHelmholtzGrowthRate.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 kelvinHelmholtzGrowthRate.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 100
diff --git a/examples/KelvinHelmholtzGrowthRate_3D/run.sh b/examples/KelvinHelmholtzGrowthRate_3D/run.sh
index 3e6e026f66b14846a5c6e8e9daf99797dc3ff87a..505d64498463bfa414ed30b25abb91ccd1b7f0df 100755
--- a/examples/KelvinHelmholtzGrowthRate_3D/run.sh
+++ b/examples/KelvinHelmholtzGrowthRate_3D/run.sh
@@ -9,7 +9,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 kelvinHelmholtzGrowthRate.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 kelvinHelmholtzGrowthRate.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 100
diff --git a/examples/KelvinHelmholtz_2D/run.sh b/examples/KelvinHelmholtz_2D/run.sh
index dbb39caf383279dbc71c2baa125499d115538654..ef823cb85b88ff1b228b6906835fac8383db8b8c 100755
--- a/examples/KelvinHelmholtz_2D/run.sh
+++ b/examples/KelvinHelmholtz_2D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 kelvinHelmholtz.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 kelvinHelmholtz.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 6
diff --git a/examples/KeplerianRing/README.md b/examples/KeplerianRing/README.md
index 1c361f275d60ef1ca46d696e2e9507bb749e531c..1cb2e2119d0f0bb093abf194ab18da91dd587d32 100644
--- a/examples/KeplerianRing/README.md
+++ b/examples/KeplerianRing/README.md
@@ -69,7 +69,7 @@ Plotting
 
 Once you have ran swift (we suggest that you use the following)
 
-    ../swift -g -S -s -t 16 keplerian_ring.yml 2>&1 | tee output.log
+    ../swift --external-gravity --stars --hydro --threads=16 keplerian_ring.yml 2>&1 | tee output.log
 
 there will be around 350 ```.hdf5``` files in your directory. To check out
 the results of the example use the plotting script:
diff --git a/examples/KeplerianRing/run.sh b/examples/KeplerianRing/run.sh
index 0195846a8839a27083594c20569b1fd4d49f4c16..236f512d1c9f5b5d660fc7d9f540c085ad3e29ab 100755
--- a/examples/KeplerianRing/run.sh
+++ b/examples/KeplerianRing/run.sh
@@ -9,7 +9,7 @@ then
 fi
 
 rm -rf keplerian_ring_*.hdf5
-../swift -g -s -t 1 -v 1 keplerian_ring.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --threads=1 --verbose=1 keplerian_ring.yml 2>&1 | tee output.log
 
 echo
 echo
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 6723f5b9bfc5f20c12ac189b0d00551bbc9f8e4c..fae4e132cdf1ac24f293060d6e3a293729d109f4 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -19,12 +19,15 @@
 MYFLAGS = 
 
 # Add the source directory and the non-standard paths to the included library headers to CFLAGS
-AM_CFLAGS = -I$(top_srcdir)/src $(HDF5_CPPFLAGS) $(GSL_INCS) $(FFTW_INCS) $(GRACKLE_INCS)
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/argparse $(HDF5_CPPFLAGS) \
+	$(GSL_INCS) $(FFTW_INCS) $(GRACKLE_INCS)
 
 AM_LDFLAGS = $(HDF5_LDFLAGS)
 
 # Extra libraries.
-EXTRA_LIBS = $(HDF5_LIBS) $(FFTW_LIBS) $(PROFILER_LIBS) $(TCMALLOC_LIBS) $(JEMALLOC_LIBS) $(TBBMALLOC_LIBS) $(GRACKLE_LIBS) $(VELOCIRAPTOR_LIBS) $(GSL_LIBS)
+EXTRA_LIBS = $(HDF5_LIBS) $(FFTW_LIBS) $(PROFILER_LIBS) $(TCMALLOC_LIBS) \
+	$(JEMALLOC_LIBS) $(TBBMALLOC_LIBS) $(GRACKLE_LIBS) \
+	$(VELOCIRAPTOR_LIBS) $(GSL_LIBS)
 
 # MPI libraries.
 MPI_LIBS = $(PARMETIS_LIBS) $(METIS_LIBS) $(MPI_THREAD_LIBS)
@@ -48,12 +51,12 @@ endif
 # Sources for swift
 swift_SOURCES = main.c
 swift_CFLAGS = $(MYFLAGS) $(AM_CFLAGS) -DENGINE_POLICY="engine_policy_keep $(ENGINE_POLICY_SETAFFINITY)"
-swift_LDADD =  ../src/.libs/libswiftsim.a $(EXTRA_LIBS)
+swift_LDADD =  ../src/.libs/libswiftsim.a ../argparse/.libs/libargparse.a $(EXTRA_LIBS)
 
 # Sources for swift_mpi, do we need an affinity policy for MPI?
 swift_mpi_SOURCES = main.c
 swift_mpi_CFLAGS = $(MYFLAGS) $(AM_CFLAGS) $(MPI_FLAGS) -DENGINE_POLICY="engine_policy_keep $(ENGINE_POLICY_SETAFFINITY)"
-swift_mpi_LDADD =  ../src/.libs/libswiftsim_mpi.a $(MPI_LIBS) $(EXTRA_LIBS)
+swift_mpi_LDADD =  ../src/.libs/libswiftsim_mpi.a ../argparse/.libs/libargparse.a $(MPI_LIBS) $(EXTRA_LIBS)
 
 # Scripts to generate ICs
 EXTRA_DIST = CoolingBox/coolingBox.yml CoolingBox/energy_plot.py CoolingBox/makeIC.py CoolingBox/run.sh \
diff --git a/examples/MultiTypes/run.sh b/examples/MultiTypes/run.sh
index 38cba70393861539f18bf9fa360d51f46dd3367d..b0a3953e3223ecf5f686e74b2c0681ae31b708d8 100755
--- a/examples/MultiTypes/run.sh
+++ b/examples/MultiTypes/run.sh
@@ -7,4 +7,4 @@ then
     python makeIC.py 9 13 7 1
 fi
 
-../swift -s -g -S -t 1 multiTypes.yml 2>&1 | tee output.log
+../swift --hydro --external-gravity --stars --threads=1 multiTypes.yml 2>&1 | tee output.log
diff --git a/examples/NFW_Halo/run.sh b/examples/NFW_Halo/run.sh
index 5501f09ef4076715ae9650daf2cded91dbc0be9e..3a21c9678487a070f568a67cccb989089e59d66a 100755
--- a/examples/NFW_Halo/run.sh
+++ b/examples/NFW_Halo/run.sh
@@ -11,7 +11,7 @@ then
 fi
 
 # self gravity G, external potential g, hydro s, threads t and high verbosity v
-../swift -g -t 6 test.yml 2>&1 | tee output.log
+../swift --external-gravity --threads=6 test.yml 2>&1 | tee output.log
 
 if command -v python3 &>/dev/null; then
     python3 makePlots.py
diff --git a/examples/Noh_1D/run.sh b/examples/Noh_1D/run.sh
index 77788bfa8429e2fbf0502068baa70598acaaa791..15efd56e7b5b41dedab31a8f1cbdf11e89a2704d 100755
--- a/examples/Noh_1D/run.sh
+++ b/examples/Noh_1D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 noh.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 noh.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 12
diff --git a/examples/Noh_2D/run.sh b/examples/Noh_2D/run.sh
index cff200801018e04ea560bd2c3fbd84057aec2d7c..5595ad8439eac02fd32dbb426e4affb41215d41a 100755
--- a/examples/Noh_2D/run.sh
+++ b/examples/Noh_2D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 2 noh.yml 2>&1 | tee output.log
+../swift --hydro --threads=2 noh.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 12
diff --git a/examples/Noh_3D/run.sh b/examples/Noh_3D/run.sh
index b9e4fb145b2465433aa2bc0362aba19cc1267461..7ff7b084f4b6297c76d3d60f4bde4ac7d12e944e 100755
--- a/examples/Noh_3D/run.sh
+++ b/examples/Noh_3D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 2 noh.yml 2>&1 | tee output.log
+../swift --hydro --threads=2 noh.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 12
diff --git a/examples/PerturbedBox_3D/run.sh b/examples/PerturbedBox_3D/run.sh
index e20bff52d18322ce377fb589900fd9e13eefe64d..ab771ea1f01e6cca3b9a3dc2cf02a4d596a64006 100755
--- a/examples/PerturbedBox_3D/run.sh
+++ b/examples/PerturbedBox_3D/run.sh
@@ -7,4 +7,4 @@ then
     python makeIC.py 50
 fi
 
-../swift -s -t 16 perturbedBox.yml 2>&1 | tee output.log
+../swift --hydro --threads=16 perturbedBox.yml 2>&1 | tee output.log
diff --git a/examples/SantaBarbara/run.sh b/examples/SantaBarbara/run.sh
index f98b13aac0ea15658319a57b07417d305d3ff509..206ba7bad03e0fff12e683ee10bbe2434a73a500 100755
--- a/examples/SantaBarbara/run.sh
+++ b/examples/SantaBarbara/run.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 # Run SWIFT
-../swift -c -s -r -G -t 28 santa_barbara.yml
+../swift --cosmology --hydro --self-gravity --threads=28 santa_barbara.yml
 
diff --git a/examples/SantaBarbara_low/run.sh b/examples/SantaBarbara_low/run.sh
index 044f9f4ef340ab95ffe643104294552469a676ce..206ba7bad03e0fff12e683ee10bbe2434a73a500 100755
--- a/examples/SantaBarbara_low/run.sh
+++ b/examples/SantaBarbara_low/run.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 # Run SWIFT
-../swift -c -s -G -t 28 santa_barbara.yml
+../swift --cosmology --hydro --self-gravity --threads=28 santa_barbara.yml
 
diff --git a/examples/SedovBlast_1D/run.sh b/examples/SedovBlast_1D/run.sh
index 4b9a84f069673bd6def3b96faec71b9d4fdd0dda..ba479214961c5957a2b19d6aa118e0f0e7ee0f63 100755
--- a/examples/SedovBlast_1D/run.sh
+++ b/examples/SedovBlast_1D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 sedov.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 sedov.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 5
diff --git a/examples/SedovBlast_2D/run.sh b/examples/SedovBlast_2D/run.sh
index a32c8f0d6f3116d5486fe1bd086bf8df49d06020..b481d4555241c17015452a2139c04c541ccf1cdc 100755
--- a/examples/SedovBlast_2D/run.sh
+++ b/examples/SedovBlast_2D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 sedov.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 sedov.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 5
diff --git a/examples/SedovBlast_3D/run.sh b/examples/SedovBlast_3D/run.sh
index 00d5e5b91c31e64f824a3d2a28c8e1a126684a74..88aec36a7b96b5fd2a7fde41f0e0c9dc7185f1e8 100755
--- a/examples/SedovBlast_3D/run.sh
+++ b/examples/SedovBlast_3D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 sedov.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 sedov.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 5
diff --git a/examples/SineWavePotential_1D/run.sh b/examples/SineWavePotential_1D/run.sh
index 077cf1c0cc64ef7a85cfd0e67f8f490b0de4ba37..a725a88a175ff39c20b958c07f2e7e84e388d417 100755
--- a/examples/SineWavePotential_1D/run.sh
+++ b/examples/SineWavePotential_1D/run.sh
@@ -6,7 +6,7 @@ then
   python makeIC.py
 fi
 
-../swift -g -s -t 2 sineWavePotential.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --threads=2 sineWavePotential.yml 2>&1 | tee output.log
 
 for f in sineWavePotential_*.hdf5
 do
diff --git a/examples/SineWavePotential_2D/run.sh b/examples/SineWavePotential_2D/run.sh
index 077cf1c0cc64ef7a85cfd0e67f8f490b0de4ba37..a725a88a175ff39c20b958c07f2e7e84e388d417 100755
--- a/examples/SineWavePotential_2D/run.sh
+++ b/examples/SineWavePotential_2D/run.sh
@@ -6,7 +6,7 @@ then
   python makeIC.py
 fi
 
-../swift -g -s -t 2 sineWavePotential.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --threads=2 sineWavePotential.yml 2>&1 | tee output.log
 
 for f in sineWavePotential_*.hdf5
 do
diff --git a/examples/SineWavePotential_3D/run.sh b/examples/SineWavePotential_3D/run.sh
index 077cf1c0cc64ef7a85cfd0e67f8f490b0de4ba37..a725a88a175ff39c20b958c07f2e7e84e388d417 100755
--- a/examples/SineWavePotential_3D/run.sh
+++ b/examples/SineWavePotential_3D/run.sh
@@ -6,7 +6,7 @@ then
   python makeIC.py
 fi
 
-../swift -g -s -t 2 sineWavePotential.yml 2>&1 | tee output.log
+../swift --external-gravity --hydro --threads=2 sineWavePotential.yml 2>&1 | tee output.log
 
 for f in sineWavePotential_*.hdf5
 do
diff --git a/examples/SmallCosmoVolume/run.sh b/examples/SmallCosmoVolume/run.sh
index e243215813598fade53c07b017e380be08558942..12c98d1b636ef4ce324f861f6db236738785f856 100755
--- a/examples/SmallCosmoVolume/run.sh
+++ b/examples/SmallCosmoVolume/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -c -s -G -t 8 small_cosmo_volume.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --threads=8 small_cosmo_volume.yml 2>&1 | tee output.log
 
 # Plot the temperature evolution
 python plotTempEvolution.py
diff --git a/examples/SmallCosmoVolume_DM/run.sh b/examples/SmallCosmoVolume_DM/run.sh
index 8a4cd944c713b387fcc38a6328bcb1d763c524a9..9c002f4643ad3cad073e6c4a39066bc20cf7b52a 100755
--- a/examples/SmallCosmoVolume_DM/run.sh
+++ b/examples/SmallCosmoVolume_DM/run.sh
@@ -8,5 +8,5 @@ then
 fi
 
 # Run SWIFT
-../swift -c -G -t 8 small_cosmo_volume_dm.yml 2>&1 | tee output.log
+../swift --cosmology --self-gravity --threads=8 small_cosmo_volume_dm.yml 2>&1 | tee output.log
 
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/README b/examples/SmallCosmoVolume_VELOCIraptor/README
new file mode 100644
index 0000000000000000000000000000000000000000..76eab82c0c434ceab334f82be8bd52e0d2dd4d08
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/README
@@ -0,0 +1,16 @@
+Small LCDM cosmological simulation generated by C. Power. Cosmology
+is WMAP9 and the box is 100Mpc/h in size with 64^3 particles.
+We use a softening length of 1/25th of the mean inter-particle separation.
+
+The ICs have been generated to run with Gadget-2 so we need to switch
+on the options to cancel the h-factors and a-factors at reading time.
+We generate gas from the ICs using SWIFT's internal mechanism and set the
+temperature to the expected gas temperature at this redshift.
+
+This example runs with Hydrodynamics and a halo finder, the halo finder 
+is run while running the simulation. At the end it is possible to 
+calculate the halo mass function of the halos in the simulated 
+volume, this is done by using haloevol.py.
+
+MD5 checksum of the ICs:
+08736c3101fd738e22f5159f78e6022b  small_cosmo_volume.hdf5
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/getHMF.py b/examples/SmallCosmoVolume_VELOCIraptor/getHMF.py
new file mode 100755
index 0000000000000000000000000000000000000000..e56df323b004dfcfcd2c75c427fa6f3ecbe37a29
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/getHMF.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+###############################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+import numpy as np
+from hmf import MassFunction
+import hmf
+from astropy.cosmology import FlatLambdaCDM
+
+
+
+def getHMFz(z, H0=70.3, Om0=0.276, Ob0=0.0455, Tcmb0=2.725, Mmin=1e10, Mmax=1e15):
+    """ Fast function to call the HMF from hmf, this function only has 
+        7 variables and will return the dn/d(log10 M) and M array.
+        z: redshift
+        H0: Hubble constant
+        Om0: Matter density
+        Ob0: Baryon density
+        Tcmb0: CMB temperature at z=0
+        Mmin: minimum mass (solar masses)
+        Mmax: Maximum mass (solar masses) 
+    """
+    new_model = FlatLambdaCDM(H0=H0, Om0=Om0, Ob0=Ob0, Tcmb0=Tcmb0)
+    hmff = MassFunction(
+        cosmo_model=new_model,
+        Mmax=np.log10(Mmax),
+        Mmin=np.log10(Mmin),
+        z=z,
+        hmf_model="ST",
+    )
+    return hmff.m, hmff.dndlog10m
+
+
+def getHMFztinker(z, H0=70.3, Om0=0.276, Ob0=0.0455, Tcmb0=2.725, Mmin=1e10, Mmax=1e15):
+    """ Fast function to call the HMF from hmf, this function only has 
+        6 variables and will return the dn/d(log10 M) and M array.
+        H0: Hubble constant
+        Om0: Matter density
+        Ob0: Baryon density
+        Tcmb0: CMB temperature at z=0
+        Mmin: minimum mass (solar masses)
+        Mmax: Maximum mass (solar masses) 
+    """
+    new_model = FlatLambdaCDM(H0=H0, Om0=Om0, Ob0=Ob0, Tcmb0=Tcmb0)
+    hmff = MassFunction(
+        cosmo_model=new_model, Mmax=np.log10(Mmax), Mmin=np.log10(Mmin), z=z
+    )
+    return hmff.m, hmff.dndlog10m
+
+
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/getIC.sh b/examples/SmallCosmoVolume_VELOCIraptor/getIC.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3b8136cc5aca00a25792655c6c505cfeeb0f2bc9
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/getIC.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/small_cosmo_volume.hdf5
+
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/haloevol.py b/examples/SmallCosmoVolume_VELOCIraptor/haloevol.py
new file mode 100755
index 0000000000000000000000000000000000000000..94e206cdf686ef5d2d3676d6fc36d6dfe8aea558
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/haloevol.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+###############################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+import numpy as np
+import h5py
+import matplotlib.pyplot as plt
+from getHMF import getHMFz, getHMFztinker
+
+dlogm = 0.2
+bins = 10 ** (np.arange(12, 15.2, dlogm))
+V = 142.0 ** 3
+
+itervalues = np.array([175, 185, 192, 198])
+
+for j in itervalues:
+    # Load the data
+    g = h5py.File("stf_%04d.VELOCIraptor.properties" % j, "r")
+    mass = g["Mass_200crit"][:] * 1e10  # convert to the correct unit
+    binnedmass, massrange = np.histogram(mass, bins=bins)
+
+    massnlarger = np.zeros(len(binnedmass))
+    for i in range(0, len(massnlarger)):
+        massnlarger[i] = np.sum(binnedmass[i:])
+
+    f = h5py.File("snap_%04d.hdf5" % (j + 1))
+    cosmo = f["Cosmology"]
+    redshift = cosmo.attrs["Redshift"][0]
+    a = cosmo.attrs["Scale-factor"][0]
+
+    # Determine the HMF
+    errormassn = massnlarger ** 0.5
+    numbden = massnlarger / V / a ** 3
+    numbdenerr = errormassn / V / a ** 3
+    massplot = (massrange[0:15] + massrange[1:16]) / 2
+    dernumbden = -np.diff(numbden) / np.diff(np.log10(massplot))
+    dererr = 2 ** 0.5 / dlogm * (numbdenerr[0:14] + numbdenerr[1:15]) / 2
+
+    plt.plot(
+        (massplot[0:14] + massplot[1:15]) / 2, dernumbden, label="SWIFT - SPH $64^3$"
+    )
+    plt.fill_between(
+        (massplot[0:14] + massplot[1:15]) / 2,
+        dernumbden - dererr,
+        dernumbden + dererr,
+        alpha=0.4,
+    )
+    plt.xscale("log")
+    plt.ylim(1e-6, 1e-1)
+    plt.xlim(10 ** 11, 10 ** 15.5)
+
+    xplace = 10 ** 14.5
+    plt.text(xplace, 10 ** -2.3, "$\Omega_m=0.276$")
+    plt.text(xplace, 10 ** -2.6, "$\Omega_b=0.0455$")
+    plt.text(xplace, 10 ** -2.9, "$\Omega_\Lambda=0.724$")
+    plt.text(xplace, 10 ** -3.2, "$h=0.703$")
+    plt.text(xplace, 10 ** -3.5, "$z=%2.2f$" % redshift)
+
+    m, dndlogm = getHMFz(redshift)
+    plt.plot(m / 0.7, dndlogm * 0.7 ** 3, label="Sheth et al. 2001")
+
+    m, dndlogm = getHMFztinker(redshift)
+    plt.plot(m / 0.7, dndlogm * 0.7 ** 3, label="Tinker et al. 2008")
+
+    plt.xlabel("M${}_{200}$ ($M_\odot$)")
+    plt.ylabel("dn/d($\log$10(M${}_{200}$) ($Mpc^{-3}$)")
+    plt.axvline(x=32 * 3.5e11, linestyle="--", color="k")
+    plt.yscale("log")
+    plt.legend()
+    plt.savefig("./HMF_%04d.png" % j)
+    plt.close()
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/run.sh b/examples/SmallCosmoVolume_VELOCIraptor/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..cde550f0a52186b8284427606ff3b71aa718cd34
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/run.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+ # Generate the initial conditions if they are not present.
+if [ ! -e small_cosmo_volume.hdf5 ]
+then
+    echo "Fetching initial conditions for the small cosmological volume example..."
+    ./getIC.sh
+fi
+
+# Run SWIFT
+../swift --cosmology --hydro --self-gravity --velociraptor --threads=8 small_cosmo_volume.yml 2>&1 | tee output.log
+
+echo "Make a plot of the HMF"
+if command -v python3 &>/dev/null; then
+    python3 haloevol.py
+else
+    python haloevol.py
+fi
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml b/examples/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c8157a7a0e0065b1f58667fb8437b9e3883eda75
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml
@@ -0,0 +1,67 @@
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.98848e43    # 10^10 M_sun
+  UnitLength_in_cgs:   3.08567758e24 # 1 Mpc
+  UnitVelocity_in_cgs: 1e5           # 1 km/s
+  UnitCurrent_in_cgs:  1             # Amperes
+  UnitTemp_in_cgs:     1             # Kelvin
+
+Cosmology:                      # WMAP9 cosmology
+  Omega_m:        0.276
+  Omega_lambda:   0.724
+  Omega_b:        0.0455
+  h:              0.703
+  a_begin:        0.019607843	# z_ini = 50.
+  a_end:          1.0		# z_end = 0.
+
+# Parameters governing the time integration
+TimeIntegration:
+  dt_min:     1e-6 
+  dt_max:     1e-2 
+
+# Parameters for the self-gravity scheme
+Gravity:
+  eta:          0.025         
+  theta:        0.3           
+  comoving_softening:     0.0889     # 1/25th of the mean inter-particle separation: 88.9 kpc
+  max_physical_softening: 0.0889     # 1/25th of the mean inter-particle separation: 88.9 kpc
+  mesh_side_length:       64
+
+# Parameters of the hydro scheme
+SPH:
+  resolution_eta:      1.2348   # "48 Ngb" with the cubic spline kernel
+  CFL_condition:       0.1
+  initial_temperature: 7075.    # (1 + z_ini)^2 * 2.72K
+  minimal_temperature: 100.
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:            snap
+  delta_time:          1.02
+  scale_factor_first:  0.02
+  
+# Parameters governing the conserved quantities statistics
+Statistics:
+  delta_time:          1.02
+  scale_factor_first:  0.02
+  
+Scheduler:
+  max_top_level_cells: 8
+  cell_split_size:     50
+  
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  small_cosmo_volume.hdf5
+  cleanup_h_factors:           1    
+  cleanup_velocity_factors:    1  
+  generate_gas_in_ics: 1            # Generate gas particles from the DM-only ICs
+  cleanup_smoothing_lengths: 1      # Since we generate gas, make use of the (expensive) cleaning-up procedure.
+
+# Structure finding options (requires velociraptor)
+StructureFinding:
+  config_file_name:     stfconfig_input.cfg
+  basename:             ./stf
+  output_time_format:   1
+  scale_factor_first:   0.02
+  delta_time:           1.02
+ 
diff --git a/examples/SmallCosmoVolume_VELOCIraptor/stfconfig_input.cfg b/examples/SmallCosmoVolume_VELOCIraptor/stfconfig_input.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..4306bae3d23aab924ce8fa3a5c50e839823fbc2f
--- /dev/null
+++ b/examples/SmallCosmoVolume_VELOCIraptor/stfconfig_input.cfg
@@ -0,0 +1,165 @@
+#suggested configuration file for hydro run and subhalo (and galaxy ie: associated baryons) catalog
+
+################################
+#input related
+################################
+#input is from a cosmological so can use parameters like box size, h, Omega_m to calculate length and density scales
+Cosmological_input=1
+
+#sets the total buffer size in bytes used to store temporary particle information
+#of mpi read threads before they are broadcast to the appropriate waiting non-read threads
+#if not set, default value is equivalent to 1e6 particles per mpi process, quite large
+#but significantly minimises the number of send/receives
+#in this example the buffer size is roughly that for a send/receive of 10000 particles
+#for 100 mpi processes
+MPI_particle_total_buf_size=100000000
+
+#gadget input related
+#NSPH_extra_blocks=0 #read extra sph blocks
+#NStar_extra_blocks=0 #read extra star blocks
+#NBH_extra_blocks=0 #read extra black hole blocks
+
+#HDF related input
+#Set the HDF name convection, 0 is illustris, 1 is gadget x, 2 is Eagle, 3 is gizmo
+HDF_name_convention=0
+#whether star particles are present in the input
+Input_includes_star_particle=1
+#bhs present
+Input_includes_bh_particle=1
+#no wind present
+Input_includes_wind_particle=0
+#no tracers present
+Input_includes_tracer_particle=0
+#no low res/extra dm particle types present
+Input_includes_extradm_particle=0
+
+################################
+#unit options, should always be provided
+################################
+#EDIT THIS SECTION!!!!
+#conversion of output length units to kpc
+Length_unit_to_kpc=1.0
+#conversion of output velocity units to km/s
+Velocity_to_kms=1.0
+#conversion of output mass units to solar masses
+Mass_to_solarmass=1.0
+#units conversion from input input to desired internal unit
+Length_unit=1.0 #default code unit,
+Velocity_unit=1.0 #default velocity unit,
+Mass_unit=1.0 #default mass unit,
+Gravity=43.0211349 #for 1e10 Msun, km/s and Mpc
+Hubble_unit=100.0 # assuming units are km/s and Mpc, then value of Hubble in km/s/Mpc
+
+################################
+#search related options
+################################
+
+#how to search a simulation
+Particle_search_type=1 #search all particles, see allvars for other types
+#for baryon search
+Baryon_searchflag=2 #if 1 search for baryons separately using phase-space search when identifying substructures, 2 allows special treatment in field FOF linking and phase-space substructure search, 0 treat the same as dark matter particles
+#for search for substruture
+Search_for_substructure=1 #if 0, end search once field objects are found
+#also useful for zoom simulations or simulations of individual objects, setting this flag means no field structure search is run
+Singlehalo_search=0 #if file is single halo in which one wishes to search for substructure
+#additional option for field haloes
+Keep_FOF=0 #if field 6DFOF search is done, allows to keep structures found in 3DFOF (can be interpreted as the inter halo stellar mass when only stellar search is used).\n
+
+#minimum size for structures
+Minimum_size=20 #min 20 particles
+Minimum_halo_size=-1 #if field halos have different minimum sizes, otherwise set to -1.
+
+#for field fof halo search
+FoF_Field_search_type=3 #5 3DFOF search for field halos, 4 for 6DFOF clean up of field halos, 3 for 6DFOF with velocity scale distinct for each halo
+Halo_linking_length_factor=2.0 #factor by which Physical_linking_length is changed when searching for field halos. Typical values are ~2 when using iterative substructure search.
+Halo_velocity_linking_length_factor=5.0 #for 6d fof halo search increase ellv from substructure search
+
+#for mean field estimates and local velocity density distribution funciton estimator related quantiites, rarely need to change this
+Cell_fraction = 0.01 #fraction of field fof halo used to determine mean velocity distribution function. Typical values are ~0.005-0.02
+Grid_type=1 #normal entropy based grid, shouldn't have to change
+Nsearch_velocity=32 #number of velocity neighbours used to calculate local velocity distribution function. Typial values are ~32
+Nsearch_physical=256 #numerof physical neighbours from which the nearest velocity neighbour set is based. Typical values are 128-512
+
+#for substructure search, rarely ever need to change this
+FoF_search_type=1 #default phase-space FOF search. Don't really need to change
+Iterative_searchflag=1 #iterative substructure search, for substructure find initial candidate substructures with smaller linking lengths then expand search region
+Outlier_threshold=2.5 #outlier threshold for a particle to be considered residing in substructure, that is how dynamically distinct a particle is. Typical values are >2
+Velocity_ratio=2.0 #ratio of speeds used in phase-space FOF
+Velocity_opening_angle=0.10 #angle between velocities. 18 degrees here, typical values are ~10-30
+Physical_linking_length=0.10 #physical linking length. IF reading periodic volumes in gadget/hdf/ramses, in units of the effective inter-particle spacing. Otherwise in user defined code units. Here set to 0.10 as iterative flag one, values of 0.1-0.3 are typical.
+Velocity_linking_length=0.20 #where scaled by structure dispersion
+Significance_level=1.0 #how significant a substructure is relative to Poisson noise. Values >= 1 are fine.
+
+#for iterative substructure search, rarely ever need to change this
+Iterative_threshold_factor=1.0 #change in threshold value when using iterative search. Here no increase in threshold if iterative or not
+Iterative_linking_length_factor=2.0 #increase in final linking final iterative substructure search will be sqrt(2.25)*this factor
+Iterative_Vratio_factor=1.0 #change in Vratio when using iterative search. no change in vratio
+Iterative_ThetaOp_factor=1.0 #change in velocity opening angle. no change in velocity opening angle
+
+#for checking for halo merger remnants, which are defined as large, well separated phase-space density maxima
+Halo_core_search=2 # searches for separate 6dfof cores in field haloes, and then more than just flags halo as merging, assigns particles to each merging "halo". 2 is full separation, 1 is flagging, 0 is off
+#if searching for cores, linking lengths. likely does not need to change much
+Use_adaptive_core_search=0 #calculate dispersions in configuration & vel space to determine linking lengths
+Use_phase_tensor_core_growth=2 #use full stepped phase-space tensor assignment
+Halo_core_ellx_fac=0.7 #how linking lengths are changed when searching for local 6DFOF cores,
+Halo_core_ellv_fac=2.0 #how velocity lengths based on dispersions are changed when searching for local 6DFOF cores
+Halo_core_ncellfac=0.005 #fraction of total halo particle number setting min size of a local 6DFOF core
+Halo_core_num_loops=8 #number of loops to iteratively search for cores
+Halo_core_loop_ellx_fac=0.75 #how much to change the configuration space linking per iteration
+Halo_core_loop_ellv_fac=1.0 #how much to change the velocity space linking per iteration
+Halo_core_loop_elln_fac=1.2 #how much to change the min number of particles per iteration
+Halo_core_phase_significance=2.0 #how significant a core must be in terms of dispersions (sigma) significance
+
+################################
+#Unbinding options (VELOCIraptor is able to accurately identify tidal debris so particles need not be bound to a structure)
+################################
+
+#unbinding related items
+Unbind_flag=1 #run unbinding
+#alpha factor used to determine whether particle is "bound" alaph*T+W<0. For standard subhalo catalogues use >0.9 but if interested in tidal debris 0.2-0.5
+Allowed_kinetic_potential_ratio=0.95
+#run unbinding of field structures, aka halos
+Bound_halos=0
+#simple Plummer softening length when calculating gravitational energy. If cosmological simulation with period, is fraction of interparticle spacing
+Softening_length=0.
+#don't keep background potential when unbinding
+Keep_background_potential=0
+
+################################
+#Cosmological parameters
+#this is typically overwritten by information in the gadget/hdf header if those input file types are read
+################################
+h_val=1.0
+Omega_m=0.3
+Omega_Lambda=0.7
+Critical_density=1.0
+Virial_density=200 #so-called virial overdensity value
+Omega_b=0. #no baryons
+
+################################
+#Calculation of properties related options
+################################
+#when calculating properties, for field objects calculate inclusive masses
+Inclusive_halo_masses=1 #calculate inclusive masses
+#ensures that output is comoving distances per little h
+Comoving_units=0
+
+################################
+#output related
+################################
+
+Write_group_array_file=0 #write a group array file
+Separate_output_files=0 #separate output into field and substructure files similar to subfind
+Binary_output=2 #binary output 1, ascii 0, and HDF 2
+
+#halo ids are adjusted by this value * 1000000000000 (or 1000000 if code compiled with the LONGINTS option turned off)
+#to ensure that halo ids are temporally unique. So if you had 100 snapshots, for snap 100 set this to 100 and 100*1000000000000 will
+#be added to the halo id as set for this snapshot, so halo 1 becomes halo 100*1000000000000+1 and halo 1 of snap 0 would just have ID=1
+
+#ALTER THIS as part of a script to get temporally unique ids
+Snapshot_value=SNAP
+
+################################
+#other options
+################################
+Verbose=0 #how talkative do you want the code to be, 0 not much, 1 a lot, 2 chatterbox
diff --git a/examples/SmallCosmoVolume_cooling/run.sh b/examples/SmallCosmoVolume_cooling/run.sh
index 454ed279503db17ea2deddb2ae982206238ec23f..b5d01cf232de518d4d449fcb9987887d5e639841 100755
--- a/examples/SmallCosmoVolume_cooling/run.sh
+++ b/examples/SmallCosmoVolume_cooling/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -c -s -G -C -t 8 small_cosmo_volume.yml 2>&1 | tee output.log
+../swift --cosmology --hydro --self-gravity --cooling --threads=8 small_cosmo_volume.yml 2>&1 | tee output.log
 
 # Plot the temperature evolution
 python plotTempEvolution.py
diff --git a/examples/SmoothedMetallicity/run.sh b/examples/SmoothedMetallicity/run.sh
index de8c55d678bcb611934af450940d8ed8e6c15d6b..9f31eac3692be4ce4ad6bb554d6a95c11d21e791 100755
--- a/examples/SmoothedMetallicity/run.sh
+++ b/examples/SmoothedMetallicity/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -n 1 -s -t 4 smoothed_metallicity.yml 2>&1 | tee output.log
+../swift --steps=1 --hydro --threads=4 smoothed_metallicity.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 1
diff --git a/examples/SodShockSpherical_2D/run.sh b/examples/SodShockSpherical_2D/run.sh
index d662d20f40ef9e221285d5820e867607804e9dbe..90be0cc83c53bee0c53d3e522ce989d829549579 100755
--- a/examples/SodShockSpherical_2D/run.sh
+++ b/examples/SodShockSpherical_2D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 sodShock.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 sodShock.yml 2>&1 | tee output.log
 
 # Get the high resolution 1D reference solution if not present.
 if [ ! -e sodShockSpherical2D_exact.txt ]
diff --git a/examples/SodShockSpherical_3D/run.sh b/examples/SodShockSpherical_3D/run.sh
index faf979869e175172ce31db6ac5021daf1758f3b0..b28b69e0aa33d3a6657aae0db819298c66e26860 100755
--- a/examples/SodShockSpherical_3D/run.sh
+++ b/examples/SodShockSpherical_3D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 sodShock.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 sodShock.yml 2>&1 | tee output.log
 
 # Get the high resolution 1D reference solution if not present.
 if [ ! -e sodShockSpherical3D_exact.txt ]
diff --git a/examples/SodShock_1D/run.sh b/examples/SodShock_1D/run.sh
index 4be4254baa4a87b105a5f3c1bfbf9059348a1e9e..fb2ba77daca880a36c58949983cf19fd631cb102 100755
--- a/examples/SodShock_1D/run.sh
+++ b/examples/SodShock_1D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 sodShock.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 sodShock.yml 2>&1 | tee output.log
 
 # Plot the result
 python plotSolution.py 1 
diff --git a/examples/SodShock_2D/run.sh b/examples/SodShock_2D/run.sh
index 9e6bbfdf1c0a7c206ce6966fdca7b20a28047dd8..730cabcb9d51c0c870b38512ad1ce6ed80253ebd 100755
--- a/examples/SodShock_2D/run.sh
+++ b/examples/SodShock_2D/run.sh
@@ -13,6 +13,6 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 sodShock.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 sodShock.yml 2>&1 | tee output.log
 
 python plotSolution.py 1
diff --git a/examples/SodShock_3D/run.sh b/examples/SodShock_3D/run.sh
index 8ed85baf73425b75f402c491a3c66785f6c6fce0..fee82ce3e1bbbe600fb170f6249f9063ab5aec70 100755
--- a/examples/SodShock_3D/run.sh
+++ b/examples/SodShock_3D/run.sh
@@ -13,6 +13,6 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 sodShock.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 sodShock.yml 2>&1 | tee output.log
 
 python plotSolution.py 1
diff --git a/examples/SquareTest_2D/run.sh b/examples/SquareTest_2D/run.sh
index 7d77e9c5bd89732970b47feb3a297ef92b345a01..f96bd4c0e19958f91c631616321a7280fa090c40 100755
--- a/examples/SquareTest_2D/run.sh
+++ b/examples/SquareTest_2D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 square.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 square.yml 2>&1 | tee output.log
 
 # Plot the solution
 python plotSolution.py 5
diff --git a/examples/SupernovaeFeedback/SN_feedback.yml b/examples/SupernovaeFeedback/SN_feedback.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a59ae302ff4052a3daf0535e93a0c2cd5e9904f5
--- /dev/null
+++ b/examples/SupernovaeFeedback/SN_feedback.yml
@@ -0,0 +1,44 @@
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1   # Grams
+  UnitLength_in_cgs:   1   # Centimeters
+  UnitVelocity_in_cgs: 1   # Centimeters per second
+  UnitCurrent_in_cgs:  1   # Amperes
+  UnitTemp_in_cgs:     1   # Kelvin
+
+# Values of some physical constants
+PhysicalConstants:
+  G:            0 # (Optional) Overwrite the value of Newton's constant used internally by the code.
+
+# Parameters governing the time integration
+TimeIntegration:
+  time_begin: 0.    # The starting time of the simulation (in internal units).
+  time_end:   5e-2  # The end time of the simulation (in internal units).
+  dt_min:     1e-7  # The minimal time-step size of the simulation (in internal units).
+  dt_max:     1e-4  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:            SN_feedback # Common part of the name of output files
+  time_first:          0.    # Time of the first output (in internal units)
+  delta_time:          1e-2  # Time difference between consecutive outputs (in internal units)
+  compression:         1
+ 
+# Parameters governing the conserved quantities statistics
+Statistics:
+  delta_time:          1e-3 # Time between statistics output
+
+# Parameters for the hydrodynamics scheme
+SPH:
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
+  CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:                    ./SN_feedback.hdf5          
+  smoothing_length_scaling:     1.
+  periodic:                    1    # Are we running with periodic ICs?
+ 
+# Parameters for the stellar models
+Stars:
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
diff --git a/examples/SupernovaeFeedback/getGlass.sh b/examples/SupernovaeFeedback/getGlass.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d5c5f590ac37c9c9431d626a2ea61b0c12c1513c
--- /dev/null
+++ b/examples/SupernovaeFeedback/getGlass.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassCube_64.hdf5
diff --git a/examples/SupernovaeFeedback/makeIC.py b/examples/SupernovaeFeedback/makeIC.py
new file mode 100644
index 0000000000000000000000000000000000000000..8a0fca2bfd21f2cf1d5052660581d97184705480
--- /dev/null
+++ b/examples/SupernovaeFeedback/makeIC.py
@@ -0,0 +1,117 @@
+###############################################################################
+ # This file is part of SWIFT.
+ # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ # 
+ # This program is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU Lesser General Public License as published
+ # by the Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ # 
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ # 
+ # You should have received a copy of the GNU Lesser General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ # 
+ ##############################################################################
+
+import h5py
+from numpy import *
+
+# Generates a swift IC file for the Sedov blast test in a periodic cubic box
+
+# Parameters
+gamma = 5./3.      # Gas adiabatic index
+rho0 = 1.          # Background density
+P0 = 1.e-6         # Background pressure
+E0= 1.             # Energy of the explosion
+N_inject = 15      # Number of particles in which to inject energy
+fileName = "SN_feedback.hdf5" 
+
+#---------------------------------------------------
+glass = h5py.File("glassCube_64.hdf5", "r")
+
+# Read particle positions and h from the glass
+pos = glass["/PartType0/Coordinates"][:,:]
+eps = 1e-6
+pos = (pos - pos.min()) / (pos.max() - pos.min() + eps)
+h = glass["/PartType0/SmoothingLength"][:] * 0.3 * 3.3
+
+numPart = size(h)
+vol = 1.
+Boxsize = 1.
+
+# Generate extra arrays
+v = zeros((numPart, 3))
+ids = linspace(1, numPart, numPart)
+m = zeros(numPart)
+u = zeros(numPart)
+r = zeros(numPart)
+
+r = sqrt((pos[:,0] - 0.5)**2 + (pos[:,1] - 0.5)**2 + (pos[:,2] - 0.5)**2)
+m[:] = rho0 * vol / numPart    
+u[:] = P0 / (rho0 * (gamma - 1))
+
+#--------------------------------------------------
+
+star_pos = zeros((1, 3))
+star_pos[:,:] = 0.5 * Boxsize
+
+star_v = zeros((1, 3))
+star_v[:,:] = 0.
+
+# increase mass to keep it at center
+star_m = 1e3 * array([rho0 * vol / numPart])
+star_ids = array([numPart + 1])
+star_h = array([h.max()])
+
+#--------------------------------------------------
+
+#File
+file = h5py.File(fileName, 'w')
+
+# Header
+grp = file.create_group("/Header")
+grp.attrs["BoxSize"] = [Boxsize]*3
+grp.attrs["NumPart_Total"] =  [numPart, 0, 0, 0, 1, 0]
+grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
+grp.attrs["NumPart_ThisFile"] = [numPart, 0, 0, 0, 1, 0]
+grp.attrs["Time"] = 0.0
+grp.attrs["NumFilesPerSnapshot"] = 1
+grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+grp.attrs["Flag_Entropy_ICs"] = 0
+grp.attrs["Dimension"] = 3
+
+#Runtime parameters
+grp = file.create_group("/RuntimePars")
+grp.attrs["PeriodicBoundariesOn"] = 0
+
+#Units
+grp = file.create_group("/Units")
+grp.attrs["Unit length in cgs (U_L)"] = 1.
+grp.attrs["Unit mass in cgs (U_M)"] = 1.
+grp.attrs["Unit time in cgs (U_t)"] = 1.
+grp.attrs["Unit current in cgs (U_I)"] = 1.
+grp.attrs["Unit temperature in cgs (U_T)"] = 1.
+
+#Particle group
+grp = file.create_group("/PartType0")
+grp.create_dataset('Coordinates', data=pos, dtype='d')
+grp.create_dataset('Velocities', data=v, dtype='f')
+grp.create_dataset('Masses', data=m, dtype='f')
+grp.create_dataset('SmoothingLength', data=h, dtype='f')
+grp.create_dataset('InternalEnergy', data=u, dtype='f')
+grp.create_dataset('ParticleIDs', data=ids, dtype='L')
+
+# stellar group
+grp = file.create_group("/PartType4")
+grp.create_dataset("Coordinates", data=star_pos, dtype="d")
+grp.create_dataset('Velocities', data=star_v, dtype='f')
+grp.create_dataset('Masses', data=star_m, dtype='f')
+grp.create_dataset('SmoothingLength', data=star_h, dtype='f')
+grp.create_dataset('ParticleIDs', data=star_ids, dtype='L')
+
+
+file.close()
diff --git a/examples/SupernovaeFeedback/run.sh b/examples/SupernovaeFeedback/run.sh
new file mode 100644
index 0000000000000000000000000000000000000000..984cee2b415f2273f951ec997f4c81d65f1a4d4a
--- /dev/null
+++ b/examples/SupernovaeFeedback/run.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+ # Generate the initial conditions if they are not present.
+if [ ! -e glassCube_64.hdf5 ]
+then
+    echo "Fetching initial glass file for the Supernovae feedback example..."
+    ./getGlass.sh
+fi
+if [ ! -e SN_feedback.hdf5 ]
+then
+    echo "Generating initial conditions for the Supernovae feedback example..."
+    python makeIC.py
+fi
+
+# Run SWIFT
+../swift --external-gravity --feedback --hydro --stars --threads=4 SN_feedback.yml 2>&1 | tee output.log
+
+# Plot the solution
+# TODO
diff --git a/examples/UniformBox_2D/run.sh b/examples/UniformBox_2D/run.sh
index ee3ef109968a65e2437ea17b42013266195d3314..3c146d8b48d1e191b043a2ead52715cd49edf9e5 100755
--- a/examples/UniformBox_2D/run.sh
+++ b/examples/UniformBox_2D/run.sh
@@ -7,4 +7,4 @@ then
     python makeIC.py 100
 fi
 
-../swift -s -t 16 uniformPlane.yml 2>&1 | tee output.log
+../swift --hydro --threads=16 uniformPlane.yml 2>&1 | tee output.log
diff --git a/examples/UniformBox_3D/run.sh b/examples/UniformBox_3D/run.sh
index 08891cdd08fccf8f43089951e94dddb33e162030..eb2648cc5277f830436dadf5902df5531985a3f0 100755
--- a/examples/UniformBox_3D/run.sh
+++ b/examples/UniformBox_3D/run.sh
@@ -7,4 +7,4 @@ then
     python makeIC.py 100
 fi
 
-../swift -s -t 16 uniformBox.yml 2>&1 | tee output.log
+../swift --hydro --threads=16 uniformBox.yml 2>&1 | tee output.log
diff --git a/examples/VacuumSpherical_2D/run.sh b/examples/VacuumSpherical_2D/run.sh
index 51d32b4de679877741b7ecd74238fecb785579e7..c88095abf3a94d4f9e9c007722896a8ac2303bb4 100755
--- a/examples/VacuumSpherical_2D/run.sh
+++ b/examples/VacuumSpherical_2D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 vacuum.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 vacuum.yml 2>&1 | tee output.log
 
 # Get the 1D high resolution reference result if not present.
 if [ ! -e vacuumSpherical2D_exact.txt ]
diff --git a/examples/VacuumSpherical_3D/run.sh b/examples/VacuumSpherical_3D/run.sh
index a136929678f745f6a3d0859ba146e1bc1c6c43d0..ef6a84be13b3f4612b2d79237e9caa47fa0bd665 100755
--- a/examples/VacuumSpherical_3D/run.sh
+++ b/examples/VacuumSpherical_3D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 16 vacuum.yml 2>&1 | tee output.log
+../swift --hydro --threads=16 vacuum.yml 2>&1 | tee output.log
 
 # Get the reference solution if it is not present.
 if [ ! -e vacuumSpherical3D_exact.txt ]
diff --git a/examples/Vacuum_1D/run.sh b/examples/Vacuum_1D/run.sh
index b141f91f877c5b553281e53cdf02fbea948b0a97..a840f7c1ba6ef4b938b53839f057072f1867a8b6 100755
--- a/examples/Vacuum_1D/run.sh
+++ b/examples/Vacuum_1D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 1 vacuum.yml 2>&1 | tee output.log
+../swift --hydro --threads=1 vacuum.yml 2>&1 | tee output.log
 
 # Plot the result
 python plotSolution.py 1
diff --git a/examples/Vacuum_2D/run.sh b/examples/Vacuum_2D/run.sh
index 5c0b2ca5e19e33e813b7ff478ed4494752c0a2a5..5a526bb5062fd6e5bf1dbe442689e915d4f20352 100755
--- a/examples/Vacuum_2D/run.sh
+++ b/examples/Vacuum_2D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 4 vacuum.yml 2>&1 | tee output.log
+../swift --hydro --threads=4 vacuum.yml 2>&1 | tee output.log
 
 # Plot the result
 python plotSolution.py 1
diff --git a/examples/Vacuum_3D/run.sh b/examples/Vacuum_3D/run.sh
index 5029626f67659bba1f22600bb5bd38859dd805ce..eaf7a32d4f833af43cdea74829b768b53fb2f5e3 100755
--- a/examples/Vacuum_3D/run.sh
+++ b/examples/Vacuum_3D/run.sh
@@ -13,7 +13,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -t 16 vacuum.yml 2>&1 | tee output.log
+../swift --hydro --threads=16 vacuum.yml 2>&1 | tee output.log
 
 # Plot the result
 python plotSolution.py 1
diff --git a/examples/ZeldovichPancake_3D/run.sh b/examples/ZeldovichPancake_3D/run.sh
index b3f802f978377a9615f7cdd1cdd14e85ae3baad2..4ced5ec57da3d3665fbc6b50160ca3ca7142bc80 100755
--- a/examples/ZeldovichPancake_3D/run.sh
+++ b/examples/ZeldovichPancake_3D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -s -c -G -t 8 zeldovichPancake.yml 2>&1 | tee output.log
+../swift ---hydro --cosmology --self-gravity --threads=8 zeldovichPancake.yml 2>&1 | tee output.log
 
 # Plot the result
 for i in {0..119}
diff --git a/examples/ZoomIn/run.sh b/examples/ZoomIn/run.sh
index 99eda1cfc779c1958d19d0c7ae234b6c211f8127..d9650dd7783ba90f732c222543c49d13256b4958 100755
--- a/examples/ZoomIn/run.sh
+++ b/examples/ZoomIn/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -b -c -G -s -S -t 8 zoom_in.yml 2>&1 | tee output.log
+../swift --feedback --cosmology --self-gravity --hydro --stars --threads=8 zoom_in.yml 2>&1 | tee output.log
 
diff --git a/examples/main.c b/examples/main.c
index d7ac2d36b358839fa696f226d89eba4d92845080..0e3cdc9b33b99aea2c8178c8469aa215c76c8fb6 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -41,6 +41,7 @@
 #endif
 
 /* Local headers. */
+#include "argparse.h"
 #include "swift.h"
 
 /* Engine policy flags. */
@@ -51,70 +52,27 @@
 /* Global profiler. */
 struct profiler prof;
 
-/**
- * @brief Help messages for the command line parameters.
- */
-void print_help_message(void) {
-
-  printf("\nUsage: swift [OPTION]... PARAMFILE\n");
-  printf("       swift_mpi [OPTION]... PARAMFILE\n\n");
-
-  printf("Valid options are:\n");
-  printf("  %2s %14s %s\n", "-a", "", "Pin runners using processor affinity.");
-  printf("  %2s %14s %s\n", "-c", "",
-         "Run with cosmological time integration.");
-  printf("  %2s %14s %s\n", "-C", "", "Run with cooling.");
-  printf(
-      "  %2s %14s %s\n", "-d", "",
-      "Dry run. Read the parameter file, allocate memory but does not read ");
-  printf(
-      "  %2s %14s %s\n", "", "",
-      "the particles from ICs and exit before the start of time integration.");
-  printf("  %2s %14s %s\n", "", "",
-         "Allows user to check validy of parameter and IC files as well as "
-         "memory limits.");
-  printf("  %2s %14s %s\n", "-D", "",
-         "Always drift all particles even the ones far from active particles. "
-         "This emulates");
-  printf("  %2s %14s %s\n", "", "",
-         "Gadget-[23] and GIZMO's default behaviours.");
-  printf("  %2s %14s %s\n", "-e", "",
-         "Enable floating-point exceptions (debugging mode).");
-  printf("  %2s %14s %s\n", "-f", "{int}",
-         "Overwrite the CPU frequency (Hz) to be used for time measurements.");
-  printf("  %2s %14s %s\n", "-g", "",
-         "Run with an external gravitational potential.");
-  printf("  %2s %14s %s\n", "-G", "", "Run with self-gravity.");
-  printf("  %2s %14s %s\n", "-M", "",
-         "Reconstruct the multipoles every time-step.");
-  printf("  %2s %14s %s\n", "-n", "{int}",
-         "Execute a fixed number of time steps. When unset use the time_end "
-         "parameter to stop.");
-  printf("  %2s %14s %s\n", "-o", "{str}",
-         "Generate a default output parameter file.");
-  printf("  %2s %14s %s\n", "-P", "{sec:par:val}",
-         "Set parameter value and overwrites values read from the parameters "
-         "file. Can be used more than once.");
-  printf("  %2s %14s %s\n", "-r", "", "Continue using restart files.");
-  printf("  %2s %14s %s\n", "-s", "", "Run with hydrodynamics.");
-  printf("  %2s %14s %s\n", "-S", "", "Run with stars.");
-  printf("  %2s %14s %s\n", "-b", "", "Run with stars feedback.");
-  printf("  %2s %14s %s\n", "-t", "{int}",
-         "The number of threads to use on each MPI rank. Defaults to 1 if not "
-         "specified.");
-  printf("  %2s %14s %s\n", "-T", "", "Print timers every time-step.");
-  printf("  %2s %14s %s\n", "-v", "[12]", "Increase the level of verbosity:");
-  printf("  %2s %14s %s\n", "", "", "1: MPI-rank 0 writes,");
-  printf("  %2s %14s %s\n", "", "", "2: All MPI-ranks write.");
-  printf("  %2s %14s %s\n", "-x", "", "Run with structure finding.");
-  printf("  %2s %14s %s\n", "-y", "{int}",
-         "Time-step frequency at which task graphs are dumped.");
-  printf("  %2s %14s %s\n", "-Y", "{int}",
-         "Time-step frequency at which threadpool tasks are dumped.");
-  printf("  %2s %14s %s\n", "-h", "", "Print this help message and exit.");
-  printf(
-      "\nSee the file parameter_example.yml for an example of "
-      "parameter file.\n");
+//  Usage string.
+static const char *const swift_usage[] = {
+    "swift [options] [[--] param-file]",
+    "swift [options] param-file",
+    "swift_mpi [options] [[--] param-file]",
+    "swift_mpi [options] param-file",
+    NULL,
+};
+
+// Function to handle multiple -P arguments.
+struct cmdparams {
+  const char *param[PARSER_MAX_NO_OF_PARAMS];
+  int nparam;
+};
+
+static int handle_cmdparam(struct argparse *self,
+                           const struct argparse_option *opt) {
+  struct cmdparams *cmdps = (struct cmdparams *)opt->data;
+  cmdps->param[cmdps->nparam] = *(char **)opt->value;
+  cmdps->nparam++;
+  return 1;
 }
 
 /**
@@ -202,202 +160,186 @@ int main(int argc, char *argv[]) {
   int verbose = 0;
   int nr_threads = 1;
   int with_verbose_timers = 0;
-  int nparams = 0;
-  char output_parameters_filename[200] = "";
-  char *cmdparams[PARSER_MAX_NO_OF_PARAMS];
-  char paramFileName[200] = "";
+  char *output_parameters_filename = NULL;
+  char *cpufreqarg = NULL;
+  char *param_filename = NULL;
   char restart_file[200] = "";
   unsigned long long cpufreq = 0;
+  struct cmdparams cmdps;
+  cmdps.nparam = 0;
+  cmdps.param[0] = NULL;
+  char *buffer = NULL;
+
+  /* Parse the command-line parameters. */
+  struct argparse_option options[] = {
+      OPT_HELP(),
+
+      OPT_GROUP("  Simulation options:"),
+      OPT_BOOLEAN('b', "feedback", &with_feedback, "Run with stars feedback",
+                  NULL, 0, 0),
+      OPT_BOOLEAN('c', "cosmology", &with_cosmology,
+                  "Run with cosmological time integration.", NULL, 0, 0),
+      OPT_BOOLEAN('C', "cooling", &with_cooling, "Run with cooling", NULL, 0,
+                  0),
+      OPT_BOOLEAN('D', "drift-all", &with_drift_all,
+                  "Always drift all particles even the ones far from active "
+                  "particles. This emulates Gadget-[23] and GIZMO's default "
+                  "behaviours.",
+                  NULL, 0, 0),
+      OPT_BOOLEAN('F', "sourceterms", &with_sourceterms, "", NULL, 0, 0),
+      OPT_BOOLEAN('g', "external-gravity", &with_external_gravity,
+                  "Run with an external gravitational potential.", NULL, 0, 0),
+      OPT_BOOLEAN('G', "self-gravity", &with_self_gravity,
+                  "Run with self-gravity.", NULL, 0, 0),
+      OPT_BOOLEAN('M', "multipole-reconstruction", &with_mpole_reconstruction,
+                  "Reconstruct the multipoles every time-step.", NULL, 0, 0),
+      OPT_BOOLEAN('s', "hydro", &with_hydro, "Run with hydrodynamics.", NULL, 0,
+                  0),
+      OPT_BOOLEAN('S', "stars", &with_stars, "Run with stars", NULL, 0, 0),
+      OPT_BOOLEAN('x', "velociraptor", &with_structure_finding,
+                  "Run with structure finding", NULL, 0, 0),
+
+      OPT_GROUP("  Control options:"),
+      OPT_BOOLEAN('a', "pin", &with_aff,
+                  "Pin runners using processor affinity.", NULL, 0, 0),
+      OPT_BOOLEAN('d', "dry-run", &dry_run,
+                  "Dry run. Read the parameter file, allocates memory but does "
+                  "not read the particles from ICs. Exits before the start of "
+                  "time integration. Checks the validity of parameters and IC "
+                  "files as well as memory limits.",
+                  NULL, 0, 0),
+      OPT_BOOLEAN('e', "fpe", &with_fp_exceptions,
+                  "Enable floating-point exceptions (debugging mode).", NULL, 0,
+                  0),
+      OPT_STRING('f', "cpu-frequency", &cpufreqarg,
+                 "Overwrite the CPU "
+                 "frequency (Hz) to be used for time measurements.",
+                 NULL, 0, 0),
+      OPT_INTEGER('n', "steps", &nsteps,
+                  "Execute a fixed number of time steps. When unset use the "
+                  "time_end parameter to stop.",
+                  NULL, 0, 0),
+      OPT_STRING('o', "output-params", &output_parameters_filename,
+                 "Generate a default output parameter file.", NULL, 0, 0),
+      OPT_STRING('P', "param", &buffer,
+                 "Set parameter value, overiding the value read from the "
+                 "parameter file. Can be used more than once {sec:par:value}.",
+                 handle_cmdparam, (intptr_t)&cmdps, 0),
+      OPT_BOOLEAN('r', "restart", &restart, "Continue using restart files.",
+                  NULL, 0, 0),
+      OPT_INTEGER('t', "threads", &nr_threads,
+                  "The number of threads to use on each MPI rank. Defaults to "
+                  "1 if not specified.",
+                  NULL, 0, 0),
+      OPT_INTEGER('T', "timers", &with_verbose_timers,
+                  "Print timers every time-step.", NULL, 0, 0),
+      OPT_INTEGER('v', "verbose", &verbose,
+                  "Run in verbose mode, in MPI mode 2 outputs from all ranks.",
+                  NULL, 0, 0),
+      OPT_INTEGER('y', "task-dumps", &dump_tasks,
+                  "Time-step frequency at which task graphs are dumped.", NULL,
+                  0, 0),
+      OPT_INTEGER('Y', "threadpool-dumps", &dump_threadpool,
+                  "Time-step frequency at which threadpool tasks are dumped.",
+                  NULL, 0, 0),
+      OPT_END(),
+  };
+  struct argparse argparse;
+  argparse_init(&argparse, options, swift_usage, 0);
+  argparse_describe(&argparse, "\nParameters:",
+                    "\nSee the file examples/parameter_example.yml for an "
+                    "example of parameter file.");
+  int nargs = argparse_parse(&argparse, argc, (const char **)argv);
+
+  /* Need a parameter file. */
+  if (nargs != 1) {
+    if (myrank == 0) argparse_usage(&argparse);
+    printf("\nError: no parameter file was supplied.\n");
+    return 1;
+  }
+  param_filename = argv[0];
 
-  /* Parse the parameters */
-  int c;
-  while ((c = getopt(argc, argv, "abcCdDef:FgGhMn:o:P:rsSt:Tv:xy:Y:")) != -1)
-    switch (c) {
-      case 'a':
-#if defined(HAVE_SETAFFINITY) && defined(HAVE_LIBNUMA)
-        with_aff = 1;
-#else
-        error("Need NUMA support for thread affinity");
+  /* Checks of options. */
+#if !defined(HAVE_SETAFFINITY) || !defined(HAVE_LIBNUMA)
+  if (with_aff) {
+    printf("Error: no NUMA support for thread affinity\n");
+    return 1;
+  }
 #endif
-        break;
-      case 'b':
-        with_feedback = 1;
-        break;
-      case 'c':
-        with_cosmology = 1;
-        break;
-      case 'C':
-        with_cooling = 1;
-        break;
-      case 'd':
-        dry_run = 1;
-        break;
-      case 'D':
-        with_drift_all = 1;
-        break;
-      case 'e':
-#ifdef HAVE_FE_ENABLE_EXCEPT
-        with_fp_exceptions = 1;
-#else
-        error("Need support for floating point exception on this platform");
+
+#ifndef HAVE_FE_ENABLE_EXCEPT
+  if (with_fp_exceptions) {
+    printf("Error: no support for floating point exceptions\n");
+    return 1;
+  }
 #endif
-        break;
-      case 'f':
-        if (sscanf(optarg, "%llu", &cpufreq) != 1) {
-          if (myrank == 0) printf("Error parsing CPU frequency (-f).\n");
-          if (myrank == 0) print_help_message();
-          return 1;
-        }
-        break;
-      case 'F':
-        with_sourceterms = 1;
-        break;
-      case 'g':
-        with_external_gravity = 1;
-        break;
-      case 'G':
-        with_self_gravity = 1;
-        break;
-      case 'h':
-        if (myrank == 0) print_help_message();
-        return 0;
-      case 'M':
-        with_mpole_reconstruction = 1;
-        break;
-      case 'n':
-        if (sscanf(optarg, "%d", &nsteps) != 1) {
-          if (myrank == 0) printf("Error parsing fixed number of steps.\n");
-          if (myrank == 0) print_help_message();
-          return 1;
-        }
-        break;
-      case 'o':
-        if (sscanf(optarg, "%s", output_parameters_filename) != 1) {
-          if (myrank == 0) {
-            printf("Error parsing output fields filename");
-            print_help_message();
-          }
-          return 1;
-        }
-        break;
-      case 'P':
-        cmdparams[nparams] = optarg;
-        nparams++;
-        break;
-      case 'r':
-        restart = 1;
-        break;
-      case 's':
-        with_hydro = 1;
-        break;
-      case 'S':
-        with_stars = 1;
-        break;
-      case 't':
-        if (sscanf(optarg, "%d", &nr_threads) != 1) {
-          if (myrank == 0)
-            printf("Error parsing the number of threads (-t).\n");
-          if (myrank == 0) print_help_message();
-          return 1;
-        }
-        break;
-      case 'T':
-        with_verbose_timers = 1;
-        break;
-      case 'v':
-        if (sscanf(optarg, "%d", &verbose) != 1) {
-          if (myrank == 0) printf("Error parsing verbosity level (-v).\n");
-          if (myrank == 0) print_help_message();
-          return 1;
-        }
-        break;
-      case 'x':
-#ifdef HAVE_VELOCIRAPTOR
-        with_structure_finding = 1;
-#else
-        error(
-            "Error: (-x) needs to have the code compiled with VELOCIraptor "
-            "linked in.");
+
+#ifndef HAVE_VELOCIRAPTOR
+  if (with_structure_finding) {
+    printf("Error: VELOCIraptor is not available\n");
+    return 1;
+  }
 #endif
-        break;
-      case 'y':
-        if (sscanf(optarg, "%d", &dump_tasks) != 1) {
-          if (myrank == 0) printf("Error parsing dump_tasks (-y). \n");
-          if (myrank == 0) print_help_message();
-          return 1;
-        }
+
 #ifndef SWIFT_DEBUG_TASKS
-        if (dump_tasks) {
-          if (myrank == 0) {
-            message("WARNING: complete task dumps are only created when "
-                    "configured with --enable-task-debugging.");
-            message("         Basic task statistics will be output.");
-          }
-        }
+  if (dump_tasks) {
+      if (myrank == 0) {
+          message("WARNING: complete task dumps are only created when "
+                  "configured with --enable-task-debugging.");
+          message("         Basic task statistics will be output.");
+      }
+  }
 #endif
-        break;
-      case 'Y':
-        if (sscanf(optarg, "%d", &dump_threadpool) != 1) {
-          if (myrank == 0) printf("Error parsing dump_threadpool (-Y). \n");
-          if (myrank == 0) print_help_message();
-          return 1;
-        }
+
 #ifndef SWIFT_DEBUG_THREADPOOL
-        if (dump_threadpool) {
-          error(
-              "Threadpool dumping is only possible if SWIFT was configured "
-              "with the "
-              "--enable-threadpool-debugging option.");
-        }
+  if (dump_threadpool) {
+    printf(
+        "Error: threadpool dumping is only possible if SWIFT was "
+        "configured with the --enable-threadpool-debugging option.\n");
+    return 1;
+  }
 #endif
-        break;
-      case '?':
-        if (myrank == 0) print_help_message();
-        return 1;
-        break;
+
+  /* The CPU frequency is a long long, so we need to parse that ourselves. */
+  if (cpufreqarg != NULL) {
+    if (sscanf(cpufreqarg, "%llu", &cpufreq) != 1) {
+      if (myrank == 0)
+        printf("Error parsing CPU frequency (%s).\n", cpufreqarg);
+      return 1;
     }
+  }
 
   /* Write output parameter file */
-  if (myrank == 0 && strcmp(output_parameters_filename, "") != 0) {
+  if (myrank == 0 && output_parameters_filename != NULL) {
     io_write_output_field_parameter(output_parameters_filename);
     printf("End of run.\n");
     return 0;
   }
 
-  /* check inputs */
-  if (optind == argc - 1) {
-    if (!strcpy(paramFileName, argv[optind++]))
-      error("Error reading parameter file name.");
-  } else if (optind > argc - 1) {
-    if (myrank == 0) printf("Error: A parameter file name must be provided\n");
-    if (myrank == 0) print_help_message();
-    return 1;
-  } else {
-    if (myrank == 0) printf("Error: Too many parameters given\n");
-    if (myrank == 0) print_help_message();
-    return 1;
-  }
   if (!with_self_gravity && !with_hydro && !with_external_gravity) {
-    if (myrank == 0)
-      printf("Error: At least one of -s, -g or -G must be chosen.\n");
-    if (myrank == 0) print_help_message();
+    if (myrank == 0) {
+      argparse_usage(&argparse);
+      printf("\nError: At least one of -s, -g or -G must be chosen.\n");
+    }
     return 1;
   }
   if (with_stars && !with_external_gravity && !with_self_gravity) {
-    if (myrank == 0)
+    if (myrank == 0) {
+      argparse_usage(&argparse);
       printf(
-          "Error: Cannot process stars without gravity, -g or -G must be "
-          "chosen.\n");
-    if (myrank == 0) print_help_message();
+          "\nError: Cannot process stars without gravity, -g or -G "
+          "must be chosen.\n");
+    }
     return 1;
   }
 
   if (!with_stars && with_feedback) {
-    if (myrank == 0)
+    if (myrank == 0) {
+      argparse_usage(&argparse);
       printf(
-          "Error: Cannot process feedback without stars, -S must be "
+          "\nError: Cannot process feedback without stars, -S must be "
           "chosen.\n");
-    if (myrank == 0) print_help_message();
+    }
     return 1;
   }
 
@@ -487,15 +429,16 @@ int main(int argc, char *argv[]) {
       (struct swift_params *)malloc(sizeof(struct swift_params));
   if (params == NULL) error("Error allocating memory for the parameter file.");
   if (myrank == 0) {
-    message("Reading runtime parameters from file '%s'", paramFileName);
-    parser_read_file(paramFileName, params);
+    message("Reading runtime parameters from file '%s'", param_filename);
+    parser_read_file(param_filename, params);
 
     /* Handle any command-line overrides. */
-    if (nparams > 0) {
+    if (cmdps.nparam > 0) {
       message(
           "Overwriting values read from the YAML file with command-line "
           "values.");
-      for (int k = 0; k < nparams; k++) parser_set_param(params, cmdparams[k]);
+      for (int k = 0; k < cmdps.nparam; k++)
+        parser_set_param(params, cmdps.param[k]);
     }
   }
 #ifdef WITH_MPI
diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml
index 9ae5fef66546aca2822a2887f9ca2104a169b2d0..6adccf2963dbeff67755bdac946e7bfb10d4a897 100644
--- a/examples/parameter_example.yml
+++ b/examples/parameter_example.yml
@@ -193,8 +193,17 @@ IsothermalPotential:
 HernquistPotential:
   useabspos:       0        # 0 -> positions based on centre, 1 -> absolute positions 
   position:        [100.,100.,100.]    # Location of centre of isothermal potential with respect to centre of the box (if 0) otherwise absolute (if 1) (internal units)
-  mass:            1e10     # Mass of the Hernquist potential
-  scalelength:     10.0     # Scale length of the potential
+  idealizeddisk:   0        # (Optional) Whether to run with idealizeddisk or without, 0 used the mass and scalelength as mandatory parameters, while 1 uses more advanced disk dependent paramters
+  mass:            1e10     # (Optional 0) default parameter, Mass of the Hernquist potential
+  scalelength:     10.0     # (Optional 0) default parameter, Scale length of the potential
+                            # If multiple X200 values are given, only one is used, in the order M200 > V200 > R200.
+  M200:            3e11     # (Optional 1a) M200 of the galaxy+halo (when used V200 and R200 are not used)
+  V200:            100.     # (Optional 1b) V200 of the galaxy+halo (when used M200 and R200 are not used, if M200 is given M200 is used)
+  R200:            10.      # (Optional 1c) R200 of the galaxy+halo (when used M200 and V200 are not used, if M200 or V200 are given they are used)
+  h:               0.704    # (Optional 1) reduced Hubble constant
+  concentration:   7.1      # (Optional 1) concentration of the Halo
+  diskfraction:              0.0434370991372   # (Optional 1) Disk mass fraction (equal to MD in MakeNewDisk and GalIC)
+  bulgefraction:              0.00705852860979  # (Optional 1) Bulge mass fraction (equal to MB in MakeNewDisk and GalIC)
   timestep_mult:   0.01     # Dimensionless pre-factor for the time-step condition, basically determines the fraction of the orbital time we use to do the time integration
   epsilon:         0.1      # Softening size (internal units)
  
diff --git a/src/engine.c b/src/engine.c
index 09f3de498fb542adaa87216b1f504bd4c295350f..ac9456f1c8a2ba909877d9f520a887e2883be08e 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -1900,6 +1900,10 @@ int engine_estimate_nr_tasks(struct engine *e) {
   int n1 = 0;
   int n2 = 0;
   if (e->policy & engine_policy_hydro) {
+    /* 2 self (density, force), 1 sort, 26/2 density pairs
+       26/2 force pairs, 1 drift, 3 ghosts, 2 kicks, 1 time-step,
+       1 end_force, 2 extra space
+     */
     n1 += 37;
     n2 += 2;
 #ifdef WITH_MPI
@@ -1927,16 +1931,25 @@ int engine_estimate_nr_tasks(struct engine *e) {
     n1 += 2;
   }
   if (e->policy & engine_policy_cooling) {
+    /* Cooling task + extra space */
     n1 += 2;
   }
   if (e->policy & engine_policy_sourceterms) {
     n1 += 2;
   }
   if (e->policy & engine_policy_stars) {
-    /* 1 self, 1 sort, 26/2 pairs */
-    n1 += 15;
+    /* 2 self (density, feedback), 1 sort, 26/2 density pairs
+       26/2 feedback pairs, 1 drift, 3 ghosts, 2 kicks, 1 time-step,
+       1 end_force, 2 extra space
+     */
+    n1 += 37;
+    n2 += 2;
+#ifdef WITH_MPI
+    n1 += 6;
+#endif
   }
 #if defined(WITH_LOGGER)
+  /* each cell logs its particles */
   n1 += 1;
 #endif
 
@@ -3602,36 +3615,53 @@ void engine_makeproxies(struct engine *e) {
               /* In the gravity case, check distances using the MAC. */
               if (with_gravity) {
 
-                /* We don't have multipoles yet (or there CoMs) so we will have
-                   to cook up something based on cell locations only. We hence
-                   need an upper limit on the distance that the CoMs in those
-                   cells could have. We then can decide whether we are too close
-                   for an M2L interaction and hence require a proxy as this pair
-                   of cells cannot rely on just an M2L calculation. */
-
-                /* Minimal distance between any two points in the cells */
-                const double min_dist_centres2 = cell_min_dist2_same_size(
-                    &cells[cid], &cells[cjd], periodic, dim);
-
-                /* Let's now assume the CoMs will shift a bit */
-                const double min_dist_CoM =
-                    sqrt(min_dist_centres2) - 2. * delta_CoM;
-                const double min_dist_CoM2 = min_dist_CoM * min_dist_CoM;
+                /* First just add the direct neighbours. Then look for
+                   some further out if the opening angle demands it */
 
-                /* Are we beyond the distance where the truncated forces are 0
-                 * but not too far such that M2L can be used? */
-                if (periodic) {
-
-                  if ((min_dist_CoM2 < max_mesh_dist2) &&
-                      (!gravity_M2L_accept(r_max, r_max, theta_crit2,
-                                           min_dist_CoM2)))
-                    proxy_type |= (int)proxy_cell_type_gravity;
+                /* This is super-ugly but checks for direct neighbours */
+                /* with periodic BC */
+                if (((abs(i - iii) <= 1 || abs(i - iii - cdim[0]) <= 1 ||
+                      abs(i - iii + cdim[0]) <= 1) &&
+                     (abs(j - jjj) <= 1 || abs(j - jjj - cdim[1]) <= 1 ||
+                      abs(j - jjj + cdim[1]) <= 1) &&
+                     (abs(k - kkk) <= 1 || abs(k - kkk - cdim[2]) <= 1 ||
+                      abs(k - kkk + cdim[2]) <= 1))) {
 
+                  proxy_type |= (int)proxy_cell_type_gravity;
                 } else {
 
-                  if (!gravity_M2L_accept(r_max, r_max, theta_crit2,
-                                          min_dist_CoM2))
-                    proxy_type |= (int)proxy_cell_type_gravity;
+                  /* We don't have multipoles yet (or there CoMs) so we will
+                     have to cook up something based on cell locations only. We
+                     hence need an upper limit on the distance that the CoMs in
+                     those cells could have. We then can decide whether we are
+                     too close for an M2L interaction and hence require a proxy
+                     as this pair of cells cannot rely on just an M2L
+                     calculation. */
+
+                  /* Minimal distance between any two points in the cells */
+                  const double min_dist_centres2 = cell_min_dist2_same_size(
+                      &cells[cid], &cells[cjd], periodic, dim);
+
+                  /* Let's now assume the CoMs will shift a bit */
+                  const double min_dist_CoM =
+                      sqrt(min_dist_centres2) - 2. * delta_CoM;
+                  const double min_dist_CoM2 = min_dist_CoM * min_dist_CoM;
+
+                  /* Are we beyond the distance where the truncated forces are 0
+                   * but not too far such that M2L can be used? */
+                  if (periodic) {
+
+                    if ((min_dist_CoM2 < max_mesh_dist2) &&
+                        (!gravity_M2L_accept(r_max, r_max, theta_crit2,
+                                             min_dist_CoM2)))
+                      proxy_type |= (int)proxy_cell_type_gravity;
+
+                  } else {
+
+                    if (!gravity_M2L_accept(r_max, r_max, theta_crit2,
+                                            min_dist_CoM2))
+                      proxy_type |= (int)proxy_cell_type_gravity;
+                  }
                 }
               }
 
diff --git a/src/logger.c b/src/logger.c
index 2f4b0593dac039db96375afcee258a25dd871549..8be521b27f949ea0d496a5207335f1ec68208489 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -25,6 +25,7 @@
 
 /* Some standard headers. */
 #include <hdf5.h>
+#include <math.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -40,28 +41,49 @@
 #include "part.h"
 #include "units.h"
 
-/* header constants
+/*
  * Thoses are definitions from the format and therefore should not be changed!
- * Size in bytes
  */
-/* size of a mask */
+/* number of bytes for a mask */
+// TODO change this to number of bits
 #define logger_mask_size 1
 
-/* size of an offset */
-#define logger_offset_size 7
+/* number of bits for chunk header */
+#define logger_header_bytes 8
 
-/* size of the version information */
+/* number bytes for an offset */
+#define logger_offset_size logger_header_bytes - logger_mask_size
+
+/* number of bytes for the version information */
 #define logger_version_size 20
 
-/* size of the size information */
-#define logger_header_number_size 2
+/* number of bytes for the labels in the header */
+#define logger_label_size 20
+
+/* number of bytes for the number in the header */
+#define logger_number_size 4
 
 char logger_version[logger_version_size] = "0.1";
 
-const unsigned int logger_datatype_size[logger_data_count] = {
-    sizeof(int),  sizeof(float),     sizeof(double),
-    sizeof(char), sizeof(long long), 1,
-};
+const struct mask_data logger_mask_data[logger_count_mask] = {
+    /* Particle's position */
+    {3 * sizeof(double), 1 << logger_x, "positions"},
+    /* Particle's velocity */
+    {3 * sizeof(float), 1 << logger_v, "velocities"},
+    /* Particle's acceleration */
+    {3 * sizeof(float), 1 << logger_a, "accelerations"},
+    /* Particle's entropy */
+    {sizeof(float), 1 << logger_u, "entropy"},
+    /* Particle's smoothing length */
+    {sizeof(float), 1 << logger_h, "smoothing length"},
+    /* Particle's density */
+    {sizeof(float), 1 << logger_rho, "density"},
+    /* Particle's constants: mass (float) and ID (long long) */
+    {sizeof(float) + sizeof(long long), 1 << logger_consts, "consts"},
+    /* Simulation time stamp: integertime and double time (e.g. scale
+       factor or time) */
+    {sizeof(integertime_t) + sizeof(double), 1 << logger_timestamp,
+     "timestamp"}};
 
 /**
  * @brief Write the header of a chunk (offset + mask).
@@ -104,39 +126,8 @@ void logger_write_data(struct dump *d, size_t *offset, size_t size,
 
   /* write data to the buffer */
   memcpy(buff, p, size);
-}
-
-/**
- * @brief Write a parameter to the file
- *
- * TODO Make it thread safe or remove it.
- *
- * write data in the following order: name, data type, data.
- * It should be used only for the file header.
- *
- * @param d #dump file
- * @param params #logger_parameters file format informations
- * @param offset (return) offset of the next chunk
- * @param p pointer to the data
- * @param name Label of the parameter (should be smaller than log->name)
- * @param data_type #logger_datatype to write
- */
-void logger_write_general_data(struct dump *d,
-                               const struct logger_parameters *params,
-                               size_t *offset, const void *p, char *name,
-                               size_t data_type) {
-  /* write name */
-  logger_write_data(d, offset, params->label_size, name);
-
-  /* write data type */
-  logger_write_data(d, offset, params->data_type_size, &data_type);
-
-  /* write value */
-  if (data_type >= logger_data_count) error("Not implemented");
-  size_t size = logger_datatype_size[data_type];
-
-  logger_write_data(d, offset, size, p);
 
+  /* Update offset to end of chunk */
   *offset += size;
 }
 
@@ -153,40 +144,21 @@ int logger_compute_chunk_size(unsigned int mask) {
   int size = logger_mask_size + logger_offset_size;
 
   /* Is this a particle or a timestep? */
-  if (mask & logger_mask_timestamp) {
+  if (mask & logger_mask_data[logger_timestamp].mask) {
 
     /* The timestamp should not contain any other bits. */
-    if (mask != logger_mask_timestamp)
+    if (mask != logger_mask_data[logger_timestamp].mask)
       error("Timestamps should not include any other data.");
 
     /* A timestamp consists of an unsigned long long int. */
-    size += sizeof(unsigned long long int);
-    size += sizeof(double);
+    size += logger_mask_data[logger_timestamp].size;
 
   } else {
 
-    /* Particle position as three doubles. */
-    if (mask & logger_mask_x) size += 3 * sizeof(double);
-
-    /* Particle velocity as three floats. */
-    if (mask & logger_mask_v) size += 3 * sizeof(float);
-
-    /* Particle accelleration as three floats. */
-    if (mask & logger_mask_a) size += 3 * sizeof(float);
-
-    /* Particle internal energy as a single float. */
-    if (mask & logger_mask_u) size += sizeof(float);
-
-    /* Particle smoothing length as a single float. */
-    if (mask & logger_mask_h) size += sizeof(float);
-
-    /* Particle density as a single float. */
-    if (mask & logger_mask_rho) size += sizeof(float);
-
-    /* Particle constants, which is a bit more complicated. */
-    if (mask & logger_mask_rho) {
-      size += sizeof(float) +     // mass
-              sizeof(long long);  // id
+    for (int i = 0; i < logger_count_mask; i++) {
+      if (mask & logger_mask_data[i].mask) {
+        size += logger_mask_data[i].size;
+      }
     }
   }
 
@@ -209,9 +181,11 @@ void logger_log_all(struct logger *log, const struct engine *e) {
 
   /* some constants */
   const struct space *s = e->s;
-  const unsigned int mask = logger_mask_x | logger_mask_v | logger_mask_a |
-                            logger_mask_u | logger_mask_h | logger_mask_rho |
-                            logger_mask_consts;
+  const unsigned int mask =
+      logger_mask_data[logger_x].mask | logger_mask_data[logger_v].mask |
+      logger_mask_data[logger_a].mask | logger_mask_data[logger_u].mask |
+      logger_mask_data[logger_h].mask | logger_mask_data[logger_rho].mask |
+      logger_mask_data[logger_consts].mask;
 
   /* loop over all parts */
   for (long long i = 0; i < e->total_nr_parts; i++) {
@@ -240,7 +214,7 @@ void logger_log_part(struct logger *log, const struct part *p,
                      unsigned int mask, size_t *offset) {
 
   /* Make sure we're not writing a timestamp. */
-  if (mask & logger_mask_timestamp)
+  if (mask & logger_mask_data[logger_timestamp].mask)
     error("You should not log particles as timestamps.");
 
   /* Start by computing the size of the message. */
@@ -248,51 +222,52 @@ void logger_log_part(struct logger *log, const struct part *p,
 
   /* Allocate a chunk of memory in the dump of the right size. */
   size_t offset_new;
-  char *buff = (char *)dump_get(log->dump, size, &offset_new);
+  char *buff = (char *)dump_get(&log->dump, size, &offset_new);
 
   /* Write the header. */
   buff = logger_write_chunk_header(buff, &mask, offset, offset_new);
 
   /* Particle position as three doubles. */
-  if (mask & logger_mask_x) {
-    memcpy(buff, p->x, 3 * sizeof(double));
-    buff += 3 * sizeof(double);
+  if (mask & logger_mask_data[logger_x].mask) {
+    memcpy(buff, p->x, logger_mask_data[logger_x].size);
+    buff += logger_mask_data[logger_x].size;
   }
 
   /* Particle velocity as three floats. */
-  if (mask & logger_mask_v) {
-    memcpy(buff, p->v, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_v].mask) {
+    memcpy(buff, p->v, logger_mask_data[logger_v].size);
+    buff += logger_mask_data[logger_v].size;
   }
 
   /* Particle accelleration as three floats. */
-  if (mask & logger_mask_a) {
-    memcpy(buff, p->a_hydro, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_a].mask) {
+    memcpy(buff, p->a_hydro, logger_mask_data[logger_a].size);
+    buff += logger_mask_data[logger_a].size;
   }
 
 #if defined(GADGET2_SPH)
 
   /* Particle internal energy as a single float. */
-  if (mask & logger_mask_u) {
-    memcpy(buff, &p->entropy, sizeof(float));
-    buff += sizeof(float);
+  if (mask & logger_mask_data[logger_u].mask) {
+    memcpy(buff, &p->entropy, logger_mask_data[logger_u].size);
+    buff += logger_mask_data[logger_u].size;
   }
 
   /* Particle smoothing length as a single float. */
-  if (mask & logger_mask_h) {
-    memcpy(buff, &p->h, sizeof(float));
-    buff += sizeof(float);
+  if (mask & logger_mask_data[logger_h].mask) {
+    memcpy(buff, &p->h, logger_mask_data[logger_h].size);
+    buff += logger_mask_data[logger_h].size;
   }
 
   /* Particle density as a single float. */
-  if (mask & logger_mask_rho) {
-    memcpy(buff, &p->rho, sizeof(float));
-    buff += sizeof(float);
+  if (mask & logger_mask_data[logger_rho].mask) {
+    memcpy(buff, &p->rho, logger_mask_data[logger_rho].size);
+    buff += logger_mask_data[logger_rho].size;
   }
 
   /* Particle constants, which is a bit more complicated. */
-  if (mask & logger_mask_consts) {
+  if (mask & logger_mask_data[logger_consts].mask) {
+    // TODO make it dependent of logger_mask_data
     memcpy(buff, &p->mass, sizeof(float));
     buff += sizeof(float);
     memcpy(buff, &p->id, sizeof(long long));
@@ -318,11 +293,12 @@ void logger_log_gpart(struct logger *log, const struct gpart *p,
                       unsigned int mask, size_t *offset) {
 
   /* Make sure we're not writing a timestamp. */
-  if (mask & logger_mask_timestamp)
+  if (mask & logger_mask_data[logger_timestamp].mask)
     error("You should not log particles as timestamps.");
 
   /* Make sure we're not looging fields not supported by gparts. */
-  if (mask & (logger_mask_u | logger_mask_rho))
+  if (mask &
+      (logger_mask_data[logger_u].mask | logger_mask_data[logger_rho].mask))
     error("Can't log SPH quantities for gparts.");
 
   /* Start by computing the size of the message. */
@@ -330,31 +306,32 @@ void logger_log_gpart(struct logger *log, const struct gpart *p,
 
   /* Allocate a chunk of memory in the dump of the right size. */
   size_t offset_new;
-  char *buff = (char *)dump_get(log->dump, size, &offset_new);
+  char *buff = (char *)dump_get(&log->dump, size, &offset_new);
 
   /* Write the header. */
   buff = logger_write_chunk_header(buff, &mask, offset, offset_new);
 
   /* Particle position as three doubles. */
-  if (mask & logger_mask_x) {
-    memcpy(buff, p->x, 3 * sizeof(double));
-    buff += 3 * sizeof(double);
+  if (mask & logger_mask_data[logger_x].mask) {
+    memcpy(buff, p->x, logger_mask_data[logger_x].size);
+    buff += logger_mask_data[logger_x].size;
   }
 
   /* Particle velocity as three floats. */
-  if (mask & logger_mask_v) {
-    memcpy(buff, p->v_full, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_v].mask) {
+    memcpy(buff, p->v_full, logger_mask_data[logger_v].size);
+    buff += logger_mask_data[logger_v].size;
   }
 
   /* Particle accelleration as three floats. */
-  if (mask & logger_mask_a) {
-    memcpy(buff, p->a_grav, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_a].mask) {
+    memcpy(buff, p->a_grav, logger_mask_data[logger_a].size);
+    buff += logger_mask_data[logger_a].size;
   }
 
   /* Particle constants, which is a bit more complicated. */
-  if (mask & logger_mask_consts) {
+  if (mask & logger_mask_data[logger_consts].mask) {
+    // TODO make it dependent of logger_mask_data
     memcpy(buff, &p->mass, sizeof(float));
     buff += sizeof(float);
     memcpy(buff, &p->id_or_neg_offset, sizeof(long long));
@@ -376,20 +353,22 @@ void logger_log_gpart(struct logger *log, const struct gpart *p,
  */
 void logger_log_timestamp(struct logger *log, integertime_t timestamp,
                           double time, size_t *offset) {
-  struct dump *dump = log->dump;
+  struct dump *dump = &log->dump;
 
   /* Start by computing the size of the message. */
-  const int size = logger_compute_chunk_size(logger_mask_timestamp);
+  const int size =
+      logger_compute_chunk_size(logger_mask_data[logger_timestamp].mask);
 
   /* Allocate a chunk of memory in the dump of the right size. */
   size_t offset_new;
   char *buff = (char *)dump_get(dump, size, &offset_new);
 
   /* Write the header. */
-  unsigned int mask = logger_mask_timestamp;
+  unsigned int mask = logger_mask_data[logger_timestamp].mask;
   buff = logger_write_chunk_header(buff, &mask, offset, offset_new);
 
   /* Store the timestamp. */
+  // TODO make it dependent of logger_mask_data
   memcpy(buff, &timestamp, sizeof(integertime_t));
   buff += sizeof(integertime_t);
 
@@ -414,10 +393,8 @@ void logger_log_timestamp(struct logger *log, integertime_t timestamp,
 void logger_ensure_size(struct logger *log, size_t total_nr_parts,
                         size_t total_nr_gparts, size_t total_nr_sparts) {
 
-  struct logger_parameters *log_params = log->params;
-
   /* count part memory */
-  size_t limit = log_params->total_size;
+  size_t limit = log->max_chunk_size;
 
   limit *= total_nr_parts;
 
@@ -428,7 +405,7 @@ void logger_ensure_size(struct logger *log, size_t total_nr_parts,
   if (total_nr_sparts > 0) error("Not implemented");
 
   /* ensure enough space in dump */
-  dump_ensure(log->dump, limit, log->buffer_scale * limit);
+  dump_ensure(&log->dump, limit, log->buffer_scale * limit);
 }
 
 /**
@@ -455,16 +432,17 @@ void logger_init(struct logger *log, struct swift_params *params) {
   strcpy(logger_name_file, log->base_name);
   strcat(logger_name_file, ".dump");
 
-  /* init parameters */
-  log->params =
-      (struct logger_parameters *)malloc(sizeof(struct logger_parameters));
-  logger_parameters_init(log->params);
+  /* Compute max size for a particle chunk */
+  int max_size = logger_offset_size + logger_mask_size;
 
-  /* init dump */
-  log->dump = malloc(sizeof(struct dump));
-  struct dump *dump_file = log->dump;
+  /* Loop over all fields except timestamp */
+  for (int i = 0; i < logger_count_mask - 1; i++) {
+    max_size += logger_mask_data[i].size;
+  }
+  log->max_chunk_size = max_size;
 
-  dump_init(dump_file, logger_name_file, buffer_size);
+  /* init dump */
+  dump_init(&log->dump, logger_name_file, buffer_size);
 }
 
 /**
@@ -472,11 +450,7 @@ void logger_init(struct logger *log, struct swift_params *params) {
  *
  * @param log The #logger
  */
-void logger_clean(struct logger *log) {
-  dump_close(log->dump);
-  logger_parameters_clean(log->params);
-  free(log->params);
-}
+void logger_clean(struct logger *log) { dump_close(&log->dump); }
 
 /**
  * @brief Write a file header to a logger file
@@ -488,8 +462,7 @@ void logger_clean(struct logger *log) {
 void logger_write_file_header(struct logger *log, const struct engine *e) {
 
   /* get required variables */
-  const struct logger_parameters log_params = *log->params;
-  struct dump *dump = log->dump;
+  struct dump *dump = &log->dump;
 
   size_t file_offset = dump->file_offset;
 
@@ -501,167 +474,35 @@ void logger_write_file_header(struct logger *log, const struct engine *e) {
   /* Write version information */
   logger_write_data(dump, &file_offset, logger_version_size, &logger_version);
 
-  /* write number of bytes used for the offsets */
-  logger_write_data(dump, &file_offset, logger_header_number_size,
-                    &log_params.offset_size);
-
   /* write offset direction */
-  int reversed = 0;
-  logger_write_data(dump, &file_offset, logger_datatype_size[logger_data_bool],
-                    &reversed);
+  const int reversed = 0;
+  logger_write_data(dump, &file_offset, logger_number_size, &reversed);
 
   /* placeholder to write the offset of the first log here */
-  char *skip_header = dump_get(dump, log_params.offset_size, &file_offset);
+  char *skip_header = dump_get(dump, logger_offset_size, &file_offset);
 
   /* write number of bytes used for names */
-  logger_write_data(dump, &file_offset, logger_header_number_size,
-                    &log_params.label_size);
-
-  /* write number of bytes used for numbers */
-  logger_write_data(dump, &file_offset, logger_header_number_size,
-                    &log_params.number_size);
-
-  /* write number of bytes used for masks */
-  logger_write_data(dump, &file_offset, logger_header_number_size,
-                    &log_params.mask_size);
+  const int label_size = logger_label_size;
+  logger_write_data(dump, &file_offset, logger_number_size, &label_size);
 
   /* write number of masks */
-  logger_write_data(dump, &file_offset, log_params.number_size,
-                    &log_params.number_mask);
+  int count_mask = logger_count_mask;
+  logger_write_data(dump, &file_offset, logger_number_size, &count_mask);
 
   /* write masks */
   // loop over all mask type
-  for (size_t i = 0; i < log_params.number_mask; i++) {
+  for (int i = 0; i < logger_count_mask; i++) {
     // mask name
-    size_t j = i * log_params.label_size;
-    logger_write_data(dump, &file_offset, log_params.label_size,
-                      &log_params.masks_name[j]);
-
-    // mask
-    logger_write_data(dump, &file_offset, log_params.mask_size,
-                      &log_params.masks[i]);
+    logger_write_data(dump, &file_offset, logger_label_size,
+                      &logger_mask_data[i].name);
 
     // mask size
-    logger_write_data(dump, &file_offset, log_params.number_size,
-                      &log_params.masks_data_size[i]);
+    logger_write_data(dump, &file_offset, logger_number_size,
+                      &logger_mask_data[i].size);
   }
 
-  /* write mask data */
-  // TODO
-  /* loop over each mask and each data in this mask */
-  /* write number of bytes for each field */
-  /* write data type (float, double, ...) */
-  /* write data name (mass, id, ...) */
-
-  /* Write data */
-  char *name = malloc(sizeof(char) * log_params.label_size);
-  strcpy(name, "time_base");
-  logger_write_general_data(dump, &log_params, &file_offset, &e->time_base,
-                            name, logger_data_double);
-
   /* last step: write first offset */
-  memcpy(skip_header, &file_offset, log_params.offset_size);
-
-  /* free memory */
-  free(name);
-}
-
-/**
- * @brief initialize the #logger_parameters with the format informations
- *
- * @param log_params #logger_parameters to initialize
- */
-void logger_parameters_init(struct logger_parameters *log_params) {
-  /* set parameters */
-  log_params->label_size = 20;
-  log_params->offset_size = 7;
-  log_params->mask_size = 1;
-  log_params->number_size = 1;
-  log_params->data_type_size = 1;
-
-  log_params->number_mask = 8;
-
-  /* set masks array */
-  log_params->masks = malloc(sizeof(size_t) * log_params->number_mask);
-  log_params->masks[0] = logger_mask_x;
-  log_params->masks[1] = logger_mask_v;
-  log_params->masks[2] = logger_mask_a;
-  log_params->masks[3] = logger_mask_u;
-  log_params->masks[4] = logger_mask_h;
-  log_params->masks[5] = logger_mask_rho;
-  log_params->masks[6] = logger_mask_consts;
-  log_params->masks[7] = logger_mask_timestamp;
-
-  /* set the mask names */
-  size_t block_size = log_params->label_size * log_params->number_mask;
-  log_params->masks_name = malloc(block_size);
-  char *cur_name = log_params->masks_name;
-
-  char tmp[log_params->label_size];
-  strcpy(tmp, "position");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "velocity");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "acceleration");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "entropy");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "cutoff radius");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "density");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "consts");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  strcpy(tmp, "timestamp");
-  memcpy(cur_name, &tmp, log_params->label_size);
-  cur_name += log_params->label_size;
-
-  /* set the data size */
-  log_params->masks_data_size =
-      malloc(sizeof(size_t) * log_params->number_mask);
-  log_params->masks_data_size[0] = 3 * sizeof(double);
-  log_params->masks_data_size[1] = 3 * sizeof(float);
-  log_params->masks_data_size[2] = 3 * sizeof(float);
-  log_params->masks_data_size[3] = sizeof(float);
-  log_params->masks_data_size[4] = sizeof(float);
-  log_params->masks_data_size[5] = sizeof(float);
-  log_params->masks_data_size[6] = sizeof(float) + sizeof(long long);
-  log_params->masks_data_size[7] = sizeof(integertime_t) + sizeof(double);
-
-  /* Compute the size of a chunk if all the mask are activated */
-  log_params->total_size = logger_offset_size + logger_mask_size;
-
-  for (size_t i = 0; i < log_params->number_mask; i++) {
-    if (log_params->masks[i] != logger_mask_timestamp)
-      log_params->total_size += log_params->masks_data_size[i];
-  }
-
-  // todo masks_type
-}
-
-/**
- * @brief Clean the #logger_parameters
- *
- * @param log_params The #logger_parameters
- */
-void logger_parameters_clean(struct logger_parameters *log_params) {
-  free(log_params->masks);
-  free(log_params->masks_name);
-  free(log_params->masks_data_size);
+  memcpy(skip_header, &file_offset, logger_offset_size);
 }
 
 /**
@@ -707,49 +548,50 @@ int logger_read_part(struct part *p, size_t *offset, const char *buff) {
   buff += logger_read_chunk_header(buff, &mask, offset, cur_offset);
 
   /* We are only interested in particle data. */
-  if (mask & logger_mask_timestamp)
+  if (mask & logger_mask_data[logger_timestamp].mask)
     error("Trying to read timestamp as particle.");
 
   /* Particle position as three doubles. */
-  if (mask & logger_mask_x) {
-    memcpy(p->x, buff, 3 * sizeof(double));
-    buff += 3 * sizeof(double);
+  if (mask & logger_mask_data[logger_x].mask) {
+    memcpy(p->x, buff, logger_mask_data[logger_x].size);
+    buff += logger_mask_data[logger_x].size;
   }
 
   /* Particle velocity as three floats. */
-  if (mask & logger_mask_v) {
-    memcpy(p->v, buff, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_v].mask) {
+    memcpy(p->v, buff, logger_mask_data[logger_v].size);
+    buff += logger_mask_data[logger_v].size;
   }
 
   /* Particle accelleration as three floats. */
-  if (mask & logger_mask_a) {
-    memcpy(p->a_hydro, buff, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_a].mask) {
+    memcpy(p->a_hydro, buff, logger_mask_data[logger_a].size);
+    buff += logger_mask_data[logger_a].size;
   }
 
 #if defined(GADGET2_SPH)
 
   /* Particle internal energy as a single float. */
-  if (mask & logger_mask_u) {
-    memcpy(&p->entropy, buff, sizeof(float));
-    buff += sizeof(float);
+  if (mask & logger_mask_data[logger_u].mask) {
+    memcpy(&p->entropy, buff, logger_mask_data[logger_u].size);
+    buff += logger_mask_data[logger_u].size;
   }
 
   /* Particle smoothing length as a single float. */
-  if (mask & logger_mask_h) {
-    memcpy(&p->h, buff, sizeof(float));
-    buff += sizeof(float);
+  if (mask & logger_mask_data[logger_h].mask) {
+    memcpy(&p->h, buff, logger_mask_data[logger_h].size);
+    buff += logger_mask_data[logger_h].size;
   }
 
   /* Particle density as a single float. */
-  if (mask & logger_mask_rho) {
-    memcpy(&p->rho, buff, sizeof(float));
-    buff += sizeof(float);
+  if (mask & logger_mask_data[logger_rho].mask) {
+    memcpy(&p->rho, buff, logger_mask_data[logger_rho].size);
+    buff += logger_mask_data[logger_rho].size;
   }
 
   /* Particle constants, which is a bit more complicated. */
-  if (mask & logger_mask_rho) {
+  if (mask & logger_mask_data[logger_rho].mask) {
+    // TODO make it dependent of logger_mask_data
     memcpy(&p->mass, buff, sizeof(float));
     buff += sizeof(float);
     memcpy(&p->id, buff, sizeof(long long));
@@ -783,33 +625,35 @@ int logger_read_gpart(struct gpart *p, size_t *offset, const char *buff) {
   buff += logger_read_chunk_header(buff, &mask, offset, cur_offset);
 
   /* We are only interested in particle data. */
-  if (mask & logger_mask_timestamp)
+  if (mask & logger_mask_data[logger_timestamp].mask)
     error("Trying to read timestamp as particle.");
 
   /* We can't store all part fields in a gpart. */
-  if (mask & (logger_mask_u | logger_mask_rho))
+  if (mask &
+      (logger_mask_data[logger_u].mask | logger_mask_data[logger_rho].mask))
     error("Trying to read SPH quantities into a gpart.");
 
   /* Particle position as three doubles. */
-  if (mask & logger_mask_x) {
-    memcpy(p->x, buff, 3 * sizeof(double));
-    buff += 3 * sizeof(double);
+  if (mask & logger_mask_data[logger_x].mask) {
+    memcpy(p->x, buff, logger_mask_data[logger_x].size);
+    buff += logger_mask_data[logger_x].size;
   }
 
   /* Particle velocity as three floats. */
-  if (mask & logger_mask_v) {
-    memcpy(p->v_full, buff, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_v].mask) {
+    memcpy(p->v_full, buff, logger_mask_data[logger_v].size);
+    buff += logger_mask_data[logger_v].size;
   }
 
   /* Particle accelleration as three floats. */
-  if (mask & logger_mask_a) {
-    memcpy(p->a_grav, buff, 3 * sizeof(float));
-    buff += 3 * sizeof(float);
+  if (mask & logger_mask_data[logger_a].mask) {
+    memcpy(p->a_grav, buff, logger_mask_data[logger_a].size);
+    buff += logger_mask_data[logger_a].size;
   }
 
   /* Particle constants, which is a bit more complicated. */
-  if (mask & logger_mask_rho) {
+  if (mask & logger_mask_data[logger_rho].mask) {
+    // TODO make it dependent of logger_mask_data
     memcpy(&p->mass, buff, sizeof(float));
     buff += sizeof(float);
     memcpy(&p->id_or_neg_offset, buff, sizeof(long long));
@@ -842,14 +686,15 @@ int logger_read_timestamp(unsigned long long int *t, double *time,
   buff += logger_read_chunk_header(buff, &mask, offset, cur_offset);
 
   /* We are only interested in timestamps. */
-  if (!(mask & logger_mask_timestamp))
+  if (!(mask & logger_mask_data[logger_timestamp].mask))
     error("Trying to read timestamp from a particle.");
 
   /* Make sure we don't have extra fields. */
-  if (mask != logger_mask_timestamp)
+  if (mask != logger_mask_data[logger_timestamp].mask)
     error("Timestamp message contains extra fields.");
 
   /* Copy the timestamp value from the buffer. */
+  // TODO make it dependent of logger_mask_data
   memcpy(t, buff, sizeof(unsigned long long int));
   buff += sizeof(unsigned long long int);
 
diff --git a/src/logger.h b/src/logger.h
index 3ac5291eaab1f0e4fc05640cc23e1705a7178c9a..56e2c8ab94c66b24df1800877bb9cfb129c3e645 100644
--- a/src/logger.h
+++ b/src/logger.h
@@ -23,6 +23,7 @@
 
 /* Includes. */
 #include "common_io.h"
+#include "dump.h"
 #include "inline.h"
 #include "timeline.h"
 #include "units.h"
@@ -73,53 +74,32 @@ struct engine;
  */
 
 /* Some constants. */
-enum logger_masks {
-  logger_mask_x = (1 << 0),
-  logger_mask_v = (1 << 1),
-  logger_mask_a = (1 << 2),
-  logger_mask_u = (1 << 3),
-  logger_mask_h = (1 << 4),
-  logger_mask_rho = (1 << 5),
-  logger_mask_consts = (1 << 6),
-  logger_mask_timestamp = (1 << 7),
+enum logger_masks_number {
+  logger_x = 0,
+  logger_v = 1,
+  logger_a = 2,
+  logger_u = 3,
+  logger_h = 4,
+  logger_rho = 5,
+  logger_consts = 6,
+  logger_timestamp = 7,  /* expect it to be before count */
+  logger_count_mask = 8, /* Need to be the last */
+} __attribute__((packed));
+
+struct mask_data {
+  /* Number of bytes for a mask */
+  int size;
+  /* Mask value */
+  unsigned int mask;
+  /* name of the mask */
+  char name[100];
 };
 
+extern const struct mask_data logger_mask_data[logger_count_mask];
+
 /* Size of the strings. */
 #define logger_string_length 200
 
-/* parameters of the logger */
-struct logger_parameters {
-  /* size of a label in bytes */
-  size_t label_size;
-
-  /* size of an offset in bytes */
-  size_t offset_size;
-
-  /* size of a mask in bytes */
-  size_t mask_size;
-
-  /* size of a number in bytes */
-  size_t number_size;
-
-  /* size of a data type in bytes */
-  size_t data_type_size;
-
-  /* number of different mask */
-  size_t number_mask;
-
-  /* value of each masks */
-  size_t *masks;
-
-  /* data size of each mask */
-  size_t *masks_data_size;
-
-  /* label of each mask */
-  char *masks_name;
-
-  /* Size of a chunk if every mask are activated */
-  size_t total_size;
-};
-
 /* structure containing global data */
 struct logger {
   /* Number of particle steps between dumping a chunk of data */
@@ -128,8 +108,8 @@ struct logger {
   /* Logger basename */
   char base_name[logger_string_length];
 
-  /* File name of the dump file */
-  struct dump *dump;
+  /* Dump file */
+  struct dump dump;
 
   /* timestamp offset for logger*/
   size_t timestamp_offset;
@@ -137,8 +117,8 @@ struct logger {
   /* scaling factor when buffer is too small */
   float buffer_scale;
 
-  /* logger parameters */
-  struct logger_parameters *params;
+  /* Size of a chunk if every mask are activated */
+  int max_chunk_size;
 
 } SWIFT_STRUCT_ALIGN;
 
@@ -151,18 +131,6 @@ struct logger_part_data {
   size_t last_offset;
 };
 
-enum logger_datatype {
-  logger_data_int,
-  logger_data_float,
-  logger_data_double,
-  logger_data_char,
-  logger_data_longlong,
-  logger_data_bool,
-  logger_data_count /* should be last */
-};
-
-extern const unsigned int logger_datatype_size[];
-
 /* Function prototypes. */
 int logger_compute_chunk_size(unsigned int mask);
 void logger_log_all(struct logger *log, const struct engine *e);
@@ -183,9 +151,6 @@ int logger_read_gpart(struct gpart *p, size_t *offset, const char *buff);
 int logger_read_timestamp(unsigned long long int *t, double *time,
                           size_t *offset, const char *buff);
 
-void logger_parameters_init(struct logger_parameters *log_params);
-void logger_parameters_clean(struct logger_parameters *log_params);
-
 /**
  * @brief Initialize the logger data for a particle.
  *
@@ -193,7 +158,7 @@ void logger_parameters_clean(struct logger_parameters *log_params);
  */
 INLINE static void logger_part_data_init(struct logger_part_data *logger) {
   logger->last_offset = 0;
-  logger->steps_since_last_output = SHRT_MAX;
+  logger->steps_since_last_output = INT_MAX;
 }
 
 /**
diff --git a/src/parallel_io.c b/src/parallel_io.c
index 481a2d8a7b7ba8fbefe77434b0f57b43d421f21d..febbb4a7db6796fd751cb1eacc174a42936d19a2 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -708,6 +708,21 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
     error("ICs dimensionality (%dD) does not match code dimensionality (%dD)",
           dimension, (int)hydro_dimension);
 
+  /* Check whether the number of files is specified (if the info exists) */
+  const hid_t hid_files = H5Aexists(h_grp, "NumFilesPerSnapshot");
+  int num_files = 1;
+  if (hid_files < 0)
+    error(
+        "Error while testing the existance of 'NumFilesPerSnapshot' attribute");
+  if (hid_files > 0)
+    io_read_attribute(h_grp, "NumFilesPerSnapshot", INT, &num_files);
+  if (num_files != 1)
+    error(
+        "ICs are split over multiples files (%d). SWIFT cannot handle this "
+        "case. The script /tools/combine_ics.py is availalbe in the repository "
+        "to combine files into a valid input file.",
+        num_files);
+
   /* Read the relevant information and print status */
   int flag_entropy_temp[6];
   io_read_attribute(h_grp, "Flag_Entropy_ICs", INT, flag_entropy_temp);
diff --git a/src/physical_constants.c b/src/physical_constants.c
index ed25ff1b2be09a04400f98476c78a537e6d8e2bf..7752f4d3130b7174863d520b3d4d3c6a3e8eb433 100644
--- a/src/physical_constants.c
+++ b/src/physical_constants.c
@@ -131,6 +131,11 @@ void phys_const_init(const struct unit_system *us, struct swift_params *params,
   internal_const->const_primordial_He_fraction =
       const_primordial_He_fraction_cgs /
       units_general_cgs_conversion_factor(us, dimension_Yp);
+
+  const float dimension_reduced_hubble[5] = {0, 0, -1, 0, 0}; /* [s^-1] */
+  internal_const->const_reduced_hubble =
+      const_reduced_hubble_cgs /
+      units_general_cgs_conversion_factor(us, dimension_reduced_hubble);
 }
 
 /**
@@ -153,6 +158,7 @@ void phys_const_print(const struct phys_const *internal_const) {
           internal_const->const_astronomical_unit);
   message("%25s = %e", "Parsec", internal_const->const_parsec);
   message("%25s = %e", "Solar mass", internal_const->const_solar_mass);
+  message("%25s = %e", "km/s/Mpc", internal_const->const_reduced_hubble);
 }
 
 /**
diff --git a/src/physical_constants.h b/src/physical_constants.h
index a1b5e9c243c54bfd97179364170e8b3bbc36fe4f..97da4b322a8bca1f978b43a4cabda2ff1cc1e517 100644
--- a/src/physical_constants.h
+++ b/src/physical_constants.h
@@ -96,6 +96,9 @@ struct phys_const {
 
   /*! Primordial Helium fraction */
   double const_primordial_He_fraction;
+
+  /*! Reduced hubble constant units (i.e. H_0 / h) */
+  double const_reduced_hubble;
 };
 
 void phys_const_init(const struct unit_system* us, struct swift_params* params,
diff --git a/src/physical_constants_cgs.h b/src/physical_constants_cgs.h
index fecd1f894af5df5db54b37883ba07e470b956bdf..4d1a54f68ba557c74fb489a9343eaf3846c481f4 100644
--- a/src/physical_constants_cgs.h
+++ b/src/physical_constants_cgs.h
@@ -98,4 +98,8 @@ const double const_T_CMB_0_cgs = 2.7255;
 /*! Primordial Helium fraction [-] */
 const double const_primordial_He_fraction_cgs = 0.245;
 
+/*! Reduced Hubble constant units (i.e. H_0 / h == 100 km / s / Mpc in CGS)
+ * [s^-1] */
+const double const_reduced_hubble_cgs = 3.2407792894458e-18;
+
 #endif /* SWIFT_PHYSICAL_CONSTANTS_CGS_H */
diff --git a/src/potential/hernquist/potential.h b/src/potential/hernquist/potential.h
index d0ec339d91376d25e0e5a2106826d07deca7115b..b98f45ff7ab4aeffd94f47f4931d3dd6c80d5642 100644
--- a/src/potential/hernquist/potential.h
+++ b/src/potential/hernquist/potential.h
@@ -170,6 +170,12 @@ static INLINE void potential_init_backend(
     const struct unit_system* us, const struct space* s,
     struct external_potential* potential) {
 
+  /* Define the default value */
+  static const int idealized_disk_default = 0;
+  static const double M200_default = 0.;
+  static const double V200_default = 0.;
+  static const double R200_default = 0.;
+
   /* Read in the position of the centre of potential */
   parser_get_param_double_array(parameter_file, "HernquistPotential:position",
                                 3, potential->x);
@@ -184,11 +190,91 @@ static INLINE void potential_init_backend(
     potential->x[2] += s->dim[2] / 2.;
   }
 
-  /* Read the other parameters of the model */
-  potential->mass =
-      parser_get_param_double(parameter_file, "HernquistPotential:mass");
-  potential->al =
-      parser_get_param_double(parameter_file, "HernquistPotential:scalelength");
+  /* check whether we use the more advanced idealized disk setting */
+  const int usedisk = parser_get_opt_param_int(
+      parameter_file, "HernquistPotential:idealizeddisk",
+      idealized_disk_default);
+
+  if (!usedisk) {
+    /* Read the parameters of the model in the case of the simple
+     * potential form \f$ \Phi = - \frac{GM}{r+a} \f$ */
+    potential->mass =
+        parser_get_param_double(parameter_file, "HernquistPotential:mass");
+    potential->al = parser_get_param_double(parameter_file,
+                                            "HernquistPotential:scalelength");
+  } else {
+
+    /* Read the parameters in the case of a idealized disk
+     * There are 3 different possible input parameters M200, V200 and R200
+     * First read in the mandatory parameters in this case */
+
+    const float G_newton = phys_const->const_newton_G;
+    const float kmoversoverMpc = phys_const->const_reduced_hubble;
+
+    /* Initialize the variables */
+    double M200 = parser_get_opt_param_double(
+        parameter_file, "HernquistPotential:M200", M200_default);
+    double V200 = parser_get_opt_param_double(
+        parameter_file, "HernquistPotential:V200", V200_default);
+    double R200 = parser_get_opt_param_double(
+        parameter_file, "HernquistPotential:R200", R200_default);
+    const double h =
+        parser_get_param_double(parameter_file, "HernquistPotential:h");
+
+    /* Hubble constant assumed for halo masses conversion */
+    const double H0 = h * kmoversoverMpc;
+
+    /* There are 3 legit runs possible with use disk,
+     * with a known M200, V200 or R200 */
+    if (M200 != 0.0) {
+      /* Calculate V200 and R200 from M200 */
+      V200 = cbrt(10. * M200 * G_newton * H0);
+      R200 = V200 / (10 * H0);
+
+    } else if (V200 != 0.0) {
+
+      /* Calculate M200 and R200 from V200 */
+      M200 = V200 * V200 * V200 / (10. * G_newton * H0);
+      R200 = V200 / (10 * H0);
+    } else if (R200 != 0.0) {
+
+      /* Calculate M200 and V200 from R200 */
+      V200 = 10. * H0 * R200;
+      M200 = V200 * V200 * V200 / (10. * G_newton * H0);
+    } else {
+      error("Please specify one of the 3 variables M200, V200 or R200");
+    }
+
+    /* message("M200 = %g, R200 = %g, V200 = %g", M200, R200, V200); */
+    /* message("H0 = %g", H0); */
+
+    /* get the concentration from the parameter file */
+    const double concentration = parser_get_param_double(
+        parameter_file, "HernquistPotential:concentration");
+
+    /* Calculate the Scale radius using the NFW definition */
+    const double RS = R200 / concentration;
+
+    /* Calculate the Hernquist equivalent scale length */
+    potential->al = RS * sqrt(1. * (log(1. + concentration) -
+                                    concentration / (1. + concentration)));
+
+    /* Depending on the disk mass and and the bulge mass the halo
+     * gets a different mass, because of this we read the fractions
+     * from the parameter file and calculate the absolute mass*/
+    const double diskfraction = parser_get_param_double(
+        parameter_file, "HernquistPotential:diskfraction");
+    const double bulgefraction = parser_get_param_double(
+        parameter_file, "HernquistPotential:bulgefraction");
+    /* Calculate the mass of the bulge and disk from the parameters  */
+    const double Mdisk = M200 * diskfraction;
+    const double Mbulge = M200 * bulgefraction;
+
+    /* Store the mass of the DM halo */
+    potential->mass = M200 - Mdisk - Mbulge;
+  }
+
+  /* Retrieve the timestep and softening of the potential */
   potential->timestep_mult = parser_get_param_float(
       parameter_file, "HernquistPotential:timestep_mult");
   const float epsilon =
@@ -199,7 +285,7 @@ static INLINE void potential_init_backend(
   /* This is the circular orbital time at the softened radius */
   const float sqrtgm = sqrtf(phys_const->const_newton_G * potential->mass);
   potential->mintime = 2.f * sqrtf(epsilon) * potential->al * M_PI *
-                       (1 + epsilon / potential->al) / sqrtgm *
+                       (1. + epsilon / potential->al) / sqrtgm *
                        potential->timestep_mult;
 }
 
diff --git a/src/runner.c b/src/runner.c
index 6d48af01184dc782d7ddca56e6d35a93d4b11eaf..f14f8d8bc2721d0edfaca542b68af645bd5ac1a0 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -97,8 +97,15 @@
 /* Import the gravity loop functions. */
 #include "runner_doiact_grav.h"
 
-/* Import the stars loop functions. */
+/* Import the stars density loop functions. */
+#define FUNCTION density
 #include "runner_doiact_stars.h"
+#undef FUNCTION
+
+/* Import the stars feedback loop functions. */
+#define FUNCTION feedback
+#include "runner_doiact_stars.h"
+#undef FUNCTION
 
 /**
  * @brief Perform source terms
@@ -2978,9 +2985,13 @@ void runner_do_logger(struct runner *r, struct cell *c, int timer) {
           /* Write particle */
           /* Currently writing everything, should adapt it through time */
           logger_log_part(e->logger, p,
-                          logger_mask_x | logger_mask_v | logger_mask_a |
-                              logger_mask_u | logger_mask_h | logger_mask_rho |
-                              logger_mask_consts,
+                          logger_mask_data[logger_x].mask |
+                              logger_mask_data[logger_v].mask |
+                              logger_mask_data[logger_a].mask |
+                              logger_mask_data[logger_u].mask |
+                              logger_mask_data[logger_h].mask |
+                              logger_mask_data[logger_rho].mask |
+                              logger_mask_data[logger_consts].mask,
                           &xp->logger_data.last_offset);
 
           /* Set counter back to zero */
diff --git a/src/runner_doiact_stars.h b/src/runner_doiact_stars.h
index 3a920ab553f3e604619dfc4b6efe506e83e9ef52..e816d80399a0fef85645c914168dd4038f55988c 100644
--- a/src/runner_doiact_stars.h
+++ b/src/runner_doiact_stars.h
@@ -17,10 +17,54 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
-#ifndef SWIFT_RUNNER_DOIACT_STARS_H
-#define SWIFT_RUNNER_DOIACT_STARS_H
 
-#include "swift.h"
+/* Before including this file, define FUNCTION, which is the
+   name of the interaction function. This creates the interaction functions
+   runner_dopair_FUNCTION, runner_doself_FUNCTION and runner_dosub_FUNCTION
+   calling the pairwise interaction function runner_iact_FUNCTION. */
+
+#define PASTE(x, y) x##_##y
+
+#define _DOSELF1_STARS(f) PASTE(runner_doself_stars, f)
+#define DOSELF1_STARS _DOSELF1_STARS(FUNCTION)
+
+#define _DO_NONSYM_PAIR1_STARS(f) PASTE(runner_do_nonsym_pair_stars, f)
+#define DO_NONSYM_PAIR1_STARS _DO_NONSYM_PAIR1_STARS(FUNCTION)
+
+#define _DOPAIR1_STARS(f) PASTE(runner_dopair_stars, f)
+#define DOPAIR1_STARS _DOPAIR1_STARS(FUNCTION)
+
+#define _DOPAIR1_SUBSET_STARS(f) PASTE(runner_dopair_subset_stars, f)
+#define DOPAIR1_SUBSET_STARS _DOPAIR1_SUBSET_STARS(FUNCTION)
+
+#define _DOSELF1_SUBSET_STARS(f) PASTE(runner_doself_subset_stars, f)
+#define DOSELF1_SUBSET_STARS _DOSELF1_SUBSET_STARS(FUNCTION)
+
+#define _DOSELF1_SUBSET_BRANCH_STARS(f) \
+  PASTE(runner_doself_subset_branch_stars, f)
+#define DOSELF1_SUBSET_BRANCH_STARS _DOSELF1_SUBSET_BRANCH_STARS(FUNCTION)
+
+#define _DOPAIR1_SUBSET_BRANCH_STARS(f) \
+  PASTE(runner_dopair_subset_branch_stars, f)
+#define DOPAIR1_SUBSET_BRANCH_STARS _DOPAIR1_SUBSET_BRANCH_STARS(FUNCTION)
+
+#define _DOSUB_SUBSET_STARS(f) PASTE(runner_dosub_subset_stars, f)
+#define DOSUB_SUBSET_STARS _DOSUB_SUBSET_STARS(FUNCTION)
+
+#define _DOSELF1_BRANCH_STARS(f) PASTE(runner_doself_branch_stars, f)
+#define DOSELF1_BRANCH_STARS _DOSELF1_BRANCH_STARS(FUNCTION)
+
+#define _DOPAIR1_BRANCH_STARS(f) PASTE(runner_dopair_branch_stars, f)
+#define DOPAIR1_BRANCH_STARS _DOPAIR1_BRANCH_STARS(FUNCTION)
+
+#define _DOSUB_PAIR1_STARS(f) PASTE(runner_dosub_pair_stars, f)
+#define DOSUB_PAIR1_STARS _DOSUB_PAIR1_STARS(FUNCTION)
+
+#define _DOSUB_SELF1_STARS(f) PASTE(runner_dosub_self_stars, f)
+#define DOSUB_SELF1_STARS _DOSUB_SELF1_STARS(FUNCTION)
+
+#define _IACT_STARS(f) PASTE(runner_iact_nonsym_stars, f)
+#define IACT_STARS _IACT_STARS(FUNCTION)
 
 /**
  * @brief Calculate the number density of #part around the #spart
@@ -29,12 +73,10 @@
  * @param c cell
  * @param timer 1 if the time is to be recorded.
  */
-void runner_doself_stars_density(struct runner *r, struct cell *c, int timer) {
+void DOSELF1_STARS(struct runner *r, struct cell *c, int timer) {
   const struct engine *e = r->e;
   const struct cosmology *cosmo = e->cosmology;
 
-  TIMER_TIC;
-
   /* Anything to do here? */
   if (!cell_is_active_stars(c, e)) return;
   if (c->hydro.count == 0 && c->stars.count == 0) return;
@@ -80,12 +122,10 @@ void runner_doself_stars_density(struct runner *r, struct cell *c, int timer) {
 #endif
 
       if (r2 > 0.f && r2 < hig2) {
-        runner_iact_nonsym_stars_density(r2, dx, hi, hj, si, pj, a, H);
+        IACT_STARS(r2, dx, hi, hj, si, pj, a, H);
       }
     } /* loop over the parts in ci. */
   }   /* loop over the sparts in ci. */
-
-  TIMER_TOC(timer_doself_stars_density);
 }
 
 /**
@@ -95,8 +135,8 @@ void runner_doself_stars_density(struct runner *r, struct cell *c, int timer) {
  * @param ci The first #cell
  * @param cj The second #cell
  */
-void runner_dosubpair_stars_density(struct runner *r, struct cell *restrict ci,
-                                    struct cell *restrict cj) {
+void DO_NONSYM_PAIR1_STARS(struct runner *r, struct cell *restrict ci,
+                           struct cell *restrict cj) {
 
   const struct engine *e = r->e;
   const struct cosmology *cosmo = e->cosmology;
@@ -153,24 +193,19 @@ void runner_dosubpair_stars_density(struct runner *r, struct cell *restrict ci,
         error("Particle pj not drifted to current time");
 #endif
 
-      if (r2 < hig2)
-        runner_iact_nonsym_stars_density(r2, dx, hi, hj, si, pj, a, H);
+      if (r2 < hig2) IACT_STARS(r2, dx, hi, hj, si, pj, a, H);
 
     } /* loop over the parts in cj. */
   }   /* loop over the parts in ci. */
 }
 
-void runner_dopair_stars_density(struct runner *r, struct cell *restrict ci,
-                                 struct cell *restrict cj, int timer) {
-
-  TIMER_TIC;
+void DOPAIR1_STARS(struct runner *r, struct cell *restrict ci,
+                   struct cell *restrict cj, int timer) {
 
   if (ci->stars.count != 0 && cj->hydro.count != 0)
-    runner_dosubpair_stars_density(r, ci, cj);
+    DO_NONSYM_PAIR1_STARS(r, ci, cj);
   if (cj->stars.count != 0 && ci->hydro.count != 0)
-    runner_dosubpair_stars_density(r, cj, ci);
-
-  if (timer) TIMER_TOC(timer_dopair_stars_density);
+    DO_NONSYM_PAIR1_STARS(r, cj, ci);
 }
 
 /**
@@ -187,18 +222,14 @@ void runner_dopair_stars_density(struct runner *r, struct cell *restrict ci,
  * @param cj The second #cell.
  * @param shift The shift vector to apply to the particles in ci.
  */
-void runner_dopair_subset_stars_density(struct runner *r,
-                                        struct cell *restrict ci,
-                                        struct spart *restrict sparts_i,
-                                        int *restrict ind, int scount,
-                                        struct cell *restrict cj,
-                                        const double *shift) {
+void DOPAIR1_SUBSET_STARS(struct runner *r, struct cell *restrict ci,
+                          struct spart *restrict sparts_i, int *restrict ind,
+                          int scount, struct cell *restrict cj,
+                          const double *shift) {
 
   const struct engine *e = r->e;
   const struct cosmology *cosmo = e->cosmology;
 
-  TIMER_TIC;
-
   const int count_j = cj->hydro.count;
   struct part *restrict parts_j = cj->hydro.parts;
 
@@ -242,12 +273,10 @@ void runner_dopair_subset_stars_density(struct runner *r,
 #endif
       /* Hit or miss? */
       if (r2 < hig2) {
-        runner_iact_nonsym_stars_density(r2, dx, hi, pj->h, spi, pj, a, H);
+        IACT_STARS(r2, dx, hi, pj->h, spi, pj, a, H);
       }
     } /* loop over the parts in cj. */
   }   /* loop over the parts in ci. */
-
-  TIMER_TOC(timer_dopair_subset_stars_density);
 }
 
 /**
@@ -260,16 +289,13 @@ void runner_dopair_subset_stars_density(struct runner *r,
  * @param ind The list of indices of particles in @c ci to interact with.
  * @param scount The number of particles in @c ind.
  */
-void runner_doself_subset_stars_density(struct runner *r,
-                                        struct cell *restrict ci,
-                                        struct spart *restrict sparts,
-                                        int *restrict ind, int scount) {
+void DOSELF1_SUBSET_STARS(struct runner *r, struct cell *restrict ci,
+                          struct spart *restrict sparts, int *restrict ind,
+                          int scount) {
 
   const struct engine *e = r->e;
   const struct cosmology *cosmo = e->cosmology;
 
-  TIMER_TIC;
-
   /* Cosmological terms */
   const float a = cosmo->a;
   const float H = cosmo->H;
@@ -315,36 +341,33 @@ void runner_doself_subset_stars_density(struct runner *r,
 
       /* Hit or miss? */
       if (r2 > 0.f && r2 < hig2) {
-        runner_iact_nonsym_stars_density(r2, dx, hi, hj, spi, pj, a, H);
+        IACT_STARS(r2, dx, hi, hj, spi, pj, a, H);
       }
     } /* loop over the parts in cj. */
   }   /* loop over the parts in ci. */
-
-  TIMER_TOC(timer_doself_subset_stars_density);
 }
 
 /**
-* @brief Determine which version of DOSELF_SUBSET needs to be called depending
-* on the optimisation level.
-
-* @param r The #runner.
-* @param ci The first #cell.
-* @param sparts The #spart to interact.
-* @param ind The list of indices of particles in @c ci to interact with.
-* @param scount The number of particles in @c ind.
-*/
-void runner_doself_subset_branch_stars_density(struct runner *r,
-                                               struct cell *restrict ci,
-                                               struct spart *restrict sparts,
-                                               int *restrict ind, int scount) {
-
-  runner_doself_subset_stars_density(r, ci, sparts, ind, scount);
+ * @brief Determine which version of DOSELF1_SUBSET_STARS needs to be called
+ * depending on the optimisation level.
+ *
+ * @param r The #runner.
+ * @param ci The first #cell.
+ * @param sparts The #spart to interact.
+ * @param ind The list of indices of particles in @c ci to interact with.
+ * @param scount The number of particles in @c ind.
+ */
+void DOSELF1_SUBSET_BRANCH_STARS(struct runner *r, struct cell *restrict ci,
+                                 struct spart *restrict sparts,
+                                 int *restrict ind, int scount) {
+
+  DOSELF1_SUBSET_STARS(r, ci, sparts, ind, scount);
 }
 
 /**
- * @brief Determine which version of DOPAIR_SUBSET needs to be called depending
- * on the
- * orientation of the cells or whether DOPAIR_SUBSET needs to be called at all.
+ * @brief Determine which version of DOPAIR1_SUBSET_STARS needs to be called
+ * depending on the orientation of the cells or whether DOPAIR1_SUBSET_STARS
+ * needs to be called at all.
  *
  * @param r The #runner.
  * @param ci The first #cell.
@@ -353,11 +376,10 @@ void runner_doself_subset_branch_stars_density(struct runner *r,
  * @param scount The number of particles in @c ind.
  * @param cj The second #cell.
  */
-void runner_dopair_subset_branch_stars_density(struct runner *r,
-                                               struct cell *restrict ci,
-                                               struct spart *restrict sparts_i,
-                                               int *restrict ind, int scount,
-                                               struct cell *restrict cj) {
+void DOPAIR1_SUBSET_BRANCH_STARS(struct runner *r, struct cell *restrict ci,
+                                 struct spart *restrict sparts_i,
+                                 int *restrict ind, int scount,
+                                 struct cell *restrict cj) {
 
   const struct engine *e = r->e;
 
@@ -370,19 +392,16 @@ void runner_dopair_subset_branch_stars_density(struct runner *r,
       shift[k] = -e->s->dim[k];
   }
 
-  runner_dopair_subset_stars_density(r, ci, sparts_i, ind, scount, cj, shift);
+  DOPAIR1_SUBSET_STARS(r, ci, sparts_i, ind, scount, cj, shift);
 }
 
-void runner_dosub_subset_stars_density(struct runner *r, struct cell *ci,
-                                       struct spart *sparts, int *ind,
-                                       int scount, struct cell *cj, int sid,
-                                       int gettimer) {
+void DOSUB_SUBSET_STARS(struct runner *r, struct cell *ci, struct spart *sparts,
+                        int *ind, int scount, struct cell *cj, int sid,
+                        int gettimer) {
 
   const struct engine *e = r->e;
   struct space *s = e->s;
 
-  TIMER_TIC;
-
   /* Should we even bother? */
   if (!cell_is_active_stars(ci, e) &&
       (cj == NULL || !cell_is_active_stars(cj, e)))
@@ -410,18 +429,17 @@ void runner_dosub_subset_stars_density(struct runner *r, struct cell *ci,
     if (cell_can_recurse_in_self_stars_task(ci)) {
 
       /* Loop over all progeny. */
-      runner_dosub_subset_stars_density(r, sub, sparts, ind, scount, NULL, -1,
-                                        0);
+      DOSUB_SUBSET_STARS(r, sub, sparts, ind, scount, NULL, -1, 0);
       for (int j = 0; j < 8; j++)
         if (ci->progeny[j] != sub && ci->progeny[j] != NULL)
-          runner_dosub_subset_stars_density(r, sub, sparts, ind, scount,
-                                            ci->progeny[j], -1, 0);
+          DOSUB_SUBSET_STARS(r, sub, sparts, ind, scount, ci->progeny[j], -1,
+                             0);
 
     }
 
     /* Otherwise, compute self-interaction. */
     else
-      runner_doself_subset_branch_stars_density(r, ci, sparts, ind, scount);
+      DOSELF1_SUBSET_BRANCH_STARS(r, ci, sparts, ind, scount);
   } /* self-interaction. */
 
   /* Otherwise, it's a pair interaction. */
@@ -441,497 +459,497 @@ void runner_dosub_subset_stars_density(struct runner *r, struct cell *ci,
         /* Regular sub-cell interactions of a single cell. */
         case 0: /* (  1 ,  1 ,  1 ) */
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
 
         case 1: /* (  1 ,  1 ,  0 ) */
           if (ci->progeny[6] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
 
         case 2: /* (  1 ,  1 , -1 ) */
           if (ci->progeny[6] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           break;
 
         case 3: /* (  1 ,  0 ,  1 ) */
           if (ci->progeny[5] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
 
         case 4: /* (  1 ,  0 ,  0 ) */
           if (ci->progeny[4] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[4] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[4] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[4] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
 
         case 5: /* (  1 ,  0 , -1 ) */
           if (ci->progeny[4] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[4] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           break;
 
         case 6: /* (  1 , -1 ,  1 ) */
           if (ci->progeny[5] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           break;
 
         case 7: /* (  1 , -1 ,  0 ) */
           if (ci->progeny[4] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[4] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           break;
 
         case 8: /* (  1 , -1 , -1 ) */
           if (ci->progeny[4] == sub && cj->progeny[3] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[4], sparts, ind,
-                                              scount, cj->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[4], sparts, ind, scount,
+                               cj->progeny[3], -1, 0);
           if (ci->progeny[4] != NULL && cj->progeny[3] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[3], sparts, ind,
-                                              scount, ci->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[3], sparts, ind, scount,
+                               ci->progeny[4], -1, 0);
           break;
 
         case 9: /* (  0 ,  1 ,  1 ) */
           if (ci->progeny[3] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
 
         case 10: /* (  0 ,  1 ,  0 ) */
           if (ci->progeny[2] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[2], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[2], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[2] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[2], -1, 0);
           if (ci->progeny[2] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[2], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[2], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[2] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[2], -1, 0);
           if (ci->progeny[2] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[2], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[2], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[2] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[2], -1, 0);
           if (ci->progeny[2] == sub && cj->progeny[5] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[2], sparts, ind,
-                                              scount, cj->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[2], sparts, ind, scount,
+                               cj->progeny[5], -1, 0);
           if (ci->progeny[2] != NULL && cj->progeny[5] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[5], sparts, ind,
-                                              scount, ci->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[5], sparts, ind, scount,
+                               ci->progeny[2], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[5] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[5], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[5] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[5], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[5], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[5] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[5], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[5] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[5], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[5], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[5] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[5], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[5] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[5], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[5], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
 
         case 11: /* (  0 ,  1 , -1 ) */
           if (ci->progeny[2] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[2], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[2], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[2] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[2], -1, 0);
           if (ci->progeny[2] == sub && cj->progeny[5] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[2], sparts, ind,
-                                              scount, cj->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[2], sparts, ind, scount,
+                               cj->progeny[5], -1, 0);
           if (ci->progeny[2] != NULL && cj->progeny[5] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[5], sparts, ind,
-                                              scount, ci->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[5], sparts, ind, scount,
+                               ci->progeny[2], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[1] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[1], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[1] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[1], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[1], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           if (ci->progeny[6] == sub && cj->progeny[5] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[6], sparts, ind,
-                                              scount, cj->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[6], sparts, ind, scount,
+                               cj->progeny[5], -1, 0);
           if (ci->progeny[6] != NULL && cj->progeny[5] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[5], sparts, ind,
-                                              scount, ci->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[5], sparts, ind, scount,
+                               ci->progeny[6], -1, 0);
           break;
 
         case 12: /* (  0 ,  0 ,  1 ) */
           if (ci->progeny[1] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[1], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[1], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[1] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[1], -1, 0);
           if (ci->progeny[1] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[1], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[1], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[1] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[1], -1, 0);
           if (ci->progeny[1] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[1], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[1], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[1] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[1], -1, 0);
           if (ci->progeny[1] == sub && cj->progeny[6] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[1], sparts, ind,
-                                              scount, cj->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[1], sparts, ind, scount,
+                               cj->progeny[6], -1, 0);
           if (ci->progeny[1] != NULL && cj->progeny[6] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[6], sparts, ind,
-                                              scount, ci->progeny[1], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[6], sparts, ind, scount,
+                               ci->progeny[1], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[3] == sub && cj->progeny[6] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[3], sparts, ind,
-                                              scount, cj->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[3], sparts, ind, scount,
+                               cj->progeny[6], -1, 0);
           if (ci->progeny[3] != NULL && cj->progeny[6] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[6], sparts, ind,
-                                              scount, ci->progeny[3], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[6], sparts, ind, scount,
+                               ci->progeny[3], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[5] == sub && cj->progeny[6] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[5], sparts, ind,
-                                              scount, cj->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[5], sparts, ind, scount,
+                               cj->progeny[6], -1, 0);
           if (ci->progeny[5] != NULL && cj->progeny[6] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[6], sparts, ind,
-                                              scount, ci->progeny[5], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[6], sparts, ind, scount,
+                               ci->progeny[5], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[0] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[0], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[0], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[0] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[0], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[0], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[2] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[2], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[2], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[2] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[2], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[2], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[4] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[4], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[4], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[4] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[4], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[4], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           if (ci->progeny[7] == sub && cj->progeny[6] != NULL)
-            runner_dosub_subset_stars_density(r, ci->progeny[7], sparts, ind,
-                                              scount, cj->progeny[6], -1, 0);
+            DOSUB_SUBSET_STARS(r, ci->progeny[7], sparts, ind, scount,
+                               cj->progeny[6], -1, 0);
           if (ci->progeny[7] != NULL && cj->progeny[6] == sub)
-            runner_dosub_subset_stars_density(r, cj->progeny[6], sparts, ind,
-                                              scount, ci->progeny[7], -1, 0);
+            DOSUB_SUBSET_STARS(r, cj->progeny[6], sparts, ind, scount,
+                               ci->progeny[7], -1, 0);
           break;
       }
 
@@ -943,23 +961,21 @@ void runner_dosub_subset_stars_density(struct runner *r, struct cell *ci,
       /* Do any of the cells need to be drifted first? */
       if (!cell_are_part_drifted(cj, e)) error("Cell should be drifted!");
 
-      runner_dopair_subset_branch_stars_density(r, ci, sparts, ind, scount, cj);
+      DOPAIR1_SUBSET_BRANCH_STARS(r, ci, sparts, ind, scount, cj);
     }
 
   } /* otherwise, pair interaction. */
-
-  if (gettimer) TIMER_TOC(timer_dosub_subset_pair_stars_density);
 }
 
 /**
- * @brief Determine which version of runner_doself needs to be called depending
+ * @brief Determine which version of DOSELF1_STARS needs to be called depending
  * on the optimisation level.
  *
  * @param r #runner
  * @param c #cell c
  *
  */
-void runner_doself_branch_stars_density(struct runner *r, struct cell *c) {
+void DOSELF1_BRANCH_STARS(struct runner *r, struct cell *c) {
 
   const struct engine *restrict e = r->e;
 
@@ -970,12 +986,11 @@ void runner_doself_branch_stars_density(struct runner *r, struct cell *c) {
   if (c->stars.h_max_old * kernel_gamma > c->dmin)
     error("Cell smaller than smoothing length");
 
-  runner_doself_stars_density(r, c, 1);
+  DOSELF1_STARS(r, c, 1);
 }
 
-#define RUNNER_STARS_CHECK_SORT(TYPE, PART)                                 \
-  void runner_stars_check_sort_##TYPE(struct cell *cj, struct cell *ci,     \
-                                      const int sid) {                      \
+#define RUNNER_CHECK_SORT(TYPE, PART, cj, ci, sid)                          \
+  ({                                                                        \
     const struct entry *restrict sort_j = cj->TYPE.sort[sid];               \
                                                                             \
     for (int pjd = 0; pjd < cj->TYPE.count; pjd++) {                        \
@@ -996,22 +1011,19 @@ void runner_doself_branch_stars_density(struct runner *r, struct cell *c) {
             cj->nodeID, ci->nodeID, d, sort_j[pjd].d, cj->TYPE.dx_max_sort, \
             cj->TYPE.dx_max_sort_old);                                      \
     }                                                                       \
-  }
-
-RUNNER_STARS_CHECK_SORT(hydro, part)
-RUNNER_STARS_CHECK_SORT(stars, spart)
+  })
 
 /**
- * @brief Determine which version of DOPAIR1 needs to be called depending on the
- * orientation of the cells or whether DOPAIR1 needs to be called at all.
+ * @brief Determine which version of DOPAIR1_STARS needs to be called depending
+ * on the orientation of the cells or whether DOPAIR1_STARS needs to be called
+ * at all.
  *
  * @param r #runner
  * @param ci #cell ci
  * @param cj #cell cj
  *
  */
-void runner_dopair_branch_stars_density(struct runner *r, struct cell *ci,
-                                        struct cell *cj) {
+void DOPAIR1_BRANCH_STARS(struct runner *r, struct cell *ci, struct cell *cj) {
 
   const struct engine *restrict e = r->e;
   const int ci_active = cell_is_active_stars(ci, e);
@@ -1055,17 +1067,17 @@ void runner_dopair_branch_stars_density(struct runner *r, struct cell *ci,
 
 #ifdef SWIFT_DEBUG_CHECKS
   if (do_ci) {
-    runner_stars_check_sort_hydro(cj, ci, sid);
-    runner_stars_check_sort_stars(ci, cj, sid);
+    RUNNER_CHECK_SORT(hydro, part, cj, ci, sid);
+    RUNNER_CHECK_SORT(stars, spart, ci, cj, sid);
   }
 
   if (do_cj) {
-    runner_stars_check_sort_hydro(ci, cj, sid);
-    runner_stars_check_sort_stars(cj, ci, sid);
+    RUNNER_CHECK_SORT(hydro, part, ci, cj, sid);
+    RUNNER_CHECK_SORT(stars, spart, cj, ci, sid);
   }
 #endif /* SWIFT_DEBUG_CHECKS */
 
-  runner_dopair_stars_density(r, ci, cj, 1);
+  DOPAIR1_STARS(r, ci, cj, 1);
 }
 
 /**
@@ -1080,14 +1092,12 @@ void runner_dopair_branch_stars_density(struct runner *r, struct cell *ci,
  * @todo Hard-code the sid on the recursive calls to avoid the
  * redundant computations to find the sid on-the-fly.
  */
-void runner_dosub_pair_stars_density(struct runner *r, struct cell *ci,
-                                     struct cell *cj, int sid, int gettimer) {
+void DOSUB_PAIR1_STARS(struct runner *r, struct cell *ci, struct cell *cj,
+                       int sid, int gettimer) {
 
   struct space *s = r->e->s;
   const struct engine *e = r->e;
 
-  TIMER_TIC;
-
   /* Should we even bother? */
   int should_do = ci->stars.count != 0 && cj->hydro.count != 0 &&
                   cell_is_active_stars(ci, e);
@@ -1109,269 +1119,193 @@ void runner_dosub_pair_stars_density(struct runner *r, struct cell *ci,
       /* Regular sub-cell interactions of a single cell. */
       case 0: /* (  1 ,  1 ,  1 ) */
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         break;
 
       case 1: /* (  1 ,  1 ,  0 ) */
         if (ci->progeny[6] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[0], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[1], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[1], -1, 0);
         break;
 
       case 2: /* (  1 ,  1 , -1 ) */
         if (ci->progeny[6] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[1], -1, 0);
         break;
 
       case 3: /* (  1 ,  0 ,  1 ) */
         if (ci->progeny[5] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[0], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[2], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[2], -1, 0);
         break;
 
       case 4: /* (  1 ,  0 ,  0 ) */
         if (ci->progeny[4] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[0], -1, 0);
         if (ci->progeny[4] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[1], -1, 0);
         if (ci->progeny[4] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[2], -1, 0);
         if (ci->progeny[4] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[3], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[0], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[1], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[2], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[3], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[0], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[1], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[2], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[3], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[1], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[2], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[3], -1, 0);
         break;
 
       case 5: /* (  1 ,  0 , -1 ) */
         if (ci->progeny[4] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[1], -1, 0);
         if (ci->progeny[4] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[3], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[1], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[3], -1, 0);
         break;
 
       case 6: /* (  1 , -1 ,  1 ) */
         if (ci->progeny[5] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[2], -1, 0);
         break;
 
       case 7: /* (  1 , -1 ,  0 ) */
         if (ci->progeny[4] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[2], -1, 0);
         if (ci->progeny[4] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[3], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[2], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[3], -1, 0);
         break;
 
       case 8: /* (  1 , -1 , -1 ) */
         if (ci->progeny[4] != NULL && cj->progeny[3] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[4], cj->progeny[3], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[4], cj->progeny[3], -1, 0);
         break;
 
       case 9: /* (  0 ,  1 ,  1 ) */
         if (ci->progeny[3] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[0], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[4], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[4], -1, 0);
         break;
 
       case 10: /* (  0 ,  1 ,  0 ) */
         if (ci->progeny[2] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[2], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[2], cj->progeny[0], -1, 0);
         if (ci->progeny[2] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[2], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[2], cj->progeny[1], -1, 0);
         if (ci->progeny[2] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[2], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[2], cj->progeny[4], -1, 0);
         if (ci->progeny[2] != NULL && cj->progeny[5] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[2], cj->progeny[5], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[2], cj->progeny[5], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[0], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[1], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[4], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[5] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[5], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[5], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[0], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[1], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[4], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[5] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[5], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[5], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[1], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[4], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[5] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[5], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[5], -1, 0);
         break;
 
       case 11: /* (  0 ,  1 , -1 ) */
         if (ci->progeny[2] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[2], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[2], cj->progeny[1], -1, 0);
         if (ci->progeny[2] != NULL && cj->progeny[5] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[2], cj->progeny[5], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[2], cj->progeny[5], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[1] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[1], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[1], -1, 0);
         if (ci->progeny[6] != NULL && cj->progeny[5] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[6], cj->progeny[5], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[6], cj->progeny[5], -1, 0);
         break;
 
       case 12: /* (  0 ,  0 ,  1 ) */
         if (ci->progeny[1] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[1], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[1], cj->progeny[0], -1, 0);
         if (ci->progeny[1] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[1], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[1], cj->progeny[2], -1, 0);
         if (ci->progeny[1] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[1], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[1], cj->progeny[4], -1, 0);
         if (ci->progeny[1] != NULL && cj->progeny[6] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[1], cj->progeny[6], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[1], cj->progeny[6], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[0], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[2], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[4], -1, 0);
         if (ci->progeny[3] != NULL && cj->progeny[6] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[3], cj->progeny[6], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[3], cj->progeny[6], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[0], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[2], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[4], -1, 0);
         if (ci->progeny[5] != NULL && cj->progeny[6] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[5], cj->progeny[6], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[5], cj->progeny[6], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[0] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[0], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[0], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[2] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[2], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[2], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[4] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[4], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[4], -1, 0);
         if (ci->progeny[7] != NULL && cj->progeny[6] != NULL)
-          runner_dosub_pair_stars_density(r, ci->progeny[7], cj->progeny[6], -1,
-                                          0);
+          DOSUB_PAIR1_STARS(r, ci->progeny[7], cj->progeny[6], -1, 0);
         break;
     }
 
@@ -1423,10 +1357,8 @@ void runner_dosub_pair_stars_density(struct runner *r, struct cell *ci,
         error("Interacting unsorted cell (sparts).");
     }
 
-    if (do_ci || do_cj) runner_dopair_branch_stars_density(r, ci, cj);
+    if (do_ci || do_cj) DOPAIR1_BRANCH_STARS(r, ci, cj);
   }
-
-  if (gettimer) TIMER_TOC(timer_dosub_pair_stars_density);
 }
 
 /**
@@ -1436,10 +1368,7 @@ void runner_dosub_pair_stars_density(struct runner *r, struct cell *ci,
  * @param ci The first #cell.
  * @param gettimer Do we have a timer ?
  */
-void runner_dosub_self_stars_density(struct runner *r, struct cell *ci,
-                                     int gettimer) {
-
-  TIMER_TIC;
+void DOSUB_SELF1_STARS(struct runner *r, struct cell *ci, int gettimer) {
 
   /* Should we even bother? */
   if (ci->hydro.count == 0 || ci->stars.count == 0 ||
@@ -1452,11 +1381,10 @@ void runner_dosub_self_stars_density(struct runner *r, struct cell *ci,
     /* Loop over all progeny. */
     for (int k = 0; k < 8; k++)
       if (ci->progeny[k] != NULL) {
-        runner_dosub_self_stars_density(r, ci->progeny[k], 0);
+        DOSUB_SELF1_STARS(r, ci->progeny[k], 0);
         for (int j = k + 1; j < 8; j++)
           if (ci->progeny[j] != NULL)
-            runner_dosub_pair_stars_density(r, ci->progeny[k], ci->progeny[j],
-                                            -1, 0);
+            DOSUB_PAIR1_STARS(r, ci->progeny[k], ci->progeny[j], -1, 0);
       }
   }
 
@@ -1466,10 +1394,6 @@ void runner_dosub_self_stars_density(struct runner *r, struct cell *ci,
     /* Drift the cell to the current timestep if needed. */
     if (!cell_are_spart_drifted(ci, r->e)) error("Interacting undrifted cell.");
 
-    runner_doself_branch_stars_density(r, ci);
+    DOSELF1_BRANCH_STARS(r, ci);
   }
-
-  if (gettimer) TIMER_TOC(timer_dosub_self_stars_density);
 }
-
-#endif  // SWIFT_RUNNER_DOIACT_STARS_H
diff --git a/src/serial_io.c b/src/serial_io.c
index 79edcd769a1fbfd81089098a69d6732519ebd621..059318df180e0d06e446f9d3f839b16439dd1b34 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -500,6 +500,23 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
       error("ICs dimensionality (%dD) does not match code dimensionality (%dD)",
             dimension, (int)hydro_dimension);
 
+    /* Check whether the number of files is specified (if the info exists) */
+    const hid_t hid_files = H5Aexists(h_grp, "NumFilesPerSnapshot");
+    int num_files = 1;
+    if (hid_files < 0)
+      error(
+          "Error while testing the existance of 'NumFilesPerSnapshot' "
+          "attribute");
+    if (hid_files > 0)
+      io_read_attribute(h_grp, "NumFilesPerSnapshot", INT, &num_files);
+    if (num_files != 1)
+      error(
+          "ICs are split over multiples files (%d). SWIFT cannot handle this "
+          "case. The script /tools/combine_ics.py is availalbe in the "
+          "repository "
+          "to combine files into a valid input file.",
+          num_files);
+
     /* Read the relevant information and print status */
     int flag_entropy_temp[6];
     io_read_attribute(h_grp, "Flag_Entropy_ICs", INT, flag_entropy_temp);
diff --git a/src/single_io.c b/src/single_io.c
index 95cdb31028566eb8e7886313b64f5a0e730aec7d..833c4a80cb2f43455d34ad3cd694255b7b19038c 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -404,6 +404,21 @@ void read_ic_single(const char* fileName,
     error("ICs dimensionality (%dD) does not match code dimensionality (%dD)",
           dimension, (int)hydro_dimension);
 
+  /* Check whether the number of files is specified (if the info exists) */
+  const hid_t hid_files = H5Aexists(h_grp, "NumFilesPerSnapshot");
+  int num_files = 1;
+  if (hid_files < 0)
+    error(
+        "Error while testing the existance of 'NumFilesPerSnapshot' attribute");
+  if (hid_files > 0)
+    io_read_attribute(h_grp, "NumFilesPerSnapshot", INT, &num_files);
+  if (num_files != 1)
+    error(
+        "ICs are split over multiples files (%d). SWIFT cannot handle this "
+        "case. The script /tools/combine_ics.py is availalbe in the repository "
+        "to combine files into a valid input file.",
+        num_files);
+
   /* Read the relevant information and print status */
   int flag_entropy_temp[6];
   io_read_attribute(h_grp, "Flag_Entropy_ICs", INT, flag_entropy_temp);
diff --git a/src/stars/Default/stars_iact.h b/src/stars/Default/stars_iact.h
index 3b066686060bcee7583fe65c032da5c12f637081..9e27f86028245a230cfd777dfc46da7b7d2f3915 100644
--- a/src/stars/Default/stars_iact.h
+++ b/src/stars/Default/stars_iact.h
@@ -38,3 +38,20 @@ runner_iact_nonsym_stars_density(float r2, const float *dx, float hi, float hj,
   ++si->num_ngb_density;
 #endif
 }
+
+/**
+ * @brief Feedback interaction between two particles (non-symmetric).
+ *
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
+ * @param hi Comoving smoothing-length of particle i.
+ * @param hj Comoving smoothing-length of particle j.
+ * @param si First sparticle.
+ * @param pj Second particle (not updated).
+ * @param a Current scale factor.
+ * @param H Current Hubble parameter.
+ */
+__attribute__((always_inline)) INLINE static void
+runner_iact_nonsym_stars_feedback(float r2, const float *dx, float hi, float hj,
+                                  struct spart *restrict si,
+                                  struct part *restrict pj, float a, float H) {}
diff --git a/src/timers.c b/src/timers.c
index ccec0a9657d3394de93055992ae4b18c05794a30..d7523edaa42570f8e5f3c01516075267988dfd9c 100644
--- a/src/timers.c
+++ b/src/timers.c
@@ -87,13 +87,7 @@ const char* timers_names[timer_count] = {
     "locktree",
     "runners",
     "step",
-    "doself_stars_density",
-    "dopair_stars_density",
     "do_stars_ghost",
-    "doself_subset_stars_density",
-    "dopair_subset_stars_density",
-    "dosubpair_stars_density",
-    "dosub_self_stars_density",
     "logger",
     "do_stars_sort",
 };
diff --git a/src/timers.h b/src/timers.h
index 48ca1e2763302a24356d15ceeba7ed982a9f169e..412f36d7de547040e29efdede9cc6826358929bc 100644
--- a/src/timers.h
+++ b/src/timers.h
@@ -88,15 +88,7 @@ enum {
   timer_locktree,
   timer_runners,
   timer_step,
-  timer_doself_stars_density,
-  timer_dopair_stars_density,
   timer_dostars_ghost,
-  timer_doself_subset_stars_density,
-  timer_dopair_subset_stars_density,
-  timer_dosub_pair_stars_density,
-  timer_dosub_self_stars_density,
-  timer_dosub_subset_pair_stars_density,
-  timer_dosub_subset_self_stars_density,
   timer_logger,
   timer_do_stars_sort,
   timer_count,
diff --git a/tools/check_interactions.sh b/tools/check_interactions.sh
index 24a534b154313927ee4b2a108d3da7ea5f4d1f31..d688e69bb36b628905668183989d08204604c631 100755
--- a/tools/check_interactions.sh
+++ b/tools/check_interactions.sh
@@ -20,7 +20,7 @@ cd examples/SedovBlast_3D/
 ./getGlass.sh
 python makeIC.py
 
-../swift -s -t 16 -n 5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7 
+../swift --hydro --threads=16 --steps=5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7 
 
 mv sedov_0000.hdf5 sedov_naive.hdf5
 
@@ -29,7 +29,7 @@ cd ../EAGLE_12/
 # Link to ICs
 ln -s /gpfs/data/Swift/web-storage/ICs/EAGLE_ICs_12.hdf5 EAGLE_ICs_12.hdf5
 
-../swift -s -t 16 -n 5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+../swift --hydro --threads=16 --steps=5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv eagle_0000.hdf5 eagle_12_naive.hdf5
 
@@ -45,13 +45,13 @@ make clean; make -j 6
 
 cd examples/SedovBlast_3D/
 
-../swift -s -t 16 -n 5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+../swift --hydro --threads=16 --steps=5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv sedov_0000.hdf5 sedov_serial.hdf5
 
 cd ../EAGLE_12/
 
-../swift -s -t 16 -n 5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7 
+../swift --hydro --threads=16 --steps=5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7 
 
 mv eagle_0000.hdf5 eagle_12_serial.hdf5
 
@@ -67,7 +67,7 @@ make clean; make -j 6
 
 cd examples/SedovBlast_3D/
 
-../swift -s -t 16 -n 5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+../swift --hydro --threads=16 --steps=5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv sedov_0000.hdf5 sedov_vec.hdf5
 
@@ -98,7 +98,7 @@ fi
 
 cd ../EAGLE_12/
 
-../swift -s -t 16 -n 5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+../swift --hydro --threads=16 --steps=5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv eagle_0000.hdf5 eagle_12_vec.hdf5
 
@@ -145,13 +145,13 @@ make clean; make -j 6
 
 cd examples/SedovBlast_3D/
 
-mpirun -np 4 ../swift_mpi -s -t 16 -n 5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+mpirun -np 4 ../swift_mpi --hydro --threads=16 --steps=5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv sedov_0000.hdf5 sedov_naive.hdf5
 
 cd ../EAGLE_12/
 
-mpirun -np 4 ../swift_mpi -s -t 16 -n 5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+mpirun -np 4 ../swift_mpi --hydro --threads=16 --steps=5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv eagle_0000.hdf5 eagle_12_naive.hdf5
 
@@ -167,13 +167,13 @@ make clean; make -j 6
 
 cd examples/SedovBlast_3D/
 
-mpirun -np 4 ../swift_mpi -s -t 16 -n 5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+mpirun -np 4 ../swift_mpi --hydro --threads=16 --steps=5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv sedov_0000.hdf5 sedov_serial.hdf5
 
 cd ../EAGLE_12/
 
-mpirun -np 4 ../swift_mpi -s -t 16 -n 5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+mpirun -np 4 ../swift_mpi --hydro --threads=16 --steps=5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv eagle_0000.hdf5 eagle_12_serial.hdf5
 
@@ -189,7 +189,7 @@ make clean; make -j 6
 
 cd examples/SedovBlast_3D/
 
-mpirun -np 4 ../swift_mpi -s -t 16 -n 5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+mpirun -np 4 ../swift_mpi --hydro --threads=16 --steps=5 sedov.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv sedov_0000.hdf5 sedov_vec.hdf5
 
@@ -220,7 +220,7 @@ fi
 
 cd ../EAGLE_12/
 
-mpirun -np 4 ../swift_mpi -s -t 16 -n 5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
+mpirun -np 4 ../swift_mpi --hydro --threads=16 --steps=5 eagle_12.yml -P SPH:h_tolerance:10 -P Snapshots:compression:7
 
 mv eagle_0000.hdf5 eagle_12_vec.hdf5