NAMD
ComputeGroupRestraintsCUDA.C
Go to the documentation of this file.
4 #include "ComputeCUDAMgr.h"
5 #include "SimParameters.h"
6 #include "Node.h"
7 #include "Molecule.h"
8 #include "InfoStream.h"
9 #define MIN_DEBUG_LEVEL 3
10 //#define DEBUGM
11 #include "Debug.h"
12 
13 #ifdef NODEGROUP_FORCE_REGISTER
14 GroupRestraintsCUDA::GroupRestraintsCUDA(const GroupRestraintParam *param, bool _mGpuOn, int _numDevices, int _deviceIndex, int grp) {
15  resParam = param;
16  groupName = param->GetGroupName();
17  mGpuOn = _mGpuOn;
18  numDevices = _numDevices;
19  deviceIndex = _deviceIndex;
20  groupRestID = grp;
21  splitOverDevicesGrp1=false;
22  splitOverDevicesGrp2=false;
23  restraintExp = param->GetExponent();
24  restraintK = param->GetForce();
25  inv_group1_mass = 0.0;
26  inv_group2_mass = 0.0;
27  const std::vector<int> &group1Index = param->GetGroup1AtomIndex();
28  const std::vector<int> &group2Index = param->GetGroup2AtomIndex();
29  numRestrainedGroup1 = group1Index.size();
30  numRestrainedGroup2 = group2Index.size();
31  totalNumRestrained = numRestrainedGroup1 + numRestrainedGroup2;
32  // If we defined a list of atoms for group 1, then we have to
33  // calculate the COM for group 1 at every steps
34  calcGroup1COM = (numRestrainedGroup1 ? true : false);
35  // groupAtomsSOAIndex stores SOAindex of group 1, followed by
36  // SOAindex of group 2
37  groupAtomsSOAIndex.resize(totalNumRestrained);
38  useDistMagnitude = param->GetUseDistMagnitude();
39  Vector center = param->GetResCenter();
40  Vector dir = param->GetResDirection();
41  resDirection = make_double3(dir.x, dir.y, dir.z);
42  resCenterVec = make_double3(center.x, center.y, center.z);
43 
44  // Allocate host and device memory
45  allocate_host<double>(&h_resEnergy, 1);
46  allocate_host<double3>(&h_diffCOM, 1);
47  allocate_host<double3>(&h_group1COM, 1);
48  allocate_host<double3>(&h_group2COM, 1);
49 
50  allocate_host<double3>(&h_resForce, 1);
51  allocate_device<double3>(&d_group1COM, 1);
52  allocate_device<double3>(&d_group2COM, 1);
53  allocate_device<int>(&d_groupAtomsSOAIndex, totalNumRestrained);
54  allocate_device<unsigned int>(&d_tbcatomic, 1);
55  // Set the counter to zero
56  cudaCheck(cudaMemset(d_tbcatomic, 0, sizeof(unsigned int)));
57  if(mGpuOn)
58  {// each needs its own peer array
59  allocate_device<double3>(&d_peer1COM, sizeof(double3));
60  allocate_device<double3>(&d_peer2COM, sizeof(double3));
61 #ifdef DEBUGM
62  allocate_host<double3>(&h_peer1COM, sizeof(double3));
63  allocate_host<double3>(&h_peer2COM, sizeof(double3)*numDevices);
64 #endif
65  }
66 
67  // Check the atom index and calculate he inverse mass
68  Molecule *mol = Node::Object()->molecule;
69  int totalAtoms = mol->numAtoms;
70  double total_mass = 0.0;
71 
72  for (int i = 0; i < numRestrainedGroup2; ++i) {
73  int index = group2Index[i];
74  if (index > -1 && index < totalAtoms) {
75  total_mass += mol->atommass(index);
76  } else {
77  char err_msg[512];
78  sprintf(err_msg, "Group restraints: Bad atom index for %s!"
79  " Atom indices must be within [%d, %d].\n", groupName, 0, totalAtoms - 1);
80  NAMD_die(err_msg);
81  }
82  }
83  inv_group2_mass = 1.0 / total_mass;
84 
85  // Do we need to calculate COM of group 1, or we have a
86  // reference position for it?
87  if (calcGroup1COM) {
88  total_mass = 0.0;
89  for (int i = 0; i < numRestrainedGroup1; ++i) {
90  int index = group1Index[i];
91  if (index > -1 && index < totalAtoms) {
92  total_mass += mol->atommass(index);
93  } else {
94  char err_msg[512];
95  sprintf(err_msg, "Group restraints: Bad atom index for %s!"
96  " Atom indices must be within [%d, %d].\n", groupName, 0, totalAtoms - 1);
97  NAMD_die(err_msg);
98  }
99  }
100  inv_group1_mass = 1.0 / total_mass;
101  } else {
102  // We defined the reference point for COM of group 1, so no need
103  // to calculate it, just copy it.
104  // Set the h_group1COM to reference COM position of group 1
105  Vector ref = param->GetGroupRes1Position();
106  h_group1COM->x = ref.x;
107  h_group1COM->y = ref.y;
108  h_group1COM->z = ref.z;
109  }
110 }
111 
112 GroupRestraintsCUDA::~GroupRestraintsCUDA() {
113  deallocate_host<double>(&h_resEnergy);
114  deallocate_host<double3>(&h_resForce);
115  deallocate_host<double3>(&h_diffCOM);
116  deallocate_host<double3>(&h_group1COM);
117  deallocate_host<double3>(&h_group2COM);
118  deallocate_device<double3>(&d_group1COM);
119  deallocate_device<double3>(&d_group2COM);
120  deallocate_device<int>(&d_groupAtomsSOAIndex);
121  deallocate_device<unsigned int>(&d_tbcatomic);
122 }
123 
125 void GroupRestraintsCUDA::updateAtoms(
126  std::vector<AtomMap*> &atomMapsList,
127  std::vector<CudaLocalRecord> &localRecords,
128  const int *h_globalToLocalID) {
129 
130  // If we need to calculate COM of group 1, we have to store
131  // index to SOA data structures for group 1
132  numRestrainedGroup1Local = numRestrainedGroup1;
133  numRestrainedGroup2Local = numRestrainedGroup2;
134  if(mGpuOn)
135  groupAtomsSOAIndex.clear();
136  if(calcGroup1COM) {
137  const std::vector<int> &group1Index = resParam->GetGroup1AtomIndex();
138  DebugM(3, "[" << CkMyPe() << "]" <<" updateAtoms grp1 "<< group1Index.size() << "\n" << endi);
139  if(numRestrainedGroup1 != group1Index.size()) {
140  char err_msg[512];
141  sprintf("Number of atoms in group 1 restraint for '%s' is changed!", groupName);
142  NAMD_bug(err_msg);
143  }
144  // Map the global index to local position in SOA data structure
145  for(int i = 0 ; i < numRestrainedGroup1; ++i){
146  int gid = group1Index[i];
147  LocalID lid;
148  DebugM(2, "[" << CkMyPe() << "]" <<" updateAtoms grp1 looking for "<< gid << "\n" << endi);
149  // Search for a valid localID in all atoms
150  for(int j = 0 ; j < atomMapsList.size(); ++j){
151  lid = atomMapsList[j]->localID(gid);
152  if( lid.pid != -1) {
153  break;
154  }
155  }
156  // Fields of lid need to be != -1, bc the atom needs to be somewhere
157  // otherwise we have a bug
158  if(lid.pid == -1){
159  if(!mGpuOn)
160  NAMD_bug("LocalAtomID not found in patchMap");
161  else
162  splitOverDevicesGrp1=true;
163  }
164  else
165  {
166  // Converts global patch ID to its local position in our SOA data structures
167  int soaPid = h_globalToLocalID[lid.pid];
168  if(soaPid>=0)
169  {
170  int soaIndex = localRecords[soaPid].bufferOffset + lid.index;
171  DebugM(2, "[" << CkMyPe() << "]" <<" updateAtoms grp1 found gid "<< gid << " as soa "<< soaIndex << "\n" << endi);
172  if(mGpuOn)
173  groupAtomsSOAIndex.push_back(soaIndex);
174  else
175  groupAtomsSOAIndex[i] = soaIndex;
176  }
177  }
178  }
179  DebugM(3, "[" << CkMyPe() << "]" <<" updateAtoms grp1 soa "<< groupAtomsSOAIndex.size() << "\n" << endi);
180  // Sort vector for better coalesce memory access. Just sort only group 1
181  if(mGpuOn)
182  {
183  numRestrainedGroup1Local = groupAtomsSOAIndex.size();
184  }
185  if(numRestrainedGroup1Local>0)
186  std::sort(groupAtomsSOAIndex.begin(), groupAtomsSOAIndex.begin()+numRestrainedGroup1Local);
187  }
188 
189  // We always calculate the COM of group 2, so we store
190  // SOAIndex of group 2, after group 1 index
191  const std::vector<int> &group2Index = resParam->GetGroup2AtomIndex();
192  if(numRestrainedGroup2 != group2Index.size()) {
193  char err_msg[512];
194  sprintf("Number of atoms in group 2 restraint for '%s' is changed!", groupName);
195  NAMD_bug(err_msg);
196  }
197  DebugM(4, "[" << CkMyPe() << "]" <<" updateAtoms grp2 "<< group2Index.size() << "\n" << endi);
198  // Map the global index to local position in SOA data structure
199  for(int i = 0 ; i < numRestrainedGroup2; ++i){
200  int gid = group2Index[i];
201  LocalID lid;
202  DebugM(2, "[" << CkMyPe() << "]" <<" updateAtoms grp2 looking for "<< gid << "\n" << endi);
203  // Search for a valid localID in all atoms
204  for(int j = 0 ; j < atomMapsList.size(); ++j){
205  lid = atomMapsList[j]->localID(gid);
206  if( lid.pid != -1) {
207  break;
208  }
209  }
210  // Fields of lid need to be != -1, bc the atom needs to be somewhere
211  // otherwise we have a bug
212  if(lid.pid == -1){
213  if(!mGpuOn)
214  NAMD_bug("LocalAtomID not found in patchMap");
215  else
216  splitOverDevicesGrp2=true;
217  }
218  else
219  {
220 
221  // Converts global patch ID to its local position in our SOA data structures
222  int soaPid = h_globalToLocalID[lid.pid];
223  if(soaPid>=0)
224  {
225  int soaIndex = localRecords[soaPid].bufferOffset + lid.index;
226  DebugM(2, "[" << CkMyPe() << "]" <<" updateAtoms grp2 found "<< gid << " as SOA "<< soaIndex << "\n" << endi);
227  // store the index for group 2, after group 1 index
228  if(mGpuOn)
229  groupAtomsSOAIndex.push_back(soaIndex);
230  else
231  groupAtomsSOAIndex[i + numRestrainedGroup1] = soaIndex;
232  DebugM(2, "[" << CkMyPe() << "]" <<" updateAtoms grp2 SOA soaidx "<< soaIndex<< " size now "<< groupAtomsSOAIndex.size() <<"\n" << endi);
233  }
234  }
235  }
236  numRestrainedGroup2Local = groupAtomsSOAIndex.size() - numRestrainedGroup1Local;
237  DebugM(3, "[" << CkMyPe() << "]" <<" updateAtoms grp2 SOA now "<< groupAtomsSOAIndex.size() << " numRestrainedGroup1Local " << numRestrainedGroup1Local << " numRestrainedGroup2Local " << numRestrainedGroup2Local <<"\n" << endi);
238  // if there are local atoms, send indices to the device
239  if(groupAtomsSOAIndex.size()>0){
240  // Sort vector for better coalesce memory access. Sort only for group 2
241  if(numRestrainedGroup2Local>0)
242  std::sort(groupAtomsSOAIndex.begin() + numRestrainedGroup1Local, groupAtomsSOAIndex.end());
243  // Update the SOA index in device
244  copy_HtoD<int>(groupAtomsSOAIndex.data(), d_groupAtomsSOAIndex, groupAtomsSOAIndex.size());
245  }
246 }
247 void GroupRestraintsCUDA::initPeerCOM(double3** d_peerCOM1G,
248  double3** d_peerCOM2G, cudaStream_t stream){
249  DebugM(3, "[" << CkMyPe() << "]" << " initPeerCOM\n" << endi);
250  initPeerCOMmgpuG(numDevices, deviceIndex, d_peerCOM1G, d_peer1COM, stream);
251  initPeerCOMmgpuG(numDevices, deviceIndex, d_peerCOM2G, d_peer2COM, stream);
252 }
253 
254 void GroupRestraintsCUDA::doCOM_mgpu(
255  const Lattice &lat,
256  const char3* d_transform,
257  const float* d_mass,
258  const double* d_pos_x,
259  const double* d_pos_y,
260  const double* d_pos_z,
261  const int grp,
262  cudaStream_t stream) {
263  groupRestID = grp;
265  DebugM(3, "[" << CkMyPe() << "]" << " doCOM_mgpu g1count "<< numRestrainedGroup1Local<< " g2count "<<numRestrainedGroup2Local << endi);
266  if(numRestrainedGroup1Local>0 && calcGroup1COM)
267  {
268  // if compute COM1 and have some of the group's atom, compute distCOM grp1
269  computeCOMMgpu(numRestrainedGroup1Local,lat,
270  d_mass, d_pos_x, d_pos_y, d_pos_z,
271  d_transform, this->d_groupAtomsSOAIndex,
272  this->d_peer1COM,
273  cudaMgr->curGrp1COM[grp],
274  this->d_tbcatomic,
275  numDevices, deviceIndex,
276  stream);
277 #ifdef DEBUGM
278  cudaCheck(cudaStreamSynchronize(stream));
279  copy_DtoH_sync<double3>(d_peer1COM, h_peer1COM, 1);
280  DebugM(3, "gid " << groupRestID <<" deviceIndex "<< deviceIndex << " g1 COM " <<h_peer1COM->x*inv_group1_mass<<", "
281  <<h_peer1COM->y*inv_group1_mass<<", "
282  <<h_peer2COM->z*inv_group1_mass<<"\n"<<endi);
283 #endif
284  }
285  if(numRestrainedGroup2Local>0)
286  {
287  // if we have some of the group's atoms, compute distCOM grp2
288  computeCOMMgpu(numRestrainedGroup2Local,lat,
289  d_mass, d_pos_x, d_pos_y, d_pos_z,
290  d_transform,
291  this->d_groupAtomsSOAIndex+numRestrainedGroup1Local,
292  this->d_peer2COM,
293  cudaMgr->curGrp2COM[grp],
294  this->d_tbcatomic, numDevices, deviceIndex,
295  stream);
296 #ifdef DEBUGM
297  cudaCheck(cudaStreamSynchronize(stream));
298  copy_DtoH_sync<double3>(d_peer2COM, h_peer2COM, 1);
299  DebugM(3, " gid "<< groupRestID << " deviceIndex "<< deviceIndex << " g2 COM " <<h_peer2COM[0].x*inv_group2_mass<<", "
300  <<h_peer2COM[0].y*inv_group2_mass<<", "
301  <<h_peer2COM[0].z*inv_group2_mass<<"\n"<<endi);
302 #endif
303  }
304 }
305 
307 void GroupRestraintsCUDA::doForce(
308  const int timeStep,
309  const int doEnergy,
310  const int doVirial,
311  const int doOutput,
312  const int grp,
313  const Lattice &lat,
314  const char3* d_transform,
315  const float* d_mass,
316  const double* d_pos_x,
317  const double* d_pos_y,
318  const double* d_pos_z,
319  double* d_f_normal_x,
320  double* d_f_normal_y,
321  double* d_f_normal_z,
322  cudaTensor* d_virial,
323  double* h_extEnergy,
324  double3* h_extForce,
325  cudaTensor* h_extVirial,
326  double3** d_peer1COM,
327  double3** d_peer2COM,
328  cudaStream_t stream) {
329  DebugM(3, "[" << CkMyPe() << "]" << " doForce g1 "<< numRestrainedGroup1Local <<" g2 "<< numRestrainedGroup2Local <<"\n" << endi);
330  // distributed COM for mGpu is not effectively the same as the 1Group
331  // case, because the force computation uses both group1 and group2
333  if (calcGroup1COM) {
334  computeGroupRestraint_2Group(
335  mGpuOn,
336  useDistMagnitude,
337  doEnergy,
338  doVirial,
339  numRestrainedGroup1Local,
340  numRestrainedGroup1Local + numRestrainedGroup2Local,
341  this->restraintExp,
342  this->restraintK,
343  this->resCenterVec,
344  this->resDirection,
345  this->inv_group1_mass,
346  this->inv_group2_mass,
347  this->d_groupAtomsSOAIndex,
348  lat,
349  d_transform,
350  d_mass,
351  d_pos_x,
352  d_pos_y,
353  d_pos_z,
354  d_f_normal_x,
355  d_f_normal_y,
356  d_f_normal_z,
357  d_virial,
358  h_extVirial,
359  this->h_resEnergy,
360  this->h_resForce,
361  this->h_group1COM,
362  this->h_group2COM,
363  this->h_diffCOM,
364  this->d_group1COM,
365  this->d_group2COM,
366  d_peer1COM,
367  d_peer2COM,
368  this->d_tbcatomic,
369  numDevices,
370  stream);
371  } else {
372  if(numRestrainedGroup2Local>0)
373  {
374  computeGroupRestraint_1Group(
375  mGpuOn,
376  useDistMagnitude,
377  doEnergy,
378  doVirial,
379  numRestrainedGroup2Local,
380  this->restraintExp,
381  this->restraintK,
382  this->resCenterVec,
383  this->resDirection,
384  this->inv_group2_mass,
385  this->d_groupAtomsSOAIndex,
386  lat,
387  d_transform,
388  d_mass,
389  d_pos_x,
390  d_pos_y,
391  d_pos_z,
392  d_f_normal_x,
393  d_f_normal_y,
394  d_f_normal_z,
395  d_virial,
396  h_extVirial,
397  this->h_resEnergy,
398  this->h_resForce,
399  this->h_group1COM,
400  this->h_group2COM,
401  this->h_diffCOM,
402  d_peer2COM,
403  this->d_group2COM,
404  this->d_tbcatomic,
405  numDevices,
406  stream);
407  }
408  }
409  if(doOutput && (numDevices==1 || deviceIndex == cudaMgr->reducerGroupRestraintDevice)){
410  cudaCheck(cudaStreamSynchronize(stream));
411  // sum up external energy and virial from this group
412  h_extEnergy[0] += h_resEnergy[0];
413  // If we have restraint to reference point, then we have net force
414  // otherwise the net force is zero for restraining two atom groups
415  if (!calcGroup1COM) {
416  h_extForce->x += h_resForce->x;
417  h_extForce->y += h_resForce->y;
418  h_extForce->z += h_resForce->z;
419  }
420 
421  char msg[1024];
422  sprintf(msg,"GRES: %9d %14s %14.4f %14.4f %14.4f %19.4f %14.4f %14.4f %14.4f\n",
423  timeStep, groupName, h_diffCOM->x, h_diffCOM->y, h_diffCOM->z,
424  h_resForce->x, h_resForce->y, h_resForce->z, h_resEnergy[0]);
425  iout << msg << endi;
426 
427  // {
428  // printf("!!!Accu. exForce: %14.8f %14.8f %14.8f, Vir.x: %14.8f %14.8f %14.8f,"
429  // "Vir.y: %14.8f %14.8f %14.8f, Vir.z: %14.8f %14.8f %14.8f \n",
430  // h_extForce->x, h_extForce->y, h_extForce->z,
431  // h_extVirial->xx, h_extVirial->xy, h_extVirial->xz,
432  // h_extVirial->yx, h_extVirial->yy, h_extVirial->yz,
433  // h_extVirial->zx, h_extVirial->zy, h_extVirial->zz);
434  // }
435  }
436 }
437 
438 // ###########################################################################
439 // # ComputeGroupRestraintsCUDA functions
440 // ###########################################################################
441 
442 ComputeGroupRestraintsCUDA::ComputeGroupRestraintsCUDA(const int outputFreq,
443  const GroupRestraintList &resList, bool _mGpuOn, int _numDevices, int _deviceIndex) {
444  gResOutputFreq = outputFreq;
445  mGpuOn = _mGpuOn;
446  numDevices = _numDevices;
447  deviceIndex = _deviceIndex;
448  const std::map<std::string, GroupRestraintParam*> & groupMap = resList.GetGroupResMap();
450  for (auto it = groupMap.begin(); it != groupMap.end(); ++it) {
451  GroupRestraintsCUDA * gResCUDA = new GroupRestraintsCUDA(it->second, mGpuOn, numDevices, deviceIndex, restraintsCUDAList.size());
452  restraintsCUDAList.push_back(gResCUDA);
453  }
454 }
455 
456 ComputeGroupRestraintsCUDA::~ComputeGroupRestraintsCUDA() {
457  int numGroup = restraintsCUDAList.size();
458  for (int i = 0; i < numGroup; ++i) {
459  delete restraintsCUDAList[i];
460  }
461  restraintsCUDAList.clear();
462 }
463 
465 void ComputeGroupRestraintsCUDA::updateAtoms(
466  std::vector<AtomMap*> &atomMapsList,
467  std::vector<CudaLocalRecord> &localRecords,
468  const int *h_globalToLocalID) {
469 
470  int numGroup = restraintsCUDAList.size();
472  for (int i = 0; i < numGroup; ++i) {
473  restraintsCUDAList[i]->updateAtoms(atomMapsList, localRecords, h_globalToLocalID);
474  if(mGpuOn && restraintsCUDAList[i]->numRestrainedGroup1Local + restraintsCUDAList[i]->numRestrainedGroup2Local >0)
475  {
476  // last one wins
477  cudaMgr->reducerGroupRestraintDevice.store(deviceIndex);
478  }
479  }
480 }
481 
482 void ComputeGroupRestraintsCUDA::initPeerCOM(cudaStream_t stream){
483  DebugM(3, "[" << CkMyPe() << "]" << " initPeerCOM\n" << endi);
484  int numGroup = restraintsCUDAList.size();
486  for (int i = 0; i < numGroup; ++i) {
487  restraintsCUDAList[i]->initPeerCOM(cudaMgr->curGrp1COM[i], cudaMgr->curGrp2COM[i], stream);
488  }
489 
490 }
491 
492 
494 void ComputeGroupRestraintsCUDA::doCOM_mgpu(
495  const Lattice &lat,
496  const char3* d_transform,
497  const float* d_mass,
498  const double* d_pos_x,
499  const double* d_pos_y,
500  const double* d_pos_z,
501  cudaStream_t stream) {
502  int numGroup = restraintsCUDAList.size();
503  DebugM(3, "[" << CkMyPe() << "]" << " doCOM_mgpu "<< numGroup <<"\n" << endi);
504  for (int gIdx = 0; gIdx < numGroup; ++gIdx) {
505  //each element will determine if it needs a distributed COM
506  restraintsCUDAList[gIdx]->doCOM_mgpu(
507  lat, d_transform,
508  d_mass, d_pos_x, d_pos_y, d_pos_z, gIdx,
509  stream);
510  }
511 }
512 
514 void ComputeGroupRestraintsCUDA::doForce(
515  const int timeStep,
516  const int doEnergy,
517  const int doVirial,
518  const Lattice &lat,
519  const char3* d_transform,
520  const float* d_mass,
521  const double* d_pos_x,
522  const double* d_pos_y,
523  const double* d_pos_z,
524  double* d_f_normal_x,
525  double* d_f_normal_y,
526  double* d_f_normal_z,
527  cudaTensor* d_virial,
528  double* h_extEnergy,
529  double3* h_extForce,
530  cudaTensor* h_extVirial,
531  cudaStream_t stream) {
532 
533  const int doOutput = (timeStep % gResOutputFreq) == 0;
534  // Since output freq is same as energyOutputFrq, we need to calculate virial
535  // for outputting energy data
536  int doVirCalc = (doOutput ? 1 : doVirial);
537  int numGroup = restraintsCUDAList.size();
538 
539  // Reset the values before we add the energy, force, and virial value
540  // for each restraint group
541  h_extEnergy[0] = 0.0;
542  h_extForce->x = 0.0;
543  h_extForce->y = 0.0;
544  h_extForce->z = 0.0;
545  h_extVirial->xx = 0.0;
546  h_extVirial->xy = 0.0;
547  h_extVirial->xz = 0.0;
548  h_extVirial->yx = 0.0;
549  h_extVirial->yy = 0.0;
550  h_extVirial->yz = 0.0;
551  h_extVirial->zx = 0.0;
552  h_extVirial->zy = 0.0;
553  h_extVirial->zz = 0.0;
555  if(doOutput && (numDevices==1 || deviceIndex == cudaMgr->reducerGroupRestraintDevice)){
556  if(timeStep % (100 * gResOutputFreq) == 0) {
557  char msg[1024];
558  sprintf(msg,"\nGRES_TITLE: %3s %14s %14s %14s %14s %19s %14s %14s %14s\n",
559  "TS", "GROUP_NAME", "DISTANCE.X", "DISTANCE.Y", "DISTANCE.Z",
560  "FORCE.X", "FORCE.Y", "FORCE.Z", "ENERGY");
561  iout << msg << endi;
562  }
563  }
564 
565  for (int gIdx = 0; gIdx < numGroup; ++gIdx) {
566  restraintsCUDAList[gIdx]->doForce(
567  timeStep, doEnergy, doVirCalc, doOutput, gIdx, lat, d_transform,
568  d_mass, d_pos_x, d_pos_y, d_pos_z,
569  d_f_normal_x, d_f_normal_y, d_f_normal_z, d_virial,
570  h_extEnergy, h_extForce, h_extVirial, cudaMgr->curGrp1COM[gIdx], cudaMgr->curGrp2COM[gIdx], stream);
571  }
572  if(doOutput && (numDevices==1 || deviceIndex == cudaMgr->reducerGroupRestraintDevice)) {
573  iout <<"\n" << endi;;
574  }
575 }
576 #endif
static Node * Object()
Definition: Node.h:86
BigReal yy
Definition: CudaUtils.h:80
BigReal zz
Definition: CudaUtils.h:84
BigReal yx
Definition: CudaUtils.h:79
Definition: Vector.h:72
BigReal yz
Definition: CudaUtils.h:81
#define DebugM(x, y)
Definition: Debug.h:75
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
BigReal z
Definition: Vector.h:74
#define iout
Definition: InfoStream.h:51
Molecule stores the structural information for the system.
Definition: Molecule.h:174
const std::map< std::string, GroupRestraintParam * > & GetGroupResMap() const
int32 index
Definition: NamdTypes.h:300
Vector GetGroupRes1Position() const
std::atomic< int > reducerGroupRestraintDevice
Vector GetResDirection() const
NAMD_HOST_DEVICE double3 make_double3(float3 a)
Definition: Vector.h:343
double3 *** curGrp2COM
void NAMD_bug(const char *err_msg)
Definition: common.C:195
BigReal xx
Definition: CudaUtils.h:76
const char * GetGroupName() const
static ComputeCUDAMgr * getComputeCUDAMgr()
double3 *** curGrp1COM
BigReal zx
Definition: CudaUtils.h:82
BigReal x
Definition: Vector.h:74
int numAtoms
Definition: Molecule.h:586
void NAMD_die(const char *err_msg)
Definition: common.C:147
PatchID pid
Definition: NamdTypes.h:299
Real atommass(int anum) const
Definition: Molecule.h:1114
BigReal xz
Definition: CudaUtils.h:78
Vector GetResCenter() const
BigReal y
Definition: Vector.h:74
const std::vector< int > & GetGroup2AtomIndex() const
#define cudaCheck(stmt)
Definition: CudaUtils.h:233
bool GetUseDistMagnitude() const
Molecule * molecule
Definition: Node.h:179
const std::vector< int > & GetGroup1AtomIndex() const
BigReal zy
Definition: CudaUtils.h:83
BigReal xy
Definition: CudaUtils.h:77