From 7095f6afaf81d1db7c1db328a985eb0258a37a1a Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Tue, 2 Jan 2018 12:39:27 -0600 Subject: [PATCH] HYC: Updated configuration to allow choice of integrator, and input of initial momentum; uses gsl --- src/Configuration.cpp | 395 +++++++++++++++++++++++++++++++++++++----- src/Configuration.h | 21 ++- 2 files changed, 370 insertions(+), 46 deletions(-) diff --git a/src/Configuration.cpp b/src/Configuration.cpp index df7d842..ef07616 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -2,9 +2,13 @@ #include "Angle.h" #include "Dihedral.h" #include "Restraint.h" - +#include <cmath> #include <cassert> - +#include <stdlib.h> /* srand, rand */ +#include <time.h> /* time */ +#include <gsl/gsl_rng.h> +#include <gsl/gsl_randist.h> +#include <gsl/gsl_math.h> #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true) { @@ -58,23 +62,53 @@ Configuration::Configuration(const char* config_file, int simNum, bool debug) : // Allocate particle variables. pos = new Vector3[num * simNum]; - type = new int[num * simNum]; + //Han-Yi Chou + if (ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + momentum = new Vector3[num * simNum]; + + type = new int[num * simNum]; serial = new int[num * simNum]; posLast = new Vector3[num * simNum]; + //Han-Yi Chou + if(ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + momLast = new Vector3[num * simNum]; name = new String[num * simNum]; currSerial = 0; // Now, load the coordinates loadedCoordinates = false; + loadedMomentum = false; //Han-Yi Chou + //I need kT here Han-Yi Chou + kT = temperature * 0.0019872065f; // `units "k K" "kcal_mol"` + //kT = temperature * 0.593f; // If we have a restart file - use it if (restartCoordinates.length() > 0) { - loadRestart(restartCoordinates.val()); + loadRestart(restartCoordinates.val()); printf("Loaded %d restart coordinates from `%s'.\n", num, restartCoordinates.val()); printf("Particle numbers specified in the configuration file will be ignored.\n"); loadedCoordinates = true; - } else { + //Han-Yi Chou Langevin dynamic + if (ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + { + if (restartMomentum.length() > 0) + { + loadRestartMomentum(restartMomentum.val()); + printf("Loaded %d restart momentum from `%s'.\n", num, restartMomentum.val()); + printf("Particle numbers specified in the configuration file will be ignored.\n"); + loadedMomentum = true; + } + else + { + printf("Warning: There is no restart momentum file when using restart coordinates in Langevin Dynamics\n"); + printf("Initialize with Boltzmann distribution\n"); + loadedMomentum = Boltzmann(COM_Velocity, num * simNum); + } + } + } + else + { // Load coordinates from a file? if (numPartsFromFile > 0) { loadedCoordinates = true; @@ -91,29 +125,59 @@ Configuration::Configuration(const char* config_file, int simNum, bool debug) : currType = j; for (int s = 0; s < simNum; ++s) - type[i + s*num] = currType; + type[i + s*num] = currType; serial[i] = currSerial++; - pos[i] = Vector3(atof(tokenList[3].val()), - atof(tokenList[4].val()), - atof(tokenList[5].val())); + pos[i] = Vector3(atof(tokenList[3].val()), atof(tokenList[4].val()), atof(tokenList[5].val())); + //Han-Yi Chou + if (ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + { + loadedMomentum = true; + if(numTokens == 9) + momentum[i] = Vector3(atof(tokenList[6].val()), atof(tokenList[7].val()), atof(tokenList[8].val())); + else + { + printf("Error occurs in %s at line %d. Please specify momentum\n", __FILE__, __LINE__); + assert(1==2); + } + } } delete[] partsFromFile; partsFromFile = NULL; - } else { - // Not loading coordinates from a file - populate(); - if (inputCoordinates.length() > 0) { - printf("Loading coordinates from %s ... ", inputCoordinates.val()); - loadedCoordinates = loadCoordinates(inputCoordinates.val()); - if (loadedCoordinates) - printf("done!\n"); - } - } - } - - + //Han-Yi Chou + for(int i = 1; i < simNum; ++i) + for(int j = 0; j < num; ++j) + serial[j + num * i] = currSerial++; + } + else + { + // Not loading coordinates from a file + populate(); + if (inputCoordinates.length() > 0) + { + printf("Loading coordinates from %s ... ", inputCoordinates.val()); + loadedCoordinates = loadCoordinates(inputCoordinates.val()); + if (loadedCoordinates) + printf("done!\n"); + } + if(ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + { + if (inputMomentum.length() > 0) + { + printf("Loading momentum from %s ... ", inputMomentum.val()); + loadedMomentum = loadMomentum(inputMomentum.val()); + if (loadedMomentum) + printf("done!\n"); + } + else + loadedMomentum = Boltzmann(COM_Velocity, num * simNum); + } + } + } + //Check initialize momentum + //if(ParticleDynamicType == String("Langevin")) + //PrintMomentum(); /* Initialize exclusions */ excludeCapacity = 256; numExcludes = 0; @@ -125,7 +189,6 @@ Configuration::Configuration(const char* config_file, int simNum, bool debug) : if (readDihedralsFromFile) readDihedrals(); if (readRestraintsFromFile) readRestraints(); - kT = temperature * 0.0019872065f; // `units "k K" "kcal_mol"` if (temperatureGridFile.length() != 0) { printf("\nFound temperature grid file: %s\n", temperatureGridFile.val()); tGrid = new BaseGrid(temperatureGridFile.val()); @@ -368,12 +431,21 @@ Configuration::Configuration(const char* config_file, int simNum, bool debug) : if (fullLongRange != 0) printf("No cell decomposition created.\n"); + } Configuration::~Configuration() { // System state delete[] pos; + //Han-Yi Chou + if (ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + delete[] momentum; + delete[] posLast; + //Han-Yi Chou + if (ParticleDynamicType == String("Langevin") || ParticleDynamicType == String("NoseHooverLangevin")) + delete[] momLast; + delete[] type; delete[] name; @@ -541,6 +613,9 @@ void Configuration::setDefaults() { inputCoordinates = ""; restartCoordinates = ""; + //Han-Yi Chou + inputMomentum = ""; + restartMomentum = ""; copyReplicaCoordinates = 1; numberFluct = 0; numberFluctPeriod = 200; @@ -589,6 +664,12 @@ void Configuration::setDefaults() { numRestraints = 0; restraints = NULL; + //Han-Yi Chou default values + ParticleDynamicType = String("Brown"); + RigidBodyDynamicType = String("Brown"); + COM_Velocity = Vector3(0.f,0.f,0.f); + ParticleLangevinIntegrator = String("BAOAB"); //The default is BAOAB + // Hidden parameters // Might be parameters later numCapFactor = 5; @@ -675,6 +756,12 @@ int Configuration::readParameters(const char * config_file) { inputCoordinates = value; else if (param == String("restartCoordinates")) restartCoordinates = value; + + //Han-Yi Chou + else if (param == String("inputMomentum")) + inputMomentum = value; + else if (param == String("restartMomentum")) + restartMomentum = value; else if (param == String("copyReplicaCoordinates")) copyReplicaCoordinates = atoi(value.val()); else if (param == String("temperature")) @@ -713,11 +800,22 @@ int Configuration::readParameters(const char * config_file) { numCap = atoi(value.val()); else if (param == String("decompPeriod")) decompPeriod = atoi(value.val()); + + //Han-Yi Chou + else if (param == String("ParticleDynamicType")) + ParticleDynamicType = value; + else if (param == String("RigidBodyDynamicType")) + RigidBodyDynamicType = value; + else if (param == String("ParticleLangevinIntegrator")) + ParticleLangevinIntegrator = value; + // PARTICLES else if (param == String("particle")) { part[++currPart] = BrownianParticleType(value); currPartClass = partClassPart; } + else if (param == String("mu")) // for Nose-Hoover Langevin + part[currPart].mu = (float) strtod(value.val(), NULL); else if (param == String("forceXGridFile")) partForceXGridFile[currPart] = value; else if (param == String("forceYGridFile")) @@ -823,18 +921,18 @@ int Configuration::readParameters(const char * config_file) { } else if (param == String("rigidBodyPotential")) { partRigidBodyGrid[currPart].push_back(value); } + //Han-Yi Chou initial COM velocity for total particles + else if (param == String("COM_Velocity")) + COM_Velocity = stringToVector3(value); + // RIGID BODY else if (param == String("rigidBody")) { // part[++currPart] = BrownianParticleType(value); rigidBody[++currRB] = RigidBodyType(value, this); currPartClass = partClassRB; } - else if (param == String("mass")) - rigidBody[currRB].mass = (float) strtod(value.val(), NULL); else if (param == String("inertia")) rigidBody[currRB].inertia = stringToVector3( value ); - else if (param == String("transDamping")) - rigidBody[currRB].transDamping = stringToVector3( value ); else if (param == String("rotDamping")) rigidBody[currRB].rotDamping = stringToVector3( value ); @@ -852,6 +950,10 @@ int Configuration::readParameters(const char * config_file) { rigidBody[currRB].initPos = stringToVector3( value ); else if (param == String("orientation")) rigidBody[currRB].initRot = stringToMatrix3( value ); + else if (param == String("momentum")) + rigidBody[currRB].initMomentum = stringToVector3(value); + else if (param == String("angularMomentum"))//for angular momentum, serve as restart purpose + rigidBody[currRB].initAngularMomentum = stringToVector3(value); else if (param == String("inputRBCoordinates")) inputRBCoordinates = value; @@ -862,6 +964,23 @@ int Configuration::readParameters(const char * config_file) { else if (currPartClass == partClassRB) rigidBody[currRB].num = atoi(value.val()); } + //set mass here Han-Yi Chou + else if (param == String("mass")) + { + if(currPartClass == partClassPart) + part[currPart].mass = (float) strtod(value.val(),NULL); + else if (currPartClass == partClassRB) + rigidBody[currRB].mass = (float) strtod(value.val(),NULL); + } + //set damping here, using anisotropic damping, i.e. data type Vector3 Han-Yi Chou + else if (param == String("transDamping")) + { + if(currPartClass == partClassPart) + part[currPart].transDamping = stringToVector3(value); + else if (currPartClass == partClassRB) + rigidBody[currRB].transDamping = stringToVector3(value); + + } else if (param == String("gridFile")) { if (currPartClass == partClassPart) partGridFile[currPart] = value; @@ -878,9 +997,33 @@ int Configuration::readParameters(const char * config_file) { // extra configuration for RB types for (int i = 0; i < numRigidTypes; i++) rigidBody[i].setDampingCoeffs(timestep); - + + //For debugging purpose Han-Yi Chou + //Print(); return numParams; } +//Han-Yi Chou +void Configuration::Print() +{ + printf("The dynamic type for particle is %s \n", ParticleDynamicType.val()); + for(int i = 0; i < numParts; ++i) + { + printf("The type %d has mass %f \n", i,part[i].mass); + printf("The diffusion coefficient is %f \n", part[i].diffusion); + printf("The translational damping is %f %f %f \n", part[i].transDamping.x, part[i].transDamping.y, part[i].transDamping.z); + } + printf("Done with check for Langevin"); + //assert(1==2); +} + +void Configuration::PrintMomentum() +{ + for(int i = 0; i < num; ++i) + { + printf("%f %f %f\n", momentum[i].x, momentum[i].y, momentum[i].z); + } + //assert(1==2); +} Vector3 Configuration::stringToVector3(String s) { // tokenize and return int numTokens = s.tokenCount(); @@ -1453,20 +1596,22 @@ void Configuration::readRestraints() { // std::sort(restraints, restraints + numRestraints, compare()); } - +//populate the type list and serial list void Configuration::populate() { - int pn = 0; - int p = 0; - - for (int i = 0; i < num; i++) { - for (int s = 0; s < simNum; ++s) - type[i + s*num] = p; - serial[i] = currSerial++; - if (++pn >= part[p].num) { - p++; - pn = 0; - } - } + for (int repID = 0; repID < simNum; ++repID) { + const int offset = repID * num; + int pn = 0; + int p = 0; + for (int i = 0; i < num; ++i) { + type[i + offset] = p; + serial[i + offset] = currSerial++; + + if (++pn >= part[p].num) { + p++; + pn = 0; + } + } + } } bool Configuration::readBondFile(const String& value, int currBond) { @@ -1531,7 +1676,7 @@ bool Configuration::readDihedralFile(const String& value, int currDihedral) { return true; } - +//Load the restart coordiantes only void Configuration::loadRestart(const char* file_name) { char line[STRLEN]; FILE* inp = fopen(file_name, "r"); @@ -1585,6 +1730,73 @@ void Configuration::loadRestart(const char* file_name) { fclose(inp); } +//Han-Yi Chou +//First the resart coordinates should be loaded +void Configuration::loadRestartMomentum(const char* file_name) +{ + char line[STRLEN]; + FILE* inp = fopen(file_name, "r"); + + if (inp == NULL) + { + printf("GrandBrownTown:loadRestart File `%s' does not exist\n", file_name); + exit(-1); + } + if(!loadedCoordinates) + { + printf("First load the restart coordinates\n"); + assert(1==2); + } + int count = 0; + while (fgets(line, STRLEN, inp) != NULL) + { + // Ignore comments. + int len = strlen(line); + if (line[0] == '#') continue; + if (len < 2) continue; + + String s(line); + int numTokens = s.tokenCount(); + if (numTokens != 4) + { + printf("GrandBrownTown:loadRestart Invalid momentum file line: %s\n", line); + fclose(inp); + exit(-1); + } + + String* tokenList = new String[numTokens]; + s.tokenize(tokenList); + if (tokenList == NULL) + { + printf("GrandBrownTown:loadRestart Invalid momentum file line: %s\n", line); + fclose(inp); + exit(-1); + } + + int typ = atoi(tokenList[0]); + float x = (float) strtod(tokenList[1],NULL); + float y = (float) strtod(tokenList[2],NULL); + float z = (float) strtod(tokenList[3],NULL); + + if (typ < 0 || typ >= numParts) + { + printf("GrandBrownTown:countRestart Invalid particle type : %d\n", typ); + fclose(inp); + exit(-1); + } + + if(typ != type[count]) + { + printf("Inconsistent in momentum file with the position file\n"); + fclose(inp); + exit(-1); + } + momentum[count] = Vector3(x,y,z); + ++count; + delete[] tokenList; + } + fclose(inp); +} bool Configuration::loadCoordinates(const char* file_name) { char line[STRLEN]; @@ -1637,6 +1849,66 @@ bool Configuration::loadCoordinates(const char* file_name) { } return true; } +//Han-Yi Chou The function populate should be called before entering this function +bool Configuration::loadMomentum(const char* file_name) +{ + char line[STRLEN]; + FILE* inp = fopen(file_name, "r"); + + if (inp == NULL) + return false; + + int count = 0; + while (fgets(line, STRLEN, inp) != NULL) + { + // Ignore comments. + int len = strlen(line); + if (line[0] == '#') + continue; + if (len < 2) + continue; + + String s(line); + int numTokens = s.tokenCount(); + if (numTokens != 3) + { + printf("ERROR: Invalid momentum file line: %s\n", line); + fclose(inp); + return false; + } + + String* tokenList = new String[numTokens]; + s.tokenize(tokenList); + if (tokenList == NULL) + { + printf("ERROR: Invalid momentum file line: %s\n", line); + fclose(inp); + return false; + } + + if (count >= num) + { + printf("WARNING: Too many momentum in momentum file %s.\n", file_name); + fclose(inp); + return false; + } + + float x = (float) strtod(tokenList[0],NULL); + float y = (float) strtod(tokenList[1],NULL); + float z = (float) strtod(tokenList[2],NULL); + momentum[count] = Vector3(x,y,z); + ++count; + delete[] tokenList; + } + fclose(inp); + + if (count < num) + { + printf("ERROR: Too few momentum in momentum file.\n"); + return false; + } + return true; +} // Count the number of atoms in the restart file. int Configuration::countRestart(const char* file_name) { @@ -1775,6 +2047,45 @@ void Configuration::getDebugForce() { } printf("\n"); } +//Han-Yi Chou setting boltzman distribution of momentum with a given center of mass velocity +//Before using this code, make sure the array type list and serial list are both already initialized +bool Configuration::Boltzmann(const Vector3& v_com, int N) +{ + int count = 0; + Vector3 total_momentum = Vector3(0.); + + gsl_rng *gslcpp_rng = gsl_rng_alloc(gsl_rng_default); + srand(time(NULL)); + gsl_rng_set (gslcpp_rng, rand() % 100000); + + for(int i = 0; i < N; ++i) + { + int typ = type[i]; + double M = part[typ].mass; + double sigma = sqrt(kT * M) * 2.046167337e4; + + Vector3 tmp(gsl_ran_gaussian(gslcpp_rng,sigma),gsl_ran_gaussian(gslcpp_rng,sigma),gsl_ran_gaussian(gslcpp_rng,sigma)); + tmp = tmp * 1e-4; + total_momentum += tmp; + momentum[(size_t)count] = tmp; + ++count; + } + if(N > 1) + { + total_momentum = total_momentum / (double)N; + + for(int i = 0; i < N; ++i) + { + int typ = type[i]; + double M = part[typ].mass; + + momentum[i] = momentum[i] - total_momentum + M * v_com; + } + } + + gsl_rng_free(gslcpp_rng); + return true; +} ////////////////////////// // Comparison operators // diff --git a/src/Configuration.h b/src/Configuration.h index b4d4587..19404a4 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -28,15 +28,12 @@ #include "RigidBodyType.h" #include "RigidBody.h" -#include <cuda.h> -#include <cuda_runtime.h> - // Units: // Energy: kcal/mol (6.947694e-24 kJ) // Temperature: Kelvin // Time: nanoseconds // Length: angstroms - +// Momentum: Da * \mu m / ns // Forward declerations class Angle; @@ -80,6 +77,12 @@ class Configuration { void getDebugForce(); + //Han-Yi Chou + bool Boltzmann(const Vector3& com_v,int N); + bool loadMomentum(const char* file_name); + void loadRestartMomentum(const char* file_name); + void Print(); + void PrintMomentum(); public: Configuration(const char * config_file, int simNum = 0, bool debug=false); ~Configuration(); @@ -94,6 +97,7 @@ public: bool loadedCoordinates; + bool loadedMomentum; // Device Variables //int *type_d; @@ -117,11 +121,14 @@ public: int numCap; // max number of particles int num; // current number of particles Vector3* pos; // position of each particle + Vector3* momentum; //momentum of each brownian particles Han-Yi Chou + Vector3 COM_Velocity; //center of mass velocity Han-Yi Chou int* type; // type of each particle int* serial; // serial number of each particle int currSerial; // the serial number of the next new particle String* name; // name of each particle Vector3* posLast; // used for current computation + Vector3* momLast; //used for Lagevin dynamics float timeLast; // used with posLast float minimumSep; // minimum separation allowed with placing new particles @@ -138,9 +145,11 @@ public: // String kTGridFile; String temperatureGridFile; String inputCoordinates; + String inputMomentum; //Han-Yi Chou String inputRBCoordinates; int copyReplicaCoordinates; String restartCoordinates; + String restartMomentum; //Han-Yi Chou int numberFluct; int interparticleForce; int tabulatedPotential; @@ -223,6 +232,10 @@ public: Restraint* restraints; + //Han-Yi Chou + String ParticleDynamicType; + String RigidBodyDynamicType; + String ParticleLangevinIntegrator; // RigidBody parameters. RigidBodyType* rigidBody; int numRigidTypes; -- GitLab