OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
DiscParticleFunctions.cpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  * This program was prepared by PSI.
7  * All rights in the program are reserved by PSI.
8  * Neither PSI nor the author(s)
9  * makes any warranty, express or implied, or assumes any liability or
10  * responsibility for the use of this software
11  *
12  * Visit www.amas.web.psi for more details
13  *
14  ***************************************************************************/
15 
16 // -*- C++ -*-
17 /***************************************************************************
18  *
19  * The IPPL Framework
20  *
21  *
22  * Visit http://people.web.psi.ch/adelmann/ for more details
23  *
24  ***************************************************************************/
25 
26 // include files
27 #include "Utility/DiscParticle.h"
28 #include "Utility/DiscConfig.h"
29 #include "Utility/DiscMeta.h"
30 #include "Message/Communicate.h"
31 #include "Message/Message.h"
32 
33 #include "Utility/PAssert.h"
34 #include "Utility/IpplInfo.h"
35 #include "Utility/IpplStats.h"
36 
37 // debugging macros
38 #ifdef IPPL_PRINTDEBUG
39 #define DPFDBG(x) x
40 #else
41 #define DPFDBG(x)
42 #endif
43 
45 // Constructor: make a DiscParticle for reading or writing.
46 // fname = name of file (without extensions)
47 // config = name of configuration file
48 // I/O mode
49 // typestr = string describing the 'type' of the Particles to be written
50 // (this is ignored if the data is being read). The string can
51 // be anything the user prefers.
52 DiscParticle::DiscParticle(const char *base, const char *config,
53  int iomode, const char *typestr) {
54 
55  initialize(base, config, typestr, iomode);
56 }
57 
58 
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::DiscParticle(const char *base,
64  int iomode, const char *typestr) {
65 
66  initialize(base, 0, typestr, iomode);
67 }
68 
69 
71 // perform initialization based on the constuctor arguments
72 void DiscParticle::initialize(const char *base, const char *config,
73  const char *typestr, int iomode) {
74 
75 
76  // save which IO mode we're running, and make sure it is OK
77  if (iomode != INPUT && iomode != OUTPUT && iomode != APPEND)
78  Ippl::abort("IO mode for DiscParticle must be INPUT, OUTPUT, or APPEND.");
79  IOMode = iomode;
80  CurrentOffset = 0;
81 
82  // save the name information
83  BaseFile = base;
84  if (typestr != 0)
85  TypeString = typestr;
86  else
87  TypeString = "unknown";
88 
89  // parse the configuration file to find our SMP's, file directories, etc.
90  // create a DiscConfig instance, which will parse the file
91  Config = new DiscConfig(config, BaseFile.c_str(), IOMode != INPUT);
92  ConfigOK = Config->ok();
93 
94  // indicate how many filesets we're reading or writing
95  /*
96  if (iomode != INPUT) {
97  ADDIPPLSTAT(incDiscFilesetWrites,Config->getNumFiles());
98  } else {
99  ADDIPPLSTAT(incDiscFilesetReads,Config->getNumFiles());
100  }
101  */
102  // read the meta information about numbers of particles, etc. in each record
103  if (ConfigOK && IOMode != OUTPUT)
104  ConfigOK = read_meta();
105 }
106 
107 
109 // Destructor
111 
112  // delete per-record information
114  for ( ; rec != RecordList.end(); ++rec)
115  delete (*rec);
116 
117  // delete the configuration file info
118  if (Config != 0)
119  delete Config;
120 }
121 
122 
124 // Query for the DiscType string for the Mth attribute in the Nth record.
125 // If there not one available, return 0.
126 const char *DiscParticle::get_DiscType(unsigned int record,
127  unsigned int attrib) const {
128  // return the string, if it is available
129  if (record < get_NumRecords() &&
130  attrib < RecordList[record]->disctypes.size())
131  return (RecordList[record]->disctypes[attrib].c_str());
132  else
133  return 0;
134 }
135 
136 
138 // Query for how many individual particles are stored in the Nth record,
139 // for just the local filesets
140 unsigned int DiscParticle::get_NumLocalParticles(unsigned int record) const {
141  unsigned int retval = 0;
142  for (unsigned int i=0; i < RecordList[record]->localparticles.size(); ++i)
143  retval += RecordList[record]->localparticles[i];
144  return retval;
145 }
146 
147 
149 // open a file in the given mode. If an error occurs, print a message
150 // and return 0.
151 FILE *DiscParticle::open_file(const std::string& fnm, const std::string& mode,
152  bool reporterr) {
153 
154  // open the file, with the given name and mode
155  FILE *f = fopen(fnm.c_str(), mode.c_str());
156 
157  // check for an error
158  if (f == 0 && reporterr) {
159  ERRORMSG("DiscParticle: Could not open file '" << fnm.c_str());
160  ERRORMSG("' on node " << Ippl::myNode() << "." << endl);
161  }
162 
163  // return the file pointer; if an error occurred, this will be zero
164  return f;
165 }
166 
167 
169 // write out a new .meta file. The .meta file contains the following
170 // information, on each line:
171 // String with type of data stored here, supplied by user
172 // Number of SMP filesets
173 // Number of Records
174 // For each record:
175 // Number of attributes (if 0, this is just for one attrib, not all)
176 // Number of local particles
177 // Number of particles total
178 // For each attribute in the record:
179 // Size of attribute elements, in bytes
180 // Offset location of start of attribute data in .data file
181 // return success of operation.
183 
184  // Sanity checking
185  if (!ConfigOK) {
186  ERRORMSG("Bad config file in DiscParticle::write_meta." << endl);
187  return false;
188  } else if (IOMode == INPUT) {
189  ERRORMSG("Trying to write a DiscParticle .meta file for a DiscParticle");
190  ERRORMSG(" created for reading." << endl);
191  return false;
192  } else if (Config->getNumFiles() > 1) {
193  ERRORMSG("Only one fileset/SMP max allowed when writing" << endl);
194  return false;
195  }
196 
197  // no need to write anything if we have no files for this SMP
198  if ((unsigned int)Ippl::myNode() != Config->getSMPBox0() || Config->getNumFiles() == 0)
199  return true;
200 
201  // open the meta data file
202  std::string filename = Config->getFilename(0) + ".meta";
203  FILE *outputMeta = open_file(filename, std::string("w"));
204  if (outputMeta == 0)
205  return false;
206 
207  // write the initial header info
208  long rnum = RecordList.size();
209  fprintf(outputMeta, "Type = %s\n", TypeString.c_str());
210  fprintf(outputMeta, "SMPs = %u\n", Config->fileSMPs());
211  fprintf(outputMeta, "Records = %ld\n", rnum);
212  fprintf(outputMeta, "NextOffset = %ld\n", CurrentOffset);
213 
214  // write information for each record
215  for (unsigned int r=0; r < RecordList.size(); ++r) {
216  // general record information
217  fprintf(outputMeta, "RecordAttribs = %u %d\n", r,
218  RecordList[r]->attributes);
219  fprintf(outputMeta, "RecordLocPtcl = %u %d\n", r,
220  RecordList[r]->localparticles[0]);
221  fprintf(outputMeta, "RecordGlobPtcl = %u %d\n", r,
222  RecordList[r]->globalparticles);
223 
224  // information about each attribute
225  fprintf(outputMeta, "RecordElemByte = %u ", r);
226  int b, bmax;
227  bmax = RecordList[r]->bytesize.size();
228  for (b=0; b<bmax; ++b)
229  fprintf(outputMeta, " %d", RecordList[r]->bytesize[b]);
230  fprintf(outputMeta, "\n");
231  fprintf(outputMeta, "RecordDiscType = %u ", r);
232  for (b=0; b<bmax; ++b)
233  fprintf(outputMeta, " %s", RecordList[r]->disctypes[b].c_str());
234  fprintf(outputMeta, "\n");
235  fprintf(outputMeta, "RecordOffset = %u ", r);
236  bmax = RecordList[r]->offset[0].size();
237  for (b=0; b<bmax; ++b)
238  fprintf(outputMeta, " %ld", RecordList[r]->offset[0][b]);
239  fprintf(outputMeta, "\n");
240  }
241 
242  // close data file and return
243  fclose(outputMeta);
244  DPFDBG(printDebug());
245  return true;
246 }
247 
248 
250 // read in data from .meta file, and replace current storage values.
251 // The format for a .meta file is described in the write_meta routine.
252 // return success of operation.
254 
255  // Sanity checking
256  if (!ConfigOK) {
257  ERRORMSG("Bad config file in DiscParticle::read_meta." << endl);
258  return false;
259  }
260 
261  bool iserror = false;
263 
264  DPFDBG(std::string dbgmsgname("DP:read_meta:"));
265  DPFDBG(dbgmsgname += Config->getConfigFile());
266  DPFDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
267  DPFDBG(dbgmsg << "Starting to read meta info: mySMP=" << Config->mySMP());
268  DPFDBG(dbgmsg << ", mybox0=" << Config->getSMPBox0());
269  DPFDBG(dbgmsg << ", numfiles=" << Config->getNumFiles());
270  DPFDBG(dbgmsg << endl);
271 
272  // initialize data before reading .meta file
273  TypeString = "unknown";
274  {
276  for ( ; rec != RecordList.end(); ++rec)
277  delete (*rec);
278  }
279  RecordList.erase(RecordList.begin(), RecordList.end());
280 
281  // on Box0 nodes, read in the meta data ... on others, wait for
282  // Box0 nodes to send info to them
283  if ((unsigned int)Ippl::myNode() == Config->getSMPBox0()) {
284  // loop over all the files on this Box0 node
285  for (unsigned int sf=0; sf < Config->getNumFiles(); ++sf) {
286  // open and parse the meta data file
287  std::string filename = Config->getFilename(sf) + ".meta";
288  DiscMeta outputMeta(filename.c_str());
289  if (outputMeta.size() == 0)
290  return false;
291 
292  // keep reading until we have all data
293  DiscMeta::iterator metaline = outputMeta.begin();
294  for ( ; metaline != outputMeta.end(); ++metaline) {
295  // get number of tokens and list of tokens in the line
296  int linesread = (*metaline).first;
297  int numtokens = (*metaline).second.first;
298  std::string *tokens = (*metaline).second.second;
299 
300  // action is based on first keyword
301  if (tokens[0] == "Type") {
302  if (numtokens > 1 && sf == 0)
303  TypeString = tokens[1];
304  } else if (tokens[0] == "SMPs" && numtokens == 2) {
305  unsigned int checkfileSMPs = atoi(tokens[1].c_str());
306  if (Config->fileSMPs() != checkfileSMPs) {
307  ERRORMSG("SMP number mismatch in file " << filename);
308  ERRORMSG(" (" << checkfileSMPs << "!=" << Config->fileSMPs());
309  ERRORMSG(")" << endl);
310  iserror = true;
311  }
312  } else if (tokens[0] == "NextOffset" && numtokens == 2) {
313  CurrentOffset = atol(tokens[1].c_str());
314  } else if (tokens[0] == "Records" && numtokens == 2) {
315  unsigned int numrec = atoi(tokens[1].c_str());
316  if (RecordList.size() != 0 && RecordList.size() != numrec) {
317  ERRORMSG("Illegal Records value in file '" << filename << "' ");
318  ERRORMSG("(" << numrec << " != " << RecordList.size() << ")");
319  ERRORMSG(endl);
320  iserror = true;
321  } else {
322  // create N empty record storage objects
323  for (int r=0; r < atoi(tokens[1].c_str()); ++r)
324  RecordList.push_back(new RecordInfo());
325  }
326  } else if (tokens[0] == "RecordAttribs" && numtokens == 3) {
327  unsigned int recnum = atoi(tokens[1].c_str());
328  int attribs = atoi(tokens[2].c_str());
329  if (recnum >= RecordList.size()) {
330  ERRORMSG("Illegal record number '" << recnum << "'" << endl);
331  iserror = true;
332  } else if (sf > 0 && attribs != RecordList[recnum]->attributes) {
333  ERRORMSG("Illegal number of attributes in file " << filename);
334  ERRORMSG(" (" << attribs << " != ");
335  ERRORMSG(RecordList[recnum]->attributes << ")" << endl);
336  iserror = true;
337  } else {
338  RecordList[recnum]->attributes = attribs;
339  }
340  } else if (tokens[0] == "RecordLocPtcl" && numtokens == 3) {
341  unsigned int recnum = atoi(tokens[1].c_str());
342  int nump = atoi(tokens[2].c_str());
343  if (recnum >= RecordList.size()) {
344  ERRORMSG("Illegal record number '" << recnum << "'" << endl);
345  iserror = true;
346  } else {
347  RecordList[recnum]->localparticles.push_back(nump);
348  }
349  } else if (tokens[0] == "RecordGlobPtcl" && numtokens == 3) {
350  unsigned int recnum = atoi(tokens[1].c_str());
351  int nump = atoi(tokens[2].c_str());
352  if (recnum >= RecordList.size()) {
353  ERRORMSG("Illegal record number '" << recnum << "'" << endl);
354  iserror = true;
355  } else if (sf > 0 && nump != RecordList[recnum]->globalparticles) {
356  ERRORMSG("Illegal number of global particles in file "<<filename);
357  ERRORMSG(" (" << nump << " != ");
358  ERRORMSG(RecordList[recnum]->globalparticles << ")" << endl);
359  iserror = true;
360  } else {
361  RecordList[recnum]->globalparticles = nump;
362  }
363  } else if (tokens[0] == "RecordElemByte" && numtokens >= 2) {
364  unsigned int recnum = atoi(tokens[1].c_str());
365  if (recnum >= RecordList.size()) {
366  ERRORMSG("Illegal record number '" << recnum << "'" << endl);
367  iserror = true;
368  } else {
369  for (int b=2; b < numtokens; ++b) {
370  int bytesize = atoi(tokens[b].c_str());
371  if (sf > 0 && bytesize != RecordList[recnum]->bytesize[b-2]) {
372  ERRORMSG("Illegal byte size for attribute " << b-2);
373  ERRORMSG(" in file " << filename << "(" << bytesize);
374  ERRORMSG(" != " << RecordList[recnum]->bytesize[b-2] << ")");
375  ERRORMSG(endl);
376  iserror = true;
377  } else if (sf == 0) {
378  RecordList[recnum]->bytesize.push_back(bytesize);
379  }
380  }
381  if (RecordList[recnum]->bytesize.size() !=
382  (RecordList[recnum]->attributes == 0 ? 1u :
383  static_cast<unsigned int>(RecordList[recnum]->attributes))) {
384  ERRORMSG("Incorrect number of byte size values in file ");
385  ERRORMSG(filename << endl);
386  iserror = true;
387  }
388  }
389  } else if (tokens[0] == "RecordDiscType" && numtokens >= 2) {
390  unsigned int recnum = atoi(tokens[1].c_str());
391  if (recnum >= RecordList.size()) {
392  ERRORMSG("Illegal record number '" << recnum << "'" << endl);
393  iserror = true;
394  } else {
395  for (int b=2; b < numtokens; ++b) {
396  if (sf > 0 && tokens[b] != RecordList[recnum]->disctypes[b-2]) {
397  ERRORMSG("Inconsistent DiscType for attribute " << b-2);
398  ERRORMSG(" in file " << filename << "(" << tokens[b]);
399  ERRORMSG(" != " << RecordList[recnum]->disctypes[b-2] << ")");
400  ERRORMSG(endl);
401  iserror = true;
402  } else if (sf == 0) {
403  RecordList[recnum]->disctypes.push_back(tokens[b]);
404  }
405  }
406  if (RecordList[recnum]->disctypes.size() !=
407  (RecordList[recnum]->attributes == 0 ? 1u :
408  static_cast<unsigned int>(RecordList[recnum]->attributes))) {
409  ERRORMSG("Incorrect number of DiscType values in file ");
410  ERRORMSG(filename << endl);
411  iserror = true;
412  }
413  }
414  } else if (tokens[0] == "RecordOffset" && numtokens >= 2) {
415  unsigned int recnum = atoi(tokens[1].c_str());
416  if (recnum >= RecordList.size()) {
417  ERRORMSG("Illegal record number '" << recnum << "'" << endl);
418  iserror = true;
419  } else {
420  std::vector<Offset_t> offsetvec;
421  for (int b=2; b < numtokens; ++b) {
422  Offset_t offset = atol(tokens[b].c_str());
423  if (sf > 0 && offset != RecordList[recnum]->offset[sf][b-2]) {
424  ERRORMSG("Illegal offset for attribute " << b-2);
425  ERRORMSG(" in file " << filename << "(");
426  ERRORMSG(static_cast<long>(offset) << " != ");
427  ERRORMSG(static_cast<long>(
428  RecordList[recnum]->offset[sf][b-2]) << ")" << endl);
429  iserror = true;
430  } else if (sf == 0) {
431  offsetvec.push_back(offset);
432  }
433  }
434  if (sf == 0) {
435  if (offsetvec.size() != (RecordList[recnum]->attributes==0 ? 1u :
436  static_cast<unsigned int>(RecordList[recnum]->attributes))) {
437  ERRORMSG("Incorrect number of offset values in file ");
438  ERRORMSG(filename << endl);
439  iserror = true;
440  } else {
441  RecordList[recnum]->offset.push_back(offsetvec);
442  }
443  }
444  }
445  } else {
446  // error in line: unknown keyword
447  iserror = true;
448  }
449 
450  DPFDBG(dbgmsg << "On box0: finished line with tokens[0]='"<<tokens[0]);
451  DPFDBG(dbgmsg << "' ... iserror = " << iserror << endl);
452 
453  // print if there was an error
454  if (iserror) {
455  ERRORMSG("Format error on line " << linesread << " in file ");
456  ERRORMSG(filename << endl);
457  break;
458  }
459  }
460 
461  // stop processing meta files is there was an error
462  if (iserror)
463  break;
464  }
465 
466  DPFDBG(dbgmsg << "Summary of meta info:" << endl);
467  DPFDBG(dbgmsg << " iserror = " << iserror << endl);
468  DPFDBG(dbgmsg << " NumRecords = " << RecordList.size() << endl);
469  DPFDBG(dbgmsg << " TypeString = " << TypeString << endl);
470  DPFDBG(dbgmsg << " NextOffset = " << static_cast<long>(CurrentOffset));
471  DPFDBG(dbgmsg << endl);
472 
473  // now send meta info to all nodes which expect it
474  int numinform = Config->getNumOtherSMP();
475  DPFDBG(dbgmsg << "Informing " << numinform << " SMP's of meta info");
476  DPFDBG(dbgmsg << endl);
477  for (int s=0; s <= numinform; ++s) {
478  int smp = Config->mySMP();
479  if (s != numinform)
480  smp = Config->getOtherSMP(s);
481  DPFDBG(dbgmsg << "SMP " << smp << " has " <<Config->getNumSMPNodes(smp));
482  DPFDBG(dbgmsg << " nodes to check." << endl);
483  for (unsigned int n=0; n < Config->getNumSMPNodes(smp); ++n) {
484  int node = Config->getSMPNode(smp, n);
485  if (node != Ippl::myNode()) {
486  // create a message with meta info
487  Message *msg = new Message;
488  ::putMessage(*msg, TypeString);
489  int errint = iserror;
490  msg->put(errint);
491  if (!iserror) {
492  long curroff = CurrentOffset;
493  msg->put(curroff);
494  int recnum = RecordList.size();
495  msg->put(recnum);
496  for (unsigned int r=0; r < RecordList.size(); ++r) {
497  int filesnum = RecordList[r]->localparticles.size();
498  msg->put(filesnum);
499  msg->put(RecordList[r]->attributes);
500  msg->put(RecordList[r]->globalparticles);
501  for (unsigned int p=0; p < RecordList[r]->localparticles.size(); ++p)
502  msg->put(RecordList[r]->localparticles[p]);
503  for (unsigned int b=0; b < RecordList[r]->bytesize.size(); ++b)
504  msg->put(RecordList[r]->bytesize[b]);
505 
506  // make sure we have disctypes ... add if necessary
507  std::string unknowndtype = "u";
508  for (unsigned int dr = RecordList[r]->disctypes.size();
509  dr < RecordList[r]->bytesize.size(); ++dr)
510  RecordList[r]->disctypes.push_back(unknowndtype);
511 
512  for (unsigned int t=0; t < RecordList[r]->bytesize.size(); ++t)
513  ::putMessage(*msg, RecordList[r]->disctypes[t]);
514  for (unsigned int z=0; z < RecordList[r]->offset.size(); ++z) {
515  for (unsigned int o=0; o < RecordList[r]->offset[z].size(); ++o) {
516  long value = RecordList[r]->offset[z][o];
517  msg->put(value);
518  }
519  }
520  }
521  }
522 
523  // send the message to the intended node
524  DPFDBG(dbgmsg<<"Sending meta info to node " << node << " with tag ");
525  DPFDBG(dbgmsg<< tag << ", on SMP " << smp << endl);
526  Ippl::Comm->send(msg, node, tag);
527  }
528  }
529  }
530 
531  } else {
532  // all other nodes (which are not Box0 nodes) should get a message
533  // telling them the meta info
534  int node = Config->getSMPBox0();
535  DPFDBG(dbgmsg << "Waiting for meta info from node " << node);
536  DPFDBG(dbgmsg << " with tag " << tag << endl);
537  Message *msg = Ippl::Comm->receive_block(node, tag);
538  PAssert(msg);
539 
540  // get info out of message
541  DPFDBG(dbgmsg << "Summary of received meta info:" << endl);
542  ::getMessage(*msg, TypeString);
543  DPFDBG(dbgmsg << " TypeString = " << TypeString << endl);
544  int errint = 0, numrec = 0, val = 0;
545  msg->get(errint);
546  iserror = (errint != 0);
547  DPFDBG(dbgmsg << " iserror = " << iserror << endl);
548  if (!iserror) {
549  long curroff = 0;
550  msg->get(curroff);
551  CurrentOffset = curroff;
552  DPFDBG(dbgmsg << " CurrentOffset = " << curroff << endl);
553  msg->get(numrec);
554  DPFDBG(dbgmsg << " NumRecords = " << numrec << endl);
555  for (int r=0; r < numrec; ++r) {
556  DPFDBG(dbgmsg << " For record " << r << ":" << endl);
557  RecordList.push_back(new RecordInfo());
558  int filesnum = RecordList[r]->localparticles.size();
559  msg->get(filesnum);
560  DPFDBG(dbgmsg << " Filesets=" << filesnum << endl);
561  msg->get(RecordList[r]->attributes);
562  int numattr = RecordList[r]->attributes;
563  if (RecordList[r]->attributes == 0)
564  numattr = 1;
565  DPFDBG(dbgmsg << " Attribs=" << numattr << endl);
566  msg->get(RecordList[r]->globalparticles);
567  DPFDBG(dbgmsg << " Global#="<<RecordList[r]->globalparticles<<endl);
568  for (int p=0; p < filesnum; ++p) {
569  msg->get(val);
570  DPFDBG(dbgmsg << " Local " << p << " = " << val << endl);
571  RecordList[r]->localparticles.push_back(val);
572  }
573  for (int b=0; b < numattr; ++b) {
574  msg->get(val);
575  DPFDBG(dbgmsg << " Bytesize " << b << " = " << val << endl);
576  RecordList[r]->bytesize.push_back(val);
577  }
578  for (int t=0; t < numattr; ++t) {
579  std::string dtype;
580  ::getMessage(*msg, dtype);
581  DPFDBG(dbgmsg << " Disctype " << t << " = " << dtype << endl);
582  RecordList[r]->disctypes.push_back(dtype);
583  }
584  for (int z=0; z < filesnum; ++z) {
585  std::vector<Offset_t> offsetvec;
586  Offset_t offset;
587  long value = 0;
588  for (int o=0; o < numattr; ++o) {
589  msg->get(value);
590  offset = value;
591  DPFDBG(dbgmsg << " Offset " << z << "," << o << " = ");
592  DPFDBG(dbgmsg << offset << endl);
593  offsetvec.push_back(offset);
594  }
595  RecordList[r]->offset.push_back(offsetvec);
596  }
597  }
598  }
599 
600  // we're done with this message
601  delete msg;
602  }
603 
604  // at the end, if there was an error, get rid of all the existing record
605  // info
606  if (iserror) {
607  DPFDBG(dbgmsg<<"Cleaning up error record info at end of read_meta"<<endl);
609  for ( ; rec != RecordList.end(); ++rec)
610  delete (*rec);
611  RecordList.erase(RecordList.begin(), RecordList.end());
612  }
613 
614  // print out summary
615  DPFDBG(printDebug());
616 
617  // return whether there was an error
618  return (!iserror);
619 }
620 
621 
623 bool DiscParticle::write_data(FILE *outputData, std::vector<Message *> &msgvec,
624  RecordInfo *info) {
625 
626  DPFDBG(Inform dbgmsg("DiscParticle::write_data", INFORM_ALL_NODES));
627 
628  // a vector for storing information about how many particles are in each msg
629  std::vector<int> numvec;
630  std::vector<Offset_t> offsetvec;
631  int totalnum = 0;
632 
633  // seek to the current offset, since the file may have changed
634  if (fseek(outputData, CurrentOffset, SEEK_SET) != 0) {
635  ERRORMSG("Error seeking to position " << static_cast<long>(CurrentOffset));
636  ERRORMSG(" in .data file for DiscParticle::write_data." << endl);
637  fclose(outputData);
638  return false;
639  }
640 
641  // loop over all the attributes in the messages
642  int numattr = info->attributes;
643  if (numattr == 0)
644  numattr = 1;
645  for (int a=0; a < numattr; ++a) {
646  DPFDBG(dbgmsg<<"Writing out data from messages for attrib " << a << endl);
647  offsetvec.push_back(CurrentOffset);
648 
649  // loop over all the nodes that provided data
650  for (unsigned int n=0; n < msgvec.size(); ++n) {
651  // for each node, get out the number of particles, get the data, and
652  // write it out
653  int nump = 0;
654  if (a == 0) {
655  msgvec[n]->get(nump);
656  numvec.push_back(nump);
657  totalnum += nump;
658  } else {
659  nump = numvec[n];
660  }
661  DPFDBG(dbgmsg << " Attrib " << a << " has " << nump << " particles ");
662  DPFDBG(dbgmsg << "from node " << n << endl);
663 
664  if (nump > 0) {
665  // get the data for this attribute
666  void *msgdata = msgvec[n]->remove();
667 
668  // write it out now ...
669  unsigned int totalbytes = nump * info->bytesize[a];
670  DPFDBG(dbgmsg << " Writing out block of " << nump << " particles, ");
671  DPFDBG(dbgmsg << "with " << totalbytes << " bytes." << endl);
672  if (fwrite(msgdata, 1, totalbytes, outputData) != totalbytes) {
673  ERRORMSG("Write error in DiscParticle::write_data" << endl);
674  fclose(outputData);
675  return false;
676  }
677 
678  // update the current offset position
679  CurrentOffset += totalbytes;
680  // ADDIPPLSTAT(incDiscBytesWritten, totalbytes);
681 
682  // free the message data storage
683  free(msgdata);
684  }
685 
686  // delete the message, if we can
687  if ((a+1) == numattr)
688  delete (msgvec[n]);
689  }
690  }
691 
692  // save the offset information for each attribute
693  DPFDBG(dbgmsg << "At end of attrib write; totalnum = " << totalnum << endl);
694  info->offset.push_back(offsetvec);
695  info->localparticles.push_back(totalnum);
696 
697  // we're done writing; return success
698  return true;
699 }
700 
701 
703 // read the data for the Nth attribute of record R, in the Fth fileset,
704 // and return the newly allocated buffer (or 0 if an error occurs).
705 void *DiscParticle::read_data(FILE *outputData, unsigned int attrib,
706  unsigned int record, unsigned int fileset) {
707 
708  DPFDBG(Inform dbgmsg("DiscParticle::read_data", INFORM_ALL_NODES));
709 
710  // determine the byte size of the attribute, and the offset
711  int nump = RecordList[record]->localparticles[fileset];
712  int bytesize = RecordList[record]->bytesize[attrib];
713  DPFDBG(dbgmsg << "Particles=" << nump << ", sizeof(T)=" << bytesize << endl);
714 
715  // if there are no particles to read, just return
716  if (nump < 1 || bytesize < 1)
717  return 0;
718 
719  // seek to proper position first, for the first attribute
720  if (attrib == 0) {
721  Offset_t seekpos = RecordList[record]->offset[fileset][attrib];
722  DPFDBG(dbgmsg << "seekpos = " << seekpos << endl);
723  if (fseek(outputData, seekpos, SEEK_SET) != 0) {
724  ERRORMSG("Error seeking to position " << static_cast<long>(seekpos));
725  ERRORMSG(" in .data file for DiscParticle::read_data." << endl);
726  fclose(outputData);
727  return 0;
728  }
729  }
730 
731  // allocate a block of memory to store the data now
732  unsigned int totalbytes = nump * bytesize;
733  void *buffer = malloc(totalbytes);
734 
735  // read the data into the provided buffer
736  DPFDBG(dbgmsg << "Reading " << totalbytes << " bytes from file ..." << endl);
737  if (fread(buffer, 1, totalbytes, outputData) != totalbytes) {
738  ERRORMSG("Read error in DiscParticle::read_data" << endl);
739  free(buffer);
740  fclose(outputData);
741  return 0;
742  }
743 
744  //DPFDBG(dbgmsg << "Read in block of " << size << " elements:" << endl);
745  //DPFDBG(for (unsigned int i=0; i < size; ++i))
746  //DPFDBG( dbgmsg << " buffer[" << i << "] = " << buffer[i] << endl);
747 
748  // ADDIPPLSTAT(incDiscBytesRead, totalbytes);
749  return buffer;
750 }
751 
752 
754 // print out debugging information for this DiscParticle
755 void DiscParticle::printDebug() { printDebug(std::cout); }
756 
757 void DiscParticle::printDebug(std::ostream& outmsg) {
758 
759  Inform msg("DiscParticle", outmsg, INFORM_ALL_NODES);
760 
761  msg << "BaseFile = " << BaseFile << endl;
762  msg << "NumRecords = " << get_NumRecords() << endl;
763  msg << "NextOffset = " << static_cast<long>(CurrentOffset) << endl;
764 
765  for (unsigned int r=0; r < get_NumRecords(); ++r) {
766  msg << "For record " << r << ":" << endl;
767  msg << " Number of attributes = " << get_NumAttributes(r) << endl;
768  msg << " Total number of particles = " << get_NumGlobalParticles(r)<<endl;
769  msg << " Byte size of attributes =";
770  for (unsigned int b=0; b < get_NumAttributes(r); ++b)
771  msg << " " << get_ElemByteSize(r, b);
772  msg << endl;
773  msg << " DiscTypes of attributes =";
774  for (unsigned int t=0; t < get_NumAttributes(r); ++t) {
775  if (get_DiscType(r, t) != 0)
776  msg << " " << get_DiscType(r, t);
777  }
778  msg << endl;
779  for (unsigned int f=0; f < Config->getNumFiles(); ++f) {
780  msg << " Local number of particles in fileset " << f << " = ";
781  msg << RecordList[r]->localparticles[f] << endl;
782  for (unsigned int a=0; a < get_NumAttributes(r); ++a) {
783  msg << " Offset of attribute " << a << " in fileset " << f << " = ";
784  msg << static_cast<long>(RecordList[r]->offset[f][a]) << endl;
785  }
786  }
787  }
788 
789  msg << "Configuration file information:" << endl;
790  Config->printDebug(msg);
791 
792  msg << endl;
793 }
794 
795 
796 /***************************************************************************
797  * $RCSfile: DiscParticleFunctions.cpp,v $ $Author: adelmann $
798  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $
799  * IPPL_VERSION_ID: $Id: DiscParticleFunctions.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $
800  ***************************************************************************/
#define DF_READ_META_TAG
Definition: Tags.h:73
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
static void abort(const char *=0, int exitcode=(-1))
Definition: IpplInfo.cpp:696
const char * get_DiscType(unsigned int record=0, unsigned int attrib=0) const
Offset_t CurrentOffset
Definition: DiscParticle.h:697
#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
#define ERRORMSG(msg)
Definition: IpplInfo.h:399
unsigned int get_NumLocalParticles(unsigned int record=0) const
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
unsigned int fileSMPs() const
Definition: DiscConfig.h:81
int next_tag(int t, int s=1000)
Definition: TagMaker.h:43
#define DPFDBG(x)
unsigned int getNumOtherSMP() const
Definition: DiscConfig.h:133
#define DF_TAG_CYCLE
Definition: Tags.h:74
unsigned int get_NumGlobalParticles(unsigned int record=0) const
Definition: DiscParticle.h:98
std::vector< RecordInfo * > RecordList
Definition: DiscParticle.h:694
void printDebug(Inform &)
Definition: DiscConfig.cpp:585
iterator begin()
Definition: DiscMeta.h:76
bool ok() const
Definition: DiscConfig.h:73
std::string BaseFile
Definition: DiscParticle.h:673
unsigned int get_NumAttributes(unsigned int record=0) const
Definition: DiscParticle.h:103
unsigned int mySMP() const
Definition: DiscConfig.h:82
unsigned int getOtherSMP(unsigned int sn) const
Definition: DiscConfig.h:139
unsigned int get_NumRecords() const
Definition: DiscParticle.h:79
std::vector< int > bytesize
Definition: DiscParticle.h:687
unsigned int getSMPNode(unsigned int n) const
Definition: DiscConfig.h:107
FILE * open_file(const std::string &fnm, const std::string &mode, bool reporterr=true)
bool write_data(FILE *outputData, std::vector< Message * > &, RecordInfo *)
Message & get(const T &cval)
Definition: Message.h:484
Message & put(const T &val)
Definition: Message.h:414
DiscConfig * Config
Definition: DiscParticle.h:666
container_t::iterator iterator
Definition: DiscMeta.h:41
void getMessage(Message &m, T &t)
Definition: Message.h:580
const std::string & getFilename(unsigned int fn) const
Definition: DiscConfig.h:125
std::string TypeString
Definition: DiscParticle.h:674
#define PAssert(c)
Definition: PAssert.h:117
std::string::iterator iterator
Definition: MSLang.h:16
void putMessage(Message &m, const T &t)
Definition: Message.h:557
unsigned int getSMPBox0() const
Definition: DiscConfig.h:113
Message * receive_block(int &node, int &tag)
Definition: Inform.h:41
static Communicate * Comm
Definition: IpplInfo.h:93
bool send(Message *, int node, int tag, bool delmsg=true)
unsigned int getNumFiles() const
Definition: DiscConfig.h:119
void initialize(const char *base, const char *config, const char *typestr, int iomode)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42