00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <cstdlib>
00029 #include <algorithm>
00030 #include "parstream.H"
00031 #include "memtrack.H"
00032
00033 using std::sort;
00034
00035 template<class T>
00036 LevelData<T>::LevelData()
00037 :m_sendbuffer(NULL), m_sendcapacity(0),
00038 m_recbuffer(NULL), m_reccapacity(0)
00039 {
00040 #ifdef MPI
00041 numSends = 0;
00042 numReceives = 0;
00043 #endif
00044 }
00045
00046 template<class T>
00047 LevelData<T>::LevelData(const DisjointBoxLayout& dp, int comps, const IntVect& ghost,
00048 const DataFactory<T>& a_factory)
00049 : m_disjointBoxLayout(dp), m_ghost(ghost), m_sendbuffer(NULL),
00050 m_sendcapacity(0), m_recbuffer(NULL),m_reccapacity(0)
00051 {
00052 #ifdef MPI
00053 numSends = 0;
00054 numReceives = 0;
00055 #endif
00056 this->m_boxLayout = dp;
00057 this->m_comps = comps;
00058 this->m_isdefined = true;
00059
00060 if(!dp.isClosed())
00061 {
00062 MayDay::Error("non-disjoint DisjointBoxLayout: LevelData<T>::LevelData(const DisjointBoxLayout& dp, int comps)");
00063 }
00064
00065 Interval interval(0, comps-1);
00066 allocateGhostVector(a_factory, ghost);
00067 setVector(*this, interval, interval);
00068
00069
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079 template<class T>
00080 void LevelData<T>::define(const DisjointBoxLayout& dp, int comps, const IntVect& ghost,
00081 const DataFactory<T> & a_factory)
00082 {
00083 this->m_isdefined = true;
00084 if(!dp.isClosed())
00085 {
00086 MayDay::Error("non-disjoint DisjointBoxLayout: LevelData<T>::define(const DisjointBoxLayout& dp,....)");
00087 }
00088 if(comps<=0)
00089 {
00090 MayDay::Error("LevelData::LevelData(const BoxLayout& dp, int comps) comps<=0");
00091 }
00092 this->m_comps = comps;
00093 this->m_boxLayout = dp;
00094
00095 m_disjointBoxLayout = dp;
00096 m_ghost = ghost;
00097
00098
00099 allocateGhostVector(a_factory, ghost);
00100
00101
00102 m_ghost = ghost;
00103
00104 #ifdef MPI
00105 m_fromMe.resize(0);
00106 m_toMe.resize(0);
00107 #endif
00108
00109 }
00110
00111
00112 template<class T>
00113 void LevelData<T>::define(const LevelData<T>& da, const DataFactory<T> & a_factory)
00114 {
00115 this->m_isdefined = true;
00116 if(this == &da) return;
00117 m_disjointBoxLayout = da.m_disjointBoxLayout;
00118 this->m_boxLayout = da.m_disjointBoxLayout;
00119 this->m_comps = da.m_comps;
00120 m_ghost = da.m_ghost;
00121
00122 Interval srcAnddest(0, this->m_comps-1);
00123
00124 allocateGhostVector(a_factory, m_ghost);
00125 setVector(da, srcAnddest, srcAnddest);
00126
00127 #ifdef MPI
00128 m_fromMe.resize(0);
00129 m_toMe.resize(0);
00130 #endif
00131 }
00132
00133
00134 template<class T>
00135 void LevelData<T>::define(const LevelData<T>& da, const Interval& comps,
00136 const DataFactory<T>& a_factory)
00137 {
00138 this->m_isdefined = true;
00139 if(this == &da){
00140 MayDay::Error(" LevelData<T>::define(const LevelData<T>& da, const Interval& comps) called with 'this'");
00141 }
00142 assert(comps.size()>0);
00143
00144
00145 assert(comps.begin()>=0);
00146
00147 m_disjointBoxLayout = da.m_disjointBoxLayout;
00148 this->m_boxLayout = da.m_disjointBoxLayout;
00149
00150 this->m_comps = comps.size();
00151
00152 m_ghost = da.m_ghost;
00153
00154 Interval dest(0, this->m_comps-1);
00155
00156 allocateGhostVector(a_factory, m_ghost);
00157
00158 setVector(da, comps, dest);
00159
00160 #ifdef MPI
00161 m_fromMe.resize(0);
00162 m_toMe.resize(0);
00163 #endif
00164 }
00165
00166 template<class T>
00167 void LevelData<T>::copyTo(const Interval& srcComps,
00168 BoxLayoutData<T>& dest,
00169 const Interval& destComps) const
00170 {
00171 if((BoxLayoutData<T>*)this == &dest) return;
00172
00173 if(this->boxLayout() == dest.boxLayout())
00174 {
00175
00176 for(DataIterator it(this->dataIterator()); it.ok(); ++it)
00177 {
00178 dest[it()].copy(this->box(it()),
00179 destComps,
00180 this->box(it()),
00181 this->operator[](it()),
00182 srcComps);
00183 }
00184 return;
00185 }
00186
00187 Copier copier(m_disjointBoxLayout, dest.boxLayout());
00188 copyTo(srcComps, dest, destComps, copier);
00189 }
00190
00191 template<class T>
00192 void LevelData<T>::copyTo(const Interval& srcComps,
00193 LevelData<T>& dest,
00194 const Interval& destComps) const
00195 {
00196 if(this == &dest){
00197 MayDay::Error("src == dest in copyTo function. Perhaps you want exchange ?");
00198 }
00199
00200 if(this->boxLayout() == dest.boxLayout() && dest.ghostVect() == IntVect::Zero)
00201 {
00202
00203 for(DataIterator it(this->dataIterator()); it.ok(); ++it)
00204 {
00205 dest[it()].copy(this->box(it()),
00206 destComps,
00207 this->box(it()),
00208 this->operator[](it()),
00209 srcComps);
00210 }
00211 return;
00212 }
00213
00214 Copier copier(m_disjointBoxLayout, dest.getBoxes(), dest.m_ghost);
00215 copyTo(srcComps, dest, destComps, copier);
00216 }
00217
00218
00219 template<class T>
00220 void LevelData<T>::copyTo(const Interval& srcComps,
00221 BoxLayoutData<T>& dest,
00222 const Interval& destComps,
00223 const Copier& copier) const
00224 {
00225
00226 makeItSo(srcComps, *this, dest, destComps, copier);
00227
00228 }
00229
00230 template<class T>
00231 void LevelData<T>::copyTo(const Interval& srcComps,
00232 LevelData<T>& dest,
00233 const Interval& destComps,
00234 const Copier& copier,
00235 const LDOperator<T>& a_op) const
00236 {
00237
00238 makeItSo(srcComps, *this, dest, destComps, copier, a_op);
00239
00240 }
00241
00242 template<class T>
00243 void LevelData<T>::exchange(const Interval& comps)
00244 {
00245
00246
00247
00248 Copier copier(m_disjointBoxLayout, m_disjointBoxLayout, m_ghost, true);
00249 exchange(comps, copier);
00250
00251
00252
00253
00254
00255
00256 }
00257
00258 template<class T>
00259 void LevelData<T>::exchange(const Interval& comps,
00260 const Copier& copier)
00261 {
00262 makeItSo(comps, *this, *this, comps, copier);
00263
00264 }
00265
00266 template<class T>
00267 void LevelData<T>::makeItSo(const Interval& a_srcComps,
00268 const LevelData<T>& a_src,
00269 BoxLayoutData<T>& a_dest,
00270 const Interval& a_destComps,
00271 const Copier& a_copier,
00272 const LDOperator<T>& a_op) const
00273 {
00274
00275
00276
00277
00278
00279
00280
00281
00282 #ifdef MPI
00283 static Copier* lastCopier=NULL;
00284
00285
00286
00287 #ifndef NDEBUG
00288
00289 #endif
00290
00291 if(T::preAllocatable() == 2 || !a_copier.bufferAllocated() ||
00292 (m_fromMe.size() + m_toMe.size() == 0) ||lastCopier != &a_copier){
00293 allocateBuffers(a_src, a_srcComps,
00294 a_dest, a_destComps,
00295 a_copier,
00296 a_op);
00297 a_copier.setBufferAllocated(true);
00298 }
00299 lastCopier = (Copier*)(&a_copier);
00300
00301 #endif
00302
00303 writeSendDataFromMeIntoBuffers(a_src, a_srcComps, a_op);
00304
00305
00306
00307
00308
00309 #ifdef MPI
00310 if (m_toMe.size() > 0) {
00311 postReceivesToMe();
00312 }
00313
00314 if (m_fromMe.size() > 0) {
00315 postSendsFromMe();
00316 }
00317 #endif
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 for(CopyIterator it(a_copier, CopyIterator::LOCAL); it.ok(); ++it)
00348 {
00349 const MotionItem& item = it();
00350 a_op.op(a_dest[item.toIndex], item.fromRegion,
00351 a_destComps,
00352 item.toRegion,
00353 a_src[item.fromIndex],
00354 a_srcComps);
00355 }
00356
00357
00358 completePendingSends();
00359
00360 unpackReceivesToMe(a_dest, a_destComps, a_op);
00361
00362 }
00363
00364 template<class T>
00365 void LevelData<T>::define(const BoxLayout& dp, int comps, const DataFactory<T>& a_factory)
00366 {
00367 MayDay::Error("LevelData<T>::define called with BoxLayout input");
00368 }
00369
00370 template<class T>
00371 void LevelData<T>::define(const BoxLayout& dp)
00372 {
00373 MayDay::Error("LevelData<T>::define called with BoxLayout input");
00374 }
00375
00376 template<class T>
00377 void LevelData<T>::define(const BoxLayoutData<T>& da, const DataFactory<T>& a_factory )
00378 {
00379 MayDay::Error("LevelData<T>::define called with BoxLayout input");
00380 }
00381
00382 template<class T>
00383 void LevelData<T>::define(const BoxLayoutData<T>& da, const Interval& comps,
00384 const DataFactory<T>& a_factory)
00385 {
00386 MayDay::Error("LevelData<T>::define called with BoxLayout input");
00387 }
00388
00389 template<class T>
00390 LevelData<T>::~LevelData()
00391 {
00392 completePendingSends();
00393 free(m_sendbuffer);
00394 free(m_recbuffer);
00395 }
00396
00397 template<class T>
00398 void LevelData<T>::apply(void (*a_func)(const Box& box, int comps, T& t))
00399 {
00400 for(DataIterator it(this->dataIterator()); it.ok(); ++it)
00401 {
00402 unsigned int index = this->m_boxLayout.index(it());
00403 a_func(m_disjointBoxLayout.get(it()), this->m_comps, *(this->m_vector[index]));
00404 }
00405 }
00406 #ifndef MPI
00407
00408 template<class T>
00409 void LevelData<T>::completePendingSends() const
00410 {;}
00411
00412 template<class T>
00413 void LevelData<T>::allocateBuffers(const LevelData<T>& a_src,
00414 const Interval& a_srcComps,
00415 const BoxLayoutData<T>& a_dest,
00416 const Interval& a_destComps,
00417 const Copier& a_copier,
00418 const LDOperator<T>& a_op
00419 ) const
00420 {;}
00421
00422 template<class T>
00423 void LevelData<T>::writeSendDataFromMeIntoBuffers(const LevelData<T>& a_src,
00424 const Interval& a_srcComps,
00425 const LDOperator<T>& a_op) const
00426 {;}
00427
00428 template<class T>
00429 void LevelData<T>::postSendsFromMe() const
00430 {;}
00431
00432 template<class T>
00433 void LevelData<T>::postReceivesToMe() const
00434 {;}
00435
00436 template<class T>
00437 void LevelData<T>::unpackReceivesToMe(BoxLayoutData<T>& a_dest,
00438 const Interval& a_destComps,
00439 const LDOperator<T>& a_op) const
00440 {;}
00441
00442 #else
00443
00444
00445
00446 template<class T>
00447 void LevelData<T>::completePendingSends() const
00448 {
00449 if(numSends > 0){
00450 int result = MPI_Waitall(numSends, m_sendRequests, m_sendStatus);
00451 if(result != MPI_SUCCESS)
00452 {
00453
00454 }
00455
00456 delete[] m_sendRequests;
00457 delete[] m_sendStatus;
00458 }
00459 numSends = 0;
00460 }
00461
00462 template<class T>
00463 void LevelData<T>::allocateBuffers(const LevelData<T>& a_src,
00464 const Interval& a_srcComps,
00465 const BoxLayoutData<T>& a_dest,
00466 const Interval& a_destComps,
00467 const Copier& a_copier,
00468 const LDOperator<T>& a_op) const
00469 {
00470 m_fromMe.resize(0);
00471 m_toMe.resize(0);
00472 size_t sendBufferSize = 0;
00473 size_t recBufferSize = 0;
00474
00475
00476
00477 for(CopyIterator it(a_copier, CopyIterator::FROM); it.ok(); ++it)
00478 {
00479 const MotionItem& item = it();
00480 bufEntry b;
00481 b.item = &item;
00482 b.size = a_op.size(a_src[item.fromIndex], item.fromRegion, a_srcComps);
00483 sendBufferSize+=b.size;
00484 b.procID = item.procID;
00485 m_fromMe.push_back(b);
00486 }
00487 sort(m_fromMe.begin(), m_fromMe.end());
00488 for(CopyIterator it(a_copier, CopyIterator::TO); it.ok(); ++it)
00489 {
00490 const MotionItem& item = it();
00491 bufEntry b;
00492 b.item = &item;
00493 if (!(T::preAllocatable() == 2))
00494 {
00495 b.size = a_op.size(a_dest[item.toIndex], item.toRegion, a_destComps);
00496 recBufferSize+=b.size;
00497 }
00498 b.procID = item.procID;
00499 m_toMe.push_back(b);
00500 }
00501 sort(m_toMe.begin(), m_toMe.end());
00502
00503 if(T::preAllocatable() == 2)
00504 {
00505
00506
00507 if(m_fromMe.size() > 0)
00508 {
00509 MPI_Request nullrequest;
00510
00511 int lastProc = -1;
00512 int messageIndex = 0;
00513 for(int i=0; i<m_fromMe.size(); ++i)
00514 {
00515 bufEntry& b = m_fromMe[i];
00516 if(b.procID == lastProc) messageIndex++;
00517 else messageIndex = 0;
00518 lastProc = b.procID;
00519 MPI_Isend(&(b.size), 1, MPI_UNSIGNED_LONG, b.procID,
00520 messageIndex, Chombo_MPI::comm, &(nullrequest));
00521 MPI_Request_free(&(nullrequest));
00522
00523
00524 }
00525 }
00526 if(m_toMe.size() > 0)
00527 {
00528 m_receiveRequests = new MPI_Request[m_toMe.size()];
00529 m_receiveStatus = new MPI_Status[m_toMe.size()];
00530 int lastProc = -1;
00531 int messageIndex = 0;
00532 for(int i=0; i<m_toMe.size(); ++i)
00533 {
00534 bufEntry& b = m_toMe[i];
00535 if(b.procID == lastProc) messageIndex++;
00536 else messageIndex = 0;
00537 lastProc = b.procID;
00538 MPI_Irecv(&(b.size), 1, MPI_UNSIGNED_LONG, b.procID,
00539 messageIndex, Chombo_MPI::comm, m_receiveRequests+i);
00540 }
00541
00542 int result = MPI_Waitall(m_toMe.size(), m_receiveRequests, m_receiveStatus);
00543 if(result != MPI_SUCCESS)
00544 {
00545 MayDay::Error("First pass of two-phase communication failed");
00546 }
00547 for(int i=0; i<m_toMe.size(); ++i) recBufferSize+= m_toMe[i].size;
00548 delete[] m_receiveRequests;
00549 delete[] m_receiveStatus;
00550 }
00551 }
00552
00553
00554
00555 if(sendBufferSize > m_sendcapacity)
00556 {
00557 free(m_sendbuffer);
00558 m_sendbuffer = malloc(sendBufferSize);
00559 if(m_sendbuffer == NULL)
00560 {
00561 MayDay::Error("Out of memory in LevelData::allocatebuffers");
00562 }
00563 m_sendcapacity = sendBufferSize;
00564 }
00565
00566 if(recBufferSize > m_reccapacity)
00567 {
00568 free(m_recbuffer);
00569 m_recbuffer = malloc(recBufferSize);
00570 if(m_recbuffer == NULL)
00571 {
00572 MayDay::Error("Out of memory in LevelData::allocatebuffers");
00573 }
00574 m_reccapacity = recBufferSize;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 char* nextFree = (char*)m_sendbuffer;
00589 if(m_fromMe.size() > 0)
00590 {
00591 for(unsigned int i=0; i<m_fromMe.size(); ++i)
00592 {
00593 m_fromMe[i].bufPtr = nextFree;
00594 nextFree += m_fromMe[i].size;
00595 }
00596 }
00597
00598 nextFree = (char*)m_recbuffer;
00599 if(m_toMe.size() > 0)
00600 {
00601 for(unsigned int i=0; i<m_toMe.size(); ++i)
00602 {
00603 m_toMe[i].bufPtr = nextFree;
00604 nextFree += m_toMe[i].size;
00605 }
00606 }
00607
00608
00609
00610
00611 }
00612
00613
00614
00615 template<class T>
00616 void LevelData<T>::writeSendDataFromMeIntoBuffers(const LevelData<T>& a_src,
00617 const Interval& a_srcComps,
00618 const LDOperator<T>& a_op) const
00619 {
00620
00621
00622 for(unsigned int i=0; i<m_fromMe.size(); ++i)
00623 {
00624 const bufEntry& entry = m_fromMe[i];
00625 a_op.linearOut(a_src[entry.item->fromIndex], entry.bufPtr,
00626 entry.item->fromRegion, a_srcComps);
00627 }
00628
00629 }
00630
00631 template<class T>
00632 void LevelData<T>::postSendsFromMe() const
00633 {
00634
00635
00636
00637
00638 numSends = m_fromMe.size();
00639 if(numSends > 1){
00640 for(unsigned int i=m_fromMe.size()-1; i>0; --i)
00641 {
00642 if(m_fromMe[i].procID == m_fromMe[i-1].procID)
00643 {
00644 numSends--;
00645 m_fromMe[i-1].size+=m_fromMe[i].size;
00646 m_fromMe[i].size = 0;
00647 }
00648 }
00649 }
00650 m_sendRequests = new MPI_Request[numSends];
00651 m_sendStatus = new MPI_Status[numSends];
00652
00653
00654 unsigned int next=0;
00655 for(int i=0; i<numSends; ++i)
00656 {
00657 const bufEntry& entry = m_fromMe[next];
00658
00659
00660 MPI_Isend(entry.bufPtr, entry.size, MPI_BYTE, entry.procID,
00661 0, Chombo_MPI::comm, m_sendRequests+i);
00662 ++next;
00663 while(next < m_fromMe.size() && m_fromMe[next].size == 0) ++next;
00664 }
00665
00666
00667 }
00668
00669 template<class T>
00670 void LevelData<T>::postReceivesToMe() const
00671 {
00672 numReceives = m_toMe.size();
00673
00674 if(numReceives > 1){
00675 for(unsigned int i=m_toMe.size()-1; i>0; --i)
00676 {
00677 if(m_toMe[i].procID == m_toMe[i-1].procID)
00678 {
00679 numReceives--;
00680 m_toMe[i-1].size+=m_toMe[i].size;
00681 m_toMe[i].size = 0;
00682 }
00683 }
00684 }
00685 m_receiveRequests = new MPI_Request[numReceives];
00686 m_receiveStatus = new MPI_Status[numReceives];
00687
00688
00689 unsigned int next=0;
00690 for(int i=0; i<numReceives; ++i)
00691 {
00692 const bufEntry& entry = m_toMe[next];
00693
00694
00695 MPI_Irecv(entry.bufPtr, entry.size, MPI_BYTE, entry.procID,
00696 0, Chombo_MPI::comm, m_receiveRequests+i);
00697 ++next;
00698 while(next < m_toMe.size() && m_toMe[next].size == 0) ++next;
00699 }
00700
00701 }
00702
00703
00704 template<class T>
00705 void LevelData<T>::unpackReceivesToMe(BoxLayoutData<T>& a_dest,
00706 const Interval& a_destComps,
00707 const LDOperator<T>& a_op) const
00708 {
00709
00710 if(numReceives > 0){
00711 int result = MPI_Waitall(numReceives, m_receiveRequests, m_receiveStatus);
00712 if(result != MPI_SUCCESS)
00713 {
00714
00715 }
00716
00717 for(unsigned int i=0; i<m_toMe.size(); ++i)
00718 {
00719 const bufEntry& entry = m_toMe[i];
00720 a_op.linearIn(a_dest[entry.item->toIndex], entry.bufPtr, entry.item->toRegion, a_destComps);
00721 }
00722
00723 delete[] m_receiveRequests;
00724 delete[] m_receiveStatus;
00725 }
00726 numReceives = 0;
00727 }
00728
00729
00730
00731 #endif
00732
00733
00734
00735
00736
00737
00738