From a07ceae20245b64c46e95998b64461684b292900 Mon Sep 17 00:00:00 2001
From: Chris Maffeo <cmaffeo2@illinois.edu>
Date: Wed, 19 Oct 2016 11:08:16 -0500
Subject: [PATCH] Fixed issues with coordinate wrapping during integration;
 improved implementation of select matrix operations

---
 BaseGrid.h         | 63 ++++++++++++++++++++-------------
 ComputeForce.cuh   |  4 +--
 Configuration.cpp  |  4 +++
 Configuration.h    |  1 +
 GrandBrownTown.cuh | 20 +++++------
 RigidBody.cu       | 31 ++++++++---------
 notes.org          | 12 +------
 useful.cu          | 78 -----------------------------------------
 useful.h           | 86 +++++++++++++++++++++++++++++++++++++---------
 9 files changed, 139 insertions(+), 160 deletions(-)

diff --git a/BaseGrid.h b/BaseGrid.h
index 4eca85d..3df015c 100644
--- a/BaseGrid.h
+++ b/BaseGrid.h
@@ -644,6 +644,14 @@ public:
 	}
 
   // Wrap coordinate: 0 <= x < l
+  HOST DEVICE   inline int quotient(float x, float l) const {
+#ifdef __CUDA_ARCH__
+	  return int(floorf( __fdividef(x,l) ));
+#else
+	  return int(floor(x/l));
+#endif
+  }
+
   HOST DEVICE inline float wrapFloat(float x, float l) const {
 		int image = int(floor(x/l));
 		x -= image*l;
@@ -651,14 +659,7 @@ public:
   }
   
   // Wrap distance: -0.5*l <= x < 0.5*l
