From f891f45dd2c8948d3d667bd375b1d2091db24cc3 Mon Sep 17 00:00:00 2001
From: Chris Maffeo <cmaffeo2@illinois.edu>
Date: Mon, 4 Jan 2016 11:37:23 -0600
Subject: [PATCH] code appears to work; much to be done; force evaluation,
 integration need to be tested

---
 Configuration.cpp      |   5 ++
 Random.h               |   2 +-
 RandomCPU.h            | 200 +++++++++++++++++++++++++++++++++++++++++
 RigidBody.cu           |   2 +
 RigidBody.h            |   5 +-
 RigidBodyController.cu |   9 +-
 RigidBodyController.h  |   4 +-
 RigidBodyType.cu       |  31 +++----
 RigidBodyType.h        |   3 +-
 notes.org              |   7 ++
 10 files changed, 242 insertions(+), 26 deletions(-)
 create mode 100644 RandomCPU.h

diff --git a/Configuration.cpp b/Configuration.cpp
index 01278da..3a75992 100644
--- a/Configuration.cpp
+++ b/Configuration.cpp
@@ -792,6 +792,11 @@ int Configuration::readParameters(const char * config_file) {
 			printf("WARNING: Unrecognized keyword `%s'.\n", param.val());
 		}
 	}
+
+	// extra configuration for RB types
+	for (int i = 0; i < numRigidTypes; i++)
+		rigidBody[i].setDampingCoeffs(timestep);
+	
 	return numParams;
 }
 Vector3 Configuration::stringToVector3(String s) {
diff --git a/Random.h b/Random.h
index 378a09d..4dcd231 100644
--- a/Random.h
+++ b/Random.h
@@ -154,7 +154,7 @@ public:
         v1 = 2.0 * uniform() - 1.0;
         v2 = 2.0 * uniform() - 1.0;
         r = v1*v1 + v2*v2;
-				printf("r %f", r);
+				// printf("r %f", r);
       }
       fac = sqrt(-2.0 * log(r)/r);
       // now make the Box-Muller transformation to get two normally
