From 61aedaecffe6fd3743daf4ff3e77f8534b161e0d Mon Sep 17 00:00:00 2001
From: d74ksy <aidan.chalk@durham.ac.uk>
Date: Mon, 2 Nov 2015 10:43:43 +0000
Subject: [PATCH] BH completed, can now output particle data, compute exact
 interaction and use plot.py to compute error

---
 examples/plot.py       |  26 ++++-----
 examples/test_bh_mpi.c | 129 +++++++++++++++++++++++++++++++++++++++--
 src/qsched.c           |  21 ++++---
 3 files changed, 151 insertions(+), 25 deletions(-)

diff --git a/examples/plot.py b/examples/plot.py
index 941a33f..ce4c28b 100644
--- a/examples/plot.py
+++ b/examples/plot.py
@@ -37,19 +37,19 @@ import os
 print "Plotting..."
 
 # Read Quickshed accelerations
-data=loadtxt("particle_dump.dat")
+data=loadtxt("particle_dump.out")
 id = data[:,0]
-accx_e=data[:,5]
-accy_e=data[:,6]
-accz_e=data[:,7]
+accx_e=data[:,4]
+accy_e=data[:,5]
+accz_e=data[:,6]
 
-accx_bh=data[:,8]
-accy_bh=data[:,9]
-accz_bh=data[:,10]
+accx_bh=data[:,7]
+accy_bh=data[:,8]
+accz_bh=data[:,9]
 
-accx_new=data[:,11]
-accy_new=data[:,12]
-accz_new=data[:,13]
+accx_new=data[:,10]
+accy_new=data[:,11]
+accz_new=data[:,12]
 
 # Sort accelerations
 rank = argsort(id)
@@ -127,7 +127,7 @@ plot(id, errx_new , 'b.')
 text(id[-1], 0.18, "B-H: $%5.3f\\pm%5.3f$\n QuickShed: $%5.3f\\pm%5.3f$"%(meanx_bh, stdx_bh, meanx_new, stdx_new), backgroundcolor="w", va="top", ha="right" )
 
 
-ylim(-0.2, 0.2)
+ylim(-2, 2)
 xlim(0,id[-1])
 grid()
 
@@ -138,7 +138,7 @@ plot(id, erry_new , 'b.')
 text(id[-1], 0.18, "B-H: $%5.3f\\pm%5.3f$\n QuickShed: $%5.3f\\pm%5.3f$"%(meany_bh, stdy_bh, meany_new, stdy_new), backgroundcolor="w", va="top", ha="right" )
 
 
-ylim(-0.2, 0.2)
+ylim(-0.02, 0.02)
 xlim(0,id[-1])
 
 grid()
@@ -150,7 +150,7 @@ plot(id, errz_bh , 'rx', label="Legacy")
 #text(id[-1], 0.18, "B-H: $%5.3f\\pm%5.3f$\n QuickShed: $%5.3f\\pm%5.3f$"%(meanz_bh, stdz_bh, meanz_new, stdz_new), backgroundcolor="w", va="top", ha="right" )
 legend(loc="upper right")
 
-ylim(-0.2, 0.2)
+ylim(-0.02, 0.02)
 xlim(0,id[-1])
 grid()
 
diff --git a/examples/test_bh_mpi.c b/examples/test_bh_mpi.c
index 20e2c35..aff0302 100644
--- a/examples/test_bh_mpi.c
+++ b/examples/test_bh_mpi.c
@@ -35,6 +35,7 @@
 
 /* Local includes. */
 #include "quicksched.h"
+#include "res.h"
 
 /* Some local constants. */
 #define cell_pool_grow 1000
@@ -48,6 +49,7 @@
 #define SANITY_CHECKS
 #define NO_COM_AS_TASK
 #define NO_COUNTERS
+#define EXACT
 
 
 
@@ -57,8 +59,13 @@ struct part {
   union {
     float a[3];
     float a_legacy[3];
+    #ifndef EXACT
     float a_exact[3];
+    #endif
   };
+    #ifdef EXACT
+    float a_exact[3];
+    #endif
   float mass;
   int id;
 };  // __attribute__((aligned(32)));
@@ -992,20 +999,103 @@ void create_tasks(struct qsched *s, struct cell *ci, struct cell *cj) {
   }   /* Otherwise it's a pair */
 }
 
