00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef DISC_PARTICLE_H
00012 #define DISC_PARTICLE_H
00013
00014
00015 #ifdef IPPL_PRINTDEBUG
00016 #define DPCTLDBG(x) x
00017 #else
00018 #define DPCTLDBG(x)
00019 #endif
00020
00021
00022 #include "Utility/DiscConfig.h"
00023 #include "Utility/Pstring.h"
00024 #include "Utility/IpplInfo.h"
00025 #include "Message/Message.h"
00026
00027
00028
00029 #ifdef IPPL_STDSTL
00030 #include <vector>
00031 using std::vector;
00032 #else
00033 #include <vector.h>
00034 #endif // IPPL_STDSTL
00035
00036 #ifdef IPPL_USE_STANDARD_HEADERS
00037 #include <iostream>
00038 using namespace std;
00039 #else
00040 #include <iostream.h>
00041 #endif
00042
00043 #include <stdio.h>
00044
00045
00046 template<class T> class ParticleBase;
00047 template<class T> class ParticleAttrib;
00048 class Message;
00049
00050 class DiscParticle {
00051
00052 public:
00053
00054
00055 enum DPMode1 { INPUT, OUTPUT, APPEND };
00056
00057
00058
00059 enum DPMode2 { ALL, ATTRIB };
00060
00061 public:
00062
00063
00064
00065
00066
00067
00068
00069 DiscParticle(const char *fname, const char *config, int iomode,
00070 const char *typestr = 0);
00071
00072
00073
00074
00075 DiscParticle(const char *fname, int iomode, const char * = 0);
00076
00077
00078 ~DiscParticle();
00079
00080
00081
00082
00083
00084
00085 bool get_OK() const { return ConfigOK; }
00086
00087
00088
00089
00090
00091 unsigned int get_NumRecords() const { return RecordList.size(); }
00092
00093
00094
00095
00096 int get_DataMode(unsigned int record=0) const {
00097 return (RecordList[record]->attributes > 0 ? ALL : ATTRIB);
00098 }
00099
00100
00101
00102 int get_IOMode() const { return IOMode; }
00103
00104
00105
00106 unsigned int get_NumLocalParticles(unsigned int record=0) const;
00107
00108
00109
00110 unsigned int get_NumGlobalParticles(unsigned int record=0) const {
00111 return RecordList[record]->globalparticles;
00112 }
00113
00114
00115 unsigned int get_NumAttributes(unsigned int record=0) const {
00116 return (get_DataMode(record)==ALL ? RecordList[record]->attributes : 1);
00117 }
00118
00119
00120 unsigned int get_ElemByteSize(unsigned int record=0,
00121 unsigned int attrib=0) const {
00122 return RecordList[record]->bytesize[attrib];
00123 }
00124
00125
00126 const char *get_TypeString() const { return TypeString.c_str(); }
00127
00128
00129
00130 const char *get_DiscType(unsigned int record=0,
00131 unsigned int attrib=0) const;
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00154
00155
00156
00157
00158
00159
00160
00161 template<class T>
00162 bool read(ParticleBase<T> &pbase, unsigned int record) {
00163 TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleBase<" + CT(T) +
00164 ">, unsigned int)");
00165 TAU_PROFILE("DiscParticle::read()", taustr,
00166 TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00167
00168
00169 ConfigOK = read_meta();
00170
00171
00172 if (!ConfigOK) {
00173 ERRORMSG("Bad config or meta file in DiscParticle::read." << endl);
00174 return false;
00175 } else if (IOMode != INPUT) {
00176 ERRORMSG("Trying to read for DiscParticle created for output." << endl);
00177 return false;
00178 } else if (record >= get_NumRecords()) {
00179 ERRORMSG("Illegal record number in DiscParticle::read." << endl);
00180 return false;
00181 } else if (get_DataMode(record) != ALL) {
00182 ERRORMSG("Record " << record << " does not contain information for an ");
00183 ERRORMSG("entire ParticleBase." << endl);
00184 return false;
00185 } else if (get_NumAttributes(record) != pbase.numAttributes()) {
00186 ERRORMSG("Record " << record <<" has a different number of attributes ");
00187 ERRORMSG("than in the given ParticleBase." << endl);
00188 return false;
00189 }
00190
00191
00192
00193
00194 for (int ca=0; ca < get_NumAttributes(record); ++ca) {
00195 if (get_ElemByteSize(record, ca)!=pbase.getAttribute(ca).elementSize()) {
00196 ERRORMSG("Mismatched data type size for attribute " << ca << " in ");
00197 ERRORMSG("DiscParticle::read." << endl);
00198 return false;
00199 }
00200 }
00201
00202 DPCTLDBG(string dbgmsgname("DiscParticle::read(ParticleBase) "));
00203 DPCTLDBG(dbgmsgname += Config->getConfigFile());
00204 DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
00205
00206
00207
00208 DPCTLDBG(dbgmsg << "Deleting existing " << pbase.getLocalNum());
00209 DPCTLDBG(dbgmsg << " particles." << endl);
00210 pbase.destroy(pbase.getLocalNum(), 0);
00211 pbase.update();
00212
00213
00214 if (Ippl::myNode() == Config->getSMPBox0()) {
00215
00216
00217 for (int sf=0; sf < Config->getNumFiles(); ++sf) {
00218
00219
00220 int localnum = RecordList[record]->localparticles[sf];
00221 if (localnum > 0) {
00222
00223
00224 string filename = Config->getFilename(sf) + ".data";
00225 DPCTLDBG(dbgmsg<<"Opening data file '" << filename << "' ..."<<endl);
00226 FILE *datafile = open_file(filename, string("r"));
00227
00228
00229 if (datafile != 0) {
00230
00231
00232 Message *msg = new Message;
00233 msg->put(localnum);
00234
00235
00236 for (int a=0; a < get_NumAttributes(record); ++a) {
00237
00238 void *buf = read_data(datafile, a, record, sf);
00239 PAssert(buf != 0);
00240
00241
00242 msg->setCopy(false).setDelete(true);
00243 msg->putmsg(buf, get_ElemByteSize(record, a), localnum);
00244 }
00245
00246
00247 DPCTLDBG(dbgmsg<<"Creating "<<localnum << " new particles."<<endl);
00248 pbase.getMessageAndCreate(*msg);
00249
00250
00251 delete msg;
00252 }
00253 }
00254 }
00255 }
00256
00257
00258 DPCTLDBG(dbgmsg << "Doing final update after reading in particles ...");
00259 DPCTLDBG(dbgmsg << endl);
00260 pbase.update();
00261 DPCTLDBG(dbgmsg << "This node now has " << pbase.getLocalNum());
00262 DPCTLDBG(dbgmsg << " local particles." << endl);
00263 return true;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 template<class T>
00286 bool read(ParticleAttrib<T> &pattr, unsigned int record) {
00287 TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleAttrib<" + CT(T) +
00288 ">, unsigned int)");
00289 TAU_PROFILE("DiscParticle::read()", taustr,
00290 TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00291
00292
00293 ConfigOK = read_meta();
00294
00295
00296 if (!ConfigOK) {
00297 ERRORMSG("Bad config or meta file in DiscParticle::read." << endl);
00298 return false;
00299 } else if (IOMode != INPUT) {
00300 ERRORMSG("Trying to read for a DiscParticle created for output."<<endl);
00301 return false;
00302 } else if (record >= get_NumRecords()) {
00303 ERRORMSG("Illegal record number in DiscParticle::read." << endl);
00304 return false;
00305 } else if (get_DataMode(record) != ATTRIB) {
00306 ERRORMSG("Record " << record << " does not contain information for a ");
00307 ERRORMSG("single ParticleAttrib." << endl);
00308 return false;
00309 } else if (get_ElemByteSize(record, 0) != pattr.elementSize()) {
00310 ERRORMSG("Mismatched attribute data type size in ");
00311 ERRORMSG("DiscParticle::read." << endl);
00312 return false;
00313 }
00314
00315
00316
00317 DPCTLDBG(string dbgmsgname("DiscParticle::read(ParticleAttrib) "));
00318 DPCTLDBG(dbgmsgname += Config->getConfigFile());
00319 DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
00320
00321
00322 DPCTLDBG(dbgmsg << "Deleting existing " << pattr.size());
00323 DPCTLDBG(dbgmsg << " particles." << endl);
00324 pattr.destroy(pattr.size(), 0);
00325
00326
00327 if (Ippl::myNode() == Config->getSMPBox0()) {
00328
00329
00330 for (int sf=0; sf < Config->getNumFiles(); ++sf) {
00331
00332
00333 int localnum = RecordList[record]->localparticles[sf];
00334 if (localnum > 0) {
00335
00336
00337 string filename = Config->getFilename(sf) + ".data";
00338 DPCTLDBG(dbgmsg<<"Opening data file '"<<filename << "' ..." << endl);
00339 FILE *datafile = open_file(filename, string("r"));
00340
00341
00342 if (datafile != 0) {
00343
00344
00345 Message *msg = new Message;
00346
00347
00348 void *buf = read_data(datafile, 0, record, sf);
00349 PAssert(buf != 0);
00350
00351
00352 msg->setCopy(false).setDelete(true);
00353 msg->putmsg(buf, get_ElemByteSize(record, 0), localnum);
00354
00355
00356 DPCTLDBG(dbgmsg<<"Creating "<<localnum<<" new particles." << endl);
00357 pattr.getMessage(*msg, localnum);
00358
00359
00360 delete msg;
00361 }
00362 }
00363 }
00364 }
00365
00366 DPCTLDBG(dbgmsg << "This node now has " << pattr.size());
00367 DPCTLDBG(dbgmsg << " local particles." << endl);
00368 return true;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00385
00386
00387
00388
00389
00390 template<class T>
00391 bool write(ParticleBase<T> &pbase) {
00392 TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleBase<" + CT(T)+">)");
00393 TAU_PROFILE("DiscParticle::write()", taustr,
00394 TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00395
00396
00397 int tag = Ippl::Comm->next_tag(FB_WRITE_TAG, FB_TAG_CYCLE);
00398
00399
00400
00401
00402
00403 if (get_NumRecords() > 0 || IOMode == APPEND)
00404 ConfigOK = read_meta();
00405
00406
00407 if (!ConfigOK) {
00408 ERRORMSG("Bad config or meta file in DiscParticle::write." << endl);
00409 return false;
00410 } else if (IOMode == INPUT) {
00411 ERRORMSG("Trying to write for a DiscParticle created for input."<<endl);
00412 return false;
00413 }
00414
00415
00416
00417 DPCTLDBG(string dbgmsgname("DiscParticle::write(ParticleBase) "));
00418 DPCTLDBG(dbgmsgname += Config->getConfigFile());
00419 DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
00420
00421
00422 RecordInfo *info = new RecordInfo;
00423 info->attributes = pbase.numAttributes();
00424 info->globalparticles = pbase.getTotalNum();
00425 for (int a=0; a < info->attributes; ++a) {
00426 info->bytesize.push_back(pbase.getAttribute(a).elementSize());
00427 info->disctypes.push_back(pbase.getAttribute(a).typeString());
00428 }
00429
00430
00431
00432 DPCTLDBG(dbgmsg << "Putting local " << pbase.getLocalNum());
00433 DPCTLDBG(dbgmsg << " particles into a message." << endl);
00434 Message *msg = new Message;
00435 pbase.putMessage(*msg, pbase.getLocalNum(), 0);
00436
00437
00438
00439 if (Ippl::myNode() == Config->getSMPBox0()) {
00440
00441
00442 string openmode = "a";
00443 if (get_NumRecords() == 0)
00444 openmode = "w";
00445 string filename = Config->getFilename(0) + ".data";
00446 DPCTLDBG(dbgmsg << "Opening data file '" << filename << "' ..." << endl);
00447 FILE *datafile = open_file(filename, openmode);
00448 if (datafile == 0) {
00449 delete info;
00450 delete msg;
00451 return false;
00452 }
00453
00454
00455
00456
00457 vector<Message *> msgvec;
00458 msgvec.push_back(msg);
00459
00460
00461
00462 int notreceived = (Config->getNumSMPNodes() - 1);
00463 for (int s=0; s < Config->getNumOtherSMP(); ++s)
00464 notreceived += Config->getNumSMPNodes(Config->getOtherSMP(s));
00465
00466
00467
00468 DPCTLDBG(dbgmsg << "Box0 node waiting to receive " << notreceived);
00469 DPCTLDBG(dbgmsg << " messages, from this SMP and ");
00470 DPCTLDBG(dbgmsg << Config->getNumOtherSMP() << " other SMPs." << endl);
00471 while (notreceived > 0) {
00472
00473 int any_node = COMM_ANY_NODE;
00474 Message *recmsg = Ippl::Comm->receive_block(any_node, tag);
00475 PAssert(recmsg != 0);
00476 notreceived--;
00477
00478 DPCTLDBG(dbgmsg<<"Received msg from node " << any_node << " w tag ");
00479 DPCTLDBG(dbgmsg<< tag << "; still waiting for " << notreceived);
00480 DPCTLDBG(dbgmsg<< " messages." << endl);
00481
00482
00483
00484 msgvec.push_back(recmsg);
00485 }
00486
00487
00488
00489
00490 if (!write_data(datafile, msgvec, info)) {
00491 delete info;
00492 return false;
00493 }
00494
00495
00496 fclose(datafile);
00497
00498 } else {
00499
00500 DPCTLDBG(dbgmsg<<"Sending " << pbase.getLocalNum()<<" ptcls to node ");
00501 DPCTLDBG(dbgmsg<< Config->getSMPBox0() << " with tag " << tag << endl);
00502 Ippl::Comm->send(msg, Config->getSMPBox0(), tag);
00503
00504
00505 info->localparticles.push_back(0);
00506 info->offset.push_back(vector<Offset_t>());
00507 }
00508
00509
00510 DPCTLDBG(dbgmsg << "Finished writing; saving RecordInfo record ..."<<endl);
00511 RecordList.push_back(info);
00512
00513
00514 if (Ippl::myNode() == Config->getSMPBox0()) {
00515 DPCTLDBG(dbgmsg << "Doing final re-write of .meta file ..." << endl);
00516 if (!write_meta())
00517 return false;
00518 }
00519
00520
00521
00522 DPCTLDBG(dbgmsg << "At final barrier at end of write ..." << endl);
00523 Ippl::Comm->barrier();
00524
00525
00526 return true;
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00537
00538
00539
00540
00541 template<class T>
00542 bool write(ParticleAttrib<T> &pattr) {
00543 TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleAttrib<" + CT(T)+">)");
00544 TAU_PROFILE("DiscParticle::write()", taustr,
00545 TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00546
00547
00548 int tag = Ippl::Comm->next_tag(FB_WRITE_TAG, FB_TAG_CYCLE);
00549
00550
00551
00552
00553
00554 if (get_NumRecords() > 0 || IOMode == APPEND)
00555 ConfigOK = read_meta();
00556
00557
00558 if (!ConfigOK) {
00559 ERRORMSG("Bad config or meta file in DiscParticle::write." << endl);
00560 return false;
00561 } else if (IOMode == INPUT) {
00562 ERRORMSG("Trying to write for a DiscParticle created for input."<<endl);
00563 return false;
00564 }
00565
00566
00567
00568 DPCTLDBG(string dbgmsgname("DiscParticle::write(ParticleAttrib) "));
00569 DPCTLDBG(dbgmsgname += Config->getConfigFile());
00570 DPCTLDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
00571
00572
00573 RecordInfo *info = new RecordInfo;
00574 info->attributes = 0;
00575 info->globalparticles = 0;
00576 info->bytesize.push_back(pattr.elementSize());
00577 info->disctypes.push_back(pattr.typeString());
00578
00579
00580
00581 DPCTLDBG(dbgmsg << "Putting local " << pattr.size());
00582 DPCTLDBG(dbgmsg << " particles into a message." << endl);
00583 Message *msg = new Message;
00584 msg->put(pattr.size());
00585 pattr.putMessage(*msg, pattr.size(), 0);
00586
00587
00588
00589 if (Ippl::myNode() == Config->getSMPBox0()) {
00590
00591
00592 string openmode = "a";
00593 if (get_NumRecords() == 0)
00594 openmode = "w";
00595 string filename = Config->getFilename(0) + ".data";
00596 DPCTLDBG(dbgmsg << "Opening data file '" << filename << "' ..." << endl);
00597 FILE *datafile = open_file(filename, openmode);
00598 if (datafile == 0) {
00599 delete info;
00600 delete msg;
00601 return false;
00602 }
00603
00604
00605
00606
00607 vector<Message *> msgvec;
00608 msgvec.push_back(msg);
00609
00610
00611
00612 int notreceived = (Config->getNumSMPNodes() - 1);
00613 for (int s=0; s < Config->getNumOtherSMP(); ++s)
00614 notreceived += Config->getNumSMPNodes(Config->getOtherSMP(s));
00615
00616
00617
00618 DPCTLDBG(dbgmsg << "Box0 node waiting to receive " << notreceived);
00619 DPCTLDBG(dbgmsg << " messages, from this SMP and ");
00620 DPCTLDBG(dbgmsg << Config->getNumOtherSMP() << " other SMPs." << endl);
00621 while (notreceived > 0) {
00622
00623 int any_node = COMM_ANY_NODE;
00624 Message *recmsg = Ippl::Comm->receive_block(any_node, tag);
00625 PAssert(recmsg != 0);
00626 notreceived--;
00627
00628 DPCTLDBG(dbgmsg<< "Received msg from node " << any_node << " w tag ");
00629 DPCTLDBG(dbgmsg<< tag << "; still waiting for " << notreceived);
00630 DPCTLDBG(dbgmsg<< " messages." << endl);
00631
00632
00633
00634 msgvec.push_back(recmsg);
00635 }
00636
00637
00638
00639
00640 if (!write_data(datafile, msgvec, info)) {
00641 delete info;
00642 return false;
00643 }
00644
00645
00646 fclose(datafile);
00647
00648 } else {
00649
00650 DPCTLDBG(dbgmsg << "Sending " << pattr.size() << " particles to node ");
00651 DPCTLDBG(dbgmsg << Config->getSMPBox0() << " with tag " << tag << endl);
00652 Ippl::Comm->send(msg, Config->getSMPBox0(), tag);
00653
00654
00655 info->localparticles.push_back(0);
00656 info->offset.push_back(vector<Offset_t>());
00657 }
00658
00659
00660 DPCTLDBG(dbgmsg << "Finished writing; saving RecordInfo record ..."<<endl);
00661 RecordList.push_back(info);
00662
00663
00664 if (Ippl::myNode() == Config->getSMPBox0()) {
00665 DPCTLDBG(dbgmsg << "Doing final re-write of .meta file ..." << endl);
00666 if (!write_meta())
00667 return false;
00668 }
00669
00670
00671
00672 DPCTLDBG(dbgmsg << "At final barrier at end of write ..." << endl);
00673 Ippl::Comm->barrier();
00674
00675
00676 return true;
00677 }
00678
00679
00680
00681
00682
00683
00684 void printDebug(ostream&);
00685 void printDebug();
00686
00687 private:
00688
00689 typedef long Offset_t;
00690
00691
00692 DiscConfig *Config;
00693 bool ConfigOK;
00694
00695
00696 int IOMode;
00697
00698
00699 string BaseFile;
00700 string TypeString;
00701
00702
00703
00704 struct RecordInfo {
00705
00706 typedef long Offset_t;
00707
00708 int attributes;
00709
00710
00711 int globalparticles;
00712 vector<int> localparticles;
00713 vector<int> bytesize;
00714 vector<vector<Offset_t> > offset;
00715 vector<string> disctypes;
00716 RecordInfo() : globalparticles(0), attributes(0) { }
00717 };
00718
00719
00720 vector<RecordInfo *> RecordList;
00721
00722
00723 Offset_t CurrentOffset;
00724
00725
00726
00727
00728
00729
00730 void initialize(const char *base, const char *config,
00731 const char *typestr, int iomode);
00732
00733
00734
00735
00736
00737 FILE *open_file(const string& fnm, const string& mode,
00738 bool reporterr = true);
00739
00740
00741
00742
00743
00744
00745 bool read_meta();
00746 bool write_meta();
00747
00748
00749
00750 void *read_data(FILE *outputData, unsigned int attrib,
00751 unsigned int record, unsigned int fileset);
00752
00753
00754
00755 bool write_data(FILE *outputData, vector<Message *> &, RecordInfo *);
00756
00757
00758
00759
00760
00761
00762 DiscParticle(const DiscParticle&);
00763 DiscParticle& operator=(const DiscParticle&);
00764 };
00765
00766 #include "Utility/DiscParticle.cpp"
00767
00768 #endif // DISC_PARTICLE_H
00769
00770
00771
00772
00773
00774