diff --git a/RandomCPU.h b/RandomCPU.h
new file mode 100644
index 0000000..c8d3b9b
--- /dev/null
+++ b/RandomCPU.h
@@ -0,0 +1,200 @@
+/**
+***  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000 by
+***  The Board of Trustees of the University of Illinois.
+***  All rights reserved.
+**/
+
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––.
+| Redundant with Random.h but with RandomCPU class since Random class is also |
+| declared in RandomCUDA.h, and I want to use both for rigidBody code         |
+`––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
+// RBTODO: make Random.h include RandomCPU.h and "typedef" this class
+
+#ifndef RANDOM_CPU_H
+#define RANDOM_CPU_H
+
+#ifdef __CUDACC__
+#define HOST __host__
+#define DEVICE __device__
+#else
+#define HOST 
+#define DEVICE 
+#endif
+
+#include "common.h"
+#include "useful.h"
+
+#ifdef _MSC_VER
+#define INT64_LITERAL(X) X ## i64
+#else
+#define INT64_LITERAL(X) X ## LL
+#endif
+
+#define	RAND48_SEED   INT64_LITERAL(0x00001234abcd330e)
+#define	RAND48_MULT   INT64_LITERAL(0x00000005deece66d)
+#define	RAND48_ADD    INT64_LITERAL(0x000000000000000b)
+#define RAND48_MASK   INT64_LITERAL(0x0000ffffffffffff)
+
+class RandomCPU {
+
+private:
+
+	float second_gaussian;
+  int64 second_gaussian_waiting;
+  int64 rand48_seed;
+  int64 rand48_mult;
+  int64 rand48_add;
+
+public:
+
+  // default constructor
+  RandomCPU(void) {
+    init(0);
+    rand48_seed = RAND48_SEED;
+  }
+
+  // constructor with seed
+  RandomCPU(unsigned long seed) {
+    init(seed);
+  }
+
+  // reinitialize with seed
+  HOST DEVICE inline void init(unsigned long seed) {
+    second_gaussian = 0;
+    second_gaussian_waiting = 0;
+    rand48_seed = seed & INT64_LITERAL(0x00000000ffffffff);
+    rand48_seed = rand48_seed << 16;
+    rand48_seed |= RAND48_SEED & INT64_LITERAL(0x0000ffff);
+    rand48_mult = RAND48_MULT;
+    rand48_add = RAND48_ADD;
+    print("INIT\n");
+  }
+
+  HOST DEVICE inline void print(char* string)
+		{
+			printf(string);
+			printf("RAND48_SEED = %d, RAND48_MULT = %d, RAND48_ADD = %d, RAND48_MASK = %d\n", RAND48_SEED, RAND48_MULT, RAND48_ADD, RAND48_MASK);
+			printf("rand48_seed = %d, rand48_mult = %d, rand48_add = %d\n", rand48_seed, rand48_mult, rand48_add);
+		}
+
+  // advance generator by one (seed = seed * mult + add, to 48 bits)
+  HOST DEVICE inline void skip(void) {
+    rand48_seed = ( rand48_seed * rand48_mult + rand48_add ) & RAND48_MASK;
+  }
+
+  // split into numStreams different steams and take stream iStream
+  void split(int iStream, int numStreams) {
+    int i;
+
+    // make sure that numStreams is odd to ensure maximum period
+    numStreams |= 1;
+
+    // iterate to get to the correct stream
+    for ( i = 0; i < iStream; ++i ) skip();
+
+    // save seed and add so we can use skip() for our calculations
+    int64 save_seed = rand48_seed;
+
+    // calculate c *= ( 1 + a + ... + a^(numStreams-1) )
+    rand48_seed = rand48_add;
+    for ( i = 1; i < numStreams; ++i ) skip();
+    int64 new_add = rand48_seed;
+
+    // calculate a = a^numStreams
+    rand48_seed = rand48_mult;
+    rand48_add  = 0;
+    for ( i = 1; i < numStreams; ++i ) skip();
+    rand48_mult = rand48_seed;
+
+    rand48_add  = new_add;
+    rand48_seed = save_seed;
+
+    second_gaussian = 0;
+    second_gaussian_waiting = 0;
+    print("END SPLIT\n");
+  }
+
+  // return a number uniformly distributed between 0 and 1
+  HOST DEVICE inline BigReal uniform(void) {
+    skip();
+    const float exp48 = ( 1.0 / (float)(INT64_LITERAL(1) << 48) );
+    return ( (float) rand48_seed * exp48 );
+  }
+
+  long poisson(BigReal lambda) {
+    const BigReal l = exp(-lambda);
+    long k = 0;
+    BigReal p = uniform();
+    
+    while (p >= l) {
+      p *= uniform();
+      k = k + 1;
+    }
+
+    return k;
+  }
+
+  // return a number from a standard gaussian distribution
+  HOST DEVICE inline BigReal gaussian(void) {
+    BigReal fac, r, v1, v2;
+
+    if (second_gaussian_waiting) {
+      second_gaussian_waiting = 0;
+      return second_gaussian;
+    } else {
+      r = 2.;                 // r >= 1.523e-8 ensures abs result < 6
+      while (r >=1. || r < 1.523e-8) { // make sure we are within unit circle
+        v1 = 2.0 * uniform() - 1.0;
+        v2 = 2.0 * uniform() - 1.0;
+        r = v1*v1 + v2*v2;
+				// printf("r %f\n", r);
+      }
+      fac = sqrt(-2.0 * log(r)/r);
+      // now make the Box-Muller transformation to get two normally
+      // distributed random numbers. Save one and return the other.
+      second_gaussian_waiting = 1;
+      second_gaussian = v1 * fac;
+      return v2 * fac;
+    }
+
+  }
+
+  // return a vector of gaussian random numbers
+  HOST DEVICE inline Vector3 gaussian_vector(void) {
+    return Vector3( gaussian(), gaussian(), gaussian() );
+  }
+
+  // return a random long
+  HOST DEVICE inline long integer(void) {
+    skip();
+    return ( ( rand48_seed >> 17 ) & INT64_LITERAL(0x000000007fffffff) );
+  }
+
+  // randomly order an array of whatever
+  template <class Elem> void reorder(Elem *a, int n) {
+    for ( int i = 0; i < (n-1); ++i ) {
+      int ie = i + ( integer() % (n-i) );
+      if ( ie == i ) continue;
+      const Elem e = a[ie];
+      a[ie] = a[i];
+      a[i] = e;
+    }
+  }
+
+};
+
+#endif  // RANDOM_CPU_H
+
diff --git a/RigidBody.cu b/RigidBody.cu
index 01739b8..9a4b1a4 100644
--- a/RigidBody.cu
+++ b/RigidBody.cu
@@ -92,6 +92,8 @@ void RigidBody::integrate(int startFinishAll) {
 	Vector3 trans; // = *p_trans;
 	Matrix3 rot = Matrix3(1); // = *p_rot;
 
+	printf("Rigid Body force\n");
+	
 #ifdef DEBUGM
 	switch (startFinishAll) {
 	case 0: // start
diff --git a/RigidBody.h b/RigidBody.h
index cebbf0f..46c827a 100644
--- a/RigidBody.h
+++ b/RigidBody.h
@@ -42,7 +42,8 @@ class RigidBody { // host side representation of rigid bodies
 	// HOST DEVICE void integrate(Vector3& old_trans, Matrix3& old_rot, int startFinishAll);
 	HOST DEVICE void integrate(int startFinishAll);
 	
-	HOST DEVICE inline String getKey() const { return key; }
+	// HOST DEVICE inline String getKey() const { return key; }
+	HOST DEVICE inline String getKey() const { return t->name; }
 
 	HOST DEVICE inline Vector3 getPosition() const { return position; }
 	HOST DEVICE inline Matrix3 getOrientation() const { return orientation; }
@@ -78,7 +79,7 @@ private:
 	// integration
 	const Configuration* c;
 	RigidBodyType* t;					/* RBTODO: const? */
-	int timestep;
+	float timestep;					
 	Vector3 force;  // lab frame
 	Vector3 torque; // lab frame (except in integrate())
 
diff --git a/RigidBodyController.cu b/RigidBodyController.cu
index 1fe941d..253ec54 100644
--- a/RigidBodyController.cu
+++ b/RigidBodyController.cu
@@ -13,7 +13,7 @@
 // #include <vector>
 #include "Debug.h"
 
-#include "Random.h"							/* RBTODO: fix this? */
+#include "RandomCPU.h"							/* RBTODO: fix this? */
 
 #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
 inline void gpuAssert(cudaError_t code, String file, int line, bool abort=true) {
@@ -46,7 +46,7 @@ RigidBodyController::RigidBodyController(const Configuration& c, const char* out
 		rigidBodyByType.push_back(tmp);
 	}
 
-	random = new Random(conf.seed + 1); /* +1 to avoid using same seed as RandomCUDA */
+	random = new RandomCPU(conf.seed + 1); /* +1 to avoid using same seed as RandomCUDA */
 	
 	initializeForcePairs();
 }
@@ -151,6 +151,7 @@ void RigidBodyController::integrate(int step) {
 			RigidBody& rb = rigidBodyByType[i][j];
 			
 			// thermostat
+			// rb.addLangevin( random->gaussian_vector(), random->gaussian_vector() );
 			rb.addLangevin( random->gaussian_vector(), random->gaussian_vector() );
 		}
 	}
@@ -387,7 +388,7 @@ void RigidBodyController::print(int step) {
 					printf("Error opening RigidBody trajectory file %s",fname);
 					exit(1);
 	      }
-	      trajFile << "# NAMD RigidBody trajectory file" << std::endl;
+	      trajFile << "# RigidBody trajectory file" << std::endl;
 	      printLegend(trajFile);
 			}
 			printData(step,trajFile);
@@ -417,7 +418,7 @@ void RigidBodyController::print(int step) {
 	      printf("Error opening rigid body restart file %s",fname);
 	      exit(1); // NAMD_err(err_msg);
 			}
-			restartFile << "# NAMD rigid body restart file" << std::endl;
+			restartFile << "# RigidBody restart file" << std::endl;
 			printLegend(restartFile);
 			printData(step,restartFile);
 			if (!restartFile) {
diff --git a/RigidBodyController.h b/RigidBodyController.h
index 79ed18b..5bfde4e 100644
--- a/RigidBodyController.h
+++ b/RigidBodyController.h
@@ -8,7 +8,7 @@
 #define NUMTHREADS 256
 
 class Configuration;
-class Random;
+class RandomCPU;
 
 class RigidBodyForcePair  {
 	friend class RigidBodyController;
@@ -87,7 +87,7 @@ private:
 	const Configuration& conf;
 	const char* outArg;
 	
-	Random* random;
+	RandomCPU* random;
 	/* RequireReduction *gridReduction; */
 	
 	Vector3* trans; // would have made these static, but
diff --git a/RigidBodyType.cu b/RigidBodyType.cu
index eca2b46..2d9ae68 100644
--- a/RigidBodyType.cu
+++ b/RigidBodyType.cu
@@ -1,7 +1,7 @@
 #include "RigidBodyType.h"
 
 void RigidBodyType::clear() {
-	num = 0;											// TODO: not 100% sure about this
+	num = 0;											// RBTODO: not 100% sure about this
 	if (reservoir != NULL) delete reservoir;
 	reservoir = NULL;
 	// pmf = NULL;
@@ -59,19 +59,17 @@ void RigidBodyType::clear() {
 // }
 
 
-void RigidBodyType::setDampingCoeffs(float timestep, float tmp_mass, Vector3 tmp_inertia, float tmp_transDamping, float tmp_rotDamping) {
-	mass = tmp_mass;
-	inertia = tmp_inertia;
-	/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––.
+// void RigidBodyType::setDampingCoeffs(float timestep, float tmp_mass, Vector3 tmp_inertia, float tmp_transDamping, float tmp_rotDamping) {
+void RigidBodyType::setDampingCoeffs(float timestep) { /* MUST ONLY BE CALLED ONCE!!! */
+	/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––.
 	| DiffCoeff = kT / dampingCoeff mass                     |
-	|                                                          |
+	|                                                        |
 	| type->DampingCoeff has units of (1/ps)                 |
-	|                                                          |
+	|                                                        |
 	| f[kcal/mol AA] = - dampingCoeff * momentum[amu AA/fs]  |
-	|                                                          |
+	|                                                        |
 	| units "(1/ps) * (amu AA/fs)" "kcal_mol/AA" * 2.3900574 |
-	`–––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
-	transDamping = 2.3900574 * tmp_transDamping;
+	`–––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
 
 	/*––––––––––––––––––––––––––––––––––––––––––––––––––––.
 	| < f(t) f(t') > = 2 kT dampingCoeff mass delta(t-t') |
@@ -79,19 +77,22 @@ void RigidBodyType::setDampingCoeffs(float timestep, float tmp_mass, Vector3 tmp
 	|  units "sqrt( k K (1/ps) amu / fs )" "kcal_mol/AA"  |
 	|    * 0.068916889                                    |
 	`––––––––––––––––––––––––––––––––––––––––––––––––––––*/
