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