diff --git a/examples/ExternalPointMass/externalPointMass.yml b/examples/ExternalPointMass/externalPointMass.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cf96535b64c078d063b6f773823ca085876c2ecc
--- /dev/null
+++ b/examples/ExternalPointMass/externalPointMass.yml
@@ -0,0 +1,55 @@
+
+# Define the system of units to use internally. 
+UnitSystem:
+  UnitMass_in_cgs:     1.9885e33     # Grams
+  UnitLength_in_cgs:   3.0856776e21  # Centimeters
+  UnitVelocity_in_cgs: 1e5           # Centimeters per second
+  UnitCurrent_in_cgs:  1   # Amperes
+  UnitTemp_in_cgs:     1   # Kelvin
+
+# Parameters for the task scheduling
+Scheduler:
+  nr_queues:        0        # The number of task queues to use. Use 0  to let the system decide.
+  cell_max_size:    8000000  # Maximal number of interactions per task (this is the default value).
+  cell_sub_size:    8000000  # Maximal number of interactions per sub-task  (this is the default value).
+  cell_split_size:  400      # Maximal number of particles per cell (this is the default value).
+
+# Parameters governing the time integration
+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-3  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters for the hydrodynamics scheme
+SPH:
+  resolution_eta:        1.2349   # Target smoothing length in units of the mean inter-particle separation (1.2349 == 48Ngbs with the cubic spline kernel).
+  delta_neighbours:      1.       # The tolerance for the targetted number of neighbours.
+  CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  max_ghost_iterations:  30       # Maximal number of iterations allowed to converge towards the smoothing length.
+  max_smoothing_length:  10.      # Maximal smoothing length allowed (in internal units).
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  Sphere.hdf5           # The file to read
+  h_scaling:  1.                    # A scaling factor to apply to all smoothing lengths in the ICs.
+  shift_x:    50.                   # A shift to apply to all particles read from the ICs (in internal units).
+  shift_y:    50.
+  shift_z:    50.
+
+# Parameters govering domain decomposition
+DomainDecomposition:
+  initial_type:       m     # The initial strategy ("g", "m", "w", or "v"). See documentation for details.
+  initial_grid_x:    10     # Grid size if the 'g' strategy is chosen.
+  initial_grid_y:    10
+  initial_grid_z:    10
+  repartition_type:   b     # The re-decomposition strategy ("n", "b", "v", "e" or "x"). See documentation for details.
+ 
+
+# External potential parameters
+PointMass:
+  position_x:      50.     # location of external point mass in internal units
+  position_y:      50.
+  position_z:      50.	
+  mass:            1e10     # mass of external point mass in internal units
+
diff --git a/examples/ExternalPointMass/makeIC.py b/examples/ExternalPointMass/makeIC.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1b032e47383d6e757306f09063a8931635ea8e9
--- /dev/null
+++ b/examples/ExternalPointMass/makeIC.py
@@ -0,0 +1,142 @@
+###############################################################################
+ # This file is part of SWIFT.
+ # Copyright (c) 2016 John A. Regan (john.a.regan@durham.ac.uk)
+ #                    Tom Theuns (tom.theuns@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
+import sys
+import numpy
+import math
+import random
+
+# Generates a random distriution of particles, for motion in an external potnetial centred at (0,0,0)
+
+# physical constants in cgs
+NEWTON_GRAVITY_CGS  = 6.672e-8
+SOLAR_MASS_IN_CGS   = 1.9885e33
+PARSEC_IN_CGS       = 3.0856776e18
+
+# choice of units
+const_unit_length_in_cgs   =   (1000*PARSEC_IN_CGS)
+const_unit_mass_in_cgs     =   (SOLAR_MASS_IN_CGS)
+const_unit_velocity_in_cgs =   (1e5)
+
+print "UnitMass_in_cgs:     ", const_unit_mass_in_cgs 
+print "UnitLength_in_cgs:   ", const_unit_length_in_cgs
+print "UnitVelocity_in_cgs: ", const_unit_velocity_in_cgs
+
+# derived units
+const_unit_time_in_cgs = (const_unit_length_in_cgs / const_unit_velocity_in_cgs)
+const_G                = ((NEWTON_GRAVITY_CGS*const_unit_mass_in_cgs*const_unit_time_in_cgs*const_unit_time_in_cgs/(const_unit_length_in_cgs*const_unit_length_in_cgs*const_unit_length_in_cgs)))
+print 'G=', const_G
+
+
+# Parameters
+periodic= 1            # 1 For periodic box
+boxSize = 100.         # 
+Radius  = boxSize / 4. # maximum radius of particles
+G       = const_G 
+Mass    = 1e10         
+
+N       = int(sys.argv[1])  # Number of particles
+L       = N**(1./3.)
+
+# these are not used but necessary for I/O
+rho = 2.              # Density
+P = 1.                # Pressure
+gamma = 5./3.         # Gas adiabatic index
+fileName = "Sphere.hdf5" 
+
+
+#---------------------------------------------------
+numPart        = N
+mass           = 1
+internalEnergy = P / ((gamma - 1.)*rho)
+
+#--------------------------------------------------
+
+#File
+file = h5py.File(fileName, 'w')
+
+# Header
+grp = file.create_group("/Header")
+grp.attrs["BoxSize"] = boxSize
+grp.attrs["NumPart_Total"] =  [0, numPart, 0, 0, 0, 0]
+grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
+grp.attrs["NumPart_ThisFile"] = [0, numPart, 0, 0, 0, 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, 0, 0, 0, 0, 0]
+
+
+#Runtime parameters
+grp = file.create_group("/RuntimePars")
+grp.attrs["PeriodicBoundariesOn"] = periodic
+
+#Particle group
+#grp0 = file.create_group("/PartType0")
+grp1 = file.create_group("/PartType1")
+#generate particle positions
+radius = Radius * (numpy.random.rand(N))**(1./3.) 
+ctheta = -1. + 2 * numpy.random.rand(N)
+stheta = numpy.sqrt(1.-ctheta**2)
+phi    =  2 * math.pi * numpy.random.rand(N)
+r      = numpy.zeros((numPart, 3))
+# r[:,0] = radius * stheta * numpy.cos(phi)
+# r[:,1] = radius * stheta * numpy.sin(phi)
+# r[:,2] = radius * ctheta
+r[:,0] = radius
+#
+speed  = numpy.sqrt(G * Mass / radius)
+v      = numpy.zeros((numPart, 3))
+omega  = speed / radius
+period = 2.*math.pi/omega
+print 'period = minimum = ',min(period), ' maximum = ',max(period)
+
+v[:,0] = -omega * r[:,1]
+v[:,1] =  omega * r[:,0]
+
+ds = grp1.create_dataset('Velocities', (numPart, 3), 'f')
+ds[()] = v
+v = numpy.zeros(1)
+
+m = numpy.full((numPart, ), mass)
+ds = grp1.create_dataset('Masses', (numPart,), 'f')
+ds[()] = m
+m = numpy.zeros(1)
+
+h = numpy.full((numPart, ), 1.1255 * boxSize / L)
+ds = grp1.create_dataset('SmoothingLength', (numPart,), 'f')
+ds[()] = h
+h = numpy.zeros(1)
+
+u = numpy.full((numPart, ), internalEnergy)
+ds = grp1.create_dataset('InternalEnergy', (numPart,), 'f')
+ds[()] = u
+u = numpy.zeros(1)
+
+
+ids = 1 + numpy.linspace(0, numPart, numPart, endpoint=False)
+ds = grp1.create_dataset('ParticleIDs', (numPart, ), 'L')
+ds[()] = ids
+
+ds = grp1.create_dataset('Coordinates', (numPart, 3), 'd')
+ds[()] = r
+
+file.close()
diff --git a/examples/ExternalPointMass/run.sh b/examples/ExternalPointMass/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..45f0e697b3ebfd5d510ee1f9f895ed3d7e4b1caf
--- /dev/null
+++ b/examples/ExternalPointMass/run.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# Generate the initial conditions if they are not present.
+if [ ! -e uniformBox.hdf5 ]
+then
+    echo "Generating initial conditions for the point mass potential box example..."
+    python makeIC.py 10000
+fi
+
+../swift -g -t 2 externalPointMass.yml
diff --git a/examples/ExternalPointMass/test.pro b/examples/ExternalPointMass/test.pro
new file mode 100644
index 0000000000000000000000000000000000000000..21c10e9d27daa45b085c6a659ba3cf7260f017fb
--- /dev/null
+++ b/examples/ExternalPointMass/test.pro
@@ -0,0 +1,65 @@
+;
+;  test energy / angular momentum conservation of test problem
+;
+@physunits
+
+indir    = '/gpfs/data/tt/Codes/Swift-git/swiftsim/examples/'
+basefile = 'output_'
+nfiles   = 657
+nfollow  = 100 ; number of particles to follow
+eout     = fltarr(nfollow, nfiles)
+ekin     = fltarr(nfollow, nfiles)
+epot     = fltarr(nfollow, nfiles)
+tout     = fltarr(nfiles)
+; set properties of potential
+uL  = 1e3 * phys.pc             ; unit of length
+uM  = phys.msun                 ; unit of mass
+uV  = 1d5                       ; unit of velocity
+
+; derived units
+constG   = 10.^(alog10(phys.g)+alog10(uM)-2d0*alog10(uV)-alog10(uL)) ;
+pcentre  = [50.,50.,50.] * 1d3 * pc / uL
+mextern  = 1d10 * msun / uM
+;
+;
+;
+ifile  = 0
+for ifile=0,nfiles-1 do begin
+;for ifile=0,3 do begin
+   inf    = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
+   time   = h5ra(inf, 'Header','Time')
+   p      = h5rd(inf,'PartType1/Coordinates')
+   v      = h5rd(inf,'PartType1/Velocities')
+   id     = h5rd(inf,'PartType1/ParticleIDs')
+   indx   = sort(id)
+;
+   id     = id[indx]
+   for ic=0,2 do begin
+      tmp = reform(p[ic,*]) & p[ic,*] = tmp[indx]
+      tmp = reform(v[ic,*]) & v[ic,*] = tmp[indx]
+   endfor
+; calculate energy
+   dd  = size(p,/dimen) & npart = dd[1]
+   ener = fltarr(npart)
+   dr   = fltarr(npart) & dv = dr
+   for ic=0,2 do dr[*] = dr[*] + (p[ic,*]-pcentre[ic])^2
+   for ic=0,2 do dv[*] = dv[*] + v[ic,*]^2
+   dr = sqrt(dr)
+;   print,'time = ',time,p[0,0],v[0,0],id[0]
+   ek   = 0.5 * dv
+   ep   = - constG * mextern / dr
+   ener = ek + ep
+   tout(ifile) = time
+   eout(*,ifile) = ener[0:nfollow-1]
+   ekin(*,ifile) = ek[0:nfollow-1]
+   epot(*,ifile) = ep[0:nfollow-1]
+endfor
+
+; calculate relative energy change
+de = 0.0 * eout
+for ifile=1, nfiles -1 do de[*,ifile] = (eout[*,ifile]-eout[*,0])/eout[*,0]
+
+
+end
+
+
diff --git a/examples/main.c b/examples/main.c
index 5a20125fe84bac5b793a2e1e2694cdfd76042051..d4538473031bc410606efc79ab6451d6273f61ad 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -3,6 +3,9 @@
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
  *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *                    Angus Lepper (angus.lepper@ed.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -268,17 +271,6 @@ int main(int argc, char *argv[]) {
   MPI_Bcast(params, sizeof(struct swift_params), MPI_BYTE, 0, MPI_COMM_WORLD);
 #endif
 
-  /* Initialize unit system */
-  struct UnitSystem us;
-  units_init(&us, params);
-  if (myrank == 0) {
-    message("Unit system: U_M = %e g.", us.UnitMass_in_cgs);
-    message("Unit system: U_L = %e cm.", us.UnitLength_in_cgs);
-    message("Unit system: U_t = %e s.", us.UnitTime_in_cgs);
-    message("Unit system: U_I = %e A.", us.UnitCurrent_in_cgs);
-    message("Unit system: U_T = %e K.", us.UnitTemperature_in_cgs);
-  }
-
 /* Prepare the domain decomposition scheme */
 #ifdef WITH_MPI
   struct partition initial_partition;
@@ -296,6 +288,25 @@ int main(int argc, char *argv[]) {
   }
 #endif
 
+  /* Initialize unit system and constants */
+  struct UnitSystem us;
+  struct phys_const prog_const;
+  units_init(&us, params);
+  phys_const_init(&us, &prog_const);
+  if (myrank == 0 && verbose > 0) {
+    message("Unit system: U_M = %e g.", us.UnitMass_in_cgs);
+    message("Unit system: U_L = %e cm.", us.UnitLength_in_cgs);
+    message("Unit system: U_t = %e s.", us.UnitTime_in_cgs);
+    message("Unit system: U_I = %e A.", us.UnitCurrent_in_cgs);
+    message("Unit system: U_T = %e K.", us.UnitTemperature_in_cgs);
+    phys_const_print(&prog_const);
+  }
+
+  /* Initialise the external potential properties */
+  struct external_potential potential;
+  if (with_external_gravity) potential_init(params, &us, &potential);
+  if (with_external_gravity && myrank == 0) potential_print(&potential);
+
   /* Read particles and space information from (GADGET) ICs */
   char ICfileName[200] = "";
   parser_get_param_string(params, "InitialConditions:file_name", ICfileName);
@@ -333,6 +344,12 @@ int main(int argc, char *argv[]) {
     for (size_t k = 0; k < Ngas; ++k) parts[k].gpart = NULL;
     Ngpart = 0;
   }
+  if (!with_hydro) {
+    free(parts);
+    parts = NULL;
+    for (size_t k = 0; k < Ngpart; ++k) if(gparts[k].id > 0) error("Linking problem");
+    Ngas = 0;
+  }
 
   /* Get the total number of particles across all nodes. */
   long long N_total[2] = {0, 0};
@@ -396,7 +413,7 @@ int main(int argc, char *argv[]) {
   if (myrank == 0) clocks_gettime(&tic);
   struct engine e;
   engine_init(&e, &s, params, nr_nodes, myrank, nr_threads, engine_policies,
-              talking);
+              talking, &prog_const, &potential);
   if (myrank == 0) {
     clocks_gettime(&toc);
     message("engine_init took %.3f %s.", clocks_diff(&tic, &toc),
diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml
index e3cd5b209c9d36f9774364a661b77f3d649c398e..228e748f3b2899639303597c92ea29ad09987313 100644
--- a/examples/parameter_example.yml
+++ b/examples/parameter_example.yml
@@ -45,3 +45,11 @@ DomainDecomposition:
   initial_grid_z:    10
   repartition_type:   b     # The re-decomposition strategy ("n", "b", "v", "e" or "x"). See documentation for details.
  
+# Parameters related to external potentials
+  
+# Point mass external potential
+PointMass:
+  position_x:      50.     # location of external point mass in internal units
+  position_y:      50.
+  position_z:      50.
+  mass:            1e10     # mass of external point mass in internal units
diff --git a/src/Makefile.am b/src/Makefile.am
index a96f35b3cf0d8a23aec4f8c0f8d16bec8638cbcd..65f093b014ed16577c4f0f36bf4636da223e6929 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,13 +35,15 @@ endif
 # List required headers
 include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \
     engine.h swift.h serial_io.h timers.h debug.h scheduler.h proxy.h parallel_io.h \
-    common_io.h single_io.h multipole.h map.h tools.h partition.h clocks.h parser.h
+    common_io.h single_io.h multipole.h map.h tools.h partition.h clocks.h parser.h \
+    physical_constants.h physical_constants_cgs.h potentials.h
 
 # Common source files
 AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \
     serial_io.c timers.c debug.c scheduler.c proxy.c parallel_io.c \
     units.c common_io.c single_io.c multipole.c version.c map.c \
-    kernel_hydro.c kernel_gravity.c tools.c part.c partition.c clocks.c parser.c
+    kernel_hydro.c kernel_gravity.c tools.c part.c partition.c clocks.c parser.c \
+    physical_constants.c potentials.c
 
 # Include files for distribution, not installation.
 nobase_noinst_HEADERS = approx_math.h atomic.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \
diff --git a/src/cell.c b/src/cell.c
index 8e47b415ac5b43558fea9a557cc352cc6dea2018..793a2e10c23cb0dd355a181e2ad658ce19dc0014 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -1,6 +1,10 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
diff --git a/src/cell.h b/src/cell.h
index a471eac44bfd3533c4220ab8c5ff2ddec724e87f..fbdaa928bda51aa76c149df1249d982fbeef64c3 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -1,6 +1,10 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -122,6 +126,9 @@ struct cell {
   /* Tasks for gravity tree. */
   struct task *grav_up, *grav_down;
 
+  /* Task for external gravity */
+  struct task *grav_external;
+
   /* Number of tasks that are associated with this cell. */
   int nr_tasks;
 
diff --git a/src/const.h b/src/const.h
index 6a52ec4796a4904629a57ffa8b32a3107bde263e..dd3e34016c1953efffca67e9c7ee1b42f455dec1 100644
--- a/src/const.h
+++ b/src/const.h
@@ -70,4 +70,7 @@
 #define GADGET2_SPH
 //#define DEFAULT_SPH
 
+/* Gravity properties */
+#define EXTERNAL_POTENTIAL_POINTMASS
+
 #endif /* SWIFT_CONST_H */
diff --git a/src/engine.c b/src/engine.c
index 7287f47b40b06a691c778a5f8d3b6c0f04721564..f022f95a2a51930a24ffa9835c5d8e46aa0088cd 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -1,7 +1,11 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *                    Angus Lepper (angus.lepper@ed.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -101,9 +105,12 @@ void engine_make_ghost_tasks(struct engine *e, struct cell *c,
                              struct cell *super) {
 
   struct scheduler *s = &e->sched;
+  const int is_with_external_gravity =
+      (e->policy & engine_policy_external_gravity) ==
+      engine_policy_external_gravity;
 
   /* Am I the super-cell? */
-  if (super == NULL && c->nr_tasks > 0) {
+  if (super == NULL && (c->count > 0 || c->gcount > 0)) {
 
     /* Remember me. */
     super = c;
@@ -111,18 +118,32 @@ void engine_make_ghost_tasks(struct engine *e, struct cell *c,
     /* Local tasks only... */
     if (c->nodeID == e->nodeID) {
 
-      /* Generate the ghost task. */
-      c->ghost = scheduler_addtask(s, task_type_ghost, task_subtype_none, 0, 0,
-                                   c, NULL, 0);
-      /* Add the drift task. */
-      c->drift = scheduler_addtask(s, task_type_drift, task_subtype_none, 0, 0,
-                                   c, NULL, 0);
       /* Add the init task. */
       c->init = scheduler_addtask(s, task_type_init, task_subtype_none, 0, 0, c,
                                   NULL, 0);
+
+      /* Add the drift task. */
+      c->drift = scheduler_addtask(s, task_type_drift, task_subtype_none, 0, 0,
+                                   c, NULL, 0);
+
       /* Add the kick task. */
       c->kick = scheduler_addtask(s, task_type_kick, task_subtype_none, 0, 0, c,
                                   NULL, 0);
+
+      if (c->count > 0) {
+
+        /* Generate the ghost task. */
+        c->ghost = scheduler_addtask(s, task_type_ghost, task_subtype_none, 0,
+                                     0, c, NULL, 0);
+      }
+
+      if (c->gcount > 0) {
+
+        /* Add the external gravity tasks */
+        if (is_with_external_gravity)
+          c->grav_external = scheduler_addtask(
+              s, task_type_grav_external, task_subtype_none, 0, 0, c, NULL, 0);
+      }
     }
   }
 
@@ -211,27 +232,29 @@ void engine_redistribute(struct engine *e) {
   space_parts_sort(s, dest, s->nr_parts, 0, nr_nodes - 1, e->verbose);
 
   /* We need to re-link the gpart partners of parts. */
-  int current_dest = dest[0];
-  size_t count_this_dest = 0;
-  for (size_t k = 0; k < s->nr_parts; ++k) {
-    if (s->parts[k].gpart != NULL) {
-
-      /* As the addresses will be invalidated by the communications, we will */
-      /* instead store the absolute index from the start of the sub-array */
-      /* of particles to be sent to a given node. */
-      /* Recall that gparts without partners have a negative id. */
-      /* We will restore the pointers on the receiving node later on. */
-      if (dest[k] != current_dest) {
-        current_dest = dest[k];
-        count_this_dest = 0;
-      }
+  if (s->nr_parts > 0) {
+    int current_dest = dest[0];
+    size_t count_this_dest = 0;
+    for (size_t k = 0; k < s->nr_parts; ++k) {
+      if (s->parts[k].gpart != NULL) {
+
+        /* As the addresses will be invalidated by the communications, we will */
+        /* instead store the absolute index from the start of the sub-array */
+        /* of particles to be sent to a given node. */
+        /* Recall that gparts without partners have a negative id. */
+        /* We will restore the pointers on the receiving node later on. */
+        if (dest[k] != current_dest) {
+          current_dest = dest[k];
+          count_this_dest = 0;
+        }
 
-      /* Debug */
-      /* if(s->parts[k].gpart->id < 0) */
-      /* 	error("Trying to link a partnerless gpart !"); */
+        /* Debug */
+        /* if(s->parts[k].gpart->id < 0) */
+        /*   error("Trying to link a partnerless gpart !"); */
 
-      s->parts[k].gpart->id = count_this_dest;
-      count_this_dest++;
+        s->parts[k].gpart->id = count_this_dest;
+        count_this_dest++;
+      }
     }
   }
 
@@ -819,7 +842,10 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
   ticks tic = getticks();
 
   /* Re-set the proxies. */
-  for (int k = 0; k < e->nr_proxies; k++) e->proxies[k].nr_parts_out = 0;
+  for (int k = 0; k < e->nr_proxies; k++) {
+    e->proxies[k].nr_parts_out = 0;
+    e->proxies[k].nr_gparts_out = 0;
+  }
 
   /* Put the parts and gparts into the corresponding proxies. */
   for (size_t k = 0; k < *Npart; k++) {
@@ -839,7 +865,7 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
 
     /* Re-link the associated gpart with the buffer offset of the part. */
     if (s->parts[offset_parts + k].gpart != NULL) {
-      s->parts[offset_parts + k].gpart->id = e->proxies[pid].nr_parts_in;
+      s->parts[offset_parts + k].gpart->id = e->proxies[pid].nr_parts_out;
     }
 
     /* Load the part and xpart into the proxy. */
@@ -898,6 +924,7 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
             count_parts_in, count_gparts_in);
   }
   if (offset_parts + count_parts_in > s->size_parts) {
+    message("re-allocating parts array.");
     s->size_parts = (offset_parts + count_parts_in) * engine_parts_size_grow;
     struct part *parts_new = NULL;
     struct xpart *xparts_new = NULL;
@@ -912,8 +939,14 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
     free(s->xparts);
     s->parts = parts_new;
     s->xparts = xparts_new;
+    for (size_t k = 0; k < offset_parts; k++) {
+      if (s->parts[k].gpart != NULL) {
+        s->parts[k].gpart->part = &s->parts[k];
+      }
+    }
   }
   if (offset_gparts + count_gparts_in > s->size_gparts) {
+    message("re-allocating gparts array.");
     s->size_gparts = (offset_gparts + count_gparts_in) * engine_parts_size_grow;
     struct gpart *gparts_new = NULL;
     if (posix_memalign((void **)&gparts_new, gpart_align,
@@ -922,6 +955,11 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
     memcpy(gparts_new, s->gparts, sizeof(struct gpart) * offset_gparts);
     free(s->gparts);
     s->gparts = gparts_new;
+    for (size_t k = 0; k < offset_gparts; k++) {
+      if (s->gparts[k].id > 0) {
+        s->gparts[k].part->gpart = &s->gparts[k];
+      }
+    }
   }
 
   /* Collect the requests for the particle data from the proxies. */
@@ -976,7 +1014,7 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
         reqs_in[pid + 1] == MPI_REQUEST_NULL &&
         reqs_in[pid + 2] == MPI_REQUEST_NULL) {
       /* Copy the particle data to the part/xpart/gpart arrays. */
-      struct proxy *p = &e->proxies[pid >> 1];
+      struct proxy *p = &e->proxies[pid / 3];
       memcpy(&s->parts[offset_parts + count_parts], p->parts_in,
              sizeof(struct part) * p->nr_parts_in);
       memcpy(&s->xparts[offset_parts + count_parts], p->xparts_in,
@@ -993,7 +1031,7 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
       for (int k = 0; k < p->nr_gparts_in; k++) {
         struct gpart *gp = &s->gparts[offset_gparts + count_gparts + k];
         if (gp->id >= 0) {
-          struct part *p = &s->parts[offset_gparts + count_parts + gp->id];
+          struct part *p = &s->parts[offset_parts + count_parts + gp->id];
           gp->part = p;
           p->gpart = gp;
         }
@@ -1004,7 +1042,7 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
       count_gparts += p->nr_gparts_in;
     }
   }
-
+  
   /* Wait for all the sends to have finished too. */
   if (nr_out > 0)
     if (MPI_Waitall(3 * e->nr_proxies, reqs_out, MPI_STATUSES_IGNORE) !=
@@ -1276,6 +1314,12 @@ void engine_make_extra_hydroloop_tasks(struct engine *e) {
     /* /\* Kick tasks should rely on the grav_down tasks of their cell. *\/ */
     /* else if (t->type == task_type_kick && t->ci->grav_down != NULL) */
     /*   scheduler_addunlock(sched, t->ci->grav_down, t); */
+
+    /* External gravity tasks should depend on init and unlock the kick */
+    else if (t->type == task_type_grav_external) {
+      scheduler_addunlock(sched, t->ci->init, t);
+      scheduler_addunlock(sched, t, t->ci->kick);
+    }
   }
 }
 
@@ -1377,7 +1421,7 @@ void engine_maketasks(struct engine *e) {
   engine_make_hydroloop_tasks(e);
 
   /* Add the gravity mm tasks. */
-  if ((e->policy & engine_policy_self_gravity) == engine_policy_self_gravity)
+  if (e->policy & engine_policy_self_gravity)
     engine_make_gravityinteraction_tasks(e);
 
   /* Split the tasks. */
@@ -1393,7 +1437,7 @@ void engine_maketasks(struct engine *e) {
   e->nr_links = 0;
 
   /* Add the gravity up/down tasks at the top-level cells and push them down. */
-  if ((e->policy & engine_policy_self_gravity) == engine_policy_self_gravity)
+  if (e->policy & engine_policy_self_gravity)
     engine_make_gravityrecursive_tasks(e);
 
   /* Count the number of tasks associated with each cell and
@@ -1412,7 +1456,7 @@ void engine_maketasks(struct engine *e) {
   engine_make_extra_hydroloop_tasks(e);
 
   /* Add the communication tasks if MPI is being used. */
-  if ((e->policy & engine_policy_mpi) == engine_policy_mpi) {
+  if (e->policy & engine_policy_mpi) {
 
     /* Loop over the proxies. */
     for (int pid = 0; pid < e->nr_proxies; pid++) {
@@ -1465,7 +1509,7 @@ int engine_marktasks(struct engine *e) {
   const ticks tic = getticks();
 
   /* Much less to do here if we're on a fixed time-step. */
-  if ((e->policy & engine_policy_fixdt) == engine_policy_fixdt) {
+  if (e->policy & engine_policy_fixdt) {
 
     /* Run through the tasks and mark as skip or not. */
     for (int k = 0; k < nr_tasks; k++) {
@@ -1754,7 +1798,7 @@ void engine_collect_kick(struct cell *c) {
   int ti_end_min = max_nr_timesteps, ti_end_max = 0;
 
   /* Only do something is the cell is non-empty */
-  if (c->count != 0) {
+  if (c->count != 0 || c->gcount != 0) {
 
     /* If this cell is not split, I'm in trouble. */
     if (!c->split) error("Cell has no super-cell.");
@@ -1853,13 +1897,11 @@ void engine_init_particles(struct engine *e) {
 
   /* Make sure all particles are ready to go */
   /* i.e. clean-up any stupid state in the ICs */
-  if ((e->policy & engine_policy_hydro) == engine_policy_hydro) {
+  if (e->policy & engine_policy_hydro) {
     space_map_cells_pre(s, 1, cell_init_parts, NULL);
   }
-  if (((e->policy & engine_policy_self_gravity) ==
-       engine_policy_self_gravity) ||
-      ((e->policy & engine_policy_external_gravity) ==
-       engine_policy_external_gravity)) {
+  if ((e->policy & engine_policy_self_gravity) ||
+      (e->policy & engine_policy_external_gravity)) {
     space_map_cells_pre(s, 1, cell_init_gparts, NULL);
   }
 
@@ -1867,22 +1909,17 @@ void engine_init_particles(struct engine *e) {
 
   engine_marktasks(e);
 
-  // printParticle(e->s->parts, 1000, e->s->nr_parts);
-  // printParticle(e->s->parts, 515050, e->s->nr_parts);
-
-  // message("\n0th DENSITY CALC\n");
-
   /* Build the masks corresponding to the policy */
   unsigned int mask = 0;
   unsigned int submask = 0;
 
   /* We always have sort tasks */
   mask |= 1 << task_type_sort;
+  mask |= 1 << task_type_init;
 
   /* Add the tasks corresponding to hydro operations to the masks */
-  if ((e->policy & engine_policy_hydro) == engine_policy_hydro) {
+  if (e->policy & engine_policy_hydro) {
 
-    mask |= 1 << task_type_init;
     mask |= 1 << task_type_self;
     mask |= 1 << task_type_pair;
     mask |= 1 << task_type_sub;
@@ -1892,20 +1929,19 @@ void engine_init_particles(struct engine *e) {
   }
 
   /* Add the tasks corresponding to self-gravity to the masks */
-  if ((e->policy & engine_policy_self_gravity) == engine_policy_self_gravity) {
+  if (e->policy & engine_policy_self_gravity) {
 
     /* Nothing here for now */
   }
 
-  /* Add the tasks corresponding to self-gravity to the masks */
-  if ((e->policy & engine_policy_external_gravity) ==
-      engine_policy_external_gravity) {
+  /* Add the tasks corresponding to external gravity to the masks */
+  if (e->policy & engine_policy_external_gravity) {
 
-    /* Nothing here for now */
+    mask |= 1 << task_type_grav_external;
   }
 
   /* Add MPI tasks if need be */
-  if ((e->policy & engine_policy_mpi) == engine_policy_mpi) {
+  if (e->policy & engine_policy_mpi) {
 
     mask |= 1 << task_type_send;
     mask |= 1 << task_type_recv;
@@ -1916,14 +1952,9 @@ void engine_init_particles(struct engine *e) {
   engine_launch(e, e->nr_threads, mask, submask);
   TIMER_TOC(timer_runners);
 
-  // message("\n0th ENTROPY CONVERSION\n")
-
   /* Apply some conversions (e.g. internal energy -> entropy) */
   space_map_cells_pre(s, 1, cell_convert_hydro, NULL);
 
-  // printParticle(e->s->parts, e->s->xparts,1000, e->s->nr_parts);
-  // printParticle(e->s->parts, e->s->xparts,515050, e->s->nr_parts);
-
   /* Ready to go */
   e->step = -1;
 }
@@ -2005,8 +2036,6 @@ void engine_step(struct engine *e) {
   }
 #endif
 
-  // message("\nDRIFT\n");
-
   /* Move forward in time */
   e->ti_old = e->ti_current;
   e->ti_current = ti_end_min;
@@ -2018,11 +2047,6 @@ void engine_step(struct engine *e) {
   /* Drift everybody */
   engine_launch(e, e->nr_threads, 1 << task_type_drift, 0);
 
-  // printParticle(e->s->parts, e->s->xparts, 1000, e->s->nr_parts);
-  // printParticle(e->s->parts, e->s->xparts, 515050, e->s->nr_parts);
-
-  // if(e->step == 2)   exit(0);
-
   if (e->nodeID == 0) {
 
     /* Print some information to the screen */
@@ -2037,8 +2061,6 @@ void engine_step(struct engine *e) {
     fflush(e->file_stats);
   }
 
-  // message("\nACCELERATION AND KICK\n");
-
   /* Re-distribute the particles amongst the nodes? */
   if (e->forcerepart != REPART_NONE) engine_repartition(e);
 
@@ -2051,11 +2073,11 @@ void engine_step(struct engine *e) {
   /* We always have sort tasks and kick tasks */
   mask |= 1 << task_type_sort;
   mask |= 1 << task_type_kick;
+  mask |= 1 << task_type_init;
 
   /* Add the tasks corresponding to hydro operations to the masks */
-  if ((e->policy & engine_policy_hydro) == engine_policy_hydro) {
+  if (e->policy & engine_policy_hydro) {
 
-    mask |= 1 << task_type_init;
     mask |= 1 << task_type_self;
     mask |= 1 << task_type_pair;
     mask |= 1 << task_type_sub;
@@ -2066,20 +2088,18 @@ void engine_step(struct engine *e) {
   }
 
   /* Add the tasks corresponding to self-gravity to the masks */
-  if ((e->policy & engine_policy_self_gravity) == engine_policy_self_gravity) {
+  if (e->policy & engine_policy_self_gravity) {
 
     /* Nothing here for now */
   }
 
-  /* Add the tasks corresponding to self-gravity to the masks */
-  if ((e->policy & engine_policy_external_gravity) ==
-      engine_policy_external_gravity) {
-
-    /* Nothing here for now */
+  /* Add the tasks corresponding to external gravity to the masks */
+  if (e->policy & engine_policy_external_gravity) {
+    mask |= 1 << task_type_grav_external;
   }
 
   /* Add MPI tasks if need be */
-  if ((e->policy & engine_policy_mpi) == engine_policy_mpi) {
+  if (e->policy & engine_policy_mpi) {
 
     mask |= 1 << task_type_send;
     mask |= 1 << task_type_recv;
@@ -2095,8 +2115,6 @@ void engine_step(struct engine *e) {
   clocks_gettime(&time2);
 
   e->wallclock_time = (float)clocks_diff(&time1, &time2);
-  // printParticle(e->s->parts, e->s->xparts,1000, e->s->nr_parts);
-  // printParticle(e->s->parts, e->s->xparts,515050, e->s->nr_parts);
 }
 
 /**
@@ -2326,11 +2344,15 @@ static bool hyperthreads_present(void) {
  * @param nr_threads The number of threads per MPI rank.
  * @param policy The queuing policy to use.
  * @param verbose Is this #engine talkative ?
+ * @param physical_constants The #phys_const used for this run.
+ * @param potential The properties of the external potential.
  */
 
 void engine_init(struct engine *e, struct space *s,
                  const struct swift_params *params, int nr_nodes, int nodeID,
-                 int nr_threads, int policy, int verbose) {
+                 int nr_threads, int policy, int verbose,
+                 const struct phys_const *physical_constants,
+                 const struct external_potential *potential) {
 
   /* Clean-up everything */
   bzero(e, sizeof(struct engine));
@@ -2361,6 +2383,8 @@ void engine_init(struct engine *e, struct space *s,
   e->verbose = verbose;
   e->count_step = 0;
   e->wallclock_time = 0.f;
+  e->physical_constants = physical_constants;
+  e->external_potential = potential;
   engine_rank = nodeID;
 
   /* Make the space link back to the engine. */
@@ -2466,7 +2490,7 @@ void engine_init(struct engine *e, struct space *s,
   engine_print_policy(e);
 
   /* Print information about the hydro scheme */
-  if ((e->policy & engine_policy_hydro) == engine_policy_hydro) {
+  if (e->policy & engine_policy_hydro) {
     if (e->nodeID == 0) message("Hydrodynamic scheme: %s.", SPH_IMPLEMENTATION);
     if (e->nodeID == 0)
       message("Hydrodynamic kernel: %s with %.2f +/- %.2f neighbours.",
@@ -2492,7 +2516,7 @@ void engine_init(struct engine *e, struct space *s,
   e->ti_current = 0;
 
   /* Fixed time-step case */
-  if ((e->policy & engine_policy_fixdt) == engine_policy_fixdt) {
+  if (e->policy & engine_policy_fixdt) {
     e->dt_min = e->dt_max;
 
     /* Find timestep on the timeline */
@@ -2572,7 +2596,7 @@ void engine_init(struct engine *e, struct space *s,
     if (pthread_create(&e->runners[k].thread, NULL, &runner_main,
                        &e->runners[k]) != 0)
       error("Failed to create runner thread.");
-    if ((e->policy & engine_policy_setaffinity) == engine_policy_setaffinity) {
+    if (e->policy & engine_policy_setaffinity) {
 #if defined(HAVE_SETAFFINITY)
 
       /* Set a reasonable queue ID. */
@@ -2598,8 +2622,8 @@ void engine_init(struct engine *e, struct space *s,
       e->runners[k].cpuid = k;
       e->runners[k].qid = k * nr_queues / e->nr_threads;
     }
-    // message( "runner %i on cpuid=%i with qid=%i." , e->runners[k].id ,
-    // e->runners[k].cpuid , e->runners[k].qid );
+    /* message( "runner %i on cpuid=%i with qid=%i." , e->runners[k].id , */
+    /* 	      e->runners[k].cpuid , e->runners[k].qid ); */
   }
 
   /* Wait for the runner threads to be in place. */
diff --git a/src/engine.h b/src/engine.h
index c8b9d7a46f8c788237e3b9ba7cb9d7d0a6e1370d..82e76481f8d1b17c6f23ee70b15b2013bb0fce64 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -1,6 +1,11 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *                    Angus Lepper (angus.lepper@ed.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -40,6 +45,8 @@
 #include "task.h"
 #include "parser.h"
 #include "partition.h"
+#include "physical_constants.h"
+#include "potentials.h"
 
 /* Some constants. */
 enum engine_policy {
@@ -164,13 +171,21 @@ struct engine {
 
   /* Are we talkative ? */
   int verbose;
+
+  /* Physical constants definition */
+  const struct phys_const *physical_constants;
+
+  /* Properties of external gravitational potential */
+  const struct external_potential *external_potential;
 };
 
 /* Function prototypes. */
 void engine_barrier(struct engine *e, int tid);
 void engine_init(struct engine *e, struct space *s,
                  const struct swift_params *params, int nr_nodes, int nodeID,
-                 int nr_threads, int policy, int verbose);
+                 int nr_threads, int policy, int verbose,
+                 const struct phys_const *physical_constants,
+                 const struct external_potential *potential);
 void engine_launch(struct engine *e, int nr_runners, unsigned int mask,
                    unsigned int submask);
 void engine_prepare(struct engine *e);
diff --git a/src/gravity/Default/gravity.h b/src/gravity/Default/gravity.h
index 92a9f64c1f84a9e949f4c0e9485f892b5c808cdc..4dd8d5b7c7194ae072f90e7703907500c208b9b9 100644
--- a/src/gravity/Default/gravity.h
+++ b/src/gravity/Default/gravity.h
@@ -1,6 +1,7 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Coypright (c) 2015 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2016 Tom Theuns (tom.theuns@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
@@ -18,19 +19,50 @@
  ******************************************************************************/
 
 #include <float.h>
+#include "potentials.h"
 
 /**
- * @brief Computes the gravity time-step of a given particle
+ * @brief Computes the gravity time-step of a given particle due to an external
+ *potential.
  *
- * @param gp Pointer to the g-particle data
+ * This function only branches towards the potential chosen by the user.
  *
+ * @param potential The properties of the external potential.
+ * @param phys_const The physical constants in internal units.
+ * @param gp Pointer to the g-particle data.
  */
+__attribute__((always_inline))
+    INLINE static float gravity_compute_timestep_external(
+        const struct external_potential* potential,
+        const struct phys_const* const phys_const,
+        const struct gpart* const gp) {
+
+  float dt = FLT_MAX;
+
+#ifdef EXTERNAL_POTENTIAL_POINTMASS
+  dt =
+      fminf(dt, external_gravity_pointmass_timestep(potential, phys_const, gp));
+#endif
+
+  return dt;
+}
 
+/**
+ * @brief Computes the gravity time-step of a given particle due to self-gravity
+ *
+ * This function only branches towards the potential chosen by the user.
+ *
+ * @param phys_const The physical constants in internal units.
+ * @param gp Pointer to the g-particle data.
+ */
 __attribute__((always_inline))
-    INLINE static float gravity_compute_timestep(struct gpart* gp) {
+    INLINE static float gravity_compute_timestep_self(
+        const struct phys_const* const phys_const,
+        const struct gpart* const gp) {
 
-  /* Currently no limit is imposed */
-  return FLT_MAX;
+  float dt = FLT_MAX;
+
+  return dt;
 }
 
 /**
@@ -71,6 +103,24 @@ __attribute__((always_inline))
 __attribute__((always_inline))
     INLINE static void gravity_end_force(struct gpart* gp) {}
 
+/**
+ * @brief Computes the gravitational acceleration induced by external potentials
+ *
+ * This function only branches towards the potential chosen by the user.
+ *
+ * @param potential The properties of the external potential.
+ * @param phys_const The physical constants in internal units.
+ * @param gp The particle to act upon.
+ */
+__attribute__((always_inline)) INLINE static void external_gravity(
+    const struct external_potential* potential,
+    const struct phys_const* const phys_const, struct gpart* gp) {
+
+#ifdef EXTERNAL_POTENTIAL_POINTMASS
+  external_gravity_pointmass(potential, phys_const, gp);
+#endif
+}
+
 /**
  * @brief Kick the additional variables
  *
diff --git a/src/gravity/Default/gravity_debug.h b/src/gravity/Default/gravity_debug.h
index 654745bfeb70dddba772af9e23797713376377a7..72ae5fd55f399448d78c6f2d1533c7f007f16dd1 100644
--- a/src/gravity/Default/gravity_debug.h
+++ b/src/gravity/Default/gravity_debug.h
@@ -24,5 +24,6 @@ __attribute__((always_inline))
       "v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e],\n "
       "mass=%.3e t_begin=%d, t_end=%d\n",
       p->x[0], p->x[1], p->x[2], p->v_full[0], p->v_full[1], p->v_full[2],
-      p->a_grav[0], p->a_grav[1], p->a_grav[2], p->mass, p->ti_begin, p->ti_end);
+      p->a_grav[0], p->a_grav[1], p->a_grav[2], p->mass, p->ti_begin,
+      p->ti_end);
 }
diff --git a/src/gravity/Default/gravity_part.h b/src/gravity/Default/gravity_part.h
index ec7e1e7e9750d957547e04e95410017fd5b0d453..a54fc1d18e7e84a1ca7a7e7913117ed207549271 100644
--- a/src/gravity/Default/gravity_part.h
+++ b/src/gravity/Default/gravity_part.h
@@ -43,6 +43,10 @@ struct gpart {
   /* Particle time of end of time-step. */
   int ti_end;
 
+  /* /\* current time of x, and of v_full *\/ */
+  /* float tx; */
+  /* float tv; */
+
   /* Anonymous union for id/part. */
   union {
 
diff --git a/src/partition.c b/src/partition.c
index c4145422de72cd03d5e76c3e5b2a9ac217420d47..70249a679edfe72bda97eddfc918a8526659d995 100644
--- a/src/partition.c
+++ b/src/partition.c
@@ -1044,7 +1044,6 @@ static int check_complete(struct space *s, int verbose, int nregions) {
   return (!failed);
 }
 
-
 /**
  * @brief Partition a space of cells based on another space of cells.
  *
@@ -1062,7 +1061,8 @@ static int check_complete(struct space *s, int verbose, int nregions) {
  *
  * @param oldh the cell dimensions of old space.
  * @param oldcdim number of cells per dimension in old space.
- * @param oldnodeIDs the nodeIDs of cells in the old space, indexed by old cellid.
+ * @param oldnodeIDs the nodeIDs of cells in the old space, indexed by old
+ *cellid.
  * @param s the space to be partitioned.
  *
  * @return 1 if the new space contains nodeIDs from all nodes, 0 otherwise.
diff --git a/src/physical_constants.c b/src/physical_constants.c
new file mode 100644
index 0000000000000000000000000000000000000000..d00d63df1c1e6a4821ce4ba50dfef9c4e0def9d2
--- /dev/null
+++ b/src/physical_constants.c
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Tom Theuns (tom.theuns@durham.ac.uk)
+ *                    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/>.
+ *
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+/* This object's header. */
+#include "physical_constants.h"
+
+/* Local headers. */
+#include "error.h"
+#include "physical_constants_cgs.h"
+
+/**
+ * @brief Converts physical constants to the internal unit system
+ *
+ * @param us The current internal system of units.
+ * @param internal_const The physical constants to initialize.
+ */
+void phys_const_init(struct UnitSystem* us, struct phys_const* internal_const) {
+
+  /* Units are declared as {U_M, U_L, U_t, U_I, U_T} */
+
+  const float dimension_G[5] = {-1, 3, -2, 0, 0};
+  internal_const->const_newton_G =
+      const_newton_G_cgs / units_general_conversion_factor(us, dimension_G);
+
+  const float dimension_c[5] = {0, 1, -1, 0, 0};
+  internal_const->const_speed_light_c =
+      const_speed_light_c_cgs /
+      units_general_conversion_factor(us, dimension_c);
+
+  const float dimension_h[5] = {1, -2, -1, 0, 0};
+  internal_const->const_planck_h =
+      const_planck_h_cgs / units_general_conversion_factor(us, dimension_h);
+  internal_const->const_planck_hbar =
+      const_planck_hbar_cgs / units_general_conversion_factor(us, dimension_h);
+
+  const float dimension_k[5] = {1, 2, -2, 0, -1};
+  internal_const->const_boltzmann_k =
+      const_boltzmann_k_cgs / units_general_conversion_factor(us, dimension_k);
+
+  const float dimension_thomson[5] = {0, 2, 0, 0, 0};
+  internal_const->const_thomson_cross_section =
+      const_thomson_cross_section_cgs /
+      units_general_conversion_factor(us, dimension_thomson);
+
+  const float dimension_ev[5] = {1, 2, -2, 0, 0};
+  internal_const->const_electron_volt =
+      const_electron_volt_cgs /
+      units_general_conversion_factor(us, dimension_ev);
+
+  const float dimension_charge[5] = {0, 0, -1, 1, 0};
+  internal_const->const_electron_charge =
+      const_electron_charge_cgs /
+      units_general_conversion_factor(us, dimension_charge);
+
+  const float dimension_mass[5] = {1, 0, 0, 0, 0};
+  internal_const->const_electron_mass =
+      const_electron_mass_cgs /
+      units_general_conversion_factor(us, dimension_mass);
+  internal_const->const_proton_mass =
+      const_proton_mass_cgs /
+      units_general_conversion_factor(us, dimension_mass);
+  internal_const->const_solar_mass =
+      const_solar_mass_cgs /
+      units_general_conversion_factor(us, dimension_mass);
+  internal_const->const_earth_mass =
+      const_earth_mass_cgs /
+      units_general_conversion_factor(us, dimension_mass);
+
+  const float dimension_time[5] = {0, 0, 1, 0, 0};
+  internal_const->const_year =
+      const_year_cgs / units_general_conversion_factor(us, dimension_time);
+
+  const float dimension_length[5] = {0, 1, 0, 0, 0};
+  internal_const->const_astronomical_unit =
+      const_astronomical_unit_cgs /
+      units_general_conversion_factor(us, dimension_length);
+  internal_const->const_parsec =
+      const_parsec_cgs / units_general_conversion_factor(us, dimension_length);
+  internal_const->const_light_year =
+      const_light_year_cgs /
+      units_general_conversion_factor(us, dimension_length);
+}
+
+void phys_const_print(struct phys_const* internal_const) {
+
+  message("%25s = %e", "Gravitational constant",
+          internal_const->const_newton_G);
+  message("%25s = %e", "Speed of light", internal_const->const_speed_light_c);
+  message("%25s = %e", "Planck constant", internal_const->const_planck_h);
+  message("%25s = %e", "Boltzmann constant", internal_const->const_boltzmann_k);
+  message("%25s = %e", "Thomson cross-section",
+          internal_const->const_thomson_cross_section);
+  message("%25s = %e", "Electron-Volt", internal_const->const_electron_volt);
+  message("%25s = %e", "Year", internal_const->const_year);
+  message("%25s = %e", "Astronomical Unit",
+          internal_const->const_astronomical_unit);
+  message("%25s = %e", "Parsec", internal_const->const_parsec);
+  message("%25s = %e", "Solar mass", internal_const->const_solar_mass);
+}
diff --git a/src/physical_constants.h b/src/physical_constants.h
new file mode 100644
index 0000000000000000000000000000000000000000..aac0fa0840e08a1140bbab67e944f7f134f4222b
--- /dev/null
+++ b/src/physical_constants.h
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Tom Theuns (tom.theuns@durham.ac.uk)
+ *                    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/>.
+ *
+ ******************************************************************************/
+#ifndef SWIFT_PHYSICAL_CONSTANTS_H
+#define SWIFT_PHYSICAL_CONSTANTS_H
+
+/* Config parameters. */
+#include "../config.h"
+
+/* Local includes. */
+#include "units.h"
+
+/* physical constants in in defined programme units */
+struct phys_const {
+
+  /* Newton's gravitationl constant */
+  double const_newton_G;
+
+  /* Speed of light in vacuum */
+  double const_speed_light_c;
+
+  /* Planck's constant */
+  double const_planck_h;
+
+  /* Planck's reduced constant */
+  double const_planck_hbar;
+
+  /* Boltzmann's constant */
+  double const_boltzmann_k;
+
+  /* Thomson cross-section */
+  double const_thomson_cross_section;
+
+  /* Charge of the electron  */
+  double const_electron_charge;
+
+  /* Electron-Volt */
+  double const_electron_volt;
+
+  /* Mass of the electron */
+  double const_electron_mass;
+
+  /* Mass of the proton */
+  double const_proton_mass;
+
+  /* (Tropical) Year */
+  double const_year;
+
+  /* Astronomical unit */
+  double const_astronomical_unit;
+
+  /* Parsec */
+  double const_parsec;
+
+  /* Light-year */
+  double const_light_year;
+
+  /* Mass of the Sun */
+  double const_solar_mass;
+
+  /* Mass of the Earth */
+  double const_earth_mass;
+};
+
+void phys_const_init(struct UnitSystem* us, struct phys_const* internal_const);
+
+void phys_const_print(struct phys_const* internal_const);
+
+#endif /* SWIFT_PHYSICAL_CONSTANTS_H */
diff --git a/src/physical_constants_cgs.h b/src/physical_constants_cgs.h
new file mode 100644
index 0000000000000000000000000000000000000000..9bd435bde9f0f80c06f0de5fee980f080c2f57d3
--- /dev/null
+++ b/src/physical_constants_cgs.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Tom Theuns (tom.theuns@durham.ac.uk)
+ *                    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/>.
+ *
+ ******************************************************************************/
+#ifndef SWIFT_PHYSICAL_CONSTANTS_CGS_H
+#define SWIFT_PHYSICAL_CONSTANTS_CGS_H
+
+/* The constants declared in this file should _NOT_ be used directly */
+/* Users should use the converted values in the phys_const structure */
+/* where all the constants are defined in the system of units specified */
+/* in the parameter file. */
+
+/* All values are taken from K.A. Olive et al. (Particle Data Group), Chin. */
+/* Phys. C, 38, 090001 (2014) and 2015 update. */
+/* http://pdg.lbl.gov/2015/reviews/rpp2015-rev-phys-constants.pdf */
+/* http://pdg.lbl.gov/2015/reviews/rpp2015-rev-astrophysical-constants.pdf */
+
+/* Newton's gravitation constant */
+const double const_newton_G_cgs = 6.67408e-8; /* g^-1 cm^3 s^-2 */
+
+/* Speed of light in vacuum */
+const double const_speed_light_c_cgs = 2.99792458e10; /* cm s^-1 */
+
+/* Planck's constant */
+const double const_planck_h_cgs = 6.626070040e-27; /* g cm^-2 s^-1 */
+
+/* Planck's reduced constant */
+const double const_planck_hbar_cgs = 1.054571800e-27; /* g cm^-2 s^-1 */
+
+/* Boltzmann's constant */
+const double const_boltzmann_k_cgs = 1.38064852e-16; /* g cm^2 s^-2 K^-1 */
+
+/* Thomson cross-section */
+const double const_thomson_cross_section_cgs = 6.6524587158e-25; /* cm^2 */
+
+/* Elementary charge */
+const double const_electron_charge_cgs = 1.6021766208e-19; /* A s^-1 */
+
+/* Electron-Volt */
+const double const_electron_volt_cgs = 1.6021766208e-12; /* g cm^2 s^-2 */
+
+/* Mass of the electron */
+const double const_electron_mass_cgs = 9.10938356e-28; /* g */
+
+/* Mass of the proton */
+const double const_proton_mass_cgs = 1.672621898e-24; /* g */
+
+/* Tropical year */
+const double const_year_cgs = 3.15569252e7; /* s */
+
+/* Astronomical unit */
+const double const_astronomical_unit_cgs = 1.49597870700e13; /* cm */
+
+/* Parsec */
+const double const_parsec_cgs = 3.08567758149e18; /* cm */
+
+/* Light-year */
+const double const_light_year_cgs = 9.46053e17; /* cm */
+
+/* Mass of the Sun */
+const double const_solar_mass_cgs = 1.9885e33; /* g */
+
+/* Mass of the Earth */
+const double const_earth_mass_cgs = 5.9726e27; /* g */
+
+#endif /* SWIFT_PHYSICAL_CONSTANTS_CGS_H */
diff --git a/src/potentials.c b/src/potentials.c
new file mode 100644
index 0000000000000000000000000000000000000000..98e57d7959963e07cfbbd2fdb60a0df504e6a487
--- /dev/null
+++ b/src/potentials.c
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Tom Theuns (tom.theuns@durham.ac.uk)
+ *                    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/>.
+ *
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+/* This object's header. */
+#include "potentials.h"
+
+/**
+ * @brief Initialises the external potential properties in the internal system
+ * of units.
+ *
+ * @param parameter_file The parsed parameter file
+ * @param us The current internal system of units
+ * @param potential The external potential properties to initialize
+ */
+void potential_init(const struct swift_params* parameter_file,
+                    struct UnitSystem* us,
+                    struct external_potential* potential) {
+
+#ifdef EXTERNAL_POTENTIAL_POINTMASS
+
+  potential->point_mass.x =
+      parser_get_param_double(parameter_file, "PointMass:position_x");
+  potential->point_mass.y =
+      parser_get_param_double(parameter_file, "PointMass:position_y");
+  potential->point_mass.z =
+      parser_get_param_double(parameter_file, "PointMass:position_z");
+  potential->point_mass.mass =
+      parser_get_param_double(parameter_file, "PointMass:mass");
+
+#endif /* EXTERNAL_POTENTIAL_POINTMASS */
+}
+
+/**
+ * @brief Prints the properties of the external potential to stdout.
+ *
+ * @param  potential The external potential properties.
+ */
+void potential_print(const struct external_potential* potential) {
+
+#ifdef EXTERNAL_POTENTIAL_POINTMASS
+  message("Point mass properties are (x,y,z) = (%e, %e, %e), M = %e",
+          potential->point_mass.x, potential->point_mass.y,
+          potential->point_mass.z, potential->point_mass.mass);
+#endif /* EXTERNAL_POTENTIAL_POINTMASS */
+}
diff --git a/src/potentials.h b/src/potentials.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c687fa4c4a64bcc0ab8cac1a5e495487fa938f1
--- /dev/null
+++ b/src/potentials.h
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Tom Theuns (tom.theuns@durham.ac.uk)
+ *                    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/>.
+ *
+ ******************************************************************************/
+
+#ifndef SWIFT_POTENTIALS_H
+#define SWIFT_POTENTIALS_H
+
+/* Config parameters. */
+#include "../config.h"
+
+/* Some standard headers. */
+#include <math.h>
+
+/* Local includes. */
+#include "const.h"
+#include "error.h"
+#include "part.h"
+#include "physical_constants.h"
+#include "units.h"
+
+/* External Potential Properties */
+struct external_potential {
+
+#ifdef EXTERNAL_POTENTIAL_POINTMASS
+  struct {
+    double x, y, z;
+    double mass;
+  } point_mass;
+#endif
+};
+
+/* Include exteral pointmass potential */
+#ifdef EXTERNAL_POTENTIAL_POINTMASS
+
+#define EXTERNAL_GRAVITY_TIMESTEP_PREFACTOR 0.03f
+
+/**
+ * @brief Computes the time-step due to the acceleration from a point mass
+ *
+ * @param potential The properties of the externa potential.
+ * @param phys_const The physical constants in internal units.
+ * @param g Pointer to the g-particle data.
+ */
+__attribute__((always_inline))
+    INLINE static float external_gravity_pointmass_timestep(
+        const struct external_potential* potential,
+        const struct phys_const* const phys_const,
+        const struct gpart* const g) {
+
+  const float G_newton = phys_const->const_newton_G;
+  const float dx = g->x[0] - potential->point_mass.x;
+  const float dy = g->x[1] - potential->point_mass.y;
+  const float dz = g->x[2] - potential->point_mass.z;
+  const float rinv = 1.f / sqrtf(dx * dx + dy * dy + dz * dz);
+  const float drdv = (g->x[0] - potential->point_mass.x) * (g->v_full[0]) +
+                     (g->x[1] - potential->point_mass.y) * (g->v_full[1]) +
+                     (g->x[2] - potential->point_mass.z) * (g->v_full[2]);
+  const float dota_x = G_newton * potential->point_mass.mass * rinv * rinv *
+                       rinv * (-g->v_full[0] + 3.f * rinv * rinv * drdv * dx);
+  const float dota_y = G_newton * potential->point_mass.mass * rinv * rinv *
+                       rinv * (-g->v_full[1] + 3.f * rinv * rinv * drdv * dy);
+  const float dota_z = G_newton * potential->point_mass.mass * rinv * rinv *
+                       rinv * (-g->v_full[2] + 3.f * rinv * rinv * drdv * dz);
+  const float dota_2 = dota_x * dota_x + dota_y * dota_y + dota_z * dota_z;
+  const float a_2 = g->a_grav[0] * g->a_grav[0] + g->a_grav[1] * g->a_grav[1] +
+                    g->a_grav[2] * g->a_grav[2];
+
+  return EXTERNAL_GRAVITY_TIMESTEP_PREFACTOR * sqrtf(a_2 / dota_2);
+}
+
+/**
+ * @brief Computes the gravitational acceleration of a particle due to a point
+ * mass
+ *
+ * @param potential The proerties of the external potential.
+ * @param phys_const The physical constants in internal units.
+ * @param g Pointer to the g-particle data.
+ */
+__attribute__((always_inline)) INLINE static void external_gravity_pointmass(
+    const struct external_potential* potential,
+    const struct phys_const* const phys_const, struct gpart* g) {
+
+  const float G_newton = phys_const->const_newton_G;
+  const float dx = g->x[0] - potential->point_mass.x;
+  const float dy = g->x[1] - potential->point_mass.y;
+  const float dz = g->x[2] - potential->point_mass.z;
+  const float rinv = 1.f / sqrtf(dx * dx + dy * dy + dz * dz);
+
+  g->a_grav[0] +=
+      -G_newton * potential->point_mass.mass * dx * rinv * rinv * rinv;
+  g->a_grav[1] +=
+      -G_newton * potential->point_mass.mass * dy * rinv * rinv * rinv;
+  g->a_grav[2] +=
+      -G_newton * potential->point_mass.mass * dz * rinv * rinv * rinv;
+}
+#endif /* EXTERNAL_POTENTIAL_POINTMASS */
+
+/* Now, some generic functions, defined in the source file */
+
+void potential_init(const struct swift_params* parameter_file,
+                    struct UnitSystem* us,
+                    struct external_potential* potential);
+
+void potential_print(const struct external_potential* potential);
+
+#endif /* SWIFT_POTENTIALS_H */
diff --git a/src/runner.c b/src/runner.c
index 25ffc9f2c2b9fff4596d680ef505e714c7595c07..2fd272039d04f2c42db3d39b2acdbe9009b19125 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -1,6 +1,10 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -68,6 +72,21 @@ const float runner_shift[13 * 3] = {
 const char runner_flip[27] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
+/* #define MY_CELL 428428428 */
+/* #define DX 0.1 */
+/* #define NX 1000 */
+/* #define CELL_ID                                                  \ */
+/*   ((int)(c->loc[0] / DX) * NX *NX + (int)(c->loc[1] / DX) * NX + \ */
+/*    (int)(c->loc[2] / DX)) */
+/* #define OUT \ */
+/*   if (CELL_ID == MY_CELL) { \ */
+/*     message(" cell= %d gcount=%d time=%f \n", CELL_ID, c->gcount,
+ * r->e->time); \ */
+/*   } */
+/* #define OUT  message(" cell %d %d %f \n",CELL_ID, c->count, r->e->time); */
+/* #define OUT  if(CELL_ID == MY_CELL) message("\n cell %f %f %f %d %d */
+/* %f\n",c->loc[0],c->loc[1],c->loc[2], CELL_ID, c->count, r->e->time); */
+
 /* Import the density loop functions. */
 #define FUNCTION density
 #include "runner_doiact.h"
@@ -80,6 +99,95 @@ const char runner_flip[27] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
 /* Import the gravity loop functions. */
 #include "runner_doiact_grav.h"
 
+/**
+ * @brief Calculate gravity acceleration from external potential
+ *
+ * @param r runner task
+ * @param c cell
+ * @param timer 1 if the time is to be recorded.
+ */
+void runner_dograv_external(struct runner *r, struct cell *c, int timer) {
+
+  struct gpart *g, *gparts = c->gparts;
+  int i, k, gcount = c->gcount;
+  const int ti_current = r->e->ti_current;
+  const struct external_potential *potential = r->e->external_potential;
+  const struct phys_const *constants = r->e->physical_constants;
+
+  TIMER_TIC;
+
+  /* Recurse? */
+  if (c->split) {
+    for (k = 0; k < 8; k++)
+      if (c->progeny[k] != NULL) runner_dograv_external(r, c->progeny[k], 0);
+    return;
+  }
+
+#ifdef TASK_VERBOSE
+  OUT;
+#endif
+
+  /* Loop over the parts in this cell. */
+  for (i = 0; i < gcount; i++) {
+
+    /* Get a direct pointer on the part. */
+    g = &gparts[i];
+
+    /* Is this part within the time step? */
+    if (g->ti_end <= ti_current) {
+
+      external_gravity(potential, constants, g);
+
+      /* /\* check for energy and angular momentum conservation - begin by */
+      /*  * synchronizing velocity*\/ */
+      /* const float dx = g->x[0] - r->e->potential->point_mass.x; */
+      /* const float dy = g->x[1] - r->e->potential->point_mass.y; */
+      /* const float dz = g->x[2] - r->e->potential->point_mass.z; */
+      /* const float dr = sqrtf((dx * dx) + (dy * dy) + (dz * dz)); */
+      /* const float rinv = 1.f / sqrtf(dx * dx + dy * dy + dz * dz); */
+
+      /* const int current_dti = g->ti_end - g->ti_begin; */
+      /* const float dt = 0.5f * current_dti * r->e->timeBase; */
+      /* const float vx = g->v_full[0] + dt * g->a_grav[0]; */
+      /* const float vy = g->v_full[1] + dt * g->a_grav[1]; */
+      /* const float vz = g->v_full[2] + dt * g->a_grav[2]; */
+
+      /* /\* E/L *\/ */
+      /* float L[3], E; */
+      /* E = 0.5 * ((vx * vx) + (vy * vy) + (vz * vz)) - */
+      /*     r->e->physical_constants->newton_gravity * */
+      /*         r->e->potential->point_mass.mass * rinv; */
+      /* L[0] = dy * vz - dz * vy; */
+      /* L[1] = dz * vx - dx * vz; */
+      /* L[2] = dx * vy - dy * vx; */
+      /* if (abs(g->id) == 1) { */
+      /*   float v2 = vx * vx + vy * vy + vz * vz; */
+      /*   float fg = r->e->physical_constants->newton_gravity * */
+      /*              r->e->potential->point_mass.mass * rinv; */
+      /*   float fga = sqrtf((g->a_grav[0] * g->a_grav[0]) + */
+      /*                     (g->a_grav[1] * g->a_grav[1]) + */
+      /*                     (g->a_grav[2] * g->a_grav[2])) * */
+      /*               dr; */
+      /*   // message("grav_external time= %f\t V_c^2= %f GM/r= %f E= %f L[2]=
+       * %f */
+      /*   // x= %f y= %f vx= %f vy= %f\n", r->e->time, v2, fg, E, L[2],
+       * g->x[0], */
+      /*   // g->x[1], vx, vy); */
+      /*   message("%f\t %f %f %f %f %f %f %f %f %f %f %f %f %f\n", r->e->time,
+       */
+      /*           g->tx, g->tv, dt, v2, fg, fga, dr, E, L[2], g->x[0], g->x[1],
+       */
+      /*           vx, vy); */
+      /*   /\* message(" G=%e M=%e\n", r->e->physical_constants->newton_gravity,
+       */
+      /*    * r->e->potential->point_mass.mass); *\/ */
+      /*   /\* exit(-1); *\/ */
+      /* } */
+    }
+  }
+  if (timer) TIMER_TOC(timer_dograv_external);
+}
+
 /**
  * @brief Sort the entries in ascending order using QuickSort.
  *
@@ -466,7 +574,6 @@ void runner_dogsort(struct runner *r, struct cell *c, int flags, int clock) {
  * @param c The cell.
  * @param timer 1 if the time is to be recorded.
  */
-
 void runner_doinit(struct runner *r, struct cell *c, int timer) {
 
   struct part *const parts = c->parts;
@@ -682,6 +789,9 @@ void runner_dodrift(struct runner *r, struct cell *c, int timer) {
   float dx_max = 0.f, dx2_max = 0.f, h_max = 0.f;
 
   TIMER_TIC
+#ifdef TASK_VERBOSE
+  OUT;
+#endif
 
   /* No children? */
   if (!c->split) {
@@ -808,6 +918,8 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
   struct part *const parts = c->parts;
   struct xpart *const xparts = c->xparts;
   struct gpart *const gparts = c->gparts;
+  const struct external_potential *potential = r->e->external_potential;
+  const struct phys_const *constants = r->e->physical_constants;
   const int is_fixdt =
       (r->e->policy & engine_policy_fixdt) == engine_policy_fixdt;
 
@@ -819,6 +931,10 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
 
   TIMER_TIC
 
+#ifdef TASK_VERBOSE
+  OUT;
+#endif
+
   /* No children? */
   if (!c->split) {
 
@@ -829,70 +945,78 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
       struct gpart *const gp = &gparts[k];
 
       /* If the g-particle has no counterpart and needs to be kicked */
-      if (gp->id < 0 && (is_fixdt || gp->ti_end <= ti_current)) {
+      if (gp->id < 0) {
 
-        /* First, finish the force calculation */
-        gravity_end_force(gp);
+        if (is_fixdt || gp->ti_end <= ti_current) {
 
-        /* Now we are ready to compute the next time-step size */
-        int new_dti;
+          /* First, finish the force calculation */
+          gravity_end_force(gp);
 
-        if (is_fixdt) {
+          /* Now we are ready to compute the next time-step size */
+          int new_dti;
 
-          /* Now we have a time step, proceed with the kick */
-          new_dti = global_dt_max * timeBase_inv;
+          if (is_fixdt) {
 
-        } else {
+            /* Now we have a time step, proceed with the kick */
+            new_dti = global_dt_max * timeBase_inv;
 
-          /* Compute the next timestep (gravity condition) */
-          float new_dt = gravity_compute_timestep(gp);
+          } else {
 
-          /* Limit timestep within the allowed range */
-          new_dt = fminf(new_dt, global_dt_max);
-          new_dt = fmaxf(new_dt, global_dt_min);
+            /* Compute the next timestep (gravity condition) */
+            const float new_dt_external =
+                gravity_compute_timestep_external(potential, constants, gp);
+            const float new_dt_self =
+                gravity_compute_timestep_self(constants, gp);
 
-          /* Convert to integer time */
-          new_dti = new_dt * timeBase_inv;
+            float new_dt = fminf(new_dt_external, new_dt_self);
 
-          /* Recover the current timestep */
-          const int current_dti = gp->ti_end - gp->ti_begin;
+            /* Limit timestep within the allowed range */
+            new_dt = fminf(new_dt, global_dt_max);
+            new_dt = fmaxf(new_dt, global_dt_min);
 
-          /* Limit timestep increase */
-          if (current_dti > 0) new_dti = min(new_dti, 2 * current_dti);
+            /* Convert to integer time */
+            new_dti = new_dt * timeBase_inv;
 
-          /* Put this timestep on the time line */
-          int dti_timeline = max_nr_timesteps;
-          while (new_dti < dti_timeline) dti_timeline /= 2;
+            /* Recover the current timestep */
+            const int current_dti = gp->ti_end - gp->ti_begin;
 
-          /* Now we have a time step, proceed with the kick */
-          new_dti = dti_timeline;
-        }
+            /* Limit timestep increase */
+            if (current_dti > 0) new_dti = min(new_dti, 2 * current_dti);
 
-        /* Compute the time step for this kick */
-        const int ti_start = (gp->ti_begin + gp->ti_end) / 2;
-        const int ti_end = gp->ti_end + new_dti / 2;
-        const double dt = (ti_end - ti_start) * timeBase;
-        const double half_dt = (ti_end - gp->ti_end) * timeBase;
+            /* Put this timestep on the time line */
+            int dti_timeline = max_nr_timesteps;
+            while (new_dti < dti_timeline) dti_timeline /= 2;
 
-        /* Move particle forward in time */
-        gp->ti_begin = gp->ti_end;
-        gp->ti_end = gp->ti_begin + new_dti;
+            /* Now we have a time step, proceed with the kick */
+            new_dti = dti_timeline;
+          }
 
-        /* Kick particles in momentum space */
-        gp->v_full[0] += gp->a_grav[0] * dt;
-        gp->v_full[1] += gp->a_grav[1] * dt;
-        gp->v_full[2] += gp->a_grav[2] * dt;
+          /* Compute the time step for this kick */
+          const int ti_start = (gp->ti_begin + gp->ti_end) / 2;
+          const int ti_end = gp->ti_end + new_dti / 2;
+          const double dt = (ti_end - ti_start) * timeBase;
+          const double half_dt = (ti_end - gp->ti_end) * timeBase;
 
-        /* Extra kick work */
-        gravity_kick_extra(gp, dt, half_dt);
+          /* Move particle forward in time */
+          gp->ti_begin = gp->ti_end;
+          gp->ti_end = gp->ti_begin + new_dti;
 
-        /* Number of updated g-particles */
-        g_updated++;
-      }
+          /* Kick particles in momentum space */
+          gp->v_full[0] += gp->a_grav[0] * dt;
+          gp->v_full[1] += gp->a_grav[1] * dt;
+          gp->v_full[2] += gp->a_grav[2] * dt;
 
-      /* Minimal time for next end of time-step */
-      ti_end_min = min(gp->ti_end, ti_end_min);
-      ti_end_max = max(gp->ti_end, ti_end_max);
+          /* Extra kick work */
+          gravity_kick_extra(gp, dt, half_dt);
+
+          /* Number of updated g-particles */
+          g_updated++;
+        }
+
+        /* Minimal time for next end of time-step */
+        ti_end_min = min(gp->ti_end, ti_end_min);
+        ti_end_max = max(gp->ti_end, ti_end_max);
+      }
     }
 
     /* Now do the hydro ones... */
@@ -929,9 +1053,17 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
 
           /* Compute the next timestep (gravity condition) */
           float new_dt_grav = FLT_MAX;
-          if (p->gpart != NULL)
-            new_dt_grav = gravity_compute_timestep(p->gpart);
+          if (p->gpart != NULL) {
 
+            const float new_dt_external = gravity_compute_timestep_external(
+                potential, constants, p->gpart);
+            const float new_dt_self =
+                gravity_compute_timestep_self(constants, p->gpart);
+
+            new_dt_grav = fminf(new_dt_external, new_dt_self);
+          }
+
+          /* Final time-step is minimum of hydro and gravity */
           float new_dt = fminf(new_dt_hydro, new_dt_grav);
 
           /* Limit change in h */
@@ -1038,7 +1170,6 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
       ti_end_min = min(p->ti_end, ti_end_min);
       ti_end_max = max(p->ti_end, ti_end_max);
     }
-
   }
 
   /* Otherwise, aggregate data from children. */
@@ -1199,6 +1330,9 @@ void *runner_main(void *data) {
         case task_type_grav_down:
           runner_dograv_down(r, t->ci);
           break;
+        case task_type_grav_external:
+          runner_dograv_external(r, t->ci, 1);
+          break;
         case task_type_part_sort:
           space_do_parts_sort();
           break;
diff --git a/src/runner.h b/src/runner.h
index ff2f93db6eae9d9e85cd9c3de6f398ed0f64c681..f052bb57cdfc92a632cc4143d74250e7b6f6e847 100644
--- a/src/runner.h
+++ b/src/runner.h
@@ -1,6 +1,10 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
diff --git a/src/space.c b/src/space.c
index ee2b8013cdfa7a885e9e9d61bf78e20aaca31366..6d4c256d502e121448238cadbe179d0000f00e88 100644
--- a/src/space.c
+++ b/src/space.c
@@ -1,22 +1,25 @@
 /*******************************************************************************
-* This file is part of SWIFT.
-* Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
-*               2016 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 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/>.
-*
-******************************************************************************/
+ * This file is part of SWIFT.
+ * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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/>.
+ *
+ ******************************************************************************/
 
 /* Config parameters. */
 #include "../config.h"
@@ -164,15 +167,17 @@ void space_regrid(struct space *s, double cell_max, int verbose) {
   /* Run through the parts and get the current h_max. */
   // tic = getticks();
   float h_max = s->cell_min / kernel_gamma / space_stretch;
-  if (s->cells != NULL) {
-    for (int k = 0; k < s->nr_cells; k++) {
-      if (s->cells[k].h_max > h_max) h_max = s->cells[k].h_max;
-    }
-  } else {
-    for (size_t k = 0; k < nr_parts; k++) {
-      if (s->parts[k].h > h_max) h_max = s->parts[k].h;
+  if (nr_parts > 0) {
+    if (s->cells != NULL) {
+      for (int k = 0; k < s->nr_cells; k++) {
+        if (s->cells[k].h_max > h_max) h_max = s->cells[k].h_max;
+      }
+    } else {
+      for (size_t k = 0; k < nr_parts; k++) {
+        if (s->parts[k].h > h_max) h_max = s->parts[k].h;
+      }
+      s->h_max = h_max;
     }
-    s->h_max = h_max;
   }
 
 /* If we are running in parallel, make sure everybody agrees on
@@ -372,7 +377,7 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
   const ticks tic = getticks();
 
   /* Be verbose about this. */
-  // message( "re)building space..." ); fflush(stdout);
+  // message("re)building space..."); fflush(stdout);
 
   /* Re-grid if necessary, or just re-set the cell data. */
   space_regrid(s, cell_max, verbose);
@@ -1280,9 +1285,11 @@ void space_do_split(struct space *s, struct cell *c) {
   if (s->nr_parts > 0)
     c->owner =
         ((c->parts - s->parts) % s->nr_parts) * s->nr_queues / s->nr_parts;
-  else
+  else if (s->nr_gparts > 0)
     c->owner =
         ((c->gparts - s->gparts) % s->nr_gparts) * s->nr_queues / s->nr_gparts;
+  else
+    c->owner = 0; /* Ok, there is really nothing on this rank... */
 }
 
 /**
@@ -1475,10 +1482,12 @@ void space_init(struct space *s, const struct swift_params *params,
   }
 
   /* Allocate the extra parts array. */
-  if (posix_memalign((void *)&s->xparts, xpart_align,
-                     Npart * sizeof(struct xpart)) != 0)
-    error("Failed to allocate xparts.");
-  bzero(s->xparts, Npart * sizeof(struct xpart));
+  if (Npart > 0) {
+    if (posix_memalign((void *)&s->xparts, xpart_align,
+                       Npart * sizeof(struct xpart)) != 0)
+      error("Failed to allocate xparts.");
+    bzero(s->xparts, Npart * sizeof(struct xpart));
+  }
 
   /* Init the space lock. */
   if (lock_init(&s->lock) != 0) error("Failed to create space spin-lock.");
diff --git a/src/space.h b/src/space.h
index 88e2f6f52774651217c4ff24e25f549d8ae1e347..ad7b9e77d484c997527d32c934bf1b85d7d54e41 100644
--- a/src/space.h
+++ b/src/space.h
@@ -1,6 +1,10 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
diff --git a/src/swift.h b/src/swift.h
index e568a28c888295affc9ec45b6d059d34f5b4bf04..4b570447345465684fc51bcd4ca96d07a4b7f518 100644
--- a/src/swift.h
+++ b/src/swift.h
@@ -40,6 +40,8 @@
 #include "parser.h"
 #include "part.h"
 #include "partition.h"
+#include "physical_constants.h"
+#include "potentials.h"
 #include "queue.h"
 #include "runner.h"
 #include "scheduler.h"
diff --git a/src/task.c b/src/task.c
index 5f1475a46e4626e1f51db673d73fd84f86e6edb6..31c2bfcb3462b9f91547ebd631f645e190c07143 100644
--- a/src/task.c
+++ b/src/task.c
@@ -1,6 +1,10 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -43,10 +47,10 @@
 
 /* Task type names. */
 const char *taskID_names[task_type_count] = {
-    "none",      "sort",       "self",       "pair",    "sub",
-    "init",      "ghost",      "drift",      "kick",    "send",
-    "recv",      "grav_pp",    "grav_mm",    "grav_up", "grav_down",
-    "part_sort", "gpart_sort", "split_cell", "rewait"};
+    "none",          "sort",      "self",       "pair",       "sub",
+    "init",          "ghost",     "drift",      "kick",       "send",
+    "recv",          "grav_pp",   "grav_mm",    "grav_up",    "grav_down",
+    "grav_external", "part_sort", "gpart_sort", "split_cell", "rewait"};
 
 const char *subtaskID_names[task_type_count] = {"none",  "density",
                                                 "force", "grav"};
diff --git a/src/task.h b/src/task.h
index 9c0ba6087d772d7362a98bc40a838c6fa3713166..25cc886f4b38456a0431fb6c7d0b7b1864053dd9 100644
--- a/src/task.h
+++ b/src/task.h
@@ -2,6 +2,9 @@
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
  *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -45,6 +48,7 @@ enum task_types {
   task_type_grav_mm,
   task_type_grav_up,
   task_type_grav_down,
+  task_type_grav_external,
   task_type_part_sort,
   task_type_gpart_sort,
   task_type_split_cell,
diff --git a/src/timers.c b/src/timers.c
index 2501d347c8cea608650ece4c2883dab85ceee058..b621d27c90902f06c3760cbef6a88237a2b3b95b 100644
--- a/src/timers.c
+++ b/src/timers.c
@@ -1,6 +1,9 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
diff --git a/src/timers.h b/src/timers.h
index de2d9edb9ed54717472e5ae1222dfb33235c3e95..bf288d73929bd664992ef3da6d531d77aa85ac3b 100644
--- a/src/timers.h
+++ b/src/timers.h
@@ -1,6 +1,9 @@
 /*******************************************************************************
  * This file is part of SWIFT.
  * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *               2016 John A. Regan (john.a.regan@durham.ac.uk)
+ *                    Tom Theuns (tom.theuns@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
@@ -37,6 +40,7 @@ enum {
   timer_dopair_density,
   timer_dopair_force,
   timer_dopair_grav,
+  timer_dograv_external,
   timer_dosub_density,
   timer_dosub_force,
   timer_dosub_grav,
diff --git a/src/units.c b/src/units.c
index 184dbe8a0df000008dba1d7003558d83b1f08cad..c0276fd4fa74136f46f2f4b7d719c124c92fa48c 100644
--- a/src/units.c
+++ b/src/units.c
@@ -39,7 +39,6 @@
 /* Includes. */
 #include "const.h"
 #include "error.h"
-#include "units.h"
 
 /**
  * @brief Initialises the UnitSystem structure with the constants given in
@@ -331,7 +330,7 @@ void units_conversion_string(char* buffer, const struct UnitSystem* us,
  * the desired quantity. See conversionFactor() for a working example
  */
 double units_general_conversion_factor(const struct UnitSystem* us,
-                                       float baseUnitsExponants[5]) {
+                                       const float baseUnitsExponants[5]) {
   double factor = 1.;
   int i;
 
@@ -349,7 +348,7 @@ double units_general_conversion_factor(const struct UnitSystem* us,
  * the desired quantity. See conversionFactor() for a working example
  */
 float units_general_h_factor(const struct UnitSystem* us,
-                             float baseUnitsExponants[5]) {
+                             const float baseUnitsExponants[5]) {
   float factor_exp = 0.f;
 
   factor_exp += -baseUnitsExponants[UNIT_MASS];
@@ -367,7 +366,7 @@ float units_general_h_factor(const struct UnitSystem* us,
  * the desired quantity. See conversionFactor() for a working example
  */
 float units_general_a_factor(const struct UnitSystem* us,
-                             float baseUnitsExponants[5]) {
+                             const float baseUnitsExponants[5]) {
   float factor_exp = 0.f;
 
   factor_exp += baseUnitsExponants[UNIT_LENGTH];
@@ -385,7 +384,7 @@ float units_general_a_factor(const struct UnitSystem* us,
  * the desired quantity. See conversionFactor() for a working example
  */
 void units_general_conversion_string(char* buffer, const struct UnitSystem* us,
-                                     float baseUnitsExponants[5]) {
+                                     const float baseUnitsExponants[5]) {
   char temp[14];
   double a_exp = units_general_a_factor(us, baseUnitsExponants);
   double h_exp = units_general_h_factor(us, baseUnitsExponants);
diff --git a/src/units.h b/src/units.h
index 3e349dc16787cd4052a3e9205b21dce3c3732448..197d3e1f1dac2e01015d44758dd079ac21c6a0b7 100644
--- a/src/units.h
+++ b/src/units.h
@@ -97,19 +97,19 @@ double units_get_base_unit(const struct UnitSystem*, enum BaseUnits);
 const char* units_get_base_unit_symbol(enum BaseUnits);
 const char* units_get_base_unit_CGS_symbol(enum BaseUnits);
 double units_general_conversion_factor(const struct UnitSystem* us,
-                                       float baseUnitsExponants[5]);
+                                       const float baseUnitsExponants[5]);
 double units_conversion_factor(const struct UnitSystem* us,
                                enum UnitConversionFactor unit);
 float units_general_h_factor(const struct UnitSystem* us,
-                             float baseUnitsExponants[5]);
+                             const float baseUnitsExponants[5]);
 float units_h_factor(const struct UnitSystem* us,
                      enum UnitConversionFactor unit);
 float units_general_a_factor(const struct UnitSystem* us,
-                             float baseUnitsExponants[5]);
+                             const float baseUnitsExponants[5]);
 float units_a_factor(const struct UnitSystem* us,
                      enum UnitConversionFactor unit);
 void units_general_conversion_string(char* buffer, const struct UnitSystem* us,
-                                     float baseUnitsExponants[5]);
+                                     const float baseUnitsExponants[5]);
 void units_conversion_string(char* buffer, const struct UnitSystem* us,
                              enum UnitConversionFactor unit);