-	DEVICE static inline float d_wrapDiff(float x, float l) {
-		// int image = int(floor(x/l));
-		int image = int(floorf( __fdividef(x,l) ));
-		x -= image*l;
-		x = (x >= 0.5f * l) ? x-l : x;
-		return x;
-  }
-	HOST DEVICE static inline float wrapDiff(float x, float l) {
+  HOST DEVICE static inline float wrapDiff(float x, float l) {
 		int image = int(floor(x/l));
 		x -= image*l;
 		if (x >= 0.5f * l)
@@ -666,15 +667,39 @@ public:
 		return x;
   }
 
+  // TODO: implement simpler approach when basis is diagonal
+  // TODO: implement device version using __fdividef and floorf
+  // TODO: make BaseGrid an abstract class that diagGrid and nonDiagGrid inherit from 
+  // TODO: test wrap and wrapDiff for non-diagonal basis
   // Wrap vector, 0 <= x < lx  &&  0 <= y < ly  &&  0 <= z < lz
   HOST DEVICE inline Vector3 wrap(Vector3 r) const {
-    Vector3 l = basisInv.transform(r - origin);
-    l.x = wrapFloat(l.x, nx);
-    l.y = wrapFloat(l.y, ny);
-    l.z = wrapFloat(l.z, nz);
-    return basis.transform(l) + origin;
+	Vector3 l = basisInv.transform(r - origin);
+	if ( basis.isDiagonal() ) {
+		r = r - Vector3(quotient(l.x,nx) * nx*basis.exx,
+						quotient(l.y,ny) * ny*basis.eyy,
+						quotient(l.z,nz) * nz*basis.ezz);
+	} else {
+		r = r - quotient(l.x,nx) * nx*basis.ex();
+		r = r - quotient(l.y,ny) * ny*basis.ey();
+		r = r - quotient(l.z,nz) * nz*basis.ez();
+	}
+	return r;
   }
-	
+
+  HOST DEVICE inline Vector3 wrapDiff(Vector3 r) const {
+	Vector3 l = basisInv.transform(r);
+	if ( basis.isDiagonal() ) {
+		r = r - Vector3(quotient(l.x+0.5f*nx,nx) * nx*basis.exx,
+						quotient(l.y+0.5f*ny,ny) * ny*basis.eyy,
+						quotient(l.z+0.5f*nz,nz) * nz*basis.ezz);
+	} else {
+		r = r - quotient(l.x+0.5f*nx,nx) * nx*basis.ex();
+		r = r - quotient(l.y+0.5f*ny,ny) * ny*basis.ey();
+		r = r - quotient(l.z+0.5f*nz,nz) * nz*basis.ez();
+	}
+	return r;
+  }
+  
   // Wrap vector distance, -0.5*l <= x < 0.5*l  && ...
   /* HOST DEVICE inline Vector3 wrapDiff(Vector3 r) const { */
   /*   Vector3 l = basisInv.transform(r); */
@@ -683,21 +708,13 @@ public:
   /*   l.z = wrapDiff(l.z, nz); */
   /*   return basis.transform(l); */
   /* } */
-  HOST DEVICE inline Vector3 wrapDiff(Vector3 r) const {
+  HOST DEVICE inline Vector3 wrapDiffOrig(Vector3 r) const {
     Vector3 l = basisInv.transform(r);
     l.x = wrapDiff(l.x, nx);
     l.y = wrapDiff(l.y, ny);
     l.z = wrapDiff(l.z, nz);
     return basis.transform(l);
   }
-  DEVICE inline Vector3 d_wrapDiff(Vector3 r) const {
-		Vector3 l = basisInv.transform(r);
-    l.x = d_wrapDiff(l.x, nx);
-    l.y = d_wrapDiff(l.y, ny);
-    l.z = d_wrapDiff(l.z, nz);
-    return basis.transform(l);
-  }
-
   Vector3 wrapDiffNearest(Vector3 r) const;
 
   // Includes the home node.
diff --git a/ComputeForce.cuh b/ComputeForce.cuh
index d9fe31b..906b169 100644
--- a/ComputeForce.cuh
+++ b/ComputeForce.cuh
@@ -471,7 +471,7 @@ __global__ void computeTabulatedKernel(
 	 	/* printf("tid,bid,pos[ai(%d)]: %d %d %f %f %f\n", ai, threadIdx.x, blockIdx.x, pos[ai].x, pos[ai].y, pos[ai].z); //*/
 
 		Vector3 dr = pos[aj] - pos[ai];
-		dr = sys->d_wrapDiff(dr);
+		dr = sys->wrapDiff(dr);
 	
     // Calculate the force based on the tabulatedPotential file
 		float d2 = dr.length2();
@@ -502,7 +502,7 @@ __global__ void computeTabulatedEnergyKernel(Vector3* force, const Vector3* __re
 
 		// RBTODO: implement wrapDiff2, returns dr2 (???)
 		Vector3 dr = pos[aj] - pos[ai];
-		dr = sys->d_wrapDiff(dr);
+		dr = sys->wrapDiff(dr);
     // Calculate the force based on the tabulatedPotential file
 		float d2 = dr.length2();
 		/* RBTODO: filter tabpot particles ahead of time */
diff --git a/Configuration.cpp b/Configuration.cpp
index 42b9f27..a52b56b 100644
--- a/Configuration.cpp
+++ b/Configuration.cpp
@@ -649,6 +649,10 @@ int Configuration::readParameters(const char * config_file) {
 		else if (param == String("kT"))
 			kT = (float) strtod(value.val(), NULL);
 		// else if (param == String("kTGridFile")) kTGridFile = value;
+		else if (param == String("temperature")) {
+			temperature =  (float) strtod(value.val(),NULL);
+			kT = 0.58622522f * temperature / 295.0f; // kcal/mol (units "295 k K" "kcal_mol")
+		}
 		else if (param == String("temperatureGrid"))
 			temperatureGrid = value;
 		else if (param == String("numberFluct"))
diff --git a/Configuration.h b/Configuration.h
index 9d23bb8..7fc75f1 100644
--- a/Configuration.h
+++ b/Configuration.h
@@ -128,6 +128,7 @@ public:
 	int tabulatedPotential;
 	int fullLongRange;
 	float kT;
+	float temperature;
 	float coulombConst;
 	float electricField;
 	float cutoff;
diff --git a/GrandBrownTown.cuh b/GrandBrownTown.cuh
index 736970e..157978d 100644
--- a/GrandBrownTown.cuh
+++ b/GrandBrownTown.cuh
@@ -82,6 +82,7 @@ void updateKernel(Vector3* pos, Vector3* __restrict__ forceInternal,
 																								 0.5*pt.diffusionGrid->nz)); 
 		Vector3 p2 = p - gridCenter;
 		p2 = sys->wrapDiff( p2 ) + gridCenter;
+			
 		/* p2 = sys->wrap( p2 ); */
 		/* p2 = p2 - gridCenter; */
 		/* printf("atom %d: ps2: %f %f %f\n", idx, p2.x, p2.y, p2.z); */
@@ -90,20 +91,20 @@ void updateKernel(Vector3* pos, Vector3* __restrict__ forceInternal,
 			diffusion = diff.e;
 			diffGrad = diff.f;
 		}
+
+		// if (idx == 0) {
+		// 	printf("force: "); force.print();
+		// }
 		
-		/* printf("atom %d: pos: %f %f %f\n", idx, p.x, p.y, p.z); */
-		/* printf("atom %d: force: %f %f %f\n", idx, force.x, force.y, force.z); */
-		/* printf("atom %d: kTlocal, diffusion, timestep: %f, %f, %f\n", */
-		/* 			 idx, kTlocal, diffusion, timestep); */
 		Vector3 tmp = step(p, kTlocal, force, diffusion, -diffGrad, timestep, sys, randoGen, num);
-		assert( tmp.length() < 10000.0f );
+		// assert( tmp.length() < 10000.0f );
 		pos[idx] = tmp;
 			
 	}
 }
 
 __device__
-Vector3 step(Vector3 r0, float kTlocal, Vector3 force, float diffusion,
+inline Vector3 step(Vector3 r0, float kTlocal, Vector3 force, float diffusion,
 						 Vector3 diffGrad, float timestep, BaseGrid *sys,
 						 Random *randoGen, int num) {
 	const int idx = blockIdx.x * blockDim.x + threadIdx.x;
@@ -111,16 +112,11 @@ Vector3 step(Vector3 r0, float kTlocal, Vector3 force, float diffusion,
 	Vector3 rando = randoGen->gaussian_vector(idx, num);
 
 	diffusion *= timestep;
-	
 	Vector3 r = r0 + (diffusion / kTlocal) * force
 							+ timestep * diffGrad
 							+ sqrtf(2.0f * diffusion) * rando;
 	// Wrap about periodic boundaries
-	Vector3 l = sys->getInverseBasis().transform(r - sys->getOrigin());
-	l.x = sys->wrapFloat(l.x, sys->getNx());
- 	l.y = sys->wrapFloat(l.y, sys->getNy());
- 	l.z = sys->wrapFloat(l.z, sys->getNz());
-	return sys->getBasis().transform(l) + sys->getOrigin();
+	return sys->wrap(r);
 }
 
 __global__ void devicePrint(RigidBodyType* rb[]) {
diff --git a/RigidBody.cu b/RigidBody.cu
index b18be2a..bd614d1 100644
--- a/RigidBody.cu
+++ b/RigidBody.cu
@@ -98,8 +98,8 @@ void RigidBody::integrate(int startFinishAll) {
 
 	if (startFinishAll == 0 || startFinishAll == 1) {
 		// propogate momenta by half step
-		momentum += 0.5 * timestep * force * impulse_to_momentum;
-		angularMomentum += 0.5 * timestep * orientation.transpose()*torque * impulse_to_momentum;
+		momentum += 0.5f * timestep * force * impulse_to_momentum;
+		angularMomentum += 0.5f * timestep * (orientation.transpose()*torque) * impulse_to_momentum;
 	} else {
 		// propogate momenta by a full timestep
 		momentum += timestep * force * impulse_to_momentum;
@@ -156,33 +156,30 @@ Matrix3 RigidBody::Rx(BigReal t) {
 	BigReal cos = (1-qt)/(1+qt);
 	BigReal sin = t/(1+qt);
 
-	Matrix3 tmp;
-	tmp.exx = 1; tmp.exy =   0; tmp.exz =    0;
-	tmp.eyx = 0; tmp.eyy = cos; tmp.eyz = -sin;
-	tmp.ezx = 0; tmp.ezy = sin; tmp.ezz =  cos;
-	return tmp;
+	return Matrix3(
+		1.0f, 0.0f, 0.0f,
+		0.0f,  cos, -sin,
+		0.0f,  sin,  cos);
 }
 Matrix3 RigidBody::Ry(BigReal t) {
 	BigReal qt = 0.25*t*t;  // for approximate calculations of sin(t) and cos(t)
 	BigReal cos = (1-qt)/(1+qt);
 	BigReal sin = t/(1+qt);
 
-	Matrix3 tmp;
-	tmp.exx =  cos; tmp.exy = 0; tmp.exz = sin;
-	tmp.eyx =    0; tmp.eyy = 1; tmp.eyz =   0;
-	tmp.ezx = -sin; tmp.ezy = 0; tmp.ezz = cos;
-	return tmp;
+	return Matrix3(
+		cos,  0.0f,  sin,
+		0.0f, 1.0f, 0.0f,
+		-sin, 0.0f,  cos);
 }
 Matrix3 RigidBody::Rz(BigReal t) {
 	BigReal qt = 0.25*t*t;  // for approximate calculations of sin(t) and cos(t)
 	BigReal cos = (1-qt)/(1+qt);
 	BigReal sin = t/(1+qt);
 
-	Matrix3 tmp;
-	tmp.exx = cos; tmp.exy = -sin; tmp.exz = 0;
-	tmp.eyx = sin; tmp.eyy =  cos; tmp.eyz = 0;
-	tmp.ezx =   0; tmp.ezy =    0; tmp.ezz = 1;
-	return tmp;
+	return Matrix3(
+		cos,  -sin, 0.0f,
+		sin,   cos, 0.0f,
+		0.0f, 0.0f, 1.0f);
 }
 Matrix3 RigidBody::eulerToMatrix(const Vector3 e) {
 	// convert euler angle input to rotation matrix
diff --git a/notes.org b/notes.org
index 4ba69a8..c748a8d 100644
--- a/notes.org
+++ b/notes.org
@@ -1,16 +1,6 @@
 
 * TODO active
-
-** re-implement exclusions
-how should this be done?
-
-*** in-thread approach, with particles i,j?
- 1) Look at whether i*j is in an array? --> potentially very memory intensive; could run out of integers!
- 2) Look at find i,j in array? --> potentially slow
- 3) Look at 
-*** post-pairlist filtering step
-
-
+** Fix wrapping routines (trouble with machine precision
 
 ** make units and kT more uniform (references to 295 K are hardcoded into RB code and Temperature code) 
 *** I would prefer to specify temperature in K, rather than specifying a scaling factor to be applied to all energies to make them kT
diff --git a/useful.cu b/useful.cu
index 9e1a118..b729cac 100644
--- a/useful.cu
+++ b/useful.cu
@@ -410,54 +410,6 @@ Matrix3::Matrix3(const float* d) {
 	setIsDiag();
 }	
 
-const Matrix3 Matrix3::operator*(float s) const {
-	Matrix3 m;
-	m.exx = s*exx;
-	m.exy = s*exy;
-	m.exz = s*exz;
-	m.eyx = s*eyx;
-	m.eyy = s*eyy;
-	m.eyz = s*eyz;
-	m.ezx = s*ezx;
-	m.ezy = s*ezy;
-	m.ezz = s*ezz;
-	m.isDiag = isDiag;
-	return m;
-}
-
-
-const Matrix3 Matrix3::operator*(const Matrix3& m) const {
-	Matrix3 ret;
-	ret.exx = exx*m.exx + exy*m.eyx + exz*m.ezx;
-	ret.eyx = eyx*m.exx + eyy*m.eyx + eyz*m.ezx;
-	ret.ezx = ezx*m.exx + ezy*m.eyx + ezz*m.ezx;
-
-	ret.exy = exx*m.exy + exy*m.eyy + exz*m.ezy;
-	ret.eyy = eyx*m.exy + eyy*m.eyy + eyz*m.ezy;
-	ret.ezy = ezx*m.exy + ezy*m.eyy + ezz*m.ezy;
-
-	ret.exz = exx*m.exz + exy*m.eyz + exz*m.ezz;
-	ret.eyz = eyx*m.exz + eyy*m.eyz + eyz*m.ezz;
-	ret.ezz = ezx*m.exz + ezy*m.eyz + ezz*m.ezz;
-	ret.setIsDiag();
-	return ret;
-}
-
-const Matrix3 Matrix3::operator-() const {
-	Matrix3 m;
-	m.exx = -exx;
-	m.exy = -exy;
-	m.exz = -exz;
-	m.eyx = -eyx;
-	m.eyy = -eyy;
-	m.eyz = -eyz;
-	m.ezx = -ezx;
-	m.ezy = -ezy;
-	m.ezz = -ezz;
-	m.isDiag = isDiag;
-	return m;
-}
-
 Matrix3 Matrix3::inverse() const {
 	Matrix3 m;
 	if (isDiag) {
@@ -483,11 +435,6 @@ float Matrix3::det() const {
 		exx*(eyy*ezz-eyz*ezy) - exy*(eyx*ezz-eyz*ezx) + exz*(eyx*ezy-eyy*ezx);
 }
 
-
-Vector3 Matrix3::ex() const { return Vector3(exx,eyx,ezx); }
-Vector3 Matrix3::ey() const { return Vector3(exy,eyy,ezy); }
-Vector3 Matrix3::ez() const { return Vector3(exz,eyz,ezz); }
-
 String Matrix3::toString() const {
 	char s[128];
 	sprintf(s, "%2.8f %2.8f %2.8f\n%2.8f %2.8f %2.8f\n%2.8f %2.8f %2.8f",
@@ -502,31 +449,6 @@ String Matrix3::toString1() const {
 	return String(s);
 }
 
-Matrix3 operator*(float s, Matrix3 m) { 
-	m.exx *= s;
-	m.exy *= s;
-	m.exz *= s;
-	m.eyx *= s;
-	m.eyy *= s;
-	m.eyz *= s;
-	m.ezx *= s;
-	m.ezy *= s;
-	m.ezz *= s;
-	return m;
-}
-
-Matrix3 operator/(Matrix3 m, float s) {
-	m.exx /= s;
-	m.exy /= s;
-	m.exz /= s;
-	m.eyx /= s;
-	m.eyy /= s;
-	m.eyz /= s;
-	m.ezx /= s;
-	m.ezy /= s;
-	m.ezz /= s;
-	return m;
-}
 
 // class IndexList
 // A growable list of integers.
diff --git a/useful.h b/useful.h
index 75a5d78..02f0e52 100644
--- a/useful.h
+++ b/useful.h
@@ -26,6 +26,7 @@ bool isInt(char c);
 
 int firstSpace(const char* s, int max);
 
+
 /*class int2 {
 public:
 	int2(int x, int y) : x(x), y(y) {}
@@ -235,6 +236,10 @@ public:
 		return ret;
 	}
 
+	HOST DEVICE inline void print() {
+		// printf("%0.3f %0.3f %0.3f\n", x,y,z);
+		printf("%0.12f %0.12f %0.12f\n", x,y,z);
+	}
 	
 	String toString() const;
 	float x, y, z;
@@ -257,6 +262,9 @@ HOST DEVICE inline Vector3 operator/(Vector3 v, float s) {
 // class Matrix3
 // Operations on 3D float matrices
 class Matrix3 {
+	friend class TrajectoryWriter;
+	friend class BaseGrid;
+	friend class RigidBodyController; /* for trajectory writing */
 public:
 	HOST DEVICE inline Matrix3() {}
 	HOST DEVICE Matrix3(float s);
@@ -265,13 +273,57 @@ public:
 	Matrix3(const Vector3& ex, const Vector3& ey, const Vector3& ez);
 	Matrix3(const float* d);
 
-	const Matrix3 operator*(float s) const;
 
-	HOST DEVICE	const Vector3 operator*(const Vector3& v) const	{ return this->transform(v); }
+	// Operators 
+	HOST DEVICE inline const Matrix3 operator*(float s) const {
+		Matrix3 m;
+		m.exx = s*exx; m.exy = s*exy; m.exz = s*exz;
+		m.eyx = s*eyx; m.eyy = s*eyy; m.eyz = s*eyz;
+		m.ezx = s*ezx; m.ezy = s*ezy; m.ezz = s*ezz;
+		m.isDiag = isDiag;
+		return m;
+	}
+	HOST DEVICE friend inline Matrix3 operator*(float s, Matrix3 m) { return m*s; }
+	HOST DEVICE friend inline Matrix3 operator/(Matrix3 m, float s) {
+		m.exx /= s; m.exy /= s; m.exz /= s;
+		m.eyx /= s;	m.eyy /= s;	m.eyz /= s;
+		m.ezx /= s;	m.ezy /= s;	m.ezz /= s;
+		return m;
+	}
 
-	const Matrix3 operator*(const Matrix3& m) const;
+	HOST DEVICE inline const Vector3 operator*(const Vector3& v) const	{ return this->transform(v); }
 
-	const Matrix3 operator-() const;
+	HOST DEVICE inline Matrix3 operator*(const Matrix3& m) const {
+		Matrix3 ret;
+		ret.exx = exx*m.exx + exy*m.eyx + exz*m.ezx;
+		ret.eyx = eyx*m.exx + eyy*m.eyx + eyz*m.ezx;
+		ret.ezx = ezx*m.exx + ezy*m.eyx + ezz*m.ezx;
+
+		ret.exy = exx*m.exy + exy*m.eyy + exz*m.ezy;
+		ret.eyy = eyx*m.exy + eyy*m.eyy + eyz*m.ezy;
+		ret.ezy = ezx*m.exy + ezy*m.eyy + ezz*m.ezy;
+
+		ret.exz = exx*m.exz + exy*m.eyz + exz*m.ezz;
+		ret.eyz = eyx*m.exz + eyy*m.eyz + eyz*m.ezz;
+		ret.ezz = ezx*m.exz + ezy*m.eyz + ezz*m.ezz;
+		ret.setIsDiag();
+		return ret;
+	}
+	
+	HOST DEVICE inline Matrix3 operator-() const {
+		Matrix3 m;
+		m.exx = -exx;
+		m.exy = -exy;
+		m.exz = -exz;
+		m.eyx = -eyx;
+		m.eyy = -eyy;
+		m.eyz = -eyz;
+		m.ezx = -ezx;
+		m.ezy = -ezy;
+		m.ezz = -ezz;
+		m.isDiag = isDiag;
+		return m;
+	}
 
 	HOST DEVICE inline Matrix3 transpose() const {
 		Matrix3 m;
@@ -288,11 +340,6 @@ public:
 		return m;
 	}
 
-	HOST DEVICE
-	Matrix3 inverse() const;
-
-	float det() const;
-
 	HOST DEVICE inline Vector3 transform(const Vector3& v) const {
 		Vector3 w;
 		if (isDiag) {
@@ -307,7 +354,6 @@ public:
 		return w;
 	}
 
-
 	HOST DEVICE inline Matrix3 transform(const Matrix3& m) const {
 		Matrix3 ret;
 		ret.exx = exx*m.exx + exy*m.eyx + exz*m.ezx;
@@ -325,6 +371,12 @@ public:
 		return ret;
 	}
 
+	
+	HOST DEVICE
+	Matrix3 inverse() const;
+
+	float det() const;
+
 	HOST DEVICE void setIsDiag() {
 		isDiag = (exy == 0 && exz == 0 &&
 							eyx == 0 && eyz == 0 &&
@@ -333,14 +385,17 @@ public:
 	
 
 	
-	Vector3 ex() const;
-	Vector3 ey() const;
-	Vector3 ez() const;
-
+	HOST DEVICE inline Vector3 ex() const { return Vector3(exx,eyx,ezx); }
+	HOST DEVICE inline Vector3 ey() const { return Vector3(exy,eyy,ezy); }
+	HOST DEVICE inline Vector3 ez() const { return Vector3(exz,eyz,ezz); }
 	String toString() const;
 
 	String toString1() const;
 
+	HOST DEVICE inline bool isDiagonal() const { return isDiag; }
+	
+	
+private:
 	float exx, exy, exz;
 	float eyx, eyy, eyz;
 	float ezx, ezy, ezz;
@@ -348,9 +403,6 @@ public:
 
 };
 
-Matrix3 operator*(float s, Matrix3 m);
-Matrix3 operator/(Matrix3 m, float s);
-
 // class IndexList
 // A growable list of integers.
 class IndexList {
-- 
GitLab