NAMD
Output.C
Go to the documentation of this file.
1 
7 /*
8  This object outputs the data collected on the master node
9 */
10 
11 #include "largefiles.h" // must be first!
12 
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #include "InfoStream.h"
17 #include "IMDOutput.h"
18 #include "Output.h"
19 #include "dcdlib.h"
20 #include "strlib.h"
21 #include "Molecule.h"
22 #include "Node.h"
23 #include "Parameters.h"
24 #include "PDB.h"
25 #include "SimParameters.h"
26 #include "Vector.h"
27 #include "structures.h"
28 #include "MStream.h"
29 #include "Communicate.h"
30 #include "PatchMap.h"
31 #include "PatchMap.inl"
32 #include "ScriptTcl.h"
33 #include "Lattice.h"
34 #include "DataExchanger.h"
35 #include <fcntl.h>
36 #include <sys/stat.h>
37 #include "PatchData.h"
38 #ifdef WIN32
39 #include <io.h>
40 #define access(PATH,MODE) _access(PATH,00)
41 #endif
42 static const short maxDCD=257; //1 byte of userdcd plus standard
43 #if defined(WIN32) && !defined(__CYGWIN__)
44 #define PATHSEPSTR "\\"
45 #define MKDIR(X) mkdir(X)
46 #else
47 #define PATHSEPSTR "/"
48 #define MKDIR(X) mkdir(X,0777)
49 #endif
50 
51 #define NAMD_open NAMD_open64
52 #define NAMD_write NAMD_write64
53 #define NAMD_close NAMD_close64
54 
55 #ifndef O_LARGEFILE
56 #define O_LARGEFILE 0x0
57 #endif
58 #define MIN_DEBUG_LEVEL 3
59 //#define DEBUGM
60 #include "Debug.h"
61 
62 // same as open, only does error checking internally
63 int NAMD_open(const char *fname) {
64  int fd;
65 
66  // open the file and die if the open fails
67 #ifdef WIN32
68  while ( (fd = _open(fname, O_WRONLY|O_CREAT|O_EXCL|O_BINARY|O_LARGEFILE,_S_IREAD|_S_IWRITE)) < 0) {
69 #else
70 #ifdef NAMD_NO_O_EXCL
71  while ( (fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE,
72 #else
73  while ( (fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE,
74 #endif
75  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
76 #endif
77  if ( errno != EINTR ) {
78  char errmsg[1024];
79  sprintf(errmsg, "Unable to open binary file %s", fname);
80  NAMD_err(errmsg);
81  }
82  }
83 
84  return fd;
85 }
86 
87 // same as write, only does error checking internally
88 void NAMD_write(int fd, const char *buf, size_t count, const char *errmsg="NAMD_write64") {
89  double firsttime = 0.;
90  while ( count ) {
91 #if defined(WIN32) && !defined(__CYGWIN__)
92  long retval = _write(fd,buf,count);
93 #else
94  ssize_t retval = write(fd,buf,count);
95 #endif
96  if ( retval < 0 && errno == EINTR ) retval = 0;
97  if ( retval < 0 && errno == ENOMEM ) {
98  if ( firsttime == 0. ) firsttime = CmiWallTimer();
99  if ( (CmiWallTimer() - firsttime) < 300. ) retval = 0;
100  }
101  if ( retval < 0 ) NAMD_err(errmsg);
102  if ( retval > count ) NAMD_bug("extra bytes written in NAMD_write64()");
103  buf += retval;
104  count -= retval;
105  }
106  if ( firsttime != 0. ) {
107  iout << iWARN << errmsg << ": NAMD_write64() retried for " << (CmiWallTimer() - firsttime) << " seconds.\n" << endi;
108  }
109 }
110 
111 // same as close, only does error checking internally
112 void NAMD_close(int fd, const char *fname) {
113 #ifdef WIN32
114  while ( _close(fd) ) {
115 #else
116  while ( close(fd) ) {
117 #endif
118  if ( errno != EINTR ) {
119  char errmsg[1024];
120  sprintf(errmsg, "Error on closing file %s", fname);
121  NAMD_err(errmsg);
122  }
123  }
124 }
125 
126 
127 #define seek_dcdfile NAMD_seek
128 
129 // These make the NAMD 1 names work in NAMD 2
130 #define namdMyNode Node::Object()
131 #define simParams simParameters
132 #define pdbData pdb
133 
134 static void lattice_to_unitcell(const Lattice *lattice, double *unitcell) {
135 
136  unitcell[0] = unitcell[2] = unitcell[5] = 0.0;
137  unitcell[1] = unitcell[3] = unitcell[4] = 0.0;
138 
139  if (lattice) {
140  const Vector &a=lattice->a();
141  const Vector &b=lattice->b();
142  const Vector &c=lattice->c();
143  unitcell[0] = (lattice->a_p()) ? a.length() : 0.0;
144  unitcell[2] = (lattice->b_p()) ? b.length() : 0.0;
145  unitcell[5] = (lattice->c_p()) ? c.length() : 0.0;
146  double cosAB = (lattice->a_p() && lattice->b_p() ) ?
147  (a*b)/(unitcell[0]*unitcell[2]) : 0.0;
148  double cosAC = (lattice->a_p() && lattice->c_p() ) ?
149  (a*c)/(unitcell[0]*unitcell[5]) : 0.0;
150  double cosBC = (lattice->b_p() && lattice->c_p() ) ?
151  (b*c)/(unitcell[2]*unitcell[5]) : 0.0;
152  if (cosAB > 1.0) cosAB = 1.0; else if (cosAB < -1.0) cosAB = -1.0;
153  if (cosAC > 1.0) cosAC = 1.0; else if (cosAC < -1.0) cosAC = -1.0;
154  if (cosBC > 1.0) cosBC = 1.0; else if (cosBC < -1.0) cosBC = -1.0;
155  unitcell[1] = cosAB;
156  unitcell[3] = cosAC;
157  unitcell[4] = cosBC;
158  }
159 }
160 
161 
162 /************************************************************************/
163 /* */
164 /* FUNCTION Output */
165 /* */
166 /* This is the constructor for the Ouput class. It just sets */
167 /* up some values for the VMD connection. */
168 /* */
169 /************************************************************************/
170 
171 Output::Output() : replicaDcdActive(0) { }
172 
173 /* END OF FUNCTION Output */
174 
175 /************************************************************************/
176 /* */
177 /* FUNCTION ~Output */
178 /* */
179 /************************************************************************/
180 
182 
183 /* END OF FUNCTION ~Output */
184 
185 std::pair<int,int> Output::coordinateNeeded(int timestep)
186 {
188 
189  if(simParams->benchTimestep) return std::make_pair(0,0);
190 
191  int positionsNeeded = 0;
192  uint16 dcdSelectionTag = 0;
193  if ( timestep >= 0 ) {
194 
195  // Output a DCD trajectory
196  if ( simParams->dcdFrequency &&
197  ((timestep % simParams->dcdFrequency) == 0) )
198  { positionsNeeded |= 1; }
199 
200  // Output a DCD Selection trajectory
201 
202  if (simParams->dcdSelectionOn)
203  {
204  Molecule *mol = Node::Object()->molecule;
205  int tagCount=0;
206  for(int index=0; index<16;++index)
207  {
208  int frequency=mol->dcdSelectionParams[index].frequency;
209  uint16 tag=mol->dcdSelectionParams[index].tag;
210  if(frequency && (timestep % frequency) == 0)
211  {
212  if(++tagCount>1)
213  positionsNeeded |=1; //multi selection means all positions
214  positionsNeeded |= 4; dcdSelectionTag = tag;
215  }
216  }
217  }
218  // Output a restart file
219  if ( simParams->restartFrequency &&
220  ((timestep % simParams->restartFrequency) == 0) )
221  { positionsNeeded |= 2; }
222 
223  // Iteractive MD
224  if ( simParams->IMDon ) {
225  if ((simParams->IMDversion == IMDversion_t::IMDv3) &&
226  (simParams->IMDsendsettings.time_switch == 0) && (simParams->IMDsendsettings.energies_switch == 0)) {
227  IMDOutput *imd = NULL;
228 #ifdef NODEGROUP_FORCE_REGISTER
229  if (simParams->CUDASOAintegrate) {
230  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
231  imd = cpdata.ckLocalBranch()->imd;
232  }
233  else
234 #endif
235  {
236  imd = Node::Object()->imd;
237  }
238  if (imd != NULL) imd->get_imd_packet();
239  }
240  if ( (((timestep % simParams->IMDfreq) == 0) ||
241  (timestep == simParams->firstTimestep) ) &&
242  ((simParams->IMDversion == IMDversion_t::IMDv2) || ((simParams->IMDversion == IMDversion_t::IMDv3)
243  && ((simParams->IMDsendsettings.box_switch == 1) || (simParams->IMDsendsettings.fcoords_switch == 1)))) )
244  { positionsNeeded |= 1; }
245  }
246 
247  }
248 
249  // Output final coordinates
250  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN ||
251  timestep == EVAL_MEASURE)
252  {
253  positionsNeeded |= 2;
254  }
255  return std::make_pair(positionsNeeded,dcdSelectionTag);
256 }
257 
258 template <class xVector, class xDone>
259 void wrap_coor_int(xVector *coor, Lattice &lattice, xDone *done) {
261  if ( *done ) return;
262  *done = 1;
263  if ( ! ( simParams->wrapAll || simParams->wrapWater ) ) return;
264  const int wrapNearest = simParams->wrapNearest;
265  const int wrapAll = simParams->wrapAll;
266  Molecule *molecule = Node::Object()->molecule;
267  int n = molecule->numAtoms;
268  int i;
269 #ifndef MEM_OPT_VERSION
270  Position *con = new Position[n];
271  for ( i = 0; i < n; ++i ) {
272  con[i] = 0;
273  int ci = molecule->get_cluster(i);
274  con[ci] += coor[i];
275  }
276  for ( i = 0; i < n; ++i ) {
277  if ( ! wrapAll && ! molecule->is_water(i) ) continue;
278  int ci = molecule->get_cluster(i);
279  if ( ci == i ) {
280  Vector coni = con[i] / molecule->get_clusterSize(i);
281  Vector trans = ( wrapNearest ?
282  lattice.wrap_nearest_delta(coni) : lattice.wrap_delta(coni) );
283  con[i] = trans;
284  }
285  coor[i] = coor[i] + con[ci];
286  }
287  delete [] con;
288 #endif
289 }
290 
291 // handle index translation between global and selection spaces
292 template <class xVector, class xDone>
293  void wrap_coor_int_dcd_selection(xVector *coor, Lattice &lattice, xDone *done, int index) {
295  if ( *done ) return;
296  *done = 1;
297  if ( ! ( simParams->wrapAll || simParams->wrapWater ) ) return;
298  const int wrapNearest = simParams->wrapNearest;
299  const int wrapAll = simParams->wrapAll;
300  Molecule *molecule = Node::Object()->molecule;
301  const int n = molecule->get_dcd_selection_size(index);
302  int i;
303 #ifndef MEM_OPT_VERSION
304  Position *con = new Position[n];
305  for ( i = 0; i < n; ++i ) {
306  int molIndex = molecule->get_atom_index_from_dcd_selection(index, i);
307  con[i] = 0;
308  int ci = molecule->get_cluster(molIndex);
309  int dcdci = molecule->get_dcd_selection_index_from_atom_id(index, ci);
310  // the cluster index might not be in the selection
311  if(dcdci>=0)
312  con[dcdci] += coor[i];
313  }
314  for ( i = 0; i < n; ++i ) {
315  int molIndex = molecule->get_atom_index_from_dcd_selection(index, i);
316  if ( ! wrapAll && ! molecule->is_water(molIndex) ) continue;
317  int ci = molecule->get_cluster(molIndex);
318  int dcdci = molecule->get_dcd_selection_index_from_atom_id(index, ci);
319  if ( ci == molIndex ) {
320  Vector coni = con[i] / molecule->get_clusterSize(molIndex);
321  Vector trans = ( wrapNearest ?
322  lattice.wrap_nearest_delta(coni) : lattice.wrap_delta(coni) );
323  con[i] = trans;
324  }
325  if(dcdci>0)
326  coor[i] = coor[i] + con[dcdci];
327  else
328  coor[i] = coor[i];
329  }
330  delete [] con;
331 #endif
332 }
333 
334  void wrap_coor_dcd_selection(Vector *coor, Lattice &lattice, double *done, int index) {
335  wrap_coor_int_dcd_selection(coor,lattice,done, index);
336 };
337 
338  void wrap_coor_dcd_selection(FloatVector *coor, Lattice &lattice, float *done, int index) {
339  wrap_coor_int_dcd_selection(coor,lattice,done, index);
340 };
341 
342 void wrap_coor(Vector *coor, Lattice &lattice, double *done) {
343  wrap_coor_int(coor,lattice,done);
344 };
345 
346 void wrap_coor(FloatVector *coor, Lattice &lattice, float *done) {
347  wrap_coor_int(coor,lattice,done);
348 };
349 
350 void Output::coordinate(int timestep, int n, Vector *coor, FloatVector *fcoor,
351  Lattice &lattice)
352 {
354  Molecule *molecule = Node::Object()->molecule;
355  double coor_wrapped = 0;
356  float fcoor_wrapped = 0;
357 
358  if ( timestep >= 0 ) {
359 
360  // Output a DCD trajectory
361  if ( simParams->dcdFrequency &&
362  ((timestep % simParams->dcdFrequency) == 0) )
363  {
364  wrap_coor(fcoor,lattice,&fcoor_wrapped);
365  output_dcdfile(timestep, n, fcoor,
366  simParams->dcdUnitCell ? &lattice : NULL, 0);
367  }
368 
369  // Output any DCD selection trajectories that this timestep mods
370  if ( simParams->dcdSelectionOn)
371  {
372  bool needCleanup = false;
373 
374  for(int index=0; index<16;++index)
375  {
376  int frequency=molecule->dcdSelectionParams[index].frequency;
377  uint16 tag=molecule->dcdSelectionParams[index].tag;
378  int size=molecule->dcdSelectionParams[index].size;
379  if(frequency>0 && (timestep % frequency) == 0)
380  {
381  FloatVector *dcdSelectionFcoor = fcoor;
382  int dcdSelectionNpoints = n;
383  if(dcdSelectionNpoints != molecule->get_dcd_selection_size(index))
384  {
385  // on intervals when some other output is also happening, we have
386  // to filter out a copy of the selection from the full
387  // collected output then wrap and output accordingly
388  dcdSelectionNpoints = size;
389  dcdSelectionFcoor = new FloatVector[dcdSelectionNpoints];
390  needCleanup = true;
391  for(int i=0; i<n ;i++)
392  {
393  int offset = molecule->get_dcd_selection_index_from_atom_id(index, i);
394  if(offset >= 0)
395  dcdSelectionFcoor[offset] = fcoor[i];
396  }
397  }
398  else
399  {
400  dcdSelectionFcoor = fcoor;
401  }
402  wrap_coor_dcd_selection(dcdSelectionFcoor, lattice, &fcoor_wrapped, index);
403  output_dcdfile(timestep, dcdSelectionNpoints, dcdSelectionFcoor,
404  simParams->dcdUnitCell ? &lattice : NULL, tag);
405  if(needCleanup)
406  delete [] dcdSelectionFcoor;
407  }
408 
409  }
410  }
411 
412  // Output a restart file
413  if ( simParams->restartFrequency &&
414  ((timestep % simParams->restartFrequency) == 0) )
415  {
416  iout << "WRITING COORDINATES TO RESTART FILE AT STEP "
417  << timestep << "\n" << endi;
418  wrap_coor(coor,lattice,&coor_wrapped);
419  output_restart_coordinates(coor, n, timestep);
420  iout << "FINISHED WRITING RESTART COORDINATES\n" <<endi;
421  fflush(stdout);
422  }
423 
424  // Interactive MD
425  if ( simParams->IMDon &&
426  ( ((timestep % simParams->IMDfreq) == 0) ||
427  (timestep == simParams->firstTimestep) ) )
428  {
429 
430  if ((simParams->IMDversion == IMDversion_t::IMDv2) || ((simParams->IMDversion == IMDversion_t::IMDv3)
431  && ((simParams->IMDsendsettings.box_switch == 1) || (simParams->IMDsendsettings.fcoords_switch == 1))))
432  {
433  IMDOutput *imd = NULL;
434 #ifdef NODEGROUP_FORCE_REGISTER
435  if (simParams->CUDASOAintegrate) {
436  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
437  imd = cpdata.ckLocalBranch()->imd;
438  }
439  else
440 #endif
441  {
442  imd = Node::Object()->imd;
443  }
444 
445  if ((imd != NULL) && ((simParams->IMDversion == IMDversion_t::IMDv3)
446  && (simParams->IMDsendsettings.box_switch == 1))) {
447  IMDBox box = {(float)lattice.a().x, (float)lattice.a().y, (float)lattice.a().z,
448  (float)lattice.b().x, (float)lattice.b().y, (float)lattice.b().z,
449  (float)lattice.c().x, (float)lattice.c().y, (float)lattice.c().z};
450 
451  if (imd != NULL) imd->gather_box(timestep, &box);
452  }
453 
454 
455  if ((imd != NULL) && ((simParams->IMDversion == IMDversion_t::IMDv2) || ((simParams->IMDversion == IMDversion_t::IMDv3)
456  && (simParams->IMDsendsettings.fcoords_switch == 1)))) {
457  if ((simParams->IMDversion == IMDversion_t::IMDv2) || ((simParams->IMDversion == IMDversion_t::IMDv3)
458  && (simParams->IMDsendsettings.wrap_switch == 1)))
459  wrap_coor(fcoor,lattice,&fcoor_wrapped);
460  if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
461  }
462 
463  }
464  }
465 
466  }
467 
468  if (timestep == EVAL_MEASURE)
469  {
470 #ifdef NAMD_TCL
471  wrap_coor(coor,lattice,&coor_wrapped);
472  Node::Object()->getScript()->measure(coor);
473 #endif
474  }
475 
476  // Output final coordinates
477  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
478  {
479  int realstep = ( timestep == FILE_OUTPUT ?
480  simParams->firstTimestep : simParams->N );
481  iout << "WRITING COORDINATES TO OUTPUT FILE AT STEP "
482  << realstep << "\n" << endi;
483  fflush(stdout);
484  wrap_coor(coor,lattice,&coor_wrapped);
485  output_final_coordinates(coor, n, realstep);
486  }
487 
488  // Close trajectory files
489  if (timestep == END_OF_RUN)
490  {
491  if (simParams->dcdFrequency) output_dcdfile(END_OF_RUN,0,0,
492  simParams->dcdUnitCell
493  ? &lattice : NULL, 0);
494  if ( simParams->dcdSelectionOn)
495  {
496  for(int dcdSelectionIndex=0; dcdSelectionIndex<16;++dcdSelectionIndex)
497  {
498  int dcdSelectionFrequency = molecule->dcdSelectionParams[dcdSelectionIndex].frequency;
499  int dcdSelectionTag = molecule->dcdSelectionParams[dcdSelectionIndex].tag;
500  if(dcdSelectionFrequency)
501  output_dcdfile(END_OF_RUN,0,0,
502  simParams->dcdUnitCell
503  ? &lattice : NULL, dcdSelectionTag);
504  }
505  }
506  }
507 
508 }
509 
510 int Output::velocityNeeded(int timestep)
511 {
513 
514  if(simParams->benchTimestep) return 0;
515 
516  int velocitiesNeeded = 0;
517 
518  if ( timestep >= 0 ) {
519 
520  // Output a velocity DCD trajectory
521  if ( simParams->velDcdFrequency &&
522  ((timestep % simParams->velDcdFrequency) == 0) )
523  { velocitiesNeeded |= 1; }
524 
525  // Output a restart file
526  if ( simParams->restartFrequency &&
527  ((timestep % simParams->restartFrequency) == 0) )
528  { velocitiesNeeded |= 2; }
529 
530  // Interactive MD
531  if ( simParams->IMDon &&
532  ( ((timestep % simParams->IMDfreq) == 0) ||
533  (timestep == simParams->firstTimestep) ) &&
534  ((simParams->IMDversion == IMDversion_t::IMDv3)
535  && (simParams->IMDsendsettings.velocities_switch == 1)) )
536  { velocitiesNeeded |= 1; }
537 
538  }
539 
540  // Output final velocities
541  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
542  {
543  velocitiesNeeded |= 2;
544  }
545 
546  return velocitiesNeeded;
547 }
548 
549 void Output::velocity(int timestep, int n, Vector *vel, FloatVector *fvel)
550 {
552 
553  if ( timestep >= 0 ) {
554 
555  // Output velocity DCD trajectory
556  if ( simParams->velDcdFrequency &&
557  ((timestep % simParams->velDcdFrequency) == 0) )
558  {
559  output_veldcdfile(timestep, n, fvel);
560  }
561 
562  // Output restart file
563  if ( simParams->restartFrequency &&
564  ((timestep % simParams->restartFrequency) == 0) )
565  {
566  iout << "WRITING VELOCITIES TO RESTART FILE AT STEP "
567  << timestep << "\n" << endi;
568  output_restart_velocities(timestep, n, vel);
569  iout << "FINISHED WRITING RESTART VELOCITIES\n" <<endi;
570  fflush(stdout);
571  }
572 
573  // Interactive MD
574  if ( simParams->IMDon && (simParams->IMDversion == IMDversion_t::IMDv3) &&
575  ( ((timestep % simParams->IMDfreq) == 0) ||
576  (timestep == simParams->firstTimestep) ) &&
577  (simParams->IMDsendsettings.velocities_switch == 1) )
578  {
579  IMDOutput *imd = NULL;
580 #ifdef NODEGROUP_FORCE_REGISTER
581  if (simParams->CUDASOAintegrate) {
582  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
583  imd = cpdata.ckLocalBranch()->imd;
584  }
585  else
586 #endif
587  {
588  imd = Node::Object()->imd;
589  }
590  if (imd != NULL) {
591  scale_fvels(fvel, n, PDBVELFACTOR);
592  imd->gather_velocities(timestep, n, fvel);
593  }
594  }
595 
596  }
597 
598  // Output final velocities
599  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
600  {
601  int realstep = ( timestep == FILE_OUTPUT ?
602  simParams->firstTimestep : simParams->N );
603  iout << "WRITING VELOCITIES TO OUTPUT FILE AT STEP "
604  << realstep << "\n" << endi;
605  fflush(stdout);
606  output_final_velocities(realstep, n, vel);
607  }
608 
609  // Close trajectory files
610  if (timestep == END_OF_RUN)
611  {
612  if (simParams->velDcdFrequency) output_veldcdfile(END_OF_RUN,0,0);
613  // close force dcd file here since no final force output below
614  if (simParams->forceDcdFrequency) output_forcedcdfile(END_OF_RUN,0,0);
615  }
616 
617 }
618 
619 int Output::forceNeeded(int timestep)
620 {
622 
623  if(simParams->benchTimestep) return 0;
624 
625  int forcesNeeded = 0;
626 
627  if ( timestep >= 0 ) {
628 
629  // Output a force DCD trajectory
630  if ( simParams->forceDcdFrequency &&
631  ((timestep % simParams->forceDcdFrequency) == 0) )
632  { forcesNeeded |= 1; }
633 
634  // Iteractive MD
635  if ( simParams->IMDon &&
636  ( ((timestep % simParams->IMDfreq) == 0) ||
637  (timestep == simParams->firstTimestep) ) &&
638  ((simParams->IMDversion == IMDversion_t::IMDv2) || ((simParams->IMDversion == IMDversion_t::IMDv3)
639  && (simParams->IMDsendsettings.forces_switch == 1))) )
640  { forcesNeeded |= 1; }
641 
642  }
643 
644  // Output forces
645  if (timestep == FORCE_OUTPUT)
646  {
647  forcesNeeded |= 2;
648  }
649 
650  return forcesNeeded;
651 }
652 
653 void Output::force(int timestep, int n, Vector *frc, FloatVector *ffrc)
654 {
656 
657  if ( timestep >= 0 ) {
658 
659  // Output force DCD trajectory
660  if ( simParams->forceDcdFrequency &&
661  ((timestep % simParams->forceDcdFrequency) == 0) )
662  {
663  output_forcedcdfile(timestep, n, ffrc);
664  }
665 
666  // Interactive MD
667  if ( simParams->IMDon && (simParams->IMDversion == IMDversion_t::IMDv3) &&
668  ( ((timestep % simParams->IMDfreq) == 0) ||
669  (timestep == simParams->firstTimestep) ) &&
670  ((simParams->IMDsendsettings.forces_switch == 1)) )
671  {
672  IMDOutput *imd = NULL;
673 #ifdef NODEGROUP_FORCE_REGISTER
674  if (simParams->CUDASOAintegrate) {
675  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
676  imd = cpdata.ckLocalBranch()->imd;
677  }
678  else
679 #endif
680  {
681  imd = Node::Object()->imd;
682  }
683  if (imd != NULL) imd->gather_forces(timestep, n, ffrc);
684  }
685 
686  }
687 
688  // Output forces
689  if (timestep == FORCE_OUTPUT)
690  {
691  int realstep = simParams->firstTimestep;
692  iout << "WRITING FORCES TO OUTPUT FILE AT STEP "
693  << realstep << "\n" << endi;
694  fflush(stdout);
695  output_forces(realstep, n, frc);
696  }
697 
698  // Trajectory file closed by velocity() above
699 
700 }
701 
702 /************************************************************************/
703 /* */
704 /* FUNCTION output_restart_coordinates */
705 /* */
706 /* INPUTS: */
707 /* coor - Array of vectors containing current positions */
708 /* n - Number of coordinates to output */
709 /* timestep - Timestep for which the coordinates are being written */
710 /* */
711 /* This function writes out the current positions of all the atoms */
712 /* in PDB format to the restart file specified by the user in the */
713 /* configuration file. */
714 /* */
715 /************************************************************************/
716 
717 void Output::output_restart_coordinates(Vector *coor, int n, int timestep)
718 
719 {
720  char comment[128]; // Comment for header of PDB file
721  char timestepstr[20];
722 
723  int baselen = strlen(namdMyNode->simParams->restartFilename);
724  char *restart_name = new char[baselen+26];
725  const char *bsuffix = ".old";
726 
727  strcpy(restart_name, namdMyNode->simParams->restartFilename);
728  if ( namdMyNode->simParams->restartSave ) {
729  sprintf(timestepstr,".%d",timestep);
730  strcat(restart_name, timestepstr);
731  bsuffix = ".BAK";
732  }
733  strcat(restart_name, ".coor");
734 
735  NAMD_backup_file(restart_name,bsuffix);
736 
737  // Check to see if we should generate a binary or PDB file
738  if (!namdMyNode->simParams->binaryRestart)
739  {
740  // Generate a PDB restart file
741  sprintf(comment, "RESTART COORDINATES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
742 
743 #ifdef NODEGROUP_FORCE_REGISTER
744  if(namdMyNode->simParams->CUDASOAintegrate){
745  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
746  PatchData* pData = cpdata.ckLocalBranch();
747  pData->pdbData->set_all_positions(coor);
748  pData->pdbData->write(restart_name, comment);
749  }
750  else
751 #endif
752  {
753  namdMyNode->pdbData->set_all_positions(coor);
754  namdMyNode->pdbData->write(restart_name, comment);
755  }
756  }
757  else
758  {
759  // Generate a binary restart file
760  write_binary_file(restart_name, n, coor);
761  }
762 
763  delete [] restart_name;
764 
765  if ( namdMyNode->simParams->restartSaveDcd ) {
766  if ( ! output_dcdfile(END_OF_RUN, 0, 0, 0, 0) ) { // close old file
767  const char *old_name = namdMyNode->simParams->dcdFilename;
768  int old_len = strlen(old_name);
769  char *new_name = new char[old_len+26];
770  strcpy(new_name, old_name);
771  if ( old_len >= 4 && ! strcmp(new_name+old_len-4,".dcd") ) {
772  old_len -= 4;
773  new_name[old_len] = 0;
774  }
775  sprintf(timestepstr,".%d",timestep);
776  strcat(new_name, timestepstr);
777  strcat(new_name, ".dcd");
778  iout << "RENAMING COORDINATE DCD FILE " << old_name << " TO " << new_name << "\n" << endi;
779  NAMD_backup_file(new_name,".BAK");
780  while ( rename(old_name, new_name) ) {
781  if ( errno == EINTR || errno == EXDEV ) continue;
782  char err_msg[257];
783  sprintf(err_msg, "Unable to rename DCD file %s to %s", old_name, new_name);
784  NAMD_err(err_msg);
785  }
786  delete [] new_name;
787  }
788  }
789 
790 }
791 /* END OF FUNCTION output_restart_coordinates */
792 
793 /************************************************************************/
794 /* */
795 /* FUNCTION output_restart_velocities */
796 /* */
797 /* INPUTS: */
798 /* vel - Array of vectors containing current velocities */
799 /* timestep - Timestep for which the velocities are being written */
800 /* */
801 /* This function writes out the current velocites of all the atoms */
802 /* in PDB format to the restart file specified by the user in the */
803 /* configuration file. */
804 /* */
805 /************************************************************************/
806 
807 void Output::output_restart_velocities(int timestep, int n, Vector *vel)
808 
809 {
810  char comment[128]; // comment for the header of PDB file
811  char timestepstr[20];
812 
813  int baselen = strlen(namdMyNode->simParams->restartFilename);
814  char *restart_name = new char[baselen+26];
815  const char *bsuffix = ".old";
816 
817  strcpy(restart_name, namdMyNode->simParams->restartFilename);
818  if ( namdMyNode->simParams->restartSave ) {
819  sprintf(timestepstr,".%d",timestep);
820  strcat(restart_name, timestepstr);
821  bsuffix = ".BAK";
822  }
823  strcat(restart_name, ".vel");
824 
825  NAMD_backup_file(restart_name,bsuffix);
826 
827  // Check to see if we should write out a PDB or a binary file
828  if (!namdMyNode->simParams->binaryRestart)
829  {
830  // Write the coordinates to a PDB file. Multiple them by 20
831  // first to make the numbers bigger
832  sprintf(comment, "RESTART VELOCITIES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
833 
834  scale_vels(vel, n, PDBVELFACTOR);
835 
836 #ifdef NODEGROUP_FORCE_REGISTER
837  if(namdMyNode->simParams->CUDASOAintegrate){
838  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
839  PatchData* pData = cpdata.ckLocalBranch();
840  pData->pdbData->set_all_positions(vel);
841  pData->pdbData->write(restart_name, comment);
842  }
843  else
844 #endif
845  {
846  namdMyNode->pdbData->set_all_positions(vel);
847  namdMyNode->pdbData->write(restart_name, comment);
848  }
849  scale_vels(vel, n, PDBVELINVFACTOR);
850  }
851  else
852  {
853  // Write the velocities to a binary file
854  write_binary_file(restart_name, n, vel);
855  }
856 
857  delete [] restart_name;
858 }
859 /* END OF FUNCTION output_restart_velocities */
860 
861 
862 
863 // This is here so it can access Output.h and Node.h
865 
866  Output *output = Node::Object()->output;
867  if ( ! output ) return;
868 
869  output->output_dcdfile(END_OF_RUN, 0, 0, 0, 0);
870  Molecule *molecule = Node::Object()->molecule;
871  for(int dcdSelectionIndex=0; dcdSelectionIndex<16;++dcdSelectionIndex)
872  {
873  int dcdSelectionFrequency = molecule->dcdSelectionParams[dcdSelectionIndex].frequency;
874  int dcdSelectionTag = molecule->dcdSelectionParams[dcdSelectionIndex].tag;
875  if(dcdSelectionFrequency)
876  output->output_dcdfile(END_OF_RUN,0,0,0,dcdSelectionTag);
877  }
878 }
879 
881 
882  Output *output = Node::Object()->output;
883  if ( ! output ) return;
884 
885  output->output_veldcdfile(END_OF_RUN, 0, 0);
886 
887 }
888 
889 void Output::setReplicaDcdIndex(int index) {
890  replicaDcdActive = 1;
891  replicaDcdIndex = index;
892 }
893 
894 void Output::replicaDcdInit(int index, const char *filename) {
895  replicaDcdActive = 1;
896  replicaDcdIndex = index;
897  int msgsize = sizeof(ReplicaDcdInitMsg) + strlen(filename);
898  ReplicaDcdInitMsg *msg = (ReplicaDcdInitMsg *) CmiAlloc(msgsize);
899  msg->srcPart = CmiMyPartition();
900  msg->dcdIndex = replicaDcdIndex;
901  msg->dcdSelectIndex = 16;
902  strcpy(msg->data, filename);
903  sendReplicaDcdInit(abs(replicaDcdIndex) % CmiNumPartitions(), msg, msgsize);
904 }
905 
906 void Output::replicaDcdSelectInit(int index, const char *tag, const char *filename) {
907  replicaDcdActive = 1;
908  replicaDcdIndex = index;
909  int msgsize = sizeof(ReplicaDcdInitMsg) + strlen(filename);
910  ReplicaDcdInitMsg *msg = (ReplicaDcdInitMsg *) CmiAlloc(msgsize);
911  msg->srcPart = CmiMyPartition();
912  msg->dcdIndex = replicaDcdIndex;
913  Molecule *molecule = namdMyNode->molecule;
915  strcpy(msg->data, filename);
916  sendReplicaDcdInit(abs(replicaDcdIndex) % CmiNumPartitions(), msg, msgsize);
917 }
918 
919 
921  replicaDcdFile &f = (msg->dcdSelectIndex<16) ? replicaDcdSelectFiles[std::make_pair(msg->dcdIndex,msg->dcdSelectIndex)]: replicaDcdFiles[msg->dcdIndex];
922  if ( f.fileid ) {
923  iout << "CLOSING REPLICA DCD FILE " << msg->dcdIndex << " " << f.filename.c_str() << "\n" << endi;
924  close_dcd_write(f.fileid);
925  f.fileid = 0;
926  }
927  f.filename = (const char*) msg->data;
928  sendReplicaDcdAck(msg->srcPart, (ReplicaDcdAckMsg*) CmiAlloc(sizeof(ReplicaDcdAckMsg)));
929 }
930 
932  Molecule *molecule = namdMyNode->molecule;
933  if ( msg->dcdSelectIndex>=16 && ! replicaDcdFiles.count(msg->dcdIndex) ||
934  ( ! replicaDcdFiles.count(msg->dcdIndex) )) {
935  char err_msg[257];
936  sprintf(err_msg, "Unknown replicaDcdFile identifier %d\n", msg->dcdIndex);
937  NAMD_die(err_msg);
938  }
939  replicaDcdFile &f = (msg->dcdSelectIndex<16) ? replicaDcdSelectFiles[std::make_pair(msg->dcdIndex,msg->dcdSelectIndex)]: replicaDcdFiles[msg->dcdIndex];
940 
941  if ( ! f.fileid ) {
942  // Open the DCD file
943  iout << "OPENING REPLICA DCD FILE " << msg->dcdIndex << " " << f.filename.c_str() << "\n" << endi;
944 
945  f.fileid=open_dcd_write(f.filename.c_str());
946 
947  if (f.fileid == DCD_FILEEXISTS) {
948  char err_msg[257];
949  sprintf(err_msg, "DCD file %s already exists!!", f.filename.c_str());
950  NAMD_err(err_msg);
951  } else if (f.fileid < 0) {
952  char err_msg[257];
953  if(msg->dcdSelectIndex<16)
954  sprintf(err_msg, "Couldn't open DCD Index %d Select Index %d file %s", msg->dcdIndex, msg->dcdSelectIndex, f.filename.c_str());
955  else
956  sprintf(err_msg, "Couldn't open DCD Index %d file %s", msg->dcdIndex, f.filename.c_str());
957  NAMD_err(err_msg);
958  } else if (! f.fileid) {
959  NAMD_bug("Output::recvReplicaDcdData open_dcd_write returned fileid of zero");
960  }
961 
962  // Write out the header
963  int ret_code = write_dcdheader(f.fileid, f.filename.c_str(),
964  msg->numAtoms, msg->NFILE, msg->NPRIV, msg->NSAVC, msg->NSTEP,
965  msg->DELTA, msg->with_unitcell);
966 
967  if (ret_code<0) {
968  NAMD_err("Writing of DCD header failed!!");
969  }
970  }
971 
972  // Write out the values for this timestep
973  iout << "WRITING TO REPLICA DCD FILE " << msg->dcdIndex << " " << f.filename.c_str() << "\n" << endi;
974  float *msgx = (float*) msg->data;
975  float *msgy = msgx + msg->numAtoms;
976  float *msgz = msgy + msg->numAtoms;
977  int ret_code = write_dcdstep(f.fileid, msg->numAtoms, msgx, msgy, msgz,
978  msg->with_unitcell ? msg->unitcell : 0);
979  if (ret_code < 0) NAMD_err("Writing of DCD step failed!!");
980 
981  sendReplicaDcdAck(msg->srcPart, (ReplicaDcdAckMsg*) CmiAlloc(sizeof(ReplicaDcdAckMsg)));
982 }
983 
984 
985 /************************************************************************/
986 /* */
987 /* FUNCTION output_dcdfile */
988 /* */
989 /* INPUTS: */
990 /* timestep - Current timestep */
991 /* n - Number of atoms in simulation */
992 /* coor - Coordinate vectors for all atoms */
993 /* lattice - periodic cell data; NULL if not to be written */
994 /* */
995 /* This function maintains the interface between the Output object */
996 /* and the dcd writing routines contained in dcdlib. */
997 /* */
998 /************************************************************************/
999 
1000 #define RAD2DEG 180.0/3.14159265359
1001 
1002 int Output::output_dcdfile(int timestep, int n, FloatVector *coor,
1003  const Lattice *lattice, int dcdSelectTag)
1004 
1005 {
1006  static Bool first[maxDCD]={true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true}; // Flag indicating first call
1007  static int fileid[maxDCD]; // File id for the dcd file
1008 
1009  static float *x = nullptr; // Array to hold x
1010  static float *y = nullptr; // Array to hold y
1011  static float *z = nullptr; // Array to hold z
1012  static int n_alloc = 0; // allocated size
1013 
1014  int i; // Loop counter
1015  int ret_code; // Return code from DCD calls
1016  SimParameters *simParams = namdMyNode->simParams;
1017  Molecule *molecule = namdMyNode->molecule;
1018  // If this is the last time we will be writing coordinates,
1019  // close the file before exiting
1020  char *dcdFilename = simParams->dcdFilename;
1021  int dcdSelectIndex=dcdSelectTag-1;
1022  if(dcdSelectTag >0 && dcdSelectTag <= 16)
1023  {// look it up
1024  dcdFilename = molecule->dcdSelectionParams[dcdSelectIndex].outFilename;
1025  }
1026  if ( timestep == END_OF_RUN ) {
1027  for ( std::map<int,replicaDcdFile>::iterator it = replicaDcdFiles.begin();
1028  it != replicaDcdFiles.end(); ++it ) {
1029  replicaDcdFile &f = it->second;
1030  if ( f.fileid ) {
1031  iout << "CLOSING REPLICA DCD FILE " << it->first << " " << f.filename.c_str() << "\n" << endi;
1032  close_dcd_write(f.fileid);
1033  f.fileid = 0;
1034  }
1035  }
1036  for ( std::map<std::pair<int,uint16_t>,replicaDcdFile>::iterator it = replicaDcdSelectFiles.begin();
1037  it != replicaDcdSelectFiles.end(); ++it ) {
1038  replicaDcdFile &f = it->second;
1039  if ( f.fileid ) {
1040  iout << "CLOSING REPLICA DCD SELECT FILE " << it->first.first << " " << f.filename.c_str() << "\n" << endi;
1041  close_dcd_write(f.fileid);
1042  f.fileid = 0;
1043  }
1044  }
1045 
1046  int rval = 0;
1047  if ( ! first[dcdSelectTag] ) {
1048  iout << "CLOSING COORDINATE DCD FILE " << dcdFilename << "\n" << endi;
1049  close_dcd_write(fileid[dcdSelectTag]);
1050  } else {
1051  iout << "COORDINATE DCD FILE " << dcdFilename << " WAS NOT CREATED\n" << endi;
1052  rval = -1;
1053  }
1054  first[dcdSelectTag] = 1;
1055  fileid[dcdSelectTag] = 0;
1056  return rval;
1057  }
1058 
1059  if ( replicaDcdActive ) {
1060  int msgsize = sizeof(ReplicaDcdDataMsg) + 3*n*sizeof(float);
1061  ReplicaDcdDataMsg *msg = (ReplicaDcdDataMsg *) CmiAlloc(msgsize);
1062  float *msgx = (float*) msg->data;
1063  float *msgy = msgx + n;
1064  float *msgz = msgy + n;
1065  for (i=0; i<n; i++) { msgx[i] = coor[i].x; }
1066  for (i=0; i<n; i++) { msgy[i] = coor[i].y; }
1067  for (i=0; i<n; i++) { msgz[i] = coor[i].z; }
1068  msg->numAtoms = n;
1069  lattice_to_unitcell(lattice,msg->unitcell);
1070  msg->with_unitcell = lattice ? 1 : 0;
1071  if(dcdSelectTag==0)
1072  msg->NSAVC = simParams->dcdFrequency;
1073  else
1074  msg->NSAVC = molecule->dcdSelectionParams[dcdSelectIndex].frequency;
1075  msg->NPRIV = timestep;
1076  msg->NSTEP = msg->NPRIV - msg->NSAVC;
1077  msg->NFILE = 0;
1078  msg->DELTA = simParams->dt/TIMEFACTOR;
1079  msg->srcPart = CmiMyPartition();
1080  msg->dcdIndex = replicaDcdIndex;
1081  msg->dcdSelectIndex = dcdSelectIndex;
1082  sendReplicaDcdData(abs(replicaDcdIndex) % CmiNumPartitions(), msg, msgsize);
1083  return 0;
1084  }
1085  if (first[dcdSelectTag])
1086  {
1087  // Allocate x, y, and z arrays since the DCD file routines
1088  // need them passed as three independant arrays to be
1089  // efficient
1090  if ( n > n_alloc ) {
1091  if (x) delete [] x;
1092  x = new float[3*n];
1093  y = x + n;
1094  z = x + 2*n;
1095  n_alloc = n;
1096  }
1097 
1098  // Open the DCD file
1099  iout << "OPENING COORDINATE DCD FILE\n" << endi;
1100  fileid[dcdSelectTag] = open_dcd_write(dcdFilename);
1101  if (fileid[dcdSelectTag] == DCD_FILEEXISTS)
1102  {
1103  char err_msg[257];
1104 
1105  sprintf(err_msg, "DCD file %s already exists!!",
1106  dcdFilename);
1107 
1108  NAMD_err(err_msg);
1109  }
1110  else if (fileid[dcdSelectTag] < 0)
1111  {
1112  char err_msg[257];
1113 
1114  sprintf(err_msg, "Couldn't open DCD file %s",
1115  dcdFilename);
1116 
1117  NAMD_err(err_msg);
1118  }
1119 
1120  int NSAVC, NFILE, NPRIV, NSTEP;
1121  if(dcdSelectTag==0)
1122  NSAVC = simParams->dcdFrequency;
1123  else
1124  NSAVC = molecule->dcdSelectionParams[dcdSelectIndex].frequency;
1125  NPRIV = timestep;
1126  NSTEP = NPRIV - NSAVC;
1127  NFILE = 0;
1128 
1129  // Write out the header
1130  ret_code = write_dcdheader(fileid[dcdSelectTag],
1131  dcdFilename,
1132  n, NFILE, NPRIV, NSAVC, NSTEP,
1133  simParams->dt/TIMEFACTOR, lattice != NULL);
1134 
1135  if (ret_code<0)
1136  {
1137  NAMD_err("Writing of DCD header failed!!");
1138  }
1139 
1140  first[dcdSelectTag] = FALSE;
1141  }
1142 
1143  // Copy the coordinates for output
1144  for (i=0; i<n; i++)
1145  {
1146  x[i] = coor[i].x;
1147  y[i] = coor[i].y;
1148  z[i] = coor[i].z;
1149  }
1150 
1151  // Write out the values for this timestep
1152  if(dcdSelectTag>0)
1153  iout << "WRITING COORDINATES TO DCD SELECT FILE " << dcdFilename << " AT STEP "
1154  << timestep << "\n" << endi;
1155  else
1156  iout << "WRITING COORDINATES TO DCD FILE " << dcdFilename << " AT STEP "
1157  << timestep << "\n" << endi;
1158  fflush(stdout);
1159  if (lattice) {
1160  double unitcell[6];
1161  lattice_to_unitcell(lattice,unitcell);
1162  ret_code = write_dcdstep(fileid[dcdSelectTag], n, x, y, z, unitcell);
1163  } else {
1164  ret_code = write_dcdstep(fileid[dcdSelectTag], n, x, y, z, NULL);
1165  }
1166  if (ret_code < 0)
1167  {
1168  NAMD_err("Writing of DCD step failed!!");
1169  }
1170 
1171  return 0;
1172 }
1173 /* END OF FUNCTION output_dcdfile */
1174 
1175 /************************************************************************/
1176 /* */
1177 /* FUNCTION output_final_coordinates */
1178 /* */
1179 /* INPUTS: */
1180 /* coor - Array of vectors containing final coordinates */
1181 /* n - Number of coordinates to output */
1182 /* timestep - Timestep that coordinates are being written in */
1183 /* */
1184 /* This function writes out the final coordinates for the */
1185 /* simulation in PDB format to the file specified in the config */
1186 /* file. */
1187 /* */
1188 /************************************************************************/
1189 
1190 void Output::output_final_coordinates(Vector *coor, int n, int timestep)
1191 
1192 {
1193  char output_name[140]; // Output filename
1194  char comment[128]; // comment for PDB header
1195 
1196  // Built the output filename
1197  strcpy(output_name, namdMyNode->simParams->outputFilename);
1198  strcat(output_name, ".coor");
1199 
1200  NAMD_backup_file(output_name);
1201 
1202  // Check to see if we should write out a binary file or a
1203  // PDB file
1204  if (!namdMyNode->simParams->binaryOutput)
1205  {
1206  sprintf(comment, "FINAL COORDINATES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
1207 
1208 #ifdef NODEGROUP_FORCE_REGISTER
1209  if(namdMyNode->simParams->CUDASOAintegrate){
1210  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
1211  PatchData* pData = cpdata.ckLocalBranch();
1212  pData->pdbData->set_all_positions(coor);
1213  pData->pdbData->write(output_name, comment);
1214  }
1215  else
1216 #endif
1217  {
1218  namdMyNode->pdbData->set_all_positions(coor);
1219  namdMyNode->pdbData->write(output_name, comment);
1220  }
1221  }
1222  else
1223  {
1224  // Write the velocities to a binary file
1225  write_binary_file(output_name, n, coor);
1226  }
1227 }
1228 /* END OF FUNCTION output_final_coordinates */
1229 
1230 /************************************************************************/
1231 /* */
1232 /* FUNCTION output_final_velocities */
1233 /* */
1234 /* INPUTS: */
1235 /* vel - Array of vectors containing final velocities */
1236 /* timestep - Timestep that vleocities are being written in */
1237 /* */
1238 /* This function writes out the final vleocities for the */
1239 /* simulation in PDB format to the file specified in the config */
1240 /* file. */
1241 /* */
1242 /************************************************************************/
1243 
1244 void Output::output_final_velocities(int timestep, int n, Vector *vel)
1245 
1246 {
1247  char output_name[140]; // Output filename
1248  char comment[128]; // Comment for PDB header
1249 
1250  // Build the output filename
1251  strcpy(output_name, namdMyNode->simParams->outputFilename);
1252  strcat(output_name, ".vel");
1253 
1254  NAMD_backup_file(output_name);
1255 
1256  // Check to see if we should write a PDB or binary file
1257  if (!(namdMyNode->simParams->binaryOutput))
1258  {
1259  // Write the final velocities to a PDB file
1260  sprintf(comment, "FINAL VELOCITIES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
1261 
1262  scale_vels(vel, n, PDBVELFACTOR);
1263 #ifdef NODEGROUP_FORCE_REGISTER
1264  if(namdMyNode->simParams->CUDASOAintegrate){
1265  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
1266  PatchData* pData = cpdata.ckLocalBranch();
1267  pData->pdbData->set_all_positions(vel);
1268  pData->pdbData->write(output_name, comment);
1269  }
1270  else
1271 #endif
1272  {
1273  namdMyNode->pdbData->set_all_positions(vel);
1274  namdMyNode->pdbData->write(output_name, comment);
1275  }
1276  scale_vels(vel, n, PDBVELINVFACTOR);
1277  }
1278  else
1279  {
1280  // Write the coordinates to a binary file
1281  write_binary_file(output_name, n, vel);
1282  }
1283 
1284 }
1285 /* END OF FUNCTION output_final_velocities */
1286 
1287 /************************************************************************/
1288 /* */
1289 /* FUNCTION output_veldcdfile */
1290 /* */
1291 /* INPUTS: */
1292 /* timestep - Current timestep */
1293 /* n - Number of atoms in simulation */
1294 /* coor - velocity vectors for all atoms */
1295 /* */
1296 /* This function maintains the interface between the Output object */
1297 /* and the dcd writing routines contained in dcdlib. This fucntion */
1298 /* writes out the velocity vectors in DCD format. */
1299 /* */
1300 /************************************************************************/
1301 
1302 void Output::output_veldcdfile(int timestep, int n, FloatVector *vel)
1303 
1304 {
1305  static Bool first=TRUE; // Flag indicating first call
1306  static int fileid; // File id for the dcd file
1307  static float *x = nullptr; // Array to hold x
1308  static float *y = nullptr; // Array to hold y
1309  static float *z = nullptr; // Array to hold z
1310  static int n_alloc = 0; // allocated size
1311  int i; // Loop counter
1312  int ret_code; // Return code from DCD calls
1314 
1315  // If this is the last time we will be writing coordinates,
1316  // close the file before exiting
1317  if ( timestep == END_OF_RUN ) {
1318  if ( ! first ) {
1319  iout << "CLOSING VELOCITY DCD FILE\n" << endi;
1320  close_dcd_write(fileid);
1321  } else {
1322  iout << "VELOCITY DCD FILE WAS NOT CREATED\n" << endi;
1323  }
1324  first = TRUE;
1325  fileid = 0;
1326  return;
1327  }
1328 
1329  if (first)
1330  {
1331  // Allocate x, y, and z arrays since the DCD file routines
1332  // need them passed as three independant arrays to be
1333  // efficient
1334  if ( n > n_alloc ) {
1335  if (x) delete [] x;
1336  x = new float[3*n];
1337  y = x + n;
1338  z = x + 2*n;
1339  n_alloc = n;
1340  }
1341 
1342  // Open the DCD file
1343  iout << "OPENING VELOCITY DCD FILE\n" << endi;
1344 
1345  fileid=open_dcd_write(namdMyNode->simParams->velDcdFilename);
1346 
1347  if (fileid == DCD_FILEEXISTS)
1348  {
1349  char err_msg[257];
1350 
1351  sprintf(err_msg, "Velocity DCD file %s already exists!!",
1352  namdMyNode->simParams->velDcdFilename);
1353 
1354  NAMD_err(err_msg);
1355  }
1356  else if (fileid < 0)
1357  {
1358  char err_msg[257];
1359 
1360  sprintf(err_msg, "Couldn't open velocity DCD file %s",
1361  namdMyNode->simParams->velDcdFilename);
1362 
1363  NAMD_err(err_msg);
1364  }
1365 
1366  int NSAVC, NFILE, NPRIV, NSTEP;
1367  NSAVC = simParams->velDcdFrequency;
1368  NPRIV = timestep;
1369  NSTEP = NPRIV - NSAVC;
1370  NFILE = 0;
1371 
1372  // Write out the header
1373  const int with_unitcell = 0;
1374  ret_code = write_dcdheader(fileid,
1375  simParams->velDcdFilename,
1376  n, NFILE, NPRIV, NSAVC, NSTEP,
1377  simParams->dt/TIMEFACTOR, with_unitcell);
1378 
1379 
1380  if (ret_code<0)
1381  {
1382  NAMD_err("Writing of velocity DCD header failed!!");
1383  }
1384 
1385  first = FALSE;
1386  }
1387 
1388  // Copy the coordinates for output
1389  for (i=0; i<n; i++)
1390  {
1391  x[i] = vel[i].x;
1392  y[i] = vel[i].y;
1393  z[i] = vel[i].z;
1394  }
1395 
1396  // Write out the values for this timestep
1397  iout << "WRITING VELOCITIES TO DCD FILE AT STEP "
1398  << timestep << "\n" << endi;
1399  fflush(stdout);
1400  ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
1401 
1402  if (ret_code < 0)
1403  {
1404  NAMD_err("Writing of velocity DCD step failed!!");
1405  }
1406 
1407 }
1408 /* END OF FUNCTION output_veldcdfile */
1409 
1410 /************************************************************************/
1411 /* */
1412 /* FUNCTION output_forces */
1413 /* */
1414 /* INPUTS: */
1415 /* frc - Array of vectors containing final forces */
1416 /* timestep - Timestep that vleocities are being written in */
1417 /* */
1418 /* This function writes out the final vleocities for the */
1419 /* simulation in PDB format to the file specified in the config */
1420 /* file. */
1421 /* */
1422 /************************************************************************/
1423 
1424 void Output::output_forces(int timestep, int n, Vector *frc)
1425 
1426 {
1427  char output_name[140]; // Output filename
1428  char comment[128]; // Comment for PDB header
1429 
1430  // Build the output filename
1431  strcpy(output_name, namdMyNode->simParams->outputFilename);
1432  strcat(output_name, ".force");
1433 
1434  NAMD_backup_file(output_name);
1435 
1436  // Check to see if we should write a PDB or binary file
1437  if (!(namdMyNode->simParams->binaryOutput))
1438  {
1439  // Write the forces to a PDB file
1440  sprintf(comment, "FORCES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
1441 #ifdef NODEGROUP_FORCE_REGISTER
1442  if(namdMyNode->simParams->CUDASOAintegrate){
1443  CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
1444  PatchData* pData = cpdata.ckLocalBranch();
1445  pData->pdbData->set_all_positions(frc);
1446  pData->pdbData->write(output_name, comment);
1447  }
1448  else
1449 #endif
1450  {
1451  namdMyNode->pdbData->set_all_positions(frc);
1452  namdMyNode->pdbData->write(output_name, comment);
1453  }
1454  }
1455  else
1456  {
1457  // Write the coordinates to a binary file
1458  write_binary_file(output_name, n, frc);
1459  }
1460 
1461 }
1462 /* END OF FUNCTION output_forces */
1463 
1464 /************************************************************************/
1465 /* */
1466 /* FUNCTION output_forcedcdfile */
1467 /* */
1468 /* INPUTS: */
1469 /* timestep - Current timestep */
1470 /* n - Number of atoms in simulation */
1471 /* frc - force vectors for all atoms */
1472 /* */
1473 /* This function maintains the interface between the Output object */
1474 /* and the dcd writing routines contained in dcdlib. This fucntion */
1475 /* writes out the force vectors in DCD format. */
1476 /* */
1477 /************************************************************************/
1478 
1479 void Output::output_forcedcdfile(int timestep, int n, FloatVector *frc)
1480 
1481 {
1482  static Bool first=TRUE; // Flag indicating first call
1483  static int fileid; // File id for the dcd file
1484  static float *x = nullptr; // Array to hold x
1485  static float *y = nullptr; // Array to hold y
1486  static float *z = nullptr; // Array to hold z
1487  static int n_alloc = 0; // allocated size
1488  int i; // Loop counter
1489  int ret_code; // Return code from DCD calls
1491 
1492  // If this is the last time we will be writing coordinates,
1493  // close the file before exiting
1494  if ( timestep == END_OF_RUN ) {
1495  if ( ! first ) {
1496  iout << "CLOSING FORCE DCD FILE\n" << endi;
1497  close_dcd_write(fileid);
1498  } else {
1499  iout << "FORCE DCD FILE WAS NOT CREATED\n" << endi;
1500  }
1501  return;
1502  }
1503 
1504  if (first)
1505  {
1506  // Allocate x, y, and z arrays since the DCD file routines
1507  // need them passed as three independant arrays to be
1508  // efficient
1509  if ( n > n_alloc ) {
1510  if (x) delete [] x;
1511  x = new float[3*n];
1512  y = x + n;
1513  z = x + 2*n;
1514  n_alloc = n;
1515  }
1516 
1517  // Open the DCD file
1518  iout << "OPENING FORCE DCD FILE\n" << endi;
1519 
1520  fileid=open_dcd_write(namdMyNode->simParams->forceDcdFilename);
1521 
1522  if (fileid == DCD_FILEEXISTS)
1523  {
1524  char err_msg[257];
1525 
1526  sprintf(err_msg, "Force DCD file %s already exists!!",
1527  namdMyNode->simParams->forceDcdFilename);
1528 
1529  NAMD_err(err_msg);
1530  }
1531  else if (fileid < 0)
1532  {
1533  char err_msg[257];
1534 
1535  sprintf(err_msg, "Couldn't open force DCD file %s",
1536  namdMyNode->simParams->forceDcdFilename);
1537 
1538  NAMD_err(err_msg);
1539  }
1540 
1541  int NSAVC, NFILE, NPRIV, NSTEP;
1542  NSAVC = simParams->forceDcdFrequency;
1543  NPRIV = timestep;
1544  NSTEP = NPRIV - NSAVC;
1545  NFILE = 0;
1546 
1547  // Write out the header
1548  const int with_unitcell = 0;
1549  ret_code = write_dcdheader(fileid,
1550  simParams->forceDcdFilename,
1551  n, NFILE, NPRIV, NSAVC, NSTEP,
1552  simParams->dt/TIMEFACTOR, with_unitcell);
1553 
1554 
1555  if (ret_code<0)
1556  {
1557  NAMD_err("Writing of force DCD header failed!!");
1558  }
1559 
1560  first = FALSE;
1561  }
1562 
1563  // Copy the coordinates for output
1564  for (i=0; i<n; i++)
1565  {
1566  x[i] = frc[i].x;
1567  y[i] = frc[i].y;
1568  z[i] = frc[i].z;
1569  }
1570 
1571  // Write out the values for this timestep
1572  iout << "WRITING FORCES TO DCD FILE AT STEP "
1573  << timestep << "\n" << endi;
1574  fflush(stdout);
1575  ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
1576 
1577  if (ret_code < 0)
1578  {
1579  NAMD_err("Writing of force DCD step failed!!");
1580  }
1581 
1582 }
1583 /* END OF FUNCTION output_forcedcdfile */
1584 
1585 /************************************************************************/
1586 /* */
1587 /* FUNCTION write_binary_file */
1588 /* */
1589 /* INPUTS: */
1590 /* fname - file name to write velocities to */
1591 /* n - Number of atoms in system */
1592 /* vels - Array of vectors */
1593 /* */
1594 /* This function writes out vectors in binary format to */
1595 /* the specified file. */
1596 /* */
1597 /************************************************************************/
1598 
1599 void Output::write_binary_file(char *fname, int n, Vector *vecs)
1600 
1601 {
1602  char errmsg[256];
1603  int fd; // File descriptor
1604  int32 n32 = n;
1605 
1606  fd = NAMD_open(fname);
1607 
1608  sprintf(errmsg, "Error on write to binary file %s", fname);
1609 
1610  // Write out the number of atoms and the vectors
1611  NAMD_write(fd, (char *) &n32, sizeof(int32), errmsg);
1612  NAMD_write(fd, (char *) vecs, sizeof(Vector)*n, errmsg);
1613 
1614  NAMD_close(fd, fname);
1615 }
1616 /* END OF FUNCTION write_binary_file */
1617 
1618 /************************************************************************/
1619 /* */
1620 /* FUNCTION scale_vels */
1621 /* */
1622 /* INPUTS: */
1623 /* v - Array of velocity vectors */
1624 /* n - Number of atoms in system */
1625 /* fact - Scaling factor */
1626 /* */
1627 /* This function scales all the vectors passed in by a constant */
1628 /* factor. This is used before writing out velocity vectors that */
1629 /* need to be resized. */
1630 /* */
1631 /************************************************************************/
1632 
1633 void Output::scale_vels(Vector *v, int n, Real fact)
1634 
1635 {
1636  int i;
1637 
1638  for (i=0; i<n; i++)
1639  {
1640  v[i].x *= fact;
1641  v[i].y *= fact;
1642  v[i].z *= fact;
1643  }
1644 }
1645 /* END OF FUNCTION scale_vels */
1646 
1647 /************************************************************************/
1648 /* */
1649 /* FUNCTION scale_fvels */
1650 /* */
1651 /* INPUTS: */
1652 /* v - Array of velocity float vectors */
1653 /* n - Number of atoms in system */
1654 /* fact - Scaling factor */
1655 /* */
1656 /* This function scales all the vectors passed in by a constant */
1657 /* factor. This is used before writing out velocity vectors that */
1658 /* need to be resized. */
1659 /* */
1660 /************************************************************************/
1661 
1662 void Output::scale_fvels(FloatVector *v, int n, Real fact)
1663 
1664 {
1665  int i;
1666 
1667  for (i=0; i<n; i++)
1668  {
1669  v[i].x *= fact;
1670  v[i].y *= fact;
1671  v[i].z *= fact;
1672  }
1673 }
1674 /* END OF FUNCTION scale_fvels */
1675 
1676 
1677 #ifdef MEM_OPT_VERSION
1678 void ParOutput::velocityMaster(int timestep, int n){
1681 
1682  if ( timestep >= 0 ) {
1683 
1684  // Output velocity DCD trajectory
1685  if ( simParams->velDcdFrequency &&
1686  ((timestep % simParams->velDcdFrequency) == 0) )
1687  {
1688  output_veldcdfile_master(timestep, n);
1689  }
1690 
1691  // Output restart file
1692  if ( simParams->restartFrequency &&
1693  ((timestep % simParams->restartFrequency) == 0) )
1694  {
1695  iout << "WRITING VELOCITIES TO RESTART FILE AT STEP "
1696  << timestep << "\n" << endi;
1697  output_restart_velocities_master(timestep, n);
1698  iout << "FINISHED WRITING RESTART VELOCITIES\n" <<endi;
1699  fflush(stdout);
1700  }
1701 
1702  }
1703 
1704  // Output final velocities
1705  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
1706  {
1707  int realstep = ( timestep == FILE_OUTPUT ?
1708  simParams->firstTimestep : simParams->N );
1709  iout << "WRITING VELOCITIES TO OUTPUT FILE AT STEP "
1710  << realstep << "\n" << endi;
1711  fflush(stdout);
1712  output_final_velocities_master(n);
1713  }
1714 
1715  // Close trajectory files
1716  if (timestep == END_OF_RUN)
1717  {
1718  if (simParams->velDcdFrequency) output_veldcdfile_master(END_OF_RUN,0);
1719  if (simParams->forceDcdFrequency) output_forcedcdfile_master(END_OF_RUN,0);
1720  }
1721 
1722 }
1723 
1724 //output atoms' velocities from id fID to tID.
1725 void ParOutput::velocitySlave(int timestep, int fID, int tID, Vector *vecs){
1727 
1728  if ( timestep >= 0 ) {
1729 
1730  // Output velocity DCD trajectory
1731  if ( simParams->velDcdFrequency &&
1732  ((timestep % simParams->velDcdFrequency) == 0) )
1733  {
1734  output_veldcdfile_slave(timestep, fID, tID, vecs);
1735  }
1736 
1737  // Output restart file
1738  if ( simParams->restartFrequency &&
1739  ((timestep % simParams->restartFrequency) == 0) )
1740  {
1741  int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
1742  output_restart_velocities_slave(timestep, fID, tID, vecs, offset);
1743  }
1744 
1745  }
1746 
1747  // Output final velocities
1748  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
1749  {
1750  int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
1751  output_final_velocities_slave(fID, tID, vecs, offset);
1752  }
1753 
1754  // Close trajectory files
1755  if (timestep == END_OF_RUN)
1756  {
1757  if (simParams->velDcdFrequency) output_veldcdfile_slave(END_OF_RUN, 0, 0, NULL);
1758  if (simParams->forceDcdFrequency) output_forcedcdfile_slave(END_OF_RUN, 0, 0, NULL);
1759  }
1760 }
1761 
1762 void ParOutput::output_veldcdfile_master(int timestep, int n){
1763  int ret_code; // Return code from DCD calls
1765 
1766  // If this is the last time we will be writing coordinates,
1767  // close the file before exiting
1768  if ( timestep == END_OF_RUN ) {
1769  if ( ! veldcdFirst ) {
1770  iout << "CLOSING VELOCITY DCD FILE\n" << endi;
1771  close_dcd_write(veldcdFileID);
1772  } else {
1773  iout << "VELOCITY DCD FILE WAS NOT CREATED\n" << endi;
1774  }
1775  return;
1776  }
1777 
1778  if (veldcdFirst)
1779  {
1780  // Open the DCD file
1781  iout << "OPENING VELOCITY DCD FILE\n" << endi;
1782 
1783 #ifndef OUTPUT_SINGLE_FILE
1784 #error OUTPUT_SINGLE_FILE not defined!
1785 #endif
1786 
1787  #if OUTPUT_SINGLE_FILE
1788  char *veldcdFilename = simParams->velDcdFilename;
1789  #else
1790  char *veldcdFilename = buildFileName(veldcdType);
1791  #endif
1792 
1793  veldcdFileID=open_dcd_write(veldcdFilename);
1794 
1795  if (veldcdFileID == DCD_FILEEXISTS)
1796  {
1797  char err_msg[257];
1798  sprintf(err_msg, "Velocity DCD file %s already exists!",veldcdFilename);
1799  NAMD_err(err_msg);
1800  }
1801  else if (veldcdFileID < 0)
1802  {
1803  char err_msg[257];
1804  sprintf(err_msg, "Couldn't open velocity DCD file %s",veldcdFilename);
1805  NAMD_err(err_msg);
1806  }
1807 
1808  #if !OUTPUT_SINGLE_FILE
1809  // Write out extra fields as MAGIC number etc.
1810  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
1811  float tmpFlt = OUTPUT_FILE_VERSION;
1812  NAMD_write(veldcdFileID, (char *) &tmpInt, sizeof(int32));
1813  NAMD_write(veldcdFileID, (char *) &tmpFlt, sizeof(float));
1814  tmpInt = simParams->numoutputprocs;
1815  NAMD_write(veldcdFileID, (char *) &tmpInt, sizeof(int32));
1816  #endif
1817 
1818  int NSAVC, NFILE, NPRIV, NSTEP;
1819  NSAVC = simParams->velDcdFrequency;
1820  NPRIV = timestep;
1821  NSTEP = NPRIV - NSAVC;
1822  NFILE = 0;
1823 
1824  // Write out the header
1825  const int with_unitcell = 0;
1826  ret_code = write_dcdheader(veldcdFileID,
1827  veldcdFilename,
1828  n, NFILE, NPRIV, NSAVC, NSTEP,
1829  simParams->dt/TIMEFACTOR, with_unitcell);
1830 
1831 
1832  if (ret_code<0)
1833  {
1834  NAMD_err("Writing of velocity DCD header failed!!");
1835  }
1836 
1837  #if !OUTPUT_SINGLE_FILE
1838  //In this case, the file name is dynamically allocated
1839  delete [] veldcdFilename;
1840  #endif
1841 
1842  veldcdFirst = FALSE;
1843  }
1844 
1845  // Write out the values for this timestep
1846  iout << "WRITING VELOCITIES TO DCD FILE AT STEP "
1847  << timestep << "\n" << endi;
1848  fflush(stdout);
1849 
1850  //In the case of writing to multiple files, only the header
1851  //of the dcd file needs to be updated. Note that the format of
1852  //the new dcd file has also changed! -Chao Mei
1853 
1854 #if OUTPUT_SINGLE_FILE
1855  //write X,Y,Z headers
1856  int totalAtoms = namdMyNode->molecule->numAtoms;
1857  write_dcdstep_par_XYZUnits(veldcdFileID, totalAtoms);
1858 #endif
1859 
1860  //update the header
1861  update_dcdstep_par_header(veldcdFileID);
1862 
1863 }
1864 
1865 void ParOutput::output_veldcdfile_slave(int timestep, int fID, int tID, Vector *vecs){
1866  int ret_code; // Return code from DCD calls
1868 
1869  // If this is the last time we will be writing coordinates,
1870  // close the file before exiting
1871  if ( timestep == END_OF_RUN ) {
1872  if ( ! veldcdFirst ) {
1873  close_dcd_write(veldcdFileID);
1874  }
1875 #if OUTPUT_SINGLE_FILE
1876  delete [] veldcdX;
1877  delete [] veldcdY;
1878  delete [] veldcdZ;
1879 #endif
1880  return;
1881  }
1882 
1883  int parN = tID-fID+1;
1884 
1885  if (veldcdFirst)
1886  {
1887 
1888  #if OUTPUT_SINGLE_FILE
1889  char *veldcdFilename = namdMyNode->simParams->velDcdFilename;
1890  #else
1891  char *veldcdFilename = buildFileName(veldcdType);
1892  #endif
1893  veldcdFileID=open_dcd_write_par_slave(veldcdFilename);
1894  if(veldcdFileID < 0)
1895  {
1896  char err_msg[257];
1897  sprintf(err_msg, "Couldn't open velocity DCD file %s",veldcdFilename);
1898  NAMD_err(err_msg);
1899  }
1900  #if OUTPUT_SINGLE_FILE
1901  //If outputting to a single file, dcd files conforms to the old format
1902  //as data are organized as 3 seperate arrays of X,Y,Z, while in the new
1903  //format used in outputing multiple files, the data are organized as an
1904  //array of XYZs.
1905  veldcdX = new float[parN];
1906  veldcdY = new float[parN];
1907  veldcdZ = new float[parN];
1908  //seek to beginning of X,Y,Z sections which means skipping header.
1909  //Cell data is not needed because this is velocity trajectory
1910  int skipbytes = get_dcdheader_size();
1911  seek_dcdfile(veldcdFileID, skipbytes, SEEK_SET);
1912  #endif
1913 
1914  #if !OUTPUT_SINGLE_FILE
1915  delete [] veldcdFilename;
1916  // Write out extra fields as MAGIC number etc.
1917  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
1918  float tmpFlt = OUTPUT_FILE_VERSION;
1919  NAMD_write(veldcdFileID, (char *) &tmpInt, sizeof(int32));
1920  NAMD_write(veldcdFileID, (char *) &tmpFlt, sizeof(float));
1921  NAMD_write(veldcdFileID, (char *) &outputID, sizeof(int));
1922  NAMD_write(veldcdFileID, (char *) &fID, sizeof(int));
1923  NAMD_write(veldcdFileID, (char *) &tID, sizeof(int));
1924  #endif
1925 
1926  veldcdFirst = FALSE;
1927  }
1928 
1929 #if OUTPUT_SINGLE_FILE
1930  //The following seek will set the stream position to the
1931  //beginning of the place where a new timestep output should
1932  //be performed.
1933  CmiAssert(sizeof(off_t)==8);
1934  int totalAtoms = namdMyNode->molecule->numAtoms;
1935 
1936  for(int i=0; i<parN; i++){
1937  veldcdX[i] = vecs[i].x;
1938  veldcdY[i] = vecs[i].y;
1939  veldcdZ[i] = vecs[i].z;
1940  }
1941 
1942  write_dcdstep_par_slave(veldcdFileID, fID, tID, totalAtoms, veldcdX, veldcdY, veldcdZ);
1943 
1944  //same with the slave output for coordiantes trajectory file
1945  //but cell data is not needed because this is velocity trajectory
1946  int atomsRemains = (totalAtoms-1)-(tID+1)+1;
1947  off_t offset = ((off_t)atomsRemains)*sizeof(float)+1*sizeof(int);
1948  seek_dcdfile(veldcdFileID, offset, SEEK_CUR);
1949 
1950 #else
1951  //write the timestep
1952  NAMD_write(veldcdFileID, (char *)&timestep, sizeof(int));
1953  //write the values for this timestep
1954  NAMD_write(veldcdFileID, (char *)vecs, sizeof(Vector)*parN);
1955 #endif
1956 }
1957 
1958 void ParOutput::output_restart_velocities_master(int timestep, int n){
1959 #if OUTPUT_SINGLE_FILE
1960  char timestepstr[20];
1961 
1962  int baselen = strlen(namdMyNode->simParams->restartFilename);
1963  char *restart_name = new char[baselen+26];
1964 
1965  strcpy(restart_name, namdMyNode->simParams->restartFilename);
1966  if ( namdMyNode->simParams->restartSave ) {
1967  sprintf(timestepstr,".%d",timestep);
1968  strcat(restart_name, timestepstr);
1969  }
1970  strcat(restart_name, ".vel");
1971 #else
1972  char *restart_name = NULL;
1973  if ( namdMyNode->simParams->restartSave )
1974  restart_name = buildFileName(velType);
1975  else
1976  restart_name = buildFileName(velType,timestep);
1977 #endif
1978 
1979  NAMD_backup_file(restart_name,".old");
1980 
1981  //Always output a binary file
1982  write_binary_file_master(restart_name, n);
1983 
1984  delete [] restart_name;
1985 }
1986 
1987 void ParOutput::output_restart_velocities_slave(int timestep, int fID, int tID, Vector *vecs, int64 offset){
1988 #if OUTPUT_SINGLE_FILE
1989  char timestepstr[20];
1990 
1991  int baselen = strlen(namdMyNode->simParams->restartFilename);
1992  char *restart_name = new char[baselen+26];
1993 
1994  strcpy(restart_name, namdMyNode->simParams->restartFilename);
1995  if ( namdMyNode->simParams->restartSave ) {
1996  sprintf(timestepstr,".%d",timestep);
1997  strcat(restart_name, timestepstr);
1998  }
1999  strcat(restart_name, ".vel");
2000 #else
2001  char *restart_name = NULL;
2002  if ( namdMyNode->simParams->restartSave )
2003  restart_name = buildFileName(velType);
2004  else
2005  restart_name = buildFileName(velType,timestep);
2006 
2007  NAMD_backup_file(restart_name,".old");
2008 #endif
2009 
2010  //Always output a binary file
2011  write_binary_file_slave(restart_name, fID, tID, vecs, offset);
2012 
2013  delete [] restart_name;
2014 }
2015 
2016 void ParOutput::output_final_velocities_master(int n){
2017 #if OUTPUT_SINGLE_FILE
2018  char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
2019  // Build the output filename
2020  strcpy(output_name, namdMyNode->simParams->outputFilename);
2021  strcat(output_name, ".vel");
2022 #else
2023  char *output_name = buildFileName(velType);
2024 #endif
2025 
2026  NAMD_backup_file(output_name);
2027 
2028  //Write the velocities to a binary file
2029  write_binary_file_master(output_name, n);
2030 }
2031 
2032 void ParOutput::output_final_velocities_slave(int fID, int tID, Vector *vecs, int64 offset){
2033 #if OUTPUT_SINGLE_FILE
2034  char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
2035  // Build the output filename
2036  strcpy(output_name, namdMyNode->simParams->outputFilename);
2037  strcat(output_name, ".vel");
2038 #else
2039  char *output_name = buildFileName(velType);
2040  NAMD_backup_file(output_name);
2041 #endif
2042 
2043  //Write the velocities to a binary file
2044  write_binary_file_slave(output_name, fID, tID, vecs, offset);
2045 
2046  delete [] output_name;
2047 }
2048 
2049 void ParOutput::write_binary_file_master(char *fname, int n){
2050  char errmsg[256];
2051  int fd; // File descriptor
2052  int32 n32 = n;
2053  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::write_binary_file_master\n");
2054  fd = NAMD_open(fname);
2055 
2056  sprintf(errmsg, "Error on write to binary file %s", fname);
2057 
2058  #if !OUTPUT_SINGLE_FILE
2059  // Write out extra fields as MAGIC number etc.
2060  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
2061  float tmpFlt = OUTPUT_FILE_VERSION;
2062  NAMD_write(fd, (char *) &tmpInt, sizeof(int32), errmsg);
2063  NAMD_write(fd, (char *) &tmpFlt, sizeof(float), errmsg);
2064  tmpInt = namdMyNode->simParams->numoutputprocs;
2065  NAMD_write(fd, (char *) &tmpInt, sizeof(int32), errmsg);
2066  #endif
2067 
2068  // Write out the number of atoms and the vectors
2069  NAMD_write(fd, (char *) &n32, sizeof(int32), errmsg);
2070 
2071  NAMD_close(fd, fname);
2072 }
2073 
2074 void ParOutput::write_binary_file_slave(char *fname, int fID, int tID, Vector *vecs, int64 offset){
2075  char errmsg[256];
2076  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::write_binary_file_slave\n");
2077 #if OUTPUT_SINGLE_FILE
2078  //the mode has to be "r+" because the file already exists
2079  FILE *ofp = fopen(fname, "rb+");
2080  if ( ! ofp ) {
2081  sprintf(errmsg, "Error on opening binary file %s", fname);
2082  NAMD_err(errmsg);
2083  }
2084 
2085  //if the output is a single file, then the file position needs to be set correctly
2086 #ifdef WIN32
2087  if ( _fseeki64(ofp, offset, SEEK_SET) )
2088 #else
2089  if ( fseeko(ofp, offset, SEEK_SET) )
2090 #endif
2091  {
2092  sprintf(errmsg, "Error on seeking binary file %s", fname);
2093  NAMD_err(errmsg);
2094  }
2095 #else
2096  //the mode has to be "w+" because the file doesn't exist yet
2097  FILE *ofp = fopen(fname, "wb+");
2098  if ( ! ofp ) {
2099  sprintf(errmsg, "Error on opening binary file %s", fname);
2100  NAMD_err(errmsg);
2101  }
2102 
2103  // Write out extra fields as MAGIC number etc.
2104  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
2105  float tmpFlt = OUTPUT_FILE_VERSION;
2106  fwrite(&tmpInt, sizeof(int32), 1, ofp);
2107  fwrite(&tmpFlt, sizeof(float), 1, ofp);
2108  fwrite(&outputID, sizeof(int), 1, ofp);
2109  fwrite(&fID, sizeof(int), 1, ofp);
2110  fwrite(&tID, sizeof(int), 1, ofp);
2111 #endif
2112 
2113  int parN = tID-fID+1;
2114  if ( fwrite(vecs, sizeof(Vector), parN, ofp) != parN ) {
2115  sprintf(errmsg, "Error on writing to binary file %s", fname);
2116  NAMD_err(errmsg);
2117  }
2118 
2119  if ( fclose(ofp) ) {
2120  sprintf(errmsg, "Error on closing binary file %s", fname);
2121  NAMD_err(errmsg);
2122  }
2123 }
2125 
2126 
2128 void ParOutput::forceMaster(int timestep, int n){
2130 
2131  if ( timestep >= 0 ) {
2132 
2133  // Output force DCD trajectory
2134  if ( simParams->forceDcdFrequency &&
2135  ((timestep % simParams->forceDcdFrequency) == 0) )
2136  {
2137  output_forcedcdfile_master(timestep, n);
2138  }
2139 
2140  }
2141 
2142  // Output forces
2143  if (timestep == FORCE_OUTPUT)
2144  {
2145  int realstep = simParams->firstTimestep;
2146  iout << "WRITING FORCES TO OUTPUT FILE AT STEP "
2147  << realstep << "\n" << endi;
2148  fflush(stdout);
2149  output_forces_master(n);
2150  }
2151 
2152  // Close trajectory files in velocityMaster above
2153 }
2154 
2155 //output atoms' forces from id fID to tID.
2156 void ParOutput::forceSlave(int timestep, int fID, int tID, Vector *vecs){
2158 
2159  if ( timestep >= 0 ) {
2160 
2161  // Output force DCD trajectory
2162  if ( simParams->forceDcdFrequency &&
2163  ((timestep % simParams->forceDcdFrequency) == 0) )
2164  {
2165  output_forcedcdfile_slave(timestep, fID, tID, vecs);
2166  }
2167 
2168  }
2169 
2170  // Output forces
2171  if (timestep == FORCE_OUTPUT)
2172  {
2173  int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
2174  output_forces_slave(fID, tID, vecs, offset);
2175  }
2176 
2177  // Close trajectory files in velocitySlave above
2178 }
2179 
2180 void ParOutput::output_forcedcdfile_master(int timestep, int n){
2181  int ret_code; // Return code from DCD calls
2183 
2184  // If this is the last time we will be writing coordinates,
2185  // close the file before exiting
2186  if ( timestep == END_OF_RUN ) {
2187  if ( ! forcedcdFirst ) {
2188  iout << "CLOSING FORCE DCD FILE\n" << endi;
2189  close_dcd_write(forcedcdFileID);
2190  } else {
2191  iout << "FORCE DCD FILE WAS NOT CREATED\n" << endi;
2192  }
2193  return;
2194  }
2195 
2196  if (forcedcdFirst)
2197  {
2198  // Open the DCD file
2199  iout << "OPENING FORCE DCD FILE\n" << endi;
2200 
2201  #if OUTPUT_SINGLE_FILE
2202  char *forcedcdFilename = simParams->forceDcdFilename;
2203  #else
2204  char *forcedcdFilename = buildFileName(forcedcdType);
2205  #endif
2206 
2207  forcedcdFileID=open_dcd_write(forcedcdFilename);
2208 
2209  if (forcedcdFileID == DCD_FILEEXISTS)
2210  {
2211  char err_msg[257];
2212  sprintf(err_msg, "Force DCD file %s already exists!",forcedcdFilename);
2213  NAMD_err(err_msg);
2214  }
2215  else if (forcedcdFileID < 0)
2216  {
2217  char err_msg[257];
2218  sprintf(err_msg, "Couldn't open force DCD file %s",forcedcdFilename);
2219  NAMD_err(err_msg);
2220  }
2221 
2222  #if !OUTPUT_SINGLE_FILE
2223  // Write out extra fields as MAGIC number etc.
2224  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
2225  float tmpFlt = OUTPUT_FILE_VERSION;
2226  NAMD_write(forcedcdFileID, (char *) &tmpInt, sizeof(int32));
2227  NAMD_write(forcedcdFileID, (char *) &tmpFlt, sizeof(float));
2228  tmpInt = simParams->numoutputprocs;
2229  NAMD_write(forcedcdFileID, (char *) &tmpInt, sizeof(int32));
2230  #endif
2231 
2232  int NSAVC, NFILE, NPRIV, NSTEP;
2233  NSAVC = simParams->forceDcdFrequency;
2234  NPRIV = timestep;
2235  NSTEP = NPRIV - NSAVC;
2236  NFILE = 0;
2237 
2238  // Write out the header
2239  const int with_unitcell = 0;
2240  ret_code = write_dcdheader(forcedcdFileID,
2241  forcedcdFilename,
2242  n, NFILE, NPRIV, NSAVC, NSTEP,
2243  simParams->dt/TIMEFACTOR, with_unitcell);
2244 
2245 
2246  if (ret_code<0)
2247  {
2248  NAMD_err("Writing of force DCD header failed!!");
2249  }
2250 
2251  #if !OUTPUT_SINGLE_FILE
2252  //In this case, the file name is dynamically allocated
2253  delete [] forcedcdFilename;
2254  #endif
2255 
2256  forcedcdFirst = FALSE;
2257  }
2258 
2259  // Write out the values for this timestep
2260  iout << "WRITING FORCES TO DCD FILE AT STEP "
2261  << timestep << "\n" << endi;
2262  fflush(stdout);
2263 
2264  //In the case of writing to multiple files, only the header
2265  //of the dcd file needs to be updated. Note that the format of
2266  //the new dcd file has also changed! -Chao Mei
2267 
2268 #if OUTPUT_SINGLE_FILE
2269  //write X,Y,Z headers
2270  int totalAtoms = namdMyNode->molecule->numAtoms;
2271  write_dcdstep_par_XYZUnits(forcedcdFileID, totalAtoms);
2272 #endif
2273 
2274  //update the header
2275  update_dcdstep_par_header(forcedcdFileID);
2276 
2277 }
2278 
2279 void ParOutput::output_forcedcdfile_slave(int timestep, int fID, int tID, Vector *vecs){
2280  int ret_code; // Return code from DCD calls
2282 
2283  // If this is the last time we will be writing coordinates,
2284  // close the file before exiting
2285  if ( timestep == END_OF_RUN ) {
2286  if ( ! forcedcdFirst ) {
2287  close_dcd_write(forcedcdFileID);
2288  }
2289 #if OUTPUT_SINGLE_FILE
2290  delete [] forcedcdX;
2291  delete [] forcedcdY;
2292  delete [] forcedcdZ;
2293 #endif
2294  return;
2295  }
2296 
2297  int parN = tID-fID+1;
2298 
2299  if (forcedcdFirst)
2300  {
2301 
2302  #if OUTPUT_SINGLE_FILE
2303  char *forcedcdFilename = namdMyNode->simParams->forceDcdFilename;
2304  #else
2305  char *forcedcdFilename = buildFileName(forcedcdType);
2306  #endif
2307  forcedcdFileID=open_dcd_write_par_slave(forcedcdFilename);
2308  if(forcedcdFileID < 0)
2309  {
2310  char err_msg[257];
2311  sprintf(err_msg, "Couldn't open force DCD file %s",forcedcdFilename);
2312  NAMD_err(err_msg);
2313  }
2314  #if OUTPUT_SINGLE_FILE
2315  //If outputting to a single file, dcd files conforms to the old format
2316  //as data are organized as 3 seperate arrays of X,Y,Z, while in the new
2317  //format used in outputing multiple files, the data are organized as an
2318  //array of XYZs.
2319  forcedcdX = new float[parN];
2320  forcedcdY = new float[parN];
2321  forcedcdZ = new float[parN];
2322  //seek to beginning of X,Y,Z sections which means skipping header.
2323  //Cell data is not needed because this is force trajectory
2324  int skipbytes = get_dcdheader_size();
2325  seek_dcdfile(forcedcdFileID, skipbytes, SEEK_SET);
2326  #endif
2327 
2328  #if !OUTPUT_SINGLE_FILE
2329  delete [] forcedcdFilename;
2330  // Write out extra fields as MAGIC number etc.
2331  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
2332  float tmpFlt = OUTPUT_FILE_VERSION;
2333  NAMD_write(forcedcdFileID, (char *) &tmpInt, sizeof(int32));
2334  NAMD_write(forcedcdFileID, (char *) &tmpFlt, sizeof(float));
2335  NAMD_write(forcedcdFileID, (char *) &outputID, sizeof(int));
2336  NAMD_write(forcedcdFileID, (char *) &fID, sizeof(int));
2337  NAMD_write(forcedcdFileID, (char *) &tID, sizeof(int));
2338  #endif
2339 
2340  forcedcdFirst = FALSE;
2341  }
2342 
2343 #if OUTPUT_SINGLE_FILE
2344  //The following seek will set the stream position to the
2345  //beginning of the place where a new timestep output should
2346  //be performed.
2347  CmiAssert(sizeof(off_t)==8);
2348  int totalAtoms = namdMyNode->molecule->numAtoms;
2349 
2350  for(int i=0; i<parN; i++){
2351  forcedcdX[i] = vecs[i].x;
2352  forcedcdY[i] = vecs[i].y;
2353  forcedcdZ[i] = vecs[i].z;
2354  }
2355 
2356  write_dcdstep_par_slave(forcedcdFileID, fID, tID, totalAtoms, forcedcdX, forcedcdY, forcedcdZ);
2357  //same with the slave output for coordiantes trajectory file
2358  //but cell data is not needed because this is force trajectory
2359  int atomsRemains = (totalAtoms-1)-(tID+1)+1;
2360  off_t offset = ((off_t)atomsRemains)*sizeof(float)+1*sizeof(int);
2361  seek_dcdfile(forcedcdFileID, offset, SEEK_CUR);
2362 #else
2363  //write the timestep
2364  NAMD_write(forcedcdFileID, (char *)&timestep, sizeof(int));
2365  //write the values for this timestep
2366  NAMD_write(forcedcdFileID, (char *)vecs, sizeof(Vector)*parN);
2367 #endif
2368 }
2369 
2370 void ParOutput::output_forces_master(int n){
2371 #if OUTPUT_SINGLE_FILE
2372  char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
2373  // Build the output filename
2374  strcpy(output_name, namdMyNode->simParams->outputFilename);
2375  strcat(output_name, ".force");
2376 #else
2377  char *output_name = buildFileName(forceType);
2378 #endif
2379 
2380  NAMD_backup_file(output_name);
2381 
2382  //Write the force to a binary file
2383  write_binary_file_master(output_name, n);
2384 }
2385 
2386 void ParOutput::output_forces_slave(int fID, int tID, Vector *vecs, int64 offset){
2387 #if OUTPUT_SINGLE_FILE
2388  char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
2389  // Build the output filename
2390  strcpy(output_name, namdMyNode->simParams->outputFilename);
2391  strcat(output_name, ".force");
2392 #else
2393  char *output_name = buildFileName(forceType);
2394  NAMD_backup_file(output_name);
2395 #endif
2396 
2397  //Write the forces to a binary file
2398  write_binary_file_slave(output_name, fID, tID, vecs, offset);
2399 
2400  delete [] output_name;
2401 }
2403 
2404 
2406 void ParOutput::coordinateMaster(int timestep, int n, Lattice &lat){
2408  Molecule *molecule = namdMyNode->molecule;
2409  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::coordinateMaster n "<< n <<"\n");
2410  if ( timestep >= 0 ) {
2411  // Output a DCD trajectory
2412  if ( simParams->dcdFrequency &&
2413  ((timestep % simParams->dcdFrequency) == 0) )
2414  {
2415  output_dcdfile_master(timestep, n,
2416  simParams->dcdUnitCell ? &lat : NULL, 0);
2417  }
2418  // Output any DCD selection trajectories that this timestep mods
2419  if ( simParams->dcdSelectionOn)
2420  {
2421  for(int index=0; index<16;++index)
2422  {
2423  int frequency = molecule->dcdSelectionParams[index].frequency;
2424  uint16 tag = molecule->dcdSelectionParams[index].tag;
2425  int size = molecule->dcdSelectionParams[index].size;
2426  if(frequency>0 && (timestep % frequency) == 0)
2427  {
2428 
2429  int dcdSelectionNpoints = molecule->get_dcd_selection_size(index);
2430  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::coordinateMaster index "<< index<< " numpoints "<<dcdSelectionNpoints <<"\n");
2431  output_dcdfile_master(timestep, dcdSelectionNpoints,
2432  simParams->dcdUnitCell ? &lat : NULL, tag);
2433  }
2434  }
2435  }
2436 
2437  // Output a restart file
2438  if ( simParams->restartFrequency &&
2439  ((timestep % simParams->restartFrequency) == 0) )
2440  {
2441  iout << "WRITING COORDINATES TO RESTART FILE AT STEP "
2442  << timestep << "\n" << endi;
2443  output_restart_coordinates_master(timestep, n);
2444  iout << "FINISHED WRITING RESTART COORDINATES\n" <<endi;
2445  fflush(stdout);
2446  }
2447 
2448 /* Interactive MD is not supported in Parallel IO
2449  // Interactive MD
2450  if ( simParams->IMDon &&
2451  ( ((timestep % simParams->IMDfreq) == 0) ||
2452  (timestep == simParams->firstTimestep) ) )
2453  {
2454  IMDOutput *imd = Node::Object()->imd;
2455  wrap_coor(fcoor,lattice,&fcoor_wrapped);
2456  if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
2457  }
2458 */
2459  }
2460 
2461 /* EVAL_MEASURE of a timestep is not supported in Parallel IO
2462  if (timestep == EVAL_MEASURE)
2463  {
2464  #ifdef NAMD_TCL
2465  wrap_coor(coor,lattice,&coor_wrapped);
2466  Node::Object()->getScript()->measure(coor);
2467  #endif
2468  }
2469 */
2470  // Output final coordinates
2471  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
2472  {
2473  int realstep = ( timestep == FILE_OUTPUT ?
2474  simParams->firstTimestep : simParams->N );
2475  iout << "WRITING COORDINATES TO OUTPUT FILE AT STEP "
2476  << realstep << "\n" << endi;
2477  fflush(stdout);
2478  output_final_coordinates_master(n);
2479  }
2480 
2481  // Close trajectory files
2482  if (timestep == END_OF_RUN)
2483  {
2484  if (simParams->dcdFrequency) output_dcdfile_master(END_OF_RUN,0,NULL, 0);
2485  if ( simParams->dcdSelectionOn)
2486  {
2487  for(int dcdSelectionIndex=0; dcdSelectionIndex<16;++dcdSelectionIndex)
2488  {
2489  int dcdSelectionFrequency = molecule->dcdSelectionParams[dcdSelectionIndex].frequency;
2490  int dcdSelectionTag = molecule->dcdSelectionParams[dcdSelectionIndex].tag;
2491  if(dcdSelectionFrequency)
2492  output_dcdfile_master(END_OF_RUN,0,NULL, dcdSelectionTag);
2493  }
2494  }
2495  }
2496 }
2497 
2498 void ParOutput::coordinateSlave(int timestep, int fID, int tID, Vector *vecs, FloatVector *fvecs){
2500  Molecule *molecule = namdMyNode->molecule;
2501  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::coordinateSlave fID "<<fID<<" tID "<<tID<<"\n");
2502  if ( timestep >= 0 ) {
2503  // Output a DCD trajectory
2504  if ( simParams->dcdFrequency &&
2505  ((timestep % simParams->dcdFrequency) == 0) )
2506  {
2507  output_dcdfile_slave(timestep, fID, tID, fvecs, 0);
2508  }
2509  if ( simParams->dcdSelectionOn)
2510  {
2511  bool needCleanup = false;
2512 
2513  for(int index=0; index<16;++index)
2514  {
2515  int frequency = molecule->dcdSelectionParams[index].frequency;
2516  uint16 tag= molecule->dcdSelectionParams[index].tag;
2517  if(frequency>0 && (timestep % frequency) == 0)
2518  {
2519  int dcdSelectionNpoints = dcdSelectionLocalSize[index];
2520  // check if there are points in the selection in this IO range
2521  if(dcdSelectionNpoints>0)
2522  {
2523  FloatVector *dcdSelectionFcoor = new FloatVector[dcdSelectionNpoints];
2524  // create a local copy of the vector containing only
2525  off_t thisTID = dcdSelectionOffsets[index];
2526  DebugM(3, "["<<CkMyPe()<<"]"<< "ParOutput::coordinateSlave index "<<index <<" localSize "<<dcdSelectionNpoints<<" offset "<< thisTID <<"\n");
2527  for(int i=0; i< dcdSelectionNpoints; ++i){
2528 
2529  dcdSelectionFcoor[i] = fvecs[dcdSelectionMap[index][i]-fID];
2530  DebugM(1, "["<<CkMyPe()<<"]"<< "ParOutput::coordinateSlave index "<<index <<" atom "<<i<<" mapto "<< dcdSelectionMap[index][i]<< " - fID "<< fID<<" -> "<< dcdSelectionMap[index][i]-fID << " coords " << dcdSelectionFcoor[i] << "\n");
2531  }
2532  output_dcdfile_slave(timestep, fID, thisTID+dcdSelectionNpoints-1, dcdSelectionFcoor, tag);
2533  delete [] dcdSelectionFcoor;
2534  }
2535  }
2536  }
2537  }
2538 
2539  // Output a restart file
2540  if ( simParams->restartFrequency &&
2541  ((timestep % simParams->restartFrequency) == 0) )
2542  {
2543  int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
2544  output_restart_coordinates_slave(timestep, fID, tID, vecs, offset);
2545  }
2546 
2547 /* Interactive MD is not supported in Parallel IO
2548  // Interactive MD
2549  if ( simParams->IMDon &&
2550  ( ((timestep % simParams->IMDfreq) == 0) ||
2551  (timestep == simParams->firstTimestep) ) )
2552  {
2553  IMDOutput *imd = Node::Object()->imd;
2554  wrap_coor(fcoor,lattice,&fcoor_wrapped);
2555  if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
2556  }
2557 */
2558  }
2559 
2560 /* EVAL_MEASURE of a timestep is not supported in Parallel IO
2561  if (timestep == EVAL_MEASURE)
2562  {
2563  #ifdef NAMD_TCL
2564  wrap_coor(coor,lattice,&coor_wrapped);
2565  Node::Object()->getScript()->measure(coor);
2566  #endif
2567  }
2568 */
2569  // Output final coordinates
2570  if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
2571  {
2572  int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
2573  output_final_coordinates_slave(fID, tID, vecs, offset);
2574  }
2575 
2576  // Close trajectory files
2577  if (timestep == END_OF_RUN)
2578  {
2579  if (simParams->dcdFrequency) output_dcdfile_slave(END_OF_RUN,0,0,NULL, 0);
2580  if ( simParams->dcdSelectionOn)
2581  {
2582  for(int index=0; index<16;++index)
2583  {
2584  uint16 tag=molecule->dcdSelectionParams[index].tag;
2585  int frequency=molecule->dcdSelectionParams[index].frequency;
2586  if(frequency)
2587  {
2588  output_dcdfile_slave(END_OF_RUN,0,0,NULL, tag);
2589  }
2590  }
2591  }
2592  }
2593 }
2594 
2595 void ParOutput::output_dcdfile_master(int timestep, int n, const Lattice *lattice, int dcdSelectTag){
2596  int ret_code; // Return code from DCD calls
2597  SimParameters *simParams = namdMyNode->simParams;
2598  Molecule *molecule = namdMyNode->molecule;
2599  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::output_dcdfile_master n "<< n << " tag "<< dcdSelectTag<< "\n");
2600  // If this is the last time we will be writing coordinates,
2601  // close the file before exiting
2602  if ( timestep == END_OF_RUN ) {
2603  if ( ! parFirst[dcdSelectTag] ) {
2604  iout << "CLOSING COORDINATE DCD FILE\n" << endi;
2605  close_dcd_write(parFileid[dcdSelectTag]);
2606  } else {
2607  iout << "COORDINATE DCD FILE WAS NOT CREATED\n" << endi;
2608  }
2609  return;
2610  }
2611  int dcdSelectIndex=dcdSelectTag-1;
2612  if (parFirst[dcdSelectTag])
2613  {
2614  // Open the DCD file
2615  iout << "OPENING COORDINATE DCD FILE\n" << endi;
2616 
2617 #if OUTPUT_SINGLE_FILE
2618  char *dcdFilename = simParams->dcdFilename;
2619 #else
2620  char *dcdFilename = buildFileName(dcdType);
2621 #endif
2622  if(dcdSelectTag >0 && dcdSelectTag <= 16)
2623  {// look it up
2624 #ifndef OUTPUT_SINGLE_FILE
2625  // nobody uses this feature, not worth writing code to handle it.
2626  NAMD_err("DCD selection not supported without OUTPUT_SINGLE_FILE!!");
2627 #endif
2628  dcdFilename = molecule->dcdSelectionParams[dcdSelectIndex].outFilename;
2629  n = molecule->dcdSelectionParams[dcdSelectIndex].size;
2630  DebugM(3, "DCD Selection File " << dcdFilename <<" tag " << dcdSelectTag<<"\n");
2631  }
2632 
2633  parFileid[dcdSelectTag] = open_dcd_write(dcdFilename);
2634  if (parFileid[dcdSelectTag] == DCD_FILEEXISTS)
2635  {
2636  char err_msg[257];
2637  sprintf(err_msg, "DCD file %s already exists!!",dcdFilename);
2638  NAMD_err(err_msg);
2639  }
2640  else if (parFileid[dcdSelectTag] < 0)
2641  {
2642  char err_msg[257];
2643  sprintf(err_msg, "Couldn't open DCD file %s",dcdFilename);
2644  NAMD_err(err_msg);
2645  }
2646 
2647  #if !OUTPUT_SINGLE_FILE
2648  // Write out extra fields as MAGIC number etc.
2649  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
2650  float tmpFlt = OUTPUT_FILE_VERSION;
2651  NAMD_write(parFileid[dcdSelectTag], (char *) &tmpInt, sizeof(int32));
2652  NAMD_write(parFileid[dcdSelectTag], (char *) &tmpFlt, sizeof(float));
2653  tmpInt = simParams->numoutputprocs;
2654  NAMD_write(parFileid[dcdSelectTag], (char *) &tmpInt, sizeof(int32));
2655  #endif
2656 
2657  int NSAVC, NFILE, NPRIV, NSTEP;
2658  NSAVC = (dcdSelectTag==0) ? simParams->dcdFrequency :
2659  NSAVC = molecule->dcdSelectionParams[dcdSelectIndex].frequency;
2660  NPRIV = timestep;
2661  NSTEP = NPRIV - NSAVC;
2662  NFILE = 0;
2663 
2664  // Write out the header
2665  ret_code = write_dcdheader(parFileid[dcdSelectTag],
2666  dcdFilename,
2667  n, NFILE, NPRIV, NSAVC, NSTEP,
2668  simParams->dt/TIMEFACTOR, lattice != NULL);
2669 
2670 
2671  if (ret_code<0)
2672  {
2673  NAMD_err("Writing of DCD header failed!!");
2674  }
2675 
2676  #if !OUTPUT_SINGLE_FILE
2677  //dcdFilename needs to be freed as it is dynamically allocated
2678  delete [] dcdFilename;
2679  #endif
2680 
2681  parFirst[dcdSelectTag] = FALSE;
2682  }
2683 
2684  // Write out the values for this timestep
2685  iout << "WRITING COORDINATES TO DCD FILE AT STEP "
2686  << timestep << "\n" << endi;
2687  fflush(stdout);
2688 
2689  //In the case of writing to multiple files, the header of the
2690  //dcd file needs to be updated. In addition, the lattice data
2691  //needs to be written if necessary. Note that the format of
2692  //the new dcd file has also changed! -Chao Mei
2693 
2694  // Write out the Cell data
2695  if (lattice) {
2696  double unitcell[6];
2697  lattice_to_unitcell(lattice,unitcell);
2698  write_dcdstep_par_cell(parFileid[dcdSelectTag], unitcell);
2699  }
2700 
2701 #if OUTPUT_SINGLE_FILE
2702  //write X,Y,Z headers
2703  int totalAtoms = namdMyNode->molecule->numAtoms;
2704  if(dcdSelectTag >0 && dcdSelectTag <= 16)
2705  {
2706  totalAtoms = molecule->dcdSelectionParams[dcdSelectIndex].size;
2707  }
2708  write_dcdstep_par_XYZUnits(parFileid[dcdSelectTag], totalAtoms);
2709 #endif
2710 
2711  //update the header
2712  update_dcdstep_par_header(parFileid[dcdSelectTag]);
2713 }
2714 
2715 void ParOutput::output_dcdfile_slave(int timestep, int fID, int tID, FloatVector *fvecs, int dcdSelectTag){
2716  int ret_code; // Return code from DCD calls
2718  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::output_dcdfile_slave fID "<<fID <<" tID "<<tID <<" tag "<< dcdSelectTag <<"\n");
2719  // If this is the last time we will be writing coordinates,
2720  // close the file before exiting
2721  if ( timestep == END_OF_RUN ) {
2722  if ( ! parFirst[dcdSelectTag] ) {
2723  close_dcd_write(parFileid[dcdSelectTag]);
2724  }
2725 #if OUTPUT_SINGLE_FILE
2726  if(cleanUpXYZ)
2727  {
2728  delete [] dcdX;
2729  delete [] dcdY;
2730  delete [] dcdZ;
2731  cleanUpXYZ=false;
2732  }
2733 #endif
2734  return;
2735  }
2736 
2737  int parN = tID-fID+1;
2738  int dcdSelectIndex=dcdSelectTag-1;
2739  if (parFirst[dcdSelectTag])
2740  {
2741 #if OUTPUT_SINGLE_FILE
2742  char *dcdFilename = simParams->dcdFilename;
2743 #else
2744  char *dcdFilename = buildFileName(dcdType);
2745 #endif
2746  if(dcdSelectTag >0 && dcdSelectTag <= 16)
2747  {// look it up
2748 #ifndef OUTPUT_SINGLE_FILE
2749  // nobody uses this feature, not worth writing code to handle it.
2750  NAMD_err("DCD selection not supported without OUTPUT_SINGLE_FILE!!");
2751 #endif
2752  Molecule *mol = Node::Object()->molecule;
2753  dcdFilename = mol->dcdSelectionParams[dcdSelectIndex].outFilename;
2754  DebugM(3, "["<<CkMyPe()<<"]"<< " DCD Selection File " << dcdFilename <<" tag " << dcdSelectTag<<"\n");
2755  }
2756 
2757  parFileid[dcdSelectTag] = open_dcd_write_par_slave(dcdFilename);
2758  if(parFileid[dcdSelectTag] < 0)
2759  {
2760  char err_msg[257];
2761  sprintf(err_msg, "Couldn't open DCD file %s", dcdFilename);
2762  NAMD_err(err_msg);
2763  }
2764 
2765 #if OUTPUT_SINGLE_FILE
2766  //seek to beginning of X,Y,Z sections which means skipping header
2767  //skip the cell data if necessary
2768  int skipbytes = get_dcdheader_size();
2769  if(simParams->dcdUnitCell) {
2770  skipbytes += sizeof(int)*2 + 6*sizeof(double);
2771  }
2772  seek_dcdfile(parFileid[dcdSelectTag], skipbytes, SEEK_SET);
2773 #endif
2774 
2775 #if !OUTPUT_SINGLE_FILE
2776  delete [] dcdFilename;
2777  // Write out extra fields as MAGIC number etc.
2778  int32 tmpInt = OUTPUT_MAGIC_NUMBER;
2779  float tmpFlt = OUTPUT_FILE_VERSION;
2780  NAMD_write(parFileid[dcdSelectTag], (char *) &tmpInt, sizeof(int32));
2781  NAMD_write(parFileid[dcdSelectTag], (char *) &tmpFlt, sizeof(float));
2782  NAMD_write(parFileid[dcdSelectTag], (char *) &outputID, sizeof(int));
2783  NAMD_write(parFileid[dcdSelectTag], (char *) &fID, sizeof(int));
2784  NAMD_write(parFileid[dcdSelectTag], (char *) &tID, sizeof(int));
2785 #endif
2786  parFirst[dcdSelectTag] = FALSE;
2787  }
2788 
2789 #if OUTPUT_SINGLE_FILE
2790  //The following seek will set the stream position to the
2791  //beginning of the place where a new timestep output should
2792  //be performed.
2793  CmiAssert(sizeof(off_t)==8);
2794  Molecule *molecule = namdMyNode->molecule;
2795  int totalAtoms = namdMyNode->molecule->numAtoms;
2796  if(dcdSelectTag >0 && dcdSelectTag <= 16)
2797  {
2798  totalAtoms = molecule->dcdSelectionParams[dcdSelectIndex].size;
2799  }
2800  // different dcd selections may be sized differently
2801  // this will grow to the largest necessary
2802  if(parN > dcdAllocSize)
2803  {
2804  if(dcdX)
2805  delete [] dcdX;
2806  if(dcdY)
2807  delete [] dcdY;
2808  if(dcdZ)
2809  delete [] dcdZ;
2810  dcdX = new float[parN];
2811  dcdY = new float[parN];
2812  dcdZ = new float[parN];
2813  dcdAllocSize = parN;
2814  }
2815  for(int i=0; i<parN; i++){
2816  dcdX[i] = fvecs[i].x;
2817  dcdY[i] = fvecs[i].y;
2818  dcdZ[i] = fvecs[i].z;
2819  }
2820 
2821  write_dcdstep_par_slave(parFileid[dcdSelectTag], fID, tID, totalAtoms, dcdX, dcdY, dcdZ);
2822 
2823  //1. Always foward to the beginning position of X,Y,Z sections in the
2824  //next timeframe.
2825  //2. SHOULD AVOID USING SEEK_END: although the file size is updated on the
2826  //master proc, slave procs should rely on this update by seeking
2827  //from SEEK_END because such info may not be updated in a timely manner
2828  //when this slave proc needs it.
2829 
2830  //We know the current position of file after slave writing is at the
2831  //end of Z output for atom "tID" (tID is the atom id indexed from 0)
2832  //(totalAtoms-1) is the last atom id, (tID+1) is the next atom id
2833  int atomsRemains = (totalAtoms-1)-(tID+1)+1;
2834  off_t offset = ((off_t)atomsRemains)*sizeof(float)+1*sizeof(int);
2835  //then skip the cell data if necessary
2836  if(simParams->dcdUnitCell) {
2837  offset += sizeof(int)*2 + 6*sizeof(double);
2838  }
2839  seek_dcdfile(parFileid[dcdSelectTag], offset, SEEK_CUR);
2840 #else
2841  //write the timestep
2842  NAMD_write(parFileid[dcdSelectTag], (char *)&timestep, sizeof(int));
2843  //write the values for this timestep
2844  NAMD_write(parFileid[dcdSelectTag], (char *)fvecs, sizeof(FloatVector)*parN);
2845 #endif
2846 }
2847 
2848 void ParOutput::output_restart_coordinates_master(int timestep, int n){
2849  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::output_restart_coordinates_master\n");
2850 #if OUTPUT_SINGLE_FILE
2851  char timestepstr[20];
2852 
2853  int baselen = strlen(namdMyNode->simParams->restartFilename);
2854  char *restart_name = new char[baselen+26];
2855 
2856  strcpy(restart_name, namdMyNode->simParams->restartFilename);
2857  if ( namdMyNode->simParams->restartSave ) {
2858  sprintf(timestepstr,".%d",timestep);
2859  strcat(restart_name, timestepstr);
2860  }
2861  strcat(restart_name, ".coor");
2862 #else
2863  char *restart_name = NULL;
2864  if ( namdMyNode->simParams->restartSave )
2865  restart_name = buildFileName(coorType);
2866  else
2867  restart_name = buildFileName(coorType,timestep);
2868 #endif
2869 
2870  NAMD_backup_file(restart_name,".old");
2871 
2872  // Generate a binary restart file
2873  write_binary_file_master(restart_name, n);
2874 
2875  delete [] restart_name;
2876 }
2877 void ParOutput::output_restart_coordinates_slave(int timestep, int fID, int tID, Vector *vecs, int64 offset){
2878  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::output_restart_coordinates_slave\n");
2879 #if OUTPUT_SINGLE_FILE
2880  char timestepstr[20];
2881 
2882  int baselen = strlen(namdMyNode->simParams->restartFilename);
2883  char *restart_name = new char[baselen+26];
2884 
2885  strcpy(restart_name, namdMyNode->simParams->restartFilename);
2886  if ( namdMyNode->simParams->restartSave ) {
2887  sprintf(timestepstr,".%d",timestep);
2888  strcat(restart_name, timestepstr);
2889  }
2890  strcat(restart_name, ".coor");
2891 #else
2892  char *restart_name = NULL;
2893  if ( namdMyNode->simParams->restartSave )
2894  restart_name = buildFileName(coorType);
2895  else
2896  restart_name = buildFileName(coorType,timestep);
2897 
2898  NAMD_backup_file(restart_name,".old");
2899 #endif
2900 
2901  // Generate a binary restart file
2902  write_binary_file_slave(restart_name, fID, tID, vecs, offset);
2903 
2904  delete [] restart_name;
2905 }
2906 
2907 void ParOutput::output_final_coordinates_master(int n){
2908  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::output_final_coordinates_master\n");
2909 #if OUTPUT_SINGLE_FILE
2910  char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
2911 
2912  // Built the output filename
2913  strcpy(output_name, namdMyNode->simParams->outputFilename);
2914  strcat(output_name, ".coor");
2915 #else
2916  char *output_name = buildFileName(coorType);
2917 #endif
2918 
2919  NAMD_backup_file(output_name);
2920 
2921  // Write the coordinates to a binary file
2922  write_binary_file_master(output_name, n);
2923 
2924  delete [] output_name;
2925 }
2926 void ParOutput::output_final_coordinates_slave(int fID, int tID, Vector *vecs, int64 offset){
2927  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::output_final_coordinates_slave\n");
2928 #if OUTPUT_SINGLE_FILE
2929  char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
2930 
2931  // Built the output filename
2932  strcpy(output_name, namdMyNode->simParams->outputFilename);
2933  strcat(output_name, ".coor");
2934 #else
2935  char *output_name = buildFileName(coorType);
2936  NAMD_backup_file(output_name);
2937 #endif
2938 
2939  // Write the coordinates to a binary file
2940  write_binary_file_slave(output_name, fID, tID, vecs, offset);
2941 
2942  delete [] output_name;
2943 }
2945 
2947 #if !OUTPUT_SINGLE_FILE
2948 char *ParOutput::buildFileName(OUTPUTFILETYPE type, int timestep){
2949  char *filename = NULL;
2950  const char *typeName = NULL;
2951  switch(type) {
2952  case dcdType:
2953  typeName = "dcd";
2954  break;
2955  case forcedcdType:
2956  typeName = "forcedcd";
2957  break;
2958  case veldcdType:
2959  typeName = "veldcd";
2960  break;
2961  case coorType:
2962  typeName = "coor";
2963  break;
2964  case forceType:
2965  typeName = "force";
2966  break;
2967  case velType:
2968  typeName = "vel";
2969  break;
2970  default:
2971  typeName = "invalid";
2972  break;
2973  }
2974  int baselen = strlen(namdMyNode->simParams->outputFilename);
2975  filename = new char[baselen+32];
2976  memset(filename, 0, baselen+32);
2977 
2978 #if 0
2979  strcpy(filename, namdMyNode->simParams->outputFilename);
2980 
2981  //check if the directory exists or not
2982  if(access(filename, F_OK)!=0) {
2983  int ret = MKDIR(filename);
2984  if(ret!=0) {
2985  char errmsg[512];
2986  sprintf(errmsg, "Error in creating top-level directory %s!", filename);
2987  NAMD_err(errmsg);
2988  }
2989  }
2990 
2991  strcat(filename, PATHSEPSTR);
2992  strcat(filename, typeName);
2993 
2994  //check if the directory exists or not
2995  if(access(filename, F_OK)!=0) {
2996  int ret = MKDIR(filename);
2997  if(ret!=0) {
2998  char errmsg[512];
2999  sprintf(errmsg, "Error in creating middle-level directory %s!", filename);
3000  NAMD_err(errmsg);
3001  }
3002  }
3003 #else
3004  sprintf(filename, "%s%s%s", namdMyNode->simParams->outputFilename, PATHSEPSTR, typeName);
3005 #endif
3006 
3007  char tmpstr[20];
3008  if(outputID == -1) {
3009  //indicating the output from master
3010  if(timestep!=-9999) {
3011  //not the default value
3012  sprintf(tmpstr, "%smeta.%d", PATHSEPSTR, timestep);
3013  }else{
3014  sprintf(tmpstr, "%smeta", PATHSEPSTR);
3015  }
3016  }else{
3017  //indicating the output from slave
3018  sprintf(tmpstr, "%s%d", PATHSEPSTR, outputID);
3019  strcat(filename, tmpstr);
3020  #if 0
3021  if(access(filename, F_OK)!=0) {
3022  int ret = MKDIR(filename);
3023  if(ret!=0) {
3024  char errmsg[512];
3025  sprintf(errmsg, "Error in creating last-level directory %s!", filename);
3026  NAMD_err(errmsg);
3027  }
3028  }
3029  #endif
3030  if(timestep!=-9999) {
3031  //not the default value
3032  sprintf(tmpstr, "%s%s_%d.%d", PATHSEPSTR,typeName,outputID,timestep);
3033  }else{
3034  sprintf(tmpstr,"%s%s_%d", PATHSEPSTR,typeName,outputID);
3035  }
3036  }
3037 
3038  strcat(filename, tmpstr);
3039  return filename;
3040 }
3041 #endif
3042 
3043 void ParOutput::setDcdSelectionParams(int index, off_t offset, size_t size, std::vector<uint32> map )
3044 {
3045  DebugM(3, "["<<CkMyPe()<<"]"<< " ParOutput::setDcdSelectionParams index "<< index <<" offset " <<offset <<" size " << size<< "\n");
3046  dcdSelectionOffsets[index] = offset;
3047  dcdSelectionLocalSize[index] = size;
3048  dcdSelectionMap[index] = map;
3049 }
3050 
3052 #endif
static Node * Object()
Definition: Node.h:86
DCDParams dcdSelectionParams[16]
Definition: Molecule.h:482
uint16_t dcdSelectIndex
Definition: DataExchanger.h:39
int open_dcd_write_par_slave(char *dcdname)
Definition: dcdlib.C:689
int frequency
Definition: common.h:255
void gather_velocities(int timestep, int N, FloatVector *velocities)
Definition: IMDOutput.C:53
NAMD_HOST_DEVICE Vector c() const
Definition: Lattice.h:270
void NAMD_err(const char *err_msg)
Definition: common.C:170
int get_atom_index_from_dcd_selection(const int index, const int atomIndex)
Definition: Molecule.h:884
void close_veldcdfile()
Definition: Output.C:880
Definition: common.h:275
NAMD_HOST_DEVICE int c_p() const
Definition: Lattice.h:291
void sendReplicaDcdInit(int dstPart, ReplicaDcdInitMsg *msg, int msgsize)
Definition: DataExchanger.C:45
void setReplicaDcdIndex(int index)
Definition: Output.C:889
int update_dcdstep_par_header(int fd)
Definition: dcdlib.C:839
#define FILE_OUTPUT
Definition: Output.h:25
IMDOutput * imd
Definition: Node.h:186
void force(int timestep, int n, Vector *frc, FloatVector *ffrc)
Produce appropriate force for the current timestep.
Definition: Output.C:653
uint16 tag
Definition: common.h:252
#define EVAL_MEASURE
Definition: Output.h:27
Definition: Vector.h:72
Output * output
Definition: Node.h:185
SimParameters * simParameters
Definition: Node.h:181
~Output()
Definition: Output.C:181
float Real
Definition: common.h:118
int32_t int32
Definition: common.h:38
#define DebugM(x, y)
Definition: Debug.h:75
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
BigReal z
Definition: Vector.h:74
float y
Definition: Vector.h:26
#define PATHSEPSTR
Definition: Output.C:47
#define FALSE
Definition: common.h:127
#define MKDIR(X)
Definition: Output.C:48
std::ostream & iWARN(std::ostream &s)
Definition: InfoStream.C:82
int get_clusterSize(int anum) const
Definition: Molecule.h:1100
void replicaDcdSelectInit(int index, const char *tag, const char *filename)
Definition: Output.C:906
void gather_coordinates(int timestep, int N, FloatVector *coords)
Definition: IMDOutput.C:44
#define OUTPUT_FILE_VERSION
Definition: Output.h:32
#define NAMD_close
Definition: Output.C:53
#define iout
Definition: InfoStream.h:51
#define seek_dcdfile
Definition: Output.C:127
Molecule stores the structural information for the system.
Definition: Molecule.h:174
NAMD_HOST_DEVICE int b_p() const
Definition: Lattice.h:290
void close_dcdfile()
Definition: Output.C:864
int open_dcd_write(const char *dcdname)
Definition: dcdlib.C:662
void wrap_coor_int_dcd_selection(xVector *coor, Lattice &lattice, xDone *done, int index)
Definition: Output.C:293
#define NAMD_open
Definition: Output.C:51
uint16_t uint16
Definition: common.h:41
#define DCD_FILEEXISTS
Definition: dcdlib.h:52
uint16_t find_or_create_dcd_selection_index(const char *keystr)
const int get_dcd_selection_size(const int index)
Definition: Molecule.h:893
void wrap_coor(Vector *coor, Lattice &lattice, double *done)
Definition: Output.C:342
void recvReplicaDcdInit(ReplicaDcdInitMsg *msg)
Definition: Output.C:920
Definition: Output.h:35
char outFilename[NAMD_FILENAME_BUFFER_SIZE]
Definition: common.h:254
int write_dcdstep_par_XYZUnits(int fd, int N)
Definition: dcdlib.C:810
static std::pair< int, int > coordinateNeeded(int timestep)
Check if the step requires to output the coordinates.
Definition: Output.C:185
Definition: imd.h:55
int get_dcdheader_size()
Definition: dcdlib.C:1005
float x
Definition: Vector.h:26
int write_dcdstep_par_cell(int fd, double *cell)
Definition: dcdlib.C:785
#define OUTPUT_MAGIC_NUMBER
Definition: Output.h:31
float z
Definition: Vector.h:26
void sendReplicaDcdData(int dstPart, ReplicaDcdDataMsg *msg, int msgsize)
Definition: DataExchanger.C:56
NAMD_HOST_DEVICE BigReal length(void) const
Definition: Vector.h:202
void replicaDcdInit(int index, const char *filename)
Definition: Output.C:894
void NAMD_bug(const char *err_msg)
Definition: common.C:195
void velocity(int timestep, int n, Vector *vel, FloatVector *fvel)
Produce appropriate velocity for the current timestep.
Definition: Output.C:549
#define namdMyNode
Definition: Output.C:130
void coordinate(int timestep, int n, Vector *coor, FloatVector *fcoor, Lattice &lattice)
Produce appropriate coordinate output for the current timestep.
Definition: Output.C:350
int Bool
Definition: common.h:142
int get_dcd_selection_index_from_atom_id(const int index, const int atomIndex)
Definition: Molecule.h:888
void recvReplicaDcdData(ReplicaDcdDataMsg *msg)
Definition: Output.C:931
int write_dcdstep(int fd, int N, float *X, float *Y, float *Z, double *cell)
Definition: dcdlib.C:736
void wrap_coor_dcd_selection(Vector *coor, Lattice &lattice, double *done, int index)
Definition: Output.C:334
BigReal x
Definition: Vector.h:74
NAMD_HOST_DEVICE int a_p() const
Definition: Lattice.h:289
int numAtoms
Definition: Molecule.h:586
#define END_OF_RUN
Definition: Output.h:26
void NAMD_die(const char *err_msg)
Definition: common.C:147
static int forceNeeded(int timestep)
Check if the step requires to output the forces.
Definition: Output.C:619
#define NAMD_write
Definition: Output.C:52
NAMD_HOST_DEVICE Vector b() const
Definition: Lattice.h:269
int write_dcdheader(int fd, const char *filename, int N, int NFILE, int NPRIV, int NSAVC, int NSTEP, double DELTA, int with_unitcell)
Definition: dcdlib.C:915
void NAMD_backup_file(const char *filename, const char *extension)
Definition: common.C:235
void gather_box(int timestep, IMDBox *box)
Definition: IMDOutput.C:71
OUTPUTFILETYPE
Definition: common.h:240
#define simParams
Definition: Output.C:131
#define O_LARGEFILE
Definition: Output.C:56
int size
Definition: common.h:259
Output()
Definition: Output.C:171
void sendReplicaDcdAck(int dstPart, ReplicaDcdAckMsg *msg)
Definition: DataExchanger.C:67
uint16_t dcdSelectIndex
Definition: DataExchanger.h:48
void gather_forces(int timestep, int N, FloatVector *forces)
Definition: IMDOutput.C:62
BigReal y
Definition: Vector.h:74
static const short maxDCD
Definition: Output.C:42
NAMD_HOST_DEVICE Vector wrap_nearest_delta(Position pos1) const
Definition: Lattice.h:233
ScriptTcl * getScript()
Definition: Node.C:1656
int write_dcdstep_par_slave(int fd, int parL, int parU, int N, float *X, float *Y, float *Z)
Definition: dcdlib.C:864
#define PDBVELFACTOR
Definition: common.h:57
#define TIMEFACTOR
Definition: common.h:55
double unitcell[6]
Definition: DataExchanger.h:51
static int velocityNeeded(int timestep)
Check if the step requires to output the velocities.
Definition: Output.C:510
int get_cluster(int anum) const
Definition: Molecule.h:1099
Definition: common.h:275
NAMD_HOST_DEVICE Vector a() const
Definition: Lattice.h:268
void close_dcd_write(int fd)
Definition: dcdlib.C:1063
Bool is_water(int)
int64_t int64
Definition: common.h:39
void measure(Vector *)
Definition: ScriptTcl.C:1400
NAMD_HOST_DEVICE Vector wrap_delta(const Position &pos1) const
Definition: Lattice.h:222
Molecule * molecule
Definition: Node.h:179
#define TRUE
Definition: common.h:128
void wrap_coor_int(xVector *coor, Lattice &lattice, xDone *done)
Definition: Output.C:259
void get_imd_packet()
Definition: IMDOutput.C:33
#define FORCE_OUTPUT
Definition: Output.h:28
static void lattice_to_unitcell(const Lattice *lattice, double *unitcell)
Definition: Output.C:134
#define PDBVELINVFACTOR
Definition: common.h:58
for(int i=0;i< n1;++i)