+inline int getindex(long long int id, struct qsched *s){
+    return id;
+}
 
 
+/**
+ * @brief Solve the particle interactions using the stupid N^2 algorithm
+ *
+ * @param N The number of particles
+ * @param parts The array of particles
+ */
+void interact_exact(int N, struct part *parts) {
 
+  int i, j, k;
+  float ir, w, r2, dx[3];
 
+  /* Loop over all particles. */
+  for (i = 0; i < N; ++i) {
 
+    /* Some things to store locally. */
+    double pix[3] = {parts[i].x[0], parts[i].x[1], parts[i].x[2]};
+    float mi = parts[i].mass;
 
+    /* Loop over every other particle. */
+    for (j = i + 1; j < N; ++j) {
 
+      /* Compute the pairwise distance. */
+      for (r2 = 0.0, k = 0; k < 3; k++) {
+        dx[k] = parts[j].x[k] - pix[k];
+        r2 += dx[k] * dx[k];
+      }
 
+      /* Apply the gravitational acceleration. */
+      ir = 1.0f / sqrtf(r2);
+      w = const_G * ir * ir * ir;
 
+      for (k = 0; k < 3; k++) {
+        float wdx = w * dx[k];
+        parts[j].a_exact[k] -= wdx * mi;
+        parts[i].a_exact[k] += wdx * parts[j].mass;
+      }
+    }
+  }
 
+#if ICHECK >= 0
+ /* for (i = 0; i < N; ++i)
+    if (parts[i].id == monitor)
+      message("[check] exact acceleration for particle %d a= %.3e %.3e %.3e\n",
+              parts[i].id, parts[i].a_exact[0], parts[i].a_exact[1],
+              parts[i].a_exact[2]);*/
+#endif
+}
 
-
-
-
+void output_parts(struct qsched *s)
+{
+    int i, j;
+    FILE *file;
+    file = fopen("particle_dump.out", "a");
+    for(i = 0; i < s->res_ranks[s->count_ranks]; i++)
+    {
+        /* We want to find particle resources, which are locked only. */
+        if(s->res[i].node == s->rank && s->res[i].num_lockers > 0)
+        {
+            struct res *resource = &s->res[i];
+            int parent_output = 0;
+            while(resource->parent > 0)
+            {
+                if( s->res[getindex(resource->parent, s)].num_lockers > 0)
+                {
+                    parent_output = 1;
+                    break;
+                }
+                resource = &s->res[getindex(resource->parent, s)];   
+            }
+            /* If we didn't output any of the parents then we need to output this guy.*/
+            if(!parent_output)
+            {
+                struct part *parts = qsched_getresdata(s, s->res[i].ID);
+                if(parts == NULL)
+                {
+                    message("Failed to output parts");
+                    fclose(file);
+                    return;
+                }
+                int count = s->res[i].size / sizeof(struct part);
+                for(j = 0; j < count; j++)
+                {   
+                    struct part cur = parts[j];
+                    fprintf(file, "%i %e %e %e %e %e %e %e %e %e %e %e %e %e\n", cur.id, cur.mass, cur.x[0], cur.x[1], cur.x[2], 
+                            cur.a_exact[0], cur.a_exact[1], cur.a_exact[2], cur.a_legacy[0], cur.a_legacy[1], cur.a_legacy[2], cur.a[0], cur.a[1], cur.a[2]);
+                }
+            }
+        }
+    }
+    fclose(file);
+    message("Output parts correctly");
+}
 
 
 
