OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
DiscParticle.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  *
7  * Visit http://people.web.psi.ch/adelmann/ for more details
8  *
9  ***************************************************************************/
10 
11 #ifndef DISC_PARTICLE_H
12 #define DISC_PARTICLE_H
13 
14 // debugging macros
15 #ifdef IPPL_PRINTDEBUG
16 #define DPCTLDBG(x) x
17 #else
18 #define DPCTLDBG(x)
19 #endif
20 
21 // include files
22 #include "Utility/DiscConfig.h"
23 #include "Utility/IpplInfo.h"
24 #include "Utility/PAssert.h"
25 #include "Message/Message.h"
26 
27 
28 
29 #include <vector>
30 #include <iostream>
31 #include <cstdio>
32 
33 // forward declarations
34 template<class T> class IpplParticleBase;
35 template<class T> class ParticleAttrib;
36 class Message;
37 
38 class DiscParticle {
39 
40 public:
41  // an enumeration used to indicate whether the file is for reading (INPUT)
42  // or writing (OUTPUT), or for appending (APPEND)
43  enum DPMode1 { INPUT, OUTPUT, APPEND };
44 
45  // an enumeration used to indicate whether we should read/write just a
46  // single attribute, or the whole set of particle attributes
47  enum DPMode2 { ALL, ATTRIB };
48 
49 public:
50  // Constructor: make a DiscParticle for reading or writing.
51  // fname = name of file (without extensions)
52  // config = name of configuration file
53  // I/O mode (INPUT, OUTPUT, or APPEND)
54  // typestr = string describing the 'type' of the Particles to be written
55  // (this is ignored if the data is being read). The string can
56  // be anything the user prefers.
57  DiscParticle(const char *fname, const char *config, int iomode,
58  const char *typestr = 0);
59 
60  // Constructor: same as above, but without a config file specified. The
61  // default config file entry that will be used is "* .", which means, for
62  // each SMP machine, assume the directory to put data files in is "."
63  DiscParticle(const char *fname, int iomode, const char * = 0);
64 
65  // Destructor.
66  ~DiscParticle();
67 
68  //
69  // accessor functions
70  //
71 
72  // Query for whether everything is OK so far.
73  bool get_OK() const { return ConfigOK; }
74 
75  // Query for the number of records in the file. If all attributes in a
76  // Particle object are being written out, this is the number of sets of
77  // attribute collections; if only single attributes are being written out,
78  // this is the number of attributes which were written.
79  unsigned int get_NumRecords() const { return RecordList.size(); }
80 
81  // Query for the mode of the Nth record, which can be either ALL (meaning
82  // an entire IpplParticleBase's list of attributes was written out), or
83  // ATTRIB (meaning only one specific attribute was written out).
84  int get_DataMode(unsigned int record=0) const {
85  return (RecordList[record]->attributes > 0 ? ALL : ATTRIB);
86  }
87 
88  // Query for how this DiscParticle is operationg, either INPUT, OUTPUT, or
89  // APPEND.
90  int get_IOMode() const { return IOMode; }
91 
92  // Query for how many individual particles are stored in the Nth record,
93  // for just the local filesets
94  unsigned int get_NumLocalParticles(unsigned int record=0) const;
95 
96  // Query for how many individual particles are stored in the Nth record,
97  // for the entire particle object (sum of all local particle counts)
98  unsigned int get_NumGlobalParticles(unsigned int record=0) const {
99  return RecordList[record]->globalparticles;
100  }
101 
102  // Query for the number of attributes in the Nth record
103  unsigned int get_NumAttributes(unsigned int record=0) const {
104  return (get_DataMode(record)==ALL ? RecordList[record]->attributes : 1);
105  }
106 
107  // Query for the number of bytes/elem in the Mth attribute in the Nth record
108  unsigned int get_ElemByteSize(unsigned int record=0,
109  unsigned int attrib=0) const {
110  return RecordList[record]->bytesize[attrib];
111  }
112 
113  // Query for the user-specified type string
114  const char *get_TypeString() const { return TypeString.c_str(); }
115 
116  // Query for the DiscType string for the Mth attribute in the Nth record.
117  // If there not one available, return 0.
118  const char *get_DiscType(unsigned int record=0,
119  unsigned int attrib=0) const;
120 
121  //
122  // read methods
123  //
124  // read the specifed record in the file into the given IpplParticleBase or
125  // ParticleAttrib object.
126  // If the method is to read all the IpplParticleBase, this will delete all the
127  // existing particles in the given object, create new ones and store the
128  // values, and then do an update. If an attribute is being read, this
129  // will only work if the number of particles in the attribute already
130  // matches the number in the file.
131 
132  // a templated read for IpplParticleBase objects. This should only be called
133  // if the object was opened with iomode == INPUT
134  // pbase = IpplParticleBase object to read into
135  // record = which record to read. DiscParticle does not keep a 'current
136  // file position' pointer, instead you explicitly request which
137  // record you wish to read.
138  // Return success of operation.
139  //mwerks template<class T>
140  //mwerks bool read(IpplParticleBase<T> &pbase, unsigned int record=0);
142  // a templated read for IpplParticleBase objects. This should only be called
143  // if the object was opened with iomode == INPUT, datamode == ALL.
144  // pbase = IpplParticleBase object to read into
145  // record = which record to read. DiscParticle does not keep a 'current
146  // file position' pointer, instead you explicitly request which
147  // record you wish to read.
148  // Return success of operation.
149  template<class T>
150  bool read(IpplParticleBase<T> &pbase, unsigned int record) {
151 
152  // re-read the meta file since it might have changed
153  ConfigOK = read_meta();
154 
155  // do some sanity checking first
156  if (!ConfigOK) {
157  ERRORMSG("Bad config or meta file in DiscParticle::read." << endl);
158  return false;
159  } else if (IOMode != INPUT) {
160  ERRORMSG("Trying to read for DiscParticle created for output." << endl);
161  return false;
162  } else if (record >= get_NumRecords()) {
163  ERRORMSG("Illegal record number in DiscParticle::read." << endl);
164  return false;
165  } else if (get_DataMode(record) != ALL) {
166  ERRORMSG("Record " << record << " does not contain information for an ");
167  ERRORMSG("entire IpplParticleBase." << endl);
168  return false;
169  } else if (get_NumAttributes(record) != pbase.numAttributes()) {
170  ERRORMSG("Record " << record <<" has a different number of attributes ");
171  ERRORMSG("than in the given IpplParticleBase." << endl);
172  return false;
173  }
174 
175 // ada: incDiscReads is not found INCIPPLSTAT(incDiscReads);
176 
177  // make sure all the attribute sizes match
178  for (unsigned int ca=0; ca < get_NumAttributes(record); ++ca) {
179  if (get_ElemByteSize(record, ca)!=pbase.getAttribute(ca).elementSize()) {
180  ERRORMSG("Mismatched data type size for attribute " << ca << " in ");
181  ERRORMSG("DiscParticle::read." << endl);
182  return false;
183  }
184  }
185 
186  DPCTLDBG(std::string dbgmsgname("DiscParticle::read(IpplParticleBase) "));
187  DPCTLDBG(dbgmsgname += Config->getConfigFile());
188  DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
189 
190  // since we're reading in data for the entire IpplParticleBase, delete all the
191  // existing particles, and do an update, before reading in new particles
192  DPCTLDBG(dbgmsg << "Deleting existing " << pbase.getLocalNum());
193  DPCTLDBG(dbgmsg << " particles." << endl);
194  pbase.destroy(pbase.getLocalNum(), 0);
195  pbase.update();
196 
197  // if we're on a box0 node, read in the data for the attributes
198  if ((unsigned int) Ippl::myNode() == Config->getSMPBox0()) {
199 
200  // loop over all the files on this Box0 node
201  for (unsigned int sf=0; sf < Config->getNumFiles(); ++sf) {
202 
203  // only need to process this file if there are particles in the file
204  int localnum = RecordList[record]->localparticles[sf];
205  if (localnum > 0) {
206 
207  // open the data file
208  std::string filename = Config->getFilename(sf) + ".data";
209  DPCTLDBG(dbgmsg<<"Opening data file '" << filename << "' ..."<<endl);
210  FILE *datafile = open_file(filename, std::string("r"));
211 
212  // if the file is available, read it
213  if (datafile != 0) {
214  // read the data for each attribute into a buffer, then put
215  // these buffers in a message.
216  Message *msg = new Message;
217  msg->put(localnum);
218 
219  // read in the data for all the attributes
220  for (unsigned int a=0; a < get_NumAttributes(record); ++a) {
221  // read the data
222  void *buf = read_data(datafile, a, record, sf);
223  PAssert(buf);
224 
225  // put it in the Message
226  msg->setCopy(false).setDelete(true);
227  msg->putmsg(buf, get_ElemByteSize(record, a), localnum);
228  }
229 
230  // create new particles, by getting them from the message
231  DPCTLDBG(dbgmsg<<"Creating "<<localnum << " new particles."<<endl);
232  pbase.getMessageAndCreate(*msg);
233 
234  // we're done with the message now
235  delete msg;
236  }
237  }
238  }
239  }
240 
241  // at the end, do an update to get everything where it is supposed to be
242  DPCTLDBG(dbgmsg << "Doing final update after reading in particles ...");
243  DPCTLDBG(dbgmsg << endl);
244  pbase.update();
245  DPCTLDBG(dbgmsg << "This node now has " << pbase.getLocalNum());
246  DPCTLDBG(dbgmsg << " local particles." << endl);
247  return true;
248  }
249 
250  // a templated read for ParticleAttrib objects. This should only be
251  // called if the object was opened with iomode == INPUT
252  // pattr = ParticleAttrib object to read into
253  // record = which record to read. DiscParticle does not keep a 'current
254  // file position' pointer, instead you explicitly request which
255  // record you wish to read.
256  // Return success of operation.
257  //mwerks template<class T>
258  //mwerks bool read(ParticleAttrib<T> &pattr, unsigned int record=0);
260  // a templated read for ParticleAttrib objects. This should only be called
261  // if the object was opened with iomode == INPUT, datamode == ATTRIB. When
262  // reading just a single attribute, the particles simply replace the existing
263  // particles in the attribute.
264  // pbase = ParticleAttrib object to read into
265  // record = which record to read. DiscParticle does not keep a 'current
266  // file position' pointer, instead you explicitly request which
267  // record you wish to read.
268  // Return success of operation.
269  template<class T>
270  bool read(ParticleAttrib<T> &pattr, unsigned int record) {
271 
272  // re-read the meta file since it might have changed
273  ConfigOK = read_meta();
274 
275  // do some sanity checking first
276  if (!ConfigOK) {
277  ERRORMSG("Bad config or meta file in DiscParticle::read." << endl);
278  return false;
279  } else if (IOMode != INPUT) {
280  ERRORMSG("Trying to read for a DiscParticle created for output."<<endl);
281  return false;
282  } else if (record >= get_NumRecords()) {
283  ERRORMSG("Illegal record number in DiscParticle::read." << endl);
284  return false;
285  } else if (get_DataMode(record) != ATTRIB) {
286  ERRORMSG("Record " << record << " does not contain information for a ");
287  ERRORMSG("single ParticleAttrib." << endl);
288  return false;
289  } else if (get_ElemByteSize(record, 0) != pattr.elementSize()) {
290  ERRORMSG("Mismatched attribute data type size in ");
291  ERRORMSG("DiscParticle::read." << endl);
292  return false;
293  }
294 
295 // ada: incDiscReads is not found INCIPPLSTAT(incDiscReads);
296 
297  DPCTLDBG(std::string dbgmsgname("DiscParticle::read(ParticleAttrib) "));
298  DPCTLDBG(dbgmsgname += Config->getConfigFile());
299  DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
300 
301  // delete all the existing particles before reading in new particles
302  DPCTLDBG(dbgmsg << "Deleting existing " << pattr.size());
303  DPCTLDBG(dbgmsg << " particles." << endl);
304  pattr.destroy(pattr.size(), 0);
305 
306  // if we're on a box0 node, read in the data for the attributes
307  if ((unsigned int) Ippl::myNode() == Config->getSMPBox0()) {
308 
309  // loop over all the files on this Box0 node
310  for (unsigned int sf=0; sf < Config->getNumFiles(); ++sf) {
311 
312  // only need to process this file if there are particles in the file
313  int localnum = RecordList[record]->localparticles[sf];
314  if (localnum > 0) {
315 
316  // open the data file
317  std::string filename = Config->getFilename(sf) + ".data";
318  DPCTLDBG(dbgmsg<<"Opening data file '"<<filename << "' ..." << endl);
319  FILE *datafile = open_file(filename, std::string("r"));
320 
321  // if the file is available, read it
322  if (datafile != 0) {
323  // read the data for each attribute into a buffer, then put
324  // these buffers in a message.
325  Message *msg = new Message;
326 
327  // read in the data for the attribute
328  void *buf = read_data(datafile, 0, record, sf);
329  PAssert(buf);
330 
331  // put it in the Message
332  msg->setCopy(false).setDelete(true);
333  msg->putmsg(buf, get_ElemByteSize(record, 0), localnum);
334 
335  // create new particles, by getting them from the message
336  DPCTLDBG(dbgmsg<<"Creating "<<localnum<<" new particles." << endl);
337  pattr.getMessage(*msg, localnum);
338 
339  // we're done with the message now
340  delete msg;
341  }
342  }
343  }
344  }
345 
346  DPCTLDBG(dbgmsg << "This node now has " << pattr.size());
347  DPCTLDBG(dbgmsg << " local particles." << endl);
348  return true;
349  }
350 
351  //
352  // write methods
353  //
354  // write the data from the given IpplParticleBase or ParticleAttrib into the
355  // file. Data is appended as a new record.
356 
357  // a templated write for IpplParticleBase objects. All attributes in the
358  // IpplParticleBase are written as a single record. This should only be
359  // called if the object was opened with iomode == OUTPUT or APPEND.
360  // pbase = IpplParticleBase object to read from.
361  // Return success of operation.
362  //mwerks template<class T>
363  //mwerks bool write(IpplParticleBase<T> &pbase);
365  // a templated write for IpplParticleBase objects. All attributes in the
366  // IpplParticleBase are written as a single record. This should only be
367  // called if the object was opened with iomode == OUTPUT or APPEND.
368  // pbase = IpplParticleBase object to read into
369  // Return success of operation.
370  template<class T>
371  bool write(IpplParticleBase<T> &pbase) {
372 
373  // generate a tag to use for communication
375 
376  // if the file already has some records, re-read the meta file in case it
377  // has changed. If we do not have any record info, and we've opened
378  // for OUTPUT, we do NOT read any possible meta file since we want to start
379  // a new file.
380  if (get_NumRecords() > 0 || IOMode == APPEND)
381  ConfigOK = read_meta();
382 
383  // do some sanity checking first
384  if (!ConfigOK) {
385  ERRORMSG("Bad config or meta file in DiscParticle::write." << endl);
386  return false;
387  } else if (IOMode == INPUT) {
388  ERRORMSG("Trying to write for a DiscParticle created for input."<<endl);
389  return false;
390  }
391 
392 // ada: incDiscWrites is not found INCIPPLSTAT(incDiscWrites);
393 
394  DPCTLDBG(std::string dbgmsgname("DiscParticle::write(IpplParticleBase) "));
395  DPCTLDBG(dbgmsgname += Config->getConfigFile());
396  DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
397 
398  // create a new record entry, and set it to the proper values
399  RecordInfo *info = new RecordInfo;
400  info->attributes = pbase.numAttributes();
401  info->globalparticles = pbase.getTotalNum();
402  for (int a=0; a < info->attributes; ++a) {
403  info->bytesize.push_back(pbase.getAttribute(a).elementSize());
404  info->disctypes.push_back(pbase.getAttribute(a).typeString());
405  }
406 
407  // Create a message with our local particles, which will then be used
408  // to write out the data
409  DPCTLDBG(dbgmsg << "Putting local " << pbase.getLocalNum());
410  DPCTLDBG(dbgmsg << " particles into a message." << endl);
411  Message *msg = new Message;
412  pbase.putMessage(*msg, pbase.getLocalNum(), 0);
413 
414  // on Box0 nodes, first write out your own particles, then write out
415  // all the other node's particles
416  if ((unsigned int) Ippl::myNode() == Config->getSMPBox0()) {
417  // create the data file, if it does not yet exist; otherwise, open
418  // it for append
419  std::string openmode = "a";
420  if (get_NumRecords() == 0)
421  openmode = "w";
422  std::string filename = Config->getFilename(0) + ".data";
423  DPCTLDBG(dbgmsg << "Opening data file '" << filename << "' ..." << endl);
424  FILE *datafile = open_file(filename, openmode);
425  if (datafile == 0) {
426  delete info;
427  delete msg;
428  return false;
429  }
430 
431  // create a vector of Messages, which will hold the info to be written
432  // out. We do not write until we have all the messages from the
433  // different nodes writing to the Box0 file.
434  std::vector<Message *> msgvec;
435  msgvec.push_back(msg);
436 
437  // write out our local attribute data, saving where we started to write
438  // determine how many other SMP nodes we expect to receive data from
439  int notreceived = (Config->getNumSMPNodes() - 1);
440  for (unsigned int s=0; s < Config->getNumOtherSMP(); ++s)
441  notreceived += Config->getNumSMPNodes(Config->getOtherSMP(s));
442 
443  // now wait for messages from all the other nodes with their particle
444  // data, and save the messages
445  DPCTLDBG(dbgmsg << "Box0 node waiting to receive " << notreceived);
446  DPCTLDBG(dbgmsg << " messages, from this SMP and ");
447  DPCTLDBG(dbgmsg << Config->getNumOtherSMP() << " other SMPs." << endl);
448  while (notreceived > 0) {
449  // receive the message
450  int any_node = COMM_ANY_NODE;
451  Message *recmsg = Ippl::Comm->receive_block(any_node, tag);
452  PAssert(recmsg);
453  notreceived--;
454 
455  DPCTLDBG(dbgmsg<<"Received msg from node " << any_node << " w tag ");
456  DPCTLDBG(dbgmsg<< tag << "; still waiting for " << notreceived);
457  DPCTLDBG(dbgmsg<< " messages." << endl);
458 
459  // get the number of particles and save the info
460  // write the info out to disk
461  msgvec.push_back(recmsg);
462  }
463 
464  // we have all the messages, so write the data to disk. This will
465  // delete all the messages and save the offset information, as well as
466  // the particle count.
467  if (!write_data(datafile, msgvec, info)) {
468  delete info;
469  return false;
470  }
471 
472  // done writing; close the file and save the particle count
473  fclose(datafile);
474 
475  } else {
476  // just send out the message with our local particles now
477  DPCTLDBG(dbgmsg<<"Sending " << pbase.getLocalNum()<<" ptcls to node ");
478  DPCTLDBG(dbgmsg<< Config->getSMPBox0() << " with tag " << tag << endl);
479  Ippl::Comm->send(msg, Config->getSMPBox0(), tag);
480 
481  // and save extra necessary info into RecordInfo struct
482  info->localparticles.push_back(0);
483  info->offset.push_back(std::vector<Offset_t>());
484  }
485 
486  // add this new record information to our list
487  DPCTLDBG(dbgmsg << "Finished writing; saving RecordInfo record ..."<<endl);
488  RecordList.push_back(info);
489 
490  // rewrite the meta file, if we're on a box0 node
491  if ((unsigned int) Ippl::myNode() == Config->getSMPBox0()) {
492  DPCTLDBG(dbgmsg << "Doing final re-write of .meta file ..." << endl);
493  if (!write_meta())
494  return false;
495  }
496 
497  // to be safe, do a barrier here, since some nodes could have had very
498  // little to do
499  DPCTLDBG(dbgmsg << "At final barrier at end of write ..." << endl);
500  Ippl::Comm->barrier();
501 
502  // return success
503  return true;
504  }
505 
506  // a templated write for ParticleAttrib objects. The single attribute
507  // data is written as a single record. This should only be
508  // called if the object was opened with iomode == OUTPUT or APPEND.
509  // pattr = ParticleAttrib object to read from.
510  // Return success of operation.
511  //mwerks template<class T>
512  //mwerks bool write(ParticleAttrib<T> &pattr);
514  // a templated write for ParticleAttrib objects. This should only be
515  // called if the object was opened with iomode == OUTPUT or APPEND.
516  // pattr = ParticleAttrib object to read from
517  // Return success of operation.
518  template<class T>
519  bool write(ParticleAttrib<T> &pattr) {
520 
521  // generate a tag to use for communication
523 
524  // if the file already has some records, re-read the meta file in case it
525  // has changed. If we do not have any record info, and we've opened
526  // for OUTPUT, we do NOT ready any possible meta file since we want to
527  // start a new file
528  if (get_NumRecords() > 0 || IOMode == APPEND)
529  ConfigOK = read_meta();
530 
531  // do some sanity checking first
532  if (!ConfigOK) {
533  ERRORMSG("Bad config or meta file in DiscParticle::write." << endl);
534  return false;
535  } else if (IOMode == INPUT) {
536  ERRORMSG("Trying to write for a DiscParticle created for input."<<endl);
537  return false;
538  }
539 
540 // ada: incDiscWrites is not found INCIPPLSTAT(incDiscWrites);
541 
542  DPCTLDBG(std::string dbgmsgname("DiscParticle::write(ParticleAttrib) "));
543  DPCTLDBG(dbgmsgname += Config->getConfigFile());
544  DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
545 
546  // create a new record entry, and set it to the proper values
547  RecordInfo *info = new RecordInfo;
548  info->attributes = 0;
549  info->globalparticles = 0;
550  info->bytesize.push_back(pattr.elementSize());
551  info->disctypes.push_back(pattr.typeString());
552 
553  // Create a message with our local particles, which will then be used
554  // to write out the data
555  DPCTLDBG(dbgmsg << "Putting local " << pattr.size());
556  DPCTLDBG(dbgmsg << " particles into a message." << endl);
557  Message *msg = new Message;
558  msg->put(pattr.size());
559  pattr.putMessage(*msg, pattr.size(), 0);
560 
561  // on Box0 nodes, first write out your own particles, then write out
562  // all the other node's particles
563  if ((unsigned int) Ippl::myNode() == Config->getSMPBox0()) {
564  // create the data file, if it does not yet exist; otherwise, open
565  // it for append
566  std::string openmode = "a";
567  if (get_NumRecords() == 0)
568  openmode = "w";
569  std::string filename = Config->getFilename(0) + ".data";
570  DPCTLDBG(dbgmsg << "Opening data file '" << filename << "' ..." << endl);
571  FILE *datafile = open_file(filename, openmode);
572  if (datafile == 0) {
573  delete info;
574  delete msg;
575  return false;
576  }
577 
578  // create a vector of Messages, which will hold the info to be written
579  // out. We do not write until we have all the messages from the
580  // different nodes writing to the Box0 file.
581  std::vector<Message *> msgvec;
582  msgvec.push_back(msg);
583 
584  // write out our local attribute data, saving where we started to write
585  // determine how many other SMP nodes we expect to receive data from
586  int notreceived = (Config->getNumSMPNodes() - 1);
587  for (unsigned int s=0; s < Config->getNumOtherSMP(); ++s)
588  notreceived += Config->getNumSMPNodes(Config->getOtherSMP(s));
589 
590  // now wait for messages from all the other nodes with their particle
591  // data, and save the messages
592  DPCTLDBG(dbgmsg << "Box0 node waiting to receive " << notreceived);
593  DPCTLDBG(dbgmsg << " messages, from this SMP and ");
594  DPCTLDBG(dbgmsg << Config->getNumOtherSMP() << " other SMPs." << endl);
595  while (notreceived > 0) {
596  // receive the message
597  int any_node = COMM_ANY_NODE;
598  Message *recmsg = Ippl::Comm->receive_block(any_node, tag);
599  PAssert(recmsg);
600  notreceived--;
601 
602  DPCTLDBG(dbgmsg<< "Received msg from node " << any_node << " w tag ");
603  DPCTLDBG(dbgmsg<< tag << "; still waiting for " << notreceived);
604  DPCTLDBG(dbgmsg<< " messages." << endl);
605 
606  // get the number of particles and save the info
607  // write the info out to disk
608  msgvec.push_back(recmsg);
609  }
610 
611  // we have all the messages, so write the data to disk. This will
612  // delete all the messages and save the offset information, as well as
613  // the particle count.
614  if (!write_data(datafile, msgvec, info)) {
615  delete info;
616  return false;
617  }
618 
619  // done writing; close the file and save the particle count
620  fclose(datafile);
621 
622  } else {
623  // just send out the message with our local particles now
624  DPCTLDBG(dbgmsg << "Sending " << pattr.size() << " particles to node ");
625  DPCTLDBG(dbgmsg << Config->getSMPBox0() << " with tag " << tag << endl);
626  Ippl::Comm->send(msg, Config->getSMPBox0(), tag);
627 
628  // and save extra necessary info into RecordInfo struct
629  info->localparticles.push_back(0);
630  info->offset.push_back(std::vector<Offset_t>());
631  }
632 
633  // add this new record information to our list
634  DPCTLDBG(dbgmsg << "Finished writing; saving RecordInfo record ..."<<endl);
635  RecordList.push_back(info);
636 
637  // rewrite the meta file, if we're on a box0 node
638  if ((unsigned int) Ippl::myNode() == Config->getSMPBox0()) {
639  DPCTLDBG(dbgmsg << "Doing final re-write of .meta file ..." << endl);
640  if (!write_meta())
641  return false;
642  }
643 
644  // to be safe, do a barrier here, since some nodes could have had very
645  // little to do
646  DPCTLDBG(dbgmsg << "At final barrier at end of write ..." << endl);
647  Ippl::Comm->barrier();
648 
649  // return success
650  return true;
651  }
652 
653  //
654  // console printing methods
655  //
656 
657  // print out debugging info to the given stream
658  void printDebug(std::ostream&);
659  void printDebug();
660 
661 private:
662  // a typedef used to select the data type for file offsets
663  typedef long Offset_t;
664 
665  // the configuration file mechanism
667  bool ConfigOK;
668 
669  // I/O mode (INPUT or OUTPUT)
670  int IOMode;
671 
672  // the base name for the output file, and the descriptive type string
673  std::string BaseFile;
674  std::string TypeString;
675 
676  // a simple struct which stores information about each record, for each
677  // file set
678  struct RecordInfo {
679  // a typedef used to select the data type for file offsets
680  typedef long Offset_t;
681 
682  int attributes; // number of attributes; 0 == just writing
683  // one attribute, > 0 == writing a whole
684  // IpplParticleBase's worth of particles
685  int globalparticles; // total number of particles in whole system
686  std::vector<int> localparticles; // number of particles in this fileset's files
687  std::vector<int> bytesize; // how many bytes/attrib elem in each attrib
688  std::vector<std::vector<Offset_t> > offset; // starting offset for attrib in .data
689  std::vector<std::string> disctypes; // attribute types determined by DiscType
691  };
692 
693  // the list of information for each record
694  std::vector<RecordInfo *> RecordList;
695 
696  // this keeps track of where in the .data file writing is occuring
698 
699  //
700  // functions used to build/query information about the processors, etc.
701  //
702 
703  // perform initialization based on the constuctor arguments
704  void initialize(const char *base, const char *config,
705  const char *typestr, int iomode);
706 
707  // open a file in the given mode. If an error occurs, print a message (but
708  // only if the last argument is true).
709  // fnm = complete name of file (can include a path)
710  // mode = open method ("r" == read, "rw" == read/write, etc.
711  FILE *open_file(const std::string& fnm, const std::string& mode,
712  bool reporterr = true);
713 
714  //
715  // read/write functions for individual components
716  //
717 
718  // read or write .meta data file information. Return success.
719  bool read_meta();
720  bool write_meta();
721 
722  // read the data for the Nth attribute of record R, in the Fth fileset,
723  // and return the newly allocated buffer (or 0 if an error occurs).
724  void *read_data(FILE *outputData, unsigned int attrib,
725  unsigned int record, unsigned int fileset);
726 
727  // write the data for a block of particles to the given file. The
728  // data is just appended to the end. Return success of write.
729  bool write_data(FILE *outputData, std::vector<Message *> &, RecordInfo *);
730 
731  //
732  // don't allow copy or assign ... this are declared but never defined,
733  // if something tries to use them it will generate a missing symbol error
734  //
735 
736  DiscParticle(const DiscParticle&);
738 };
739 
740 #include "Utility/DiscParticle.hpp"
741 
742 #endif // DISC_PARTICLE_H
743 
744 /***************************************************************************
745  * $RCSfile: DiscParticle.h,v $ $Author: adelmann $
746  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $
747  * IPPL_VERSION_ID: $Id: DiscParticle.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $
748  ***************************************************************************/
bool read(ParticleAttrib< T > &pattr, unsigned int record)
Definition: DiscParticle.h:270
void * read_data(FILE *outputData, unsigned int attrib, unsigned int record, unsigned int fileset)
const std::string & getConfigFile() const
Definition: DiscConfig.h:76
std::vector< std::vector< Offset_t > > offset
Definition: DiscParticle.h:688
#define DPCTLDBG(x)
Definition: DiscParticle.h:18
const char * get_DiscType(unsigned int record=0, unsigned int attrib=0) const
bool get_OK() const
Definition: DiscParticle.h:73
virtual size_t getMessage(Message &, size_t)
Offset_t CurrentOffset
Definition: DiscParticle.h:697
int get_DataMode(unsigned int record=0) const
Definition: DiscParticle.h:84
#define INFORM_ALL_NODES
Definition: Inform.h:38
std::vector< int > localparticles
Definition: DiscParticle.h:686
unsigned int get_ElemByteSize(unsigned int record=0, unsigned int attrib=0) const
Definition: DiscParticle.h:108
attrib_container_t::size_type numAttributes() const
#define ERRORMSG(msg)
Definition: IpplInfo.h:399
size_t size(void) const
void destroy(size_t, size_t, bool=false)
unsigned int get_NumLocalParticles(unsigned int record=0) const
void barrier(void)
const int COMM_ANY_NODE
Definition: Communicate.h:40
static int myNode()
Definition: IpplInfo.cpp:794
unsigned int getNumSMPNodes() const
Definition: DiscConfig.h:101
DiscParticle(const char *fname, const char *config, int iomode, const char *typestr=0)
bool info
Info flag.
Definition: Options.cpp:8
bool read(IpplParticleBase< T > &pbase, unsigned int record)
Definition: DiscParticle.h:150
int next_tag(int t, int s=1000)
Definition: TagMaker.h:43
unsigned int getNumOtherSMP() const
Definition: DiscConfig.h:133
size_t getTotalNum() const
unsigned int get_NumGlobalParticles(unsigned int record=0) const
Definition: DiscParticle.h:98
std::vector< RecordInfo * > RecordList
Definition: DiscParticle.h:694
unsigned int elementSize() const
Message & putmsg(void *, int, int=0)
size_t getLocalNum() const
std::string BaseFile
Definition: DiscParticle.h:673
unsigned int get_NumAttributes(unsigned int record=0) const
Definition: DiscParticle.h:103
unsigned int getOtherSMP(unsigned int sn) const
Definition: DiscConfig.h:139
virtual size_t putMessage(Message &, size_t, size_t)
unsigned int get_NumRecords() const
Definition: DiscParticle.h:79
std::vector< int > bytesize
Definition: DiscParticle.h:687
virtual void destroy(size_t M, size_t I, bool optDestroy=true)
const char * get_TypeString() const
Definition: DiscParticle.h:114
FILE * open_file(const std::string &fnm, const std::string &mode, bool reporterr=true)
bool write_data(FILE *outputData, std::vector< Message * > &, RecordInfo *)
virtual void update()
size_t putMessage(Message &, size_t, size_t)
Message & put(const T &val)
Definition: Message.h:414
DiscConfig * Config
Definition: DiscParticle.h:666
#define FB_TAG_CYCLE
Definition: Tags.h:62
const std::string & getFilename(unsigned int fn) const
Definition: DiscConfig.h:125
ParticleAttribBase & getAttribute(attrib_container_t::size_type N)
std::string TypeString
Definition: DiscParticle.h:674
int get_IOMode() const
Definition: DiscParticle.h:90
const std::string & typeString() const
#define PAssert(c)
Definition: PAssert.h:117
unsigned int getSMPBox0() const
Definition: DiscConfig.h:113
bool write(ParticleAttrib< T > &pattr)
Definition: DiscParticle.h:519
size_t getMessageAndCreate(Message &)
std::vector< std::string > disctypes
Definition: DiscParticle.h:689
Message * receive_block(int &node, int &tag)
Definition: Inform.h:41
Message & setDelete(const bool c)
Definition: Message.h:339
static Communicate * Comm
Definition: IpplInfo.h:93
Message & setCopy(const bool c)
Definition: Message.h:327
bool send(Message *, int node, int tag, bool delmsg=true)
unsigned int getNumFiles() const
Definition: DiscConfig.h:119
#define FB_WRITE_TAG
Definition: Tags.h:60
DiscParticle & operator=(const DiscParticle &)
void initialize(const char *base, const char *config, const char *typestr, int iomode)
bool write(IpplParticleBase< T > &pbase)
Definition: DiscParticle.h:371
Inform & endl(Inform &inf)
Definition: Inform.cpp:42