-	float Temp = 295;								/* RBTODO: Fix!!!! */
-	transForceCoeff = 0.068916889 * Vector3::element_sqrt( 2*Temp*mass*tmp_transDamping/timestep );
+	float Temp = 295; /* RBTODO: temperature should be read from grid? Or set in uniformly in config file */
+	transForceCoeff = 0.068916889 * Vector3::element_sqrt( 2*Temp*mass*transDamping/timestep );
 
 	// setup for langevin
 	// langevin = rbParams->langevin;
 	// if (langevin) {
 	// T = - dampingCoeff * angularMomentum
-	rotDamping = 2.3900574 * tmp_rotDamping;
 
 	// < f(t) f(t') > = 2 kT dampingCoeff inertia delta(t-t')
 	rotTorqueCoeff = 0.068916889 *
-		Vector3::element_sqrt( 2*Temp* Vector3::element_mult(inertia,tmp_rotDamping) / timestep );
-	//  }
+		Vector3::element_sqrt( 2*Temp* Vector3::element_mult(inertia,rotDamping) / timestep );
+
+
+	transDamping = 2.3900574 * transDamping;
+	rotDamping = 2.3900574 * rotDamping;
+		
 }
 
 void RigidBodyType::addPotentialGrid(String s) {
diff --git a/RigidBodyType.h b/RigidBodyType.h
index 04eb55a..707b3d1 100644
--- a/RigidBodyType.h
+++ b/RigidBodyType.h
@@ -38,8 +38,7 @@ RigidBodyType(const String& name = "") :
   void addPotentialGrid(String s);
 	void addDensityGrid(String s);
 	void updateRaw();
-	void setDampingCoeffs(float timestep, float tmp_mass, Vector3 tmp_inertia,
-												 float tmp_transDamping, float tmp_rotDamping);
+	void setDampingCoeffs(float timestep);
 	
 public:
 
diff --git a/notes.org b/notes.org
index 28b02e9..b64defb 100644
--- a/notes.org
+++ b/notes.org
@@ -2,6 +2,13 @@
 ** make rigid body object device pointer
 ** branch rb-device: have RBType objects hold device pointers for raw RigidBodyGrids
 
+* TODO eventually
+** read restart file
+** multiple "PMF" grids associated with each RB type
+** each RB gets temperature from grid
+** optionally don't eval forces every ts
+
+
 
 * organization
 ** RgidBodyController (RBC) holds device pointers, manages force evaluation and integration
-- 
GitLab