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