From 61a869c38ba300ca850b7c2bbfa981ac3a23a63c Mon Sep 17 00:00:00 2001
From: James Willis <james.s.willis@durham.ac.uk>
Date: Wed, 27 Jun 2018 16:25:10 +0100
Subject: [PATCH] Added engine policy to run FOF search with command line
 argument 'u'. Run FOF search on the same steps that a snapshot is dumped.

---
 examples/main.c | 21 +++++++++++++++++++--
 src/engine.c    | 31 +++++++++++++++++++------------
 src/engine.h    |  8 ++++++--
 3 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/examples/main.c b/examples/main.c
index 1992e903f9..61e39aae77 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -190,6 +190,7 @@ int main(int argc, char *argv[]) {
   int with_self_gravity = 0;
   int with_hydro = 0;
   int with_stars = 0;
+  int with_fof = 0;
   int with_fp_exceptions = 0;
   int with_drift_all = 0;
   int with_mpole_reconstruction = 0;
@@ -205,7 +206,7 @@ int main(int argc, char *argv[]) {
 
   /* Parse the parameters */
   int c;
-  while ((c = getopt(argc, argv, "acCdDef:FgGhMn:o:P:rsSt:Tv:y:Y:")) != -1)
+  while ((c = getopt(argc, argv, "acCdDef:FgGhMn:o:P:rsSt:Tuv:y:Y:")) != -1)
     switch (c) {
       case 'a':
 #if defined(HAVE_SETAFFINITY) && defined(HAVE_LIBNUMA)
@@ -295,6 +296,9 @@ int main(int argc, char *argv[]) {
       case 'T':
         with_verbose_timers = 1;
         break;
+      case 'u':
+        with_fof = 1;
+        break;
       case 'v':
         if (sscanf(optarg, "%d", &verbose) != 1) {
           if (myrank == 0) printf("Error parsing verbosity level (-v).\n");
@@ -371,6 +375,14 @@ int main(int argc, char *argv[]) {
     if (myrank == 0) print_help_message();
     return 1;
   }
+  if (with_fof && !with_external_gravity && !with_self_gravity) {
+    if (myrank == 0)
+      printf(
+          "Error: Cannot perform FOF search without gravity, -g or -G must be "
+          "chosen.\n");
+    if (myrank == 0) print_help_message();
+    return 1;
+  }
 
 /* Let's pin the main thread, now we know if affinity will be used. */
 #if defined(HAVE_SETAFFINITY) && defined(HAVE_LIBNUMA) && defined(_GNU_SOURCE)
@@ -822,9 +834,10 @@ int main(int argc, char *argv[]) {
     if (with_cooling) engine_policies |= engine_policy_cooling;
     if (with_sourceterms) engine_policies |= engine_policy_sourceterms;
     if (with_stars) engine_policies |= engine_policy_stars;
+    if (with_fof) engine_policies |= engine_policy_fof;
 
     /* Initialise the FOF parameters. */
-    fof_init(&s, N_total[0], N_total[1]);
+    if (with_fof) fof_init(&s, N_total[0], N_total[1]);
       
     /* Initialize the engine with the space and policies. */
     if (myrank == 0) clocks_gettime(&tic);
@@ -896,6 +909,10 @@ int main(int argc, char *argv[]) {
     /* Write the state of the system before starting time integration. */
     engine_dump_snapshot(&e);
     engine_print_stats(&e);
+  
+    /* Perform first FOF search after the first snapshot dump. */
+    if (e.policy & engine_policy_fof) fof_search_tree(&s);
+
   }
 
   /* Legend */
diff --git a/src/engine.c b/src/engine.c
index f018688e3f..b97376a7e1 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -104,7 +104,8 @@ const char *engine_policy_names[] = {"none",
                                      "reconstruct multi-poles",
                                      "cooling",
                                      "sourceterms",
-                                     "stars"};
+                                     "stars",
+                                     "fof search"};
 
 /** The rank of the engine as a global variable (for messages). */
 int engine_rank;
@@ -4361,16 +4362,6 @@ void engine_init_particles(struct engine *e, int flag_entropy_ICs,
   space_init_parts(s, e->verbose);
   space_init_gparts(s, e->verbose);
 
-  message("Performing Friends Of Friends search.");
-
-
-  ticks tic = getticks();
-  fof_search_tree(s);
-  message("Serial tree FOF search took: %.3f %s.",
-          clocks_from_ticks(getticks() - tic), clocks_getunit());
-
-  message("Friends Of Friends search finished.");
-
   /* Now, launch the calculation */
   TIMER_TIC;
   engine_launch(e);
@@ -4665,10 +4656,14 @@ void engine_step(struct engine *e) {
   if (e->ti_end_min >= e->ti_next_snapshot && e->ti_next_snapshot > 0)
     e->dump_snapshot = 1;
 
+  /* Do we want to perform a FOF search? */
+  if ((e->policy & engine_policy_fof) && e->dump_snapshot)
+    e->run_fof = 1;
+
   /* Drift everybody (i.e. what has not yet been drifted) */
   /* to the current time */
   int drifted_all =
-      (e->dump_snapshot || e->forcerebuild || e->forcerepart || e->save_stats);
+      (e->dump_snapshot || e->forcerebuild || e->forcerepart || e->save_stats || e->run_fof);
   if (drifted_all) engine_drift_all(e);
 
   /* Write a snapshot ? */
@@ -4681,6 +4676,17 @@ void engine_step(struct engine *e) {
     engine_compute_next_snapshot_time(e);
   }
 
+  /* Perform a FOF search. */
+  if(e->run_fof) {
+    
+    ticks tic = getticks();
+    fof_search_tree(e->s);
+    message("FOF search took: %.3f %s.",
+        clocks_from_ticks(getticks() - tic), clocks_getunit());
+
+    e->run_fof = 0;
+  }
+
   /* Save some  statistics */
   if (e->save_stats) {
 
@@ -5586,6 +5592,7 @@ void engine_config(int restart, struct engine *e, struct swift_params *params,
   e->restart_file = restart_file;
   e->restart_next = 0;
   e->restart_dt = 0;
+  e->run_fof = 0;
   engine_rank = nodeID;
 
   /* Get the number of queues */
diff --git a/src/engine.h b/src/engine.h
index 044bf6c895..48464b9e69 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -70,9 +70,10 @@ enum engine_policy {
   engine_policy_reconstruct_mpoles = (1 << 12),
   engine_policy_cooling = (1 << 13),
   engine_policy_sourceterms = (1 << 14),
-  engine_policy_stars = (1 << 15)
+  engine_policy_stars = (1 << 15),
+  engine_policy_fof = (1 << 16)
 };
-#define engine_maxpolicy 15
+#define engine_maxpolicy 16
 extern const char *engine_policy_names[];
 
 /**
@@ -217,6 +218,9 @@ struct engine {
   struct unit_system *snapshot_units;
   int snapshot_output_count;
 
+  /* FOF information */
+  int run_fof;
+
   /* Statistics information */
   double a_first_statistics;
   double time_first_statistics;
-- 
GitLab