00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _BOXLAYOUTDATAI_H_
00012 #define _BOXLAYOUTDATAI_H_
00013
00014 #include <cstdlib>
00015 #include <algorithm>
00016 #include <limits.h>
00017 #include <list>
00018
00019 #include "parstream.H"
00020 #include "memtrack.H"
00021 #include "Misc.H"
00022 #include "CH_Timer.H"
00023 #include "NamespaceHeader.H"
00024
00025 using std::sort;
00026
00027 template<class T>
00028 int BoxLayoutData<T>::s_verbosity = 0;
00029
00030 template <class T>
00031 T* DefaultDataFactory<T>::create(const Box& box,
00032 int ncomps,
00033 const DataIndex& a_datInd) const
00034 {
00035 return new T(box, ncomps);
00036 }
00037
00038 template<class T>
00039 inline bool BoxLayoutData<T>::isDefined() const
00040 {
00041 return m_isdefined;
00042 }
00043
00044 template <class T>
00045 inline void BoxLayoutData<T>::setVector(const BoxLayoutData<T>& da,
00046 const Interval& srcComps,
00047 const Interval& destComps)
00048 {
00049 if(&da != this)
00050 {
00051 for(DataIterator it(this->dataIterator()); it.ok(); ++it)
00052 {
00053 this->m_vector[this->m_boxLayout.lindex(it())]->copy( this->box(it()), destComps,
00054 this->box(it()), da[it()], srcComps);
00055 }
00056 }
00057 }
00058
00059 template<class T>
00060 inline void BoxLayoutData<T>::define(const BoxLayoutData<T>& da, const Interval& comps,
00061 const DataFactory<T>& factory)
00062 {
00063 if(this == &da){
00064 MayDay::Error("BoxLayoutData<T>::define(const LayoutData<T>& da,.....) called with 'this'");
00065 }
00066 CH_assert(comps.size()>0);
00067 CH_assert(comps.end()<=m_comps);
00068 CH_assert(comps.begin()>=0);
00069 this->m_boxLayout = da.boxLayout();
00070
00071 this->m_comps = comps.size();
00072
00073 Interval dest(0, m_comps-1);
00074 allocateGhostVector(factory);
00075 setVector(da, comps, dest);
00076
00077
00078 }
00079
00080 template<class T>
00081 inline void BoxLayoutData<T>::define(const BoxLayout& boxes, int comps,
00082 const DataFactory<T>& factory)
00083 {
00084 CH_assert(boxes.isClosed());
00085 this->m_boxLayout = boxes;
00086 m_comps = comps;
00087 m_isdefined = true;
00088 allocateGhostVector(factory);
00089
00090 }
00091
00092 template<class T>
00093 inline void BoxLayoutData<T>::define(const BoxLayout& boxes)
00094 {
00095 MayDay::Error("BoxLayoutData<T>::define(const BoxLayout& boxes)...needs comps");
00096 }
00097
00098 template <class T>
00099 inline BoxLayoutData<T>::BoxLayoutData():m_comps(0) ,m_buff(0)
00100 {
00101 m_isdefined = false;
00102 #ifdef CH_MPI
00103 this->numSends = 0;
00104 this->numReceives = 0;
00105 #endif
00106 }
00107 template<class T>
00108 inline BoxLayoutData<T>::BoxLayoutData(const BoxLayout& boxes, int comps,
00109 const DataFactory<T>& factory)
00110 :m_comps(comps),m_buff(NULL)
00111 {
00112 CH_assert(boxes.isClosed());
00113 this->m_boxLayout = boxes;
00114 m_isdefined = true;
00115 allocateGhostVector(factory);
00116 #ifdef CH_MPI
00117
00118 this->numSends = 0;
00119 this->numReceives = 0;
00120 #endif
00121 }
00122
00123 template<class T>
00124 BoxLayoutData<T>::~BoxLayoutData()
00125 {
00126 completePendingSends();
00127 }
00128
00129 template<class T>
00130 inline void BoxLayoutData<T>::define(const BoxLayoutData<T>& da,
00131 const DataFactory<T>& factory)
00132 {
00133 if(this != &da){
00134 m_isdefined = da.m_isdefined;
00135 this->m_boxLayout = da.boxLayout();
00136 m_comps = da.nComp();
00137 Interval srcAnddest(0, m_comps-1);
00138 allocateGhostVector(factory);
00139 setVector(da, srcAnddest, srcAnddest);
00140 }
00141
00142 }
00143 template<class T>
00144 inline void BoxLayoutData<T>::clear()
00145 {
00146 if(this->m_callDelete == true){
00147 for(unsigned int i=0; i<this->m_vector.size(); ++i)
00148 {
00149 delete this->m_vector[i];
00150 this->m_vector[i] = NULL;
00151 }
00152 }
00153 m_isdefined = false;
00154 }
00155
00156 template<class T>
00157 inline void BoxLayoutData<T>::allocateGhostVector(const DataFactory<T>& factory, const IntVect& ghost)
00158 {
00159 if(this->m_callDelete == true){
00160 for(unsigned int i=0; i<this->m_vector.size(); ++i)
00161 {
00162 delete this->m_vector[i];
00163 this->m_vector[i] = NULL;
00164 }
00165 }
00166
00167 this->m_callDelete = factory.callDelete();
00168
00169 DataIterator it(this->dataIterator());
00170 this->m_vector.resize(it.size(), NULL);
00171
00172 for(; it.ok(); ++it)
00173 {
00174 unsigned int index = this->m_boxLayout.lindex(it());
00175 Box abox = this->box(it());
00176 abox.grow(ghost);
00177 this->m_vector[index] = factory.create(abox, m_comps, it());
00178 if(this->m_vector[index] == NULL)
00179 {
00180 MayDay::Error("OutOfMemory in BoxLayoutData::allocateGhostVector");
00181 }
00182 }
00183 }
00184
00185 template<class T>
00186 inline void BoxLayoutData<T>::apply(void (*a_func)(const Box& box, int comps, T& t))
00187 {
00188 for(DataIterator it(this->dataIterator()); it.ok(); ++it)
00189 {
00190 unsigned int index = this->m_boxLayout.lindex(it());
00191 a_func(this->box(it()), m_comps, *(this->m_vector[index]));
00192 }
00193 }
00194
00195
00196 template <class T>
00197 AliasDataFactory<T>::AliasDataFactory(BoxLayoutData<T>* a_original, const Interval& interval)
00198 {
00199 define(a_original, interval);
00200 }
00201
00202 template <class T>
00203 void AliasDataFactory<T>::define(BoxLayoutData<T>* a_original, const Interval& interval)
00204 {
00205 m_origPointer = a_original;
00206 m_interval = interval;
00207 }
00208
00209 template <class T>
00210 T* AliasDataFactory<T>::create(const Box& a_box, int ncomps, const DataIndex& a_dataInd) const
00211 {
00212
00213 CH_assert(ncomps = m_interval.size());
00214 T* rtn = new T(m_interval, m_origPointer->operator[](a_dataInd));
00215 return rtn;
00216 }
00217
00218 template<class T>
00219 void BoxLayoutData<T>::makeItSo(const Interval& a_srcComps,
00220 const BoxLayoutData<T>& a_src,
00221 BoxLayoutData<T>& a_dest,
00222 const Interval& a_destComps,
00223 const Copier& a_copier,
00224 const LDOperator<T>& a_op) const
00225 {
00226 makeItSoBegin(a_srcComps, a_src, a_dest, a_destComps, a_copier, a_op);
00227 makeItSoLocalCopy(a_srcComps, a_src, a_dest, a_destComps, a_copier, a_op);
00228 makeItSoEnd(a_dest, a_destComps, a_op);
00229 }
00230
00231 template<class T>
00232 void BoxLayoutData<T>::makeItSoBegin(const Interval& a_srcComps,
00233 const BoxLayoutData<T>& a_src,
00234 BoxLayoutData<T>& a_dest,
00235 const Interval& a_destComps,
00236 const Copier& a_copier,
00237 const LDOperator<T>& a_op) const
00238 {
00239
00240
00241 #ifdef CH_MPI
00242
00243 allocateBuffers(a_src, a_srcComps,
00244 a_dest, a_destComps,
00245 a_copier,
00246 a_op);
00247
00248
00249 writeSendDataFromMeIntoBuffers(a_src, a_srcComps, a_op);
00250
00251
00252
00253
00254 {
00255 CH_TIME("post messages");
00256 this->numReceives = m_buff->m_toMe.size();
00257 if (this->numReceives > 0) {
00258 postReceivesToMe();
00259 }
00260
00261 this->numSends = m_buff->m_fromMe.size();
00262 if (this->numSends > 0) {
00263 postSendsFromMe();
00264 }
00265 }
00266 #endif
00267
00268 }
00269
00270 template<class T>
00271 void BoxLayoutData<T>::makeItSoLocalCopy(const Interval& a_srcComps,
00272 const BoxLayoutData<T>& a_src,
00273 BoxLayoutData<T>& a_dest,
00274 const Interval& a_destComps,
00275 const Copier& a_copier,
00276 const LDOperator<T>& a_op) const
00277 {
00278
00279 CH_TIME("local copying");
00280 for(CopyIterator it(a_copier, CopyIterator::LOCAL); it.ok(); ++it)
00281 {
00282 const MotionItem& item = it();
00283
00284
00285
00286
00287
00288 a_op.op(a_dest[item.toIndex], item.fromRegion,
00289 a_destComps,
00290 item.toRegion,
00291 a_src[item.fromIndex],
00292 a_srcComps);
00293
00294 }
00295 }
00296
00297
00298 template<class T>
00299 void BoxLayoutData<T>::makeItSoEnd(BoxLayoutData<T>& a_dest,
00300 const Interval& a_destComps,
00301 const LDOperator<T>& a_op) const
00302 {
00303
00304 completePendingSends();
00305
00306 unpackReceivesToMe(a_dest, a_destComps, a_op);
00307
00308 }
00309
00310
00311 #ifndef CH_MPI
00312
00313 template<class T>
00314 void BoxLayoutData<T>::completePendingSends() const
00315 {}
00316
00317 template<class T>
00318 void BoxLayoutData<T>::allocateBuffers(const BoxLayoutData<T>& a_src,
00319 const Interval& a_srcComps,
00320 const BoxLayoutData<T>& a_dest,
00321 const Interval& a_destComps,
00322 const Copier& a_copier,
00323 const LDOperator<T>& a_op
00324 ) const
00325 {}
00326
00327 template<class T>
00328 void BoxLayoutData<T>::writeSendDataFromMeIntoBuffers(const BoxLayoutData<T>& a_src,
00329 const Interval& a_srcComps,
00330 const LDOperator<T>& a_op) const
00331 {}
00332
00333 template<class T>
00334 void BoxLayoutData<T>::postSendsFromMe() const
00335 {}
00336
00337 template<class T>
00338 void BoxLayoutData<T>::postReceivesToMe() const
00339 {}
00340
00341 template<class T>
00342 void BoxLayoutData<T>::unpackReceivesToMe(BoxLayoutData<T>& a_dest,
00343 const Interval& a_destComps,
00344 const LDOperator<T>& a_op) const
00345 {}
00346
00347 template<class T>
00348 void BoxLayoutData<T>::unpackReceivesToMe_append(LayoutData<Vector<RefCountedPtr<T> > >& a_dest,
00349 const Interval& a_destComps,
00350 int ncomp,
00351 const DataFactory<T>& factory,
00352 const LDOperator<T>& a_op) const
00353 {}
00354
00355 #else
00356
00357
00358
00359 template<class T>
00360 void BoxLayoutData<T>::completePendingSends() const
00361 {
00362 CH_TIME("completePendingSends");
00363 if(this->numSends > 0){
00364 m_sendStatus.resize(this->numSends);
00365 int result = MPI_Waitall(this->numSends, &(m_sendRequests[0]), &(m_sendStatus[0]));
00366 if(result != MPI_SUCCESS)
00367 {
00368
00369 }
00370
00371
00372 }
00373 this->numSends = 0;
00374 }
00375
00376
00377 template<class T>
00378 void BoxLayoutData<T>::allocateBuffers(const BoxLayoutData<T>& a_src,
00379 const Interval& a_srcComps,
00380 const BoxLayoutData<T>& a_dest,
00381 const Interval& a_destComps,
00382 const Copier& a_copier,
00383 const LDOperator<T>& a_op) const
00384 {
00385 CH_TIME("MPI_allocateBuffers");
00386 m_buff = &(((Copier&)a_copier).m_buffers);
00387 if(m_buff->isDefined(a_srcComps.size()) && T::preAllocatable()<2) return;
00388
00389 m_buff->m_ncomps = a_srcComps.size();
00390
00391 m_buff->m_fromMe.resize(0);
00392 m_buff->m_toMe.resize(0);
00393 size_t sendBufferSize = 0;
00394 size_t recBufferSize = 0;
00395
00396
00397 T dummy;
00398 for(CopyIterator it(a_copier, CopyIterator::FROM); it.ok(); ++it)
00399 {
00400 const MotionItem& item = it();
00401 CopierBuffer::bufEntry b;
00402 b.item = &item;
00403 b.size = a_op.size(a_src[item.fromIndex], item.fromRegion, a_srcComps);
00404 sendBufferSize+=b.size;
00405 b.procID = item.procID;
00406 m_buff->m_fromMe.push_back(b);
00407 }
00408 sort(m_buff->m_fromMe.begin(), m_buff->m_fromMe.end());
00409 for(CopyIterator it(a_copier, CopyIterator::TO); it.ok(); ++it)
00410 {
00411 const MotionItem& item = it();
00412 CopierBuffer::bufEntry b;
00413 b.item = &item;
00414 if(T::preAllocatable() == 0)
00415 {
00416 b.size = a_op.size(dummy, item.fromRegion, a_destComps);
00417 recBufferSize+=b.size;
00418 }
00419 else if (T::preAllocatable() == 1)
00420 {
00421 b.size = a_op.size(a_dest[item.toIndex], item.fromRegion, a_destComps);
00422 recBufferSize+=b.size;
00423 }
00424 b.procID = item.procID;
00425 m_buff->m_toMe.push_back(b);
00426 }
00427 sort(m_buff->m_toMe.begin(), m_buff->m_toMe.end());
00428
00429 if(T::preAllocatable() == 2)
00430 {
00431 CH_TIME("MPI_ Phase 1 of 2 Phase: preAllocatable==2");
00432 if(s_verbosity > 0) pout()<<"preAllocatable==2\n";
00433
00434
00435
00436 Vector<unsigned long> fdata;
00437 Vector<unsigned long> tdata;
00438 int count = 1;
00439 int scount = 1;
00440 if(m_buff->m_toMe.size() > 0)
00441 {
00442 tdata.resize(m_buff->m_toMe.size(), ULONG_MAX);
00443 m_receiveRequests.resize(numProc()-1);
00444 m_receiveStatus.resize(numProc()-1);
00445 MPI_Request* Rptr = &(m_receiveRequests[0]);
00446
00447 int lastProc = m_buff->m_toMe[0].procID;
00448 int messageSize = 1;
00449 unsigned long * dataPtr = &(tdata[0]);
00450 int i = 1;
00451
00452 for(;i<m_buff->m_toMe.size(); ++i)
00453 {
00454 CopierBuffer::bufEntry& b = m_buff->m_toMe[i];
00455 if(b.procID == lastProc)
00456 messageSize++;
00457 else
00458 {
00459
00460 MPI_Irecv(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
00461 1, Chombo_MPI::comm, Rptr);
00462 Rptr++;
00463
00464 lastProc = b.procID;
00465 messageSize = 1;
00466 dataPtr = &(tdata[i]);
00467 count++;
00468 }
00469 }
00470
00471 MPI_Irecv(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
00472 1, Chombo_MPI::comm, Rptr );
00473
00474
00475 }
00476 if(m_buff->m_fromMe.size() > 0)
00477 {
00478 fdata.resize(m_buff->m_fromMe.size());
00479 fdata[0]=m_buff->m_fromMe[0].size;
00480 m_sendRequests.resize(numProc()-1);
00481 m_sendStatus.resize(numProc()-1);
00482 MPI_Request* Rptr = &(m_sendRequests[0]);
00483
00484 int lastProc = m_buff->m_fromMe[0].procID;
00485 int messageSize = 1;
00486 unsigned long * dataPtr = &(fdata[0]);
00487 int i = 1;
00488 for(;i<m_buff->m_fromMe.size(); ++i)
00489 {
00490 fdata[i] = m_buff->m_fromMe[i].size;
00491 CopierBuffer::bufEntry& b = m_buff->m_fromMe[i];
00492 if(b.procID == lastProc)
00493 messageSize++;
00494 else
00495 {
00496
00497 MPI_Isend(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
00498 1, Chombo_MPI::comm, Rptr);
00499
00500
00501 Rptr++;
00502 lastProc = b.procID;
00503 messageSize = 1;
00504 dataPtr = &(fdata[i]);
00505 scount++;
00506 }
00507 }
00508
00509 MPI_Isend(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
00510 1, Chombo_MPI::comm, Rptr);
00511
00512
00513 }
00514
00515 if(m_buff->m_toMe.size() > 0)
00516 {
00517
00518 int result = MPI_Waitall(count, &(m_receiveRequests[0]), &(m_receiveStatus[0]));
00519 if(result != MPI_SUCCESS)
00520 {
00521 MayDay::Error("First pass of two-phase communication failed");
00522 }
00523
00524 for(int i=0; i<m_buff->m_toMe.size(); ++i) {
00525 CH_assert(tdata[i] != ULONG_MAX);
00526 m_buff->m_toMe[i].size = tdata[i];
00527 recBufferSize+= tdata[i];
00528 }
00529
00530
00531 }
00532 if(m_buff->m_fromMe.size() > 0)
00533 {
00534
00535 int result = MPI_Waitall(scount, &(m_sendRequests[0]), &(m_sendStatus[0]));
00536 if(result != MPI_SUCCESS)
00537 {
00538 MayDay::Error("First pass of two-phase communication failed");
00539 }
00540
00541 }
00542 }
00543
00544
00545
00546 if(sendBufferSize > m_buff->m_sendcapacity)
00547 {
00548 freeMT((m_buff->m_sendbuffer));
00549 if(s_verbosity > 0) pout()<<"malloc send buffer "<<sendBufferSize<<std::endl;
00550 (m_buff->m_sendbuffer) = mallocMT(sendBufferSize);
00551 if((m_buff->m_sendbuffer) == NULL)
00552 {
00553 MayDay::Error("Out of memory in BoxLayoutData::allocatebuffers");
00554 }
00555 m_buff->m_sendcapacity = sendBufferSize;
00556 }
00557
00558 if(recBufferSize > m_buff->m_reccapacity)
00559 {
00560 freeMT(m_buff->m_recbuffer);
00561 if(s_verbosity > 0) pout()<<"malloc receive buffer "<<recBufferSize<<std::endl;
00562 m_buff->m_recbuffer = mallocMT(recBufferSize);
00563 if(m_buff->m_recbuffer == NULL)
00564 {
00565 MayDay::Error("Out of memory in BoxLayoutData::allocatebuffers");
00566 }
00567 m_buff->m_reccapacity = recBufferSize;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 char* nextFree = (char*)(m_buff->m_sendbuffer);
00581 if(m_buff->m_fromMe.size() > 0)
00582 {
00583 for(unsigned int i=0; i<m_buff->m_fromMe.size(); ++i)
00584 {
00585 m_buff->m_fromMe[i].bufPtr = nextFree;
00586 nextFree += m_buff->m_fromMe[i].size;
00587 }
00588 }
00589
00590 nextFree = (char*)m_buff->m_recbuffer;
00591 if(m_buff->m_toMe.size() > 0)
00592 {
00593 for(unsigned int i=0; i<m_buff->m_toMe.size(); ++i)
00594 {
00595 m_buff->m_toMe[i].bufPtr = nextFree;
00596 nextFree += m_buff->m_toMe[i].size;
00597 }
00598 }
00599
00600
00601
00602
00603 }
00604
00605 template<class T>
00606 void BoxLayoutData<T>::writeSendDataFromMeIntoBuffers(const BoxLayoutData<T>& a_src,
00607 const Interval& a_srcComps,
00608 const LDOperator<T>& a_op) const
00609 {
00610 CH_TIME("write Data to buffers");
00611 for(unsigned int i=0; i<m_buff->m_fromMe.size(); ++i)
00612 {
00613 const CopierBuffer::bufEntry& entry = m_buff->m_fromMe[i];
00614 a_op.linearOut(a_src[entry.item->fromIndex], entry.bufPtr,
00615 entry.item->fromRegion, a_srcComps);
00616 }
00617 }
00618
00619 template<class T>
00620 void BoxLayoutData<T>::postSendsFromMe() const
00621 {
00622 CH_TIME("post Sends");
00623
00624
00625
00626 this->numSends = m_buff->m_fromMe.size();
00627
00628 if(this->numSends > 1){
00629 for(unsigned int i=m_buff->m_fromMe.size()-1; i>0; --i)
00630 {
00631 if(m_buff->m_fromMe[i].procID == m_buff->m_fromMe[i-1].procID)
00632 {
00633 this->numSends--;
00634 m_buff->m_fromMe[i-1].size = m_buff->m_fromMe[i-1].size + m_buff->m_fromMe[i].size;
00635 m_buff->m_fromMe[i].size = 0;
00636 }
00637 }
00638 }
00639 m_sendRequests.resize(this->numSends);
00640 std::list<MPI_Request> extraRequests;
00641
00642 unsigned int next=0;
00643 long long maxSize = 0;
00644 for(int i=0; i<this->numSends; ++i)
00645 {
00646 const CopierBuffer::bufEntry& entry = m_buff->m_fromMe[next];
00647 char* buffer = (char*)entry.bufPtr;
00648 size_t bsize = entry.size;
00649 int idtag=0;
00650 while(bsize > CH_MAX_MPI_MESSAGE_SIZE){
00651 extraRequests.push_back(MPI_Request());
00652 {
00653 CH_TIME("MPI_Isend");
00654 MPI_Isend(buffer, CH_MAX_MPI_MESSAGE_SIZE, MPI_BYTE, entry.procID,
00655 idtag, Chombo_MPI::comm, &(extraRequests.back()));
00656 }
00657 maxSize = CH_MAX_MPI_MESSAGE_SIZE;
00658 bsize -= CH_MAX_MPI_MESSAGE_SIZE;
00659 buffer+=CH_MAX_MPI_MESSAGE_SIZE;
00660 idtag++;
00661 }
00662 {
00663 CH_TIME("MPI_Isend");
00664 MPI_Isend(buffer, bsize, MPI_BYTE, entry.procID,
00665 idtag, Chombo_MPI::comm, &(m_sendRequests[i]));
00666 }
00667 maxSize = Max<long long>(bsize, maxSize);
00668 ++next;
00669 while(next < m_buff->m_fromMe.size() && m_buff->m_fromMe[next].size == 0) ++next;
00670 }
00671 for(std::list<MPI_Request>::iterator it = extraRequests.begin(); it != extraRequests.end(); ++it){
00672 m_sendRequests.push_back(*it);
00673 }
00674 this->numSends = m_sendRequests.size();
00675
00676 CH_MaxMPISendSize = Max<long long>(CH_MaxMPISendSize, maxSize);
00677
00678 }
00679
00680 template<class T>
00681 void BoxLayoutData<T>::postReceivesToMe() const
00682 {
00683 CH_TIME("post Receives");
00684 this->numReceives = m_buff->m_toMe.size();
00685
00686 if(this->numReceives > 1){
00687 for(unsigned int i=m_buff->m_toMe.size()-1; i>0; --i)
00688 {
00689 if(m_buff->m_toMe[i].procID == m_buff->m_toMe[i-1].procID)
00690 {
00691 this->numReceives--;
00692 m_buff->m_toMe[i-1].size += m_buff->m_toMe[i].size;
00693 m_buff->m_toMe[i].size = 0;
00694 }
00695
00696 }
00697 }
00698 m_receiveRequests.resize(this->numReceives);
00699 std::list<MPI_Request> extraRequests;
00700 unsigned int next=0;
00701 long long maxSize = 0;
00702 for(int i=0; i<this->numReceives; ++i)
00703 {
00704 const CopierBuffer::bufEntry& entry = m_buff->m_toMe[next];
00705 char* buffer = (char*)entry.bufPtr;
00706 size_t bsize = entry.size;
00707 int idtag=0;
00708 while(bsize > CH_MAX_MPI_MESSAGE_SIZE){
00709 extraRequests.push_back(MPI_Request());
00710 {
00711 CH_TIME("MPI_Irecv");
00712 MPI_Irecv(buffer, CH_MAX_MPI_MESSAGE_SIZE, MPI_BYTE, entry.procID,
00713 idtag, Chombo_MPI::comm, &(extraRequests.back()));
00714 }
00715 maxSize = CH_MAX_MPI_MESSAGE_SIZE;
00716 bsize -= CH_MAX_MPI_MESSAGE_SIZE;
00717 buffer+=CH_MAX_MPI_MESSAGE_SIZE;
00718 idtag++;
00719 }
00720 {
00721 CH_TIME("MPI_Irecv");
00722 MPI_Irecv(buffer, bsize, MPI_BYTE, entry.procID,
00723 idtag, Chombo_MPI::comm, &(m_receiveRequests[i]));
00724 }
00725 ++next;
00726 maxSize = Max<long long>(bsize, maxSize);
00727 while(next < m_buff->m_toMe.size() && m_buff->m_toMe[next].size == 0) ++next;
00728 }
00729 for(std::list<MPI_Request>::iterator it = extraRequests.begin(); it != extraRequests.end(); ++it){
00730 m_receiveRequests.push_back(*it);
00731 }
00732 this->numReceives = m_receiveRequests.size();
00733
00734 CH_MaxMPIRecvSize = Max<long long>(CH_MaxMPIRecvSize, maxSize);
00735
00736
00737 }
00738
00739 template<class T>
00740 void BoxLayoutData<T>::unpackReceivesToMe(BoxLayoutData<T>& a_dest,
00741 const Interval& a_destComps,
00742 const LDOperator<T>& a_op) const
00743 {
00744
00745 CH_TIME("unpack messages");
00746 if(this->numReceives > 0){
00747 m_receiveStatus.resize(this->numReceives);
00748 int result;
00749 {
00750 CH_TIME("MPI_Waitall");
00751 result = MPI_Waitall(this->numReceives, &(m_receiveRequests[0]),
00752 &(m_receiveStatus[0]));
00753 }
00754 if(result != MPI_SUCCESS)
00755 {
00756
00757 }
00758
00759 for(unsigned int i=0; i<m_buff->m_toMe.size(); ++i)
00760 {
00761 const CopierBuffer::bufEntry& entry = m_buff->m_toMe[i];
00762 a_op.linearIn(a_dest[entry.item->toIndex], entry.bufPtr, entry.item->toRegion, a_destComps);
00763 }
00764
00765
00766 }
00767 this->numReceives = 0;
00768 }
00769
00770 template<class T>
00771 void BoxLayoutData<T>::unpackReceivesToMe_append(LayoutData<Vector<RefCountedPtr<T> > >& a_dest,
00772 const Interval& a_destComps,
00773 int ncomp,
00774 const DataFactory<T>& factory,
00775
00776 const LDOperator<T>& a_op) const
00777 {
00778
00779 if(this->numReceives > 0){
00780 m_receiveStatus.resize(this->numReceives);
00781 int result;
00782 {
00783 CH_TIME("MPI_Waitall");
00784 result = MPI_Waitall(this->numReceives, &(m_receiveRequests[0]),
00785 &(m_receiveStatus[0]));
00786 }
00787 if(result != MPI_SUCCESS)
00788 {
00789
00790 }
00791
00792 for(unsigned int i=0; i<m_buff->m_toMe.size(); ++i)
00793 {
00794 const CopierBuffer::bufEntry& entry = m_buff->m_toMe[i];
00795 const MotionItem& item = *(entry.item);
00796 RefCountedPtr<T> newT( factory.create(item.toRegion, ncomp, item.toIndex) );;
00797
00798 a_op.linearIn(*newT, entry.bufPtr, item.toRegion, a_destComps);
00799 a_dest[item.toIndex].push_back(newT);
00800 }
00801
00802
00803 }
00804 this->numReceives = 0;
00805 }
00806 #endif
00807
00808 template <class T>
00809 void BoxLayoutData<T>::generalCopyTo(const BoxLayout& a_destGrids,
00810 LayoutData<Vector<RefCountedPtr<T> > >& a_dest,
00811 const Interval& a_srcComps,
00812 const ProblemDomain& a_domain,
00813 const Copier& a_copier,
00814 const DataFactory<T>& factory) const
00815 {
00816
00817 CH_assert(T::preAllocatable() == 0);
00818 a_dest.define(a_destGrids);
00819
00820 LDOperator<T> a_op;
00821
00822 int ncomp = a_srcComps.size();
00823 Interval destComps(0, ncomp-1);
00824 allocateBuffers(*this, a_srcComps,
00825 *this, destComps,
00826 a_copier, a_op);
00827
00828 writeSendDataFromMeIntoBuffers(*this, a_srcComps, a_op);
00829
00830
00831
00832
00833 #ifdef CH_MPI
00834 this->numReceives = m_buff->m_toMe.size();
00835 if (this->numReceives > 0) {
00836 postReceivesToMe();
00837 }
00838
00839 this->numSends = m_buff->m_fromMe.size();
00840 if (this->numSends > 0) {
00841 postSendsFromMe();
00842 }
00843 #endif
00844
00845
00846 for(CopyIterator it(a_copier, CopyIterator::LOCAL); it.ok(); ++it)
00847 {
00848 const MotionItem& item = it();
00849 RefCountedPtr<T> newT( factory.create(item.toRegion, ncomp, item.toIndex) );
00850
00851 a_op.op(*newT, item.fromRegion,
00852 destComps,
00853 item.toRegion,
00854 this->operator[](item.fromIndex),
00855 a_srcComps);
00856 a_dest[item.toIndex].push_back(newT);
00857 }
00858
00859
00860 completePendingSends();
00861
00862 unpackReceivesToMe_append(a_dest, destComps, ncomp, factory, a_op);
00863 }
00864
00865
00866 template <class T>
00867 void BoxLayoutData<T>::generalCopyTo(const BoxLayout& a_destGrids,
00868 LayoutData<Vector<RefCountedPtr<T> > >& a_dest,
00869 const Interval& a_srcComps,
00870 const ProblemDomain& a_domain,
00871 const DataFactory<T>& factory) const
00872 {
00873 Copier copier;
00874 copier.define(this->m_boxLayout, a_destGrids, a_domain, IntVect::Zero);
00875
00876 generalCopyTo(a_destGrids, a_dest, a_srcComps, a_domain, copier, factory);
00877 }
00878
00879 #include "NamespaceFooter.H"
00880 #endif