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