From ac8a2f2c326f411db94710c38e8352392eaeeeda Mon Sep 17 00:00:00 2001
From: "Peter W. Draper" <p.w.draper@durham.ac.uk>
Date: Mon, 28 Sep 2015 17:41:09 +0100
Subject: [PATCH] Revert "Revert "add a number of checks on system sanity that
 happen between each step in engine_step.""

This reverts commit 089024322c0f93dd168a8810224ce5008a100e6a.

Conflicts:
	examples/test.c
	src/debug.c
---
 examples/test.c |  4 +--
 src/debug.c     | 16 +++++++--
 src/debug.h     |  2 +-
 src/engine.c    | 94 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/engine.h    |  1 +
 src/space.c     |  2 +-
 6 files changed, 113 insertions(+), 6 deletions(-)

diff --git a/examples/test.c b/examples/test.c
index 8ee735a57f..aaa8ac160c 100644
--- a/examples/test.c
+++ b/examples/test.c
@@ -784,8 +784,8 @@ int main(int argc, char *argv[]) {
   /* Initialize the engine with this space. */
   tic = getticks();
   message("nr_nodes is %i.", nr_nodes);
-  engine_init(&e, &s, dt_max, nr_threads, nr_queues, nr_nodes, myrank,
-              ENGINE_POLICY | engine_policy_steal);
+  engine_init(&e, &s, dt_max, nr_threads, nr_queues, nr_nodes, myrank , 
+              ENGINE_POLICY | engine_policy_steal | engine_policy_paranoid);
   if (myrank == 0)
     message("engine_init took %.3f ms.",
             ((double)(getticks() - tic)) / CPU_TPS * 1000);
diff --git a/src/debug.c b/src/debug.c
index d55d544345..0ebbd44ae0 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -20,8 +20,20 @@
 
 #include <stdio.h>
 
-#include "const.h"
-#include "part.h"
+/* This object's header. */
+#include "debug.h"
+
+/**
+ * @brief Dump the information pertaining to the given cell.
+ */
+
+void print_cell(struct cell *c) {
+  printf(
+      "## Cell 0x%0zx: loc=[%.3e,%.3e,%.3e], h=[%.3e,%.3e,%.3e], depth=%i, "
+      "split=%i, maxdepth=%i.\n",
+      (size_t)c, c->loc[0], c->loc[1], c->loc[2], c->h[0], c->h[1], c->h[2],
+      c->depth, c->split, c->maxdepth);
+}
 
 /**
  * @brief Looks for the particle with the given id and prints its information to
diff --git a/src/debug.h b/src/debug.h
index ddd33d527e..42269fc267 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -23,7 +23,7 @@
 #include "cell.h"
 #include "part.h"
 
-
+void print_cell(struct cell *c);
 void printParticle(struct part *parts, long long int i, int N);
 void printgParticle(struct gpart *parts, long long int i, int N);
 void printParticle_single(struct part *p);
diff --git a/src/engine.c b/src/engine.c
index fcecde15fb..90c0e12414 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -62,6 +62,79 @@
 /** The rank of the engine as a global variable (for messages). */
 int engine_rank;
 
+/**
+ * @brief Check if a single particle is OK.
+ *
+ * @return Zero if all checks passed, non-zero otherwise.
+ */
+int engine_check_part(struct part *p) {
+  if (p == NULL || p->mass == 0.0f || p->h == 0.0f) {
+    message("Bad particle data.");
+    printParticle_single(p);
+    return 1;
+  } else if (p->x[0] == 0.0 && p->x[1] == 0.0 && p->x[2] == 0.0) {
+    message("Bad particle location.");
+    printParticle_single(p);
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+/**
+ * @brief Check if a cell's data is reasonable, also check if its particles
+ *        are OK.
+ *
+ * @return Zero if all checks passed, non-zero otherwise.
+ */
+
+void engine_check_cell(struct cell *c, void *data) {
+  /* Check the cell data. */
+  if (c->count == 0) {
+    print_cell(c);
+    error("Empty cell.");
+  }
+
+  /* Check the particles. */
+  for (int k = 0; k < c->count; k++) {
+    if (engine_check_part(&c->parts[k])) {
+      print_cell(c);
+      error("Bad particle in cell.");
+    }
+  }
+
+  /* Check that the progeny, if any, contain all the particles. */
+  if (c->split) {
+    int count = 0;
+    for (int k = 0; k < 8; k++) {
+      if (c->progeny[k] != NULL) {
+        count += c->progeny[k]->count;
+      }
+    }
+    if (count != c->count) {
+      print_cell(c);
+      error("Progeny cell counts don't add up.");
+    }
+  }
+}
+
+/**
+ * @brief Runs a series of checks to make sure we have no bad particles.
+ */
+
+void engine_check(struct engine *e) {
+  /* Check all particles directly. */
+  struct space *s = e->s;
+  for (int k = 0; k < s->nr_parts; k++) {
+    if (engine_check_part(&s->parts[k])) {
+      error("Bad particle s->parts[%i], aborting.", k);
+    }
+  }
+
+  /* Check each cell in the space. */
+  space_map_cells_post(s, 1, &engine_check_cell, NULL);
+}
+
 /**
  * @brief Link a density/force task to a cell.
  *
@@ -1720,6 +1793,7 @@ void hassorted(struct cell *c) {
  *
  * @param e The #engine.
  */
+
 void engine_step(struct engine *e) {
 
   int k;
@@ -1733,6 +1807,11 @@ void engine_step(struct engine *e) {
 
   TIMER_TIC2
 
+  if (e->policy & engine_policy_paranoid) {
+    message("Checking system sanity...");
+    engine_check(e);
+  }
+
   /* Get the maximum dt. */
   if (e->policy & engine_policy_multistep) {
     dt_step = 2.0f * dt;
@@ -1766,6 +1845,11 @@ void engine_step(struct engine *e) {
   //   printParticle(parts, k);
   // printParticle( e->s->parts , 3392063069037 , e->s->nr_parts );
 
+  if (e->policy & engine_policy_paranoid) {
+    message("Checking system sanity...");
+    engine_check(e);
+  }
+
   /* Re-distribute the particles amongst the nodes? */
   if ( e->forcerepart )
     engine_repartition( e );
@@ -1775,6 +1859,11 @@ void engine_step(struct engine *e) {
     engine_check(e);
   }
 
+  if (e->policy & engine_policy_paranoid) {
+    message("Checking system sanity...");
+    engine_check(e);
+  }
+
   /* Prepare the space. */
   engine_prepare(e);
 
@@ -1792,6 +1881,11 @@ void engine_step(struct engine *e) {
                     (1 << task_type_grav_up) | (1 << task_type_grav_down) |
                     (1 << task_type_link));
 
+  if (e->policy & engine_policy_paranoid) {
+    message("Checking system sanity...");
+    engine_check(e);
+  }
+
   TIMER_TOC(timer_runners);
 
   // engine_single_force( e->s->dim , 8328423931905 , e->s->parts ,
diff --git a/src/engine.h b/src/engine.h
index 65aa028401..caa286e7d3 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -41,6 +41,7 @@
 #define engine_policy_cputight 64
 #define engine_policy_mpi 128
 #define engine_policy_setaffinity 256
+#define engine_policy_paranoid 512
 
 #define engine_queue_scale 1.2
 #define engine_maxtaskspercell 128
diff --git a/src/space.c b/src/space.c
index eeb42f328f..157850080b 100644
--- a/src/space.c
+++ b/src/space.c
@@ -844,7 +844,7 @@ static void rec_map_cells_post(struct cell *c, int full,
 }
 
 /**
- * @brief Map a function to all particles in a aspace.
+ * @brief Map a function to all particles in a space.
  *
  * @param s The #space we are working in.
  * @param full Map to all cells, including cells with sub-cells.
-- 
GitLab