@@ -1024,7 +1114,7 @@ void create_tasks(struct qsched *s, struct cell *ci, struct cell *cj) {
  */
 void test_bh(int N, int nr_threads, int runs, char *fileName) {
 
-  int k;
+  int i, k;
   struct cell *root = NULL;
   struct part *parts;
   qsched_res_t parts_res;
@@ -1154,6 +1244,15 @@ if(s.rank == 0)
 }
    qsched_sync_resources(&s);
 
+#ifdef EXACT
+    if(s.rank == 0)
+    {
+        interact_exact(N, parts);
+    }
+
+    MPI_Barrier(s.comm);
+#endif
+
 if(s.rank == 0)
 {
     create_tasks(&s, root, NULL);
@@ -1166,6 +1265,28 @@ qsched_run_MPI(&s, nr_threads, runner);
     printf("Hello world from processor %s, rank = %i, count_ranks = %i\n",
            processor_name, s.rank, s.count_ranks);
 
+if(s.rank == 0)
+{
+    file = fopen("particle_dump.out", "w");
+  fprintf(file,
+          "ID m x y z a_exact.x   a_exact.y    a_exact.z    a_legacy.x    "
+          "a_legacy.y    a_legacy.z    a_new.x     a_new.y    a_new.z\n");
+    fclose(file);
+}
+
+//Output the parts:
+for(i = 0; i < s.count_ranks; i++)
+{
+    //If it is our turn to output parts.
+    if(s.rank == i)
+    {
+        output_parts(&s);
+    }
+    MPI_Barrier(s.comm);
+}
+
+//Need to clean up everything.
+
     // Finalize the MPI environment.
     MPI_Finalize();
 }
diff --git a/src/qsched.c b/src/qsched.c
index 25a9261..0b88d3f 100644
--- a/src/qsched.c
+++ b/src/qsched.c
@@ -858,10 +858,10 @@ void qsched_partition_compute_costs( struct qsched *s, idx_t *res_costs)
             res_costs[getindex(t->locks[j],s)] += t->cost;
         }
 
-        /*for(j = 0; j < t->nr_uses; j++)
+        for(j = 0; j < t->nr_uses; j++)
         {
-            res_costs[getindex(t->uses[j],s)] = t->cost;
-        }*/
+            res_costs[getindex(t->uses[j],s)] += 1;
+        }
     }   
 }
 
@@ -884,14 +884,14 @@ void qsched_partition_build_nodelist(struct qsched *s, idx_t *nodelist, long lon
     for(i = 0; i < s->res_ranks[s->count_ranks]; i++)
     {
         //If the resources is locked (or used).
-        if(s->res[i].num_lockers > 0 /*|| s->res[i].num_users > 0*/){
+        if(s->res[i].num_lockers > 0 || s->res[i].num_users > 0){
             
             r = &s->res[i];
             //If it has a parent.
             if(r->parent != -1)
             {
                 //If the parent is locked then we don't need this.
-                if(s->res[getindex(r->parent,s)].num_lockers > 0 /*|| s->res[getindex(r->parent,s)].num_users > 0*/)
+                if(s->res[getindex(r->parent,s)].num_lockers > 0 || s->res[getindex(r->parent,s)].num_users > 0)
                 {
                     noderef[node_count] = -1;
                     continue;
@@ -901,7 +901,7 @@ void qsched_partition_build_nodelist(struct qsched *s, idx_t *nodelist, long lon
                     while(r->parent != -1)
                     {
                         r = getres(r->parent, s);
-                        if(r->num_lockers > 0 /*|| r->num_users > 0*/)
+                        if(r->num_lockers > 0 || r->num_users > 0)
                         {
                             noderef[node_count] = 0;
                             break;
@@ -1544,6 +1544,7 @@ void tsched_free(struct tsched *ts) {
 
 long long int tsched_addtask ( struct tsched *ts , int type , unsigned int flags , void *data , int data_size , int cost ){
 
+static int i = 0;
 void *temp;
     struct task *t;
     long long int id;
@@ -1619,7 +1620,9 @@ void *temp;
     ts->count += 1;
     
     t->node = ts->rank;
-     
+    i++;
+    if(i % 1000 == 0)
+        message("Added %i send/recv tasks", i/2);
     /* Return the task ID. */
     return id;
 
@@ -2967,7 +2970,7 @@ for(i = 0; i < node_count; i++)
         options[ METIS_OPTION_CONTIG ] = 0; //TODO 1
         options[ METIS_OPTION_NCUTS ] = 10;
         options[ METIS_OPTION_NITER ] = 10;
-        options[ METIS_OPTION_UFACTOR ] = 30;
+        options[ METIS_OPTION_UFACTOR ] = 300;
         options[ METIS_OPTION_SEED ] = 359872345;
     
         idx_t one = 1;
@@ -3441,6 +3444,8 @@ printf("Rank[%i]: qsched_prepare_mpi took %lli (= %e) ticks\n", s->rank,
 
         printf("Rank[%i]: Execution took %lli (= %e) ticks\n", s->rank,
          toc - tic, (float)(toc - tic));
+
+    MPI_Barrier(s->comm);
 #else
     error( "QuickSched was not compiled with OpenMP support." );
 #endif
-- 
GitLab