NAMD
ComputeSMDCUDA.C
Go to the documentation of this file.
1 #include "ComputeSMDCUDA.h"
2 #include "ComputeSMDCUDAKernel.h"
3 #include "SimParameters.h"
4 #include "PDB.h"
5 #include "PDBData.h"
6 #include "Node.h"
7 #include "Molecule.h"
8 #include "InfoStream.h"
9 
10 #ifdef NODEGROUP_FORCE_REGISTER
11 
12 ComputeSMDCUDA::ComputeSMDCUDA(
13  std::vector<HomePatch*> &patchList,
14  double springConstant,
15  double transverseSpringConstant,
16  double velocity,
17  double3 direction,
18  int outputFrequency,
19  int firstTimeStep,
20  const char* filename,
21  int numAtoms){
22 
23  // I could use an initializer list, but I don't like them
24  this->patchList = &patchList;
25  this->springConstant = springConstant;
26  this->transverseSpringConstant = transverseSpringConstant;
27  this->velocity = velocity;
28  this->direction = direction;
29  this->outputFrequency = outputFrequency;
30  this->firstTimeStep = firstTimeStep;
31  this->filename = filename;
32  this->numAtoms = numAtoms;
33  smdAtomsGlobalIndex.clear();
34  // I need to save the global index of atoms. That way I can quickly rebuild the SMD index vector
35  allocate_host<double3>(&curCOM, 1);
36  parseAtoms();
37 
38  smdAtomsSOAIndex.resize(this->numSMDAtoms);
39  allocate_device<unsigned int>(&d_tbcatomic, 1);
40  allocate_device<double3>(&d_curCOM, 1);
41  allocate_device<int>(&d_smdAtomsSOAIndex, this->numSMDAtoms);
42  // set the current COM value to {0, 0, 0}
43  curCOM->x = 0.0;
44  curCOM->y = 0.0;
45  curCOM->z = 0.0;
46  copy_HtoD<double3>(curCOM, d_curCOM, 1);
47  cudaCheck(cudaMemset(d_tbcatomic, 0, sizeof(unsigned int)));
48 }
49 
50 ComputeSMDCUDA::~ComputeSMDCUDA(){
51  deallocate_host<double3>(&curCOM);
52  deallocate_device<unsigned int>(&d_tbcatomic);
53  deallocate_device<int>(&d_smdAtomsSOAIndex);
54 }
55 
56 // This builds the global vector index - swiped from GlobalMasterSMD.C
57 void ComputeSMDCUDA::parseAtoms(){
58  PDB smdpdb(filename);
59  origCOM.x = origCOM.y = origCOM.z = 0;
60  Molecule *mol = Node::Object()->molecule; // to get masses
61  int numPDBAtoms = smdpdb.num_atoms();
62  if(numPDBAtoms < 1 ) NAMD_die("No Atoms found in SMDFile\n");
63 
64  BigReal imass = 0;
65 
66  if (numPDBAtoms != this->numAtoms){
67  fprintf(stderr, "Error, wrong numPDB (%d vs %d)\n",numPDBAtoms, this->numAtoms);
68  NAMD_die("The number of atoms in SMDFile must be equal to the total number of atoms in the structure!\n");
69  }
70 
71  // Would this work on PDB atoms? Is the data replicated for everyone?
72  for(int i = 0; i < numPDBAtoms; i++){
73  // MEMOPT obviously doesn't work with CUDASOA, so we can just use this
74  PDBAtom *atom = smdpdb.atom(i);
75  if(atom->occupancy()){ // It's a SMD atom! Add it to the list
76  smdAtomsGlobalIndex.push_back(i);
77 
78  // compute the center of mass
79  BigReal mass = mol->atommass(i);
80  origCOM.x += atom->xcoor()*mass;
81  origCOM.y += atom->ycoor()*mass;
82  origCOM.z += atom->zcoor()*mass;
83  imass += mass;
84  }
85  }
86 
87  inv_group_mass = 1.0 / imass;
88  origCOM.x *= inv_group_mass;
89  origCOM.y *= inv_group_mass;
90  origCOM.z *= inv_group_mass;
91 
92  if (imass == 0) // we didn't find any!
93  NAMD_die("SMDFile contained no SMD atoms (atoms w/ nonzero occupancy)\n");
94 
95  this->numSMDAtoms = smdAtomsGlobalIndex.size();
96 }
97 
98 void ComputeSMDCUDA::updateAtoms(
99  std::vector<AtomMap*> &atomMapsList,
100  std::vector<CudaLocalRecord> &localRecords,
101  const int* h_globalToLocalID) {
102 
103  for(int i = 0 ; i < this->numSMDAtoms; i++){
104  int gid = smdAtomsGlobalIndex[i];
105  LocalID lid;
106  // Search for a valid localID in all atoms
107  for(int j = 0 ; j < atomMapsList.size(); j++){
108  lid = atomMapsList[j]->localID(gid);
109  if( lid.pid != -1) break;
110  }
111 
112  //JM NOTE: Fields of lid need to be != -1, bc the atom needs to be somewhere
113  // otherwise we have a bug
114  if(lid.pid == -1){
115  NAMD_bug(" LocalAtomID not found in patchMap");
116  }
117 
118  int soaPid = h_globalToLocalID[lid.pid]; // Converts global patch ID to its local position in our SOA data structures
119  int soaIndex = localRecords[soaPid].bufferOffset + lid.index;
120 
121  smdAtomsSOAIndex[i] = soaIndex;
122  }
123  // Sort vector for better coalesce memory access
124  std::sort(smdAtomsSOAIndex.begin(), smdAtomsSOAIndex.end());
125  copy_HtoD<int>(smdAtomsSOAIndex.data(), d_smdAtomsSOAIndex, this->numSMDAtoms);
126 }
127 
128 void ComputeSMDCUDA::doForce(
129  const int timeStep,
130  const Lattice &lat,
131  const bool doEnergy,
132  const float* d_mass,
133  const double* d_pos_x,
134  const double* d_pos_y,
135  const double* d_pos_z,
136  const char3* d_transform,
137  double* d_f_normal_x,
138  double* d_f_normal_y,
139  double* d_f_normal_z,
140  cudaTensor* d_extVirial,
141  double* h_extEnergy,
142  double3* h_extForce,
143  cudaTensor* h_extVirial,
144  cudaStream_t stream
145  )
146 {
147  const int doOutput = (timeStep % this->outputFrequency) == 0;
148  computeSMDForce(
149  lat,
150  this->inv_group_mass,
151  this->springConstant,
152  this->transverseSpringConstant,
153  this->velocity,
154  this->direction,
155  doEnergy || doOutput,
156  timeStep,
157  this->origCOM,
158  d_mass,
159  d_pos_x,
160  d_pos_y,
161  d_pos_z,
162  d_transform,
163  d_f_normal_x,
164  d_f_normal_y,
165  d_f_normal_z,
166  this->numSMDAtoms,
167  this->d_smdAtomsSOAIndex,
168  this->d_curCOM,
169  this->curCOM,
170  d_extVirial,
171  h_extEnergy,
172  h_extForce,
173  h_extVirial,
174  this->d_tbcatomic,
175  stream
176  );
177 
178  if(doOutput){
179  cudaCheck(cudaStreamSynchronize(stream));
180  Vector p(curCOM->x, curCOM->y, curCOM->z);
181  Vector f(h_extForce->x, h_extForce->y, h_extForce->z);
182  if(timeStep % (100*this->outputFrequency) == 0) {
183  iout << "SMDTITLE: TS CURRENT_POSITION FORCE\n" << endi;
184  }
185  iout << "SMD " << timeStep << ' ' << p << ' ' << f*PNPERKCALMOL << '\n' << endi;
186  }
187 }
188 
189 #endif // NODEGROUP_FORCE_REGISTER
static Node * Object()
Definition: Node.h:86
Definition: PDB.h:36
Definition: Vector.h:72
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
BigReal zcoor(void)
Definition: PDBData.C:433
#define iout
Definition: InfoStream.h:51
Molecule stores the structural information for the system.
Definition: Molecule.h:175
int32 index
Definition: NamdTypes.h:290
void NAMD_bug(const char *err_msg)
Definition: common.C:195
BigReal ycoor(void)
Definition: PDBData.C:429
void NAMD_die(const char *err_msg)
Definition: common.C:147
PatchID pid
Definition: NamdTypes.h:289
Real atommass(int anum) const
Definition: Molecule.h:1107
BigReal xcoor(void)
Definition: PDBData.C:425
#define PNPERKCALMOL
Definition: common.h:59
#define cudaCheck(stmt)
Definition: CudaUtils.h:233
BigReal occupancy(void)
Definition: PDBData.C:444
Molecule * molecule
Definition: Node.h:179
double BigReal
Definition: common.h:123