Chombo + EB  3.0
BoxLayoutDataI.H
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3  * _______ __
4  * / ___/ / ___ __ _ / / ___
5  * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6  * \___/_//_/\___/_/_/_/_.__/\___/
7  * Please refer to Copyright.txt, in Chombo's root directory.
8  */
9 #endif
10 
11 #ifndef _BOXLAYOUTDATAI_H_
12 #define _BOXLAYOUTDATAI_H_
13 
14 #include <cstdlib>
15 #include <algorithm>
16 #include <limits.h>
17 #include <list>
18 
19 #include "parstream.H"
20 #include "memtrack.H"
21 #include "Misc.H"
22 #include "CH_Timer.H"
23 #include "NamespaceHeader.H"
24 #include "BaseFabMacros.H"
25 
26 using std::sort;
27 
28 template<class T>
30 
31 template <class T>
33  int ncomps,
34  const DataIndex& a_datInd) const
35 {
36  return new T(box, ncomps);
37 }
38 
39 template<class T>
40 inline bool BoxLayoutData<T>::isDefined() const
41 {
42  return m_isdefined;
43 }
44 
45 template <class T>
47  const Interval& srcComps,
48  const Interval& destComps)
49 {
50  if (&da != this)
51  {
52  for (DataIterator it(this->dataIterator()); it.ok(); ++it)
53  {
54  this->m_vector[it().datInd()]->copy( this->box(it()), destComps,
55  this->box(it()), da[it()], srcComps);
56  }
57  }
58 }
59 
60 template<class T>
61 inline void BoxLayoutData<T>::define(const BoxLayoutData<T>& da, const Interval& comps,
62  const DataFactory<T>& factory)
63 {
64  if (this == &da)
65  {
66  MayDay::Error("BoxLayoutData<T>::define(const LayoutData<T>& da,.....) called with 'this'");
67  }
68  CH_assert(comps.size()>0);
69  CH_assert(comps.end()<=m_comps);
70  CH_assert(comps.begin()>=0);
71  this->m_boxLayout = da.boxLayout();
72 
73  this->m_comps = comps.size();
74 
75  Interval dest(0, m_comps-1);
76  allocateGhostVector(factory);
77  setVector(da, comps, dest);
78 
79 
80 }
81 
82 template<class T>
83 inline void BoxLayoutData<T>::define(const BoxLayout& boxes, int comps,
84  const DataFactory<T>& factory)
85 {
86  CH_assert(boxes.isClosed());
87  this->m_boxLayout = boxes;
88  m_comps = comps;
89  m_isdefined = true;
90  allocateGhostVector(factory);
91 
92 }
93 
94 template<class T>
95 inline void BoxLayoutData<T>::define(const BoxLayout& boxes)
96 {
97  MayDay::Error("BoxLayoutData<T>::define(const BoxLayout& boxes)...needs comps");
98 }
99 
100 template <class T>
102 {
103  m_isdefined = false;
104 #ifdef CH_MPI
105  this->numSends = 0;
106  this->numReceives = 0;
107 #endif
108 }
109 template<class T>
110 inline BoxLayoutData<T>::BoxLayoutData(const BoxLayout& boxes, int comps,
111  const DataFactory<T>& factory)
112  :m_comps(comps),m_buff(NULL)
113 {
114  CH_assert(boxes.isClosed());
115  this->m_boxLayout = boxes;
116  m_isdefined = true;
117  allocateGhostVector(factory);
118 #ifdef CH_MPI
119 
120  this->numSends = 0;
121  this->numReceives = 0;
122 #endif
123 }
124 
125 template<class T>
127 {
128  CH_TIME("~BoxLayoutData");
130 }
131 
132 template<class T>
134  const DataFactory<T>& factory)
135 {
136  if (this != &da)
137  {
139  this->m_boxLayout = da.boxLayout();
140  m_comps = da.nComp();
141  Interval srcAnddest(0, m_comps-1);
142  allocateGhostVector(factory);
143  setVector(da, srcAnddest, srcAnddest);
144  }
145 
146 }
147 template<class T>
149 {
150  if (this->m_callDelete == true)
151  {
152  for (unsigned int i=0; i<this->m_vector.size(); ++i)
153  {
154  delete this->m_vector[i];
155  this->m_vector[i] = NULL;
156  }
157 #if CH_USE_MEMORY_TRACKING
158  this->m_vector.bytes -= sizeof(T)*this->m_vector.size();
159 #endif
160  }
161  m_isdefined = false;
162 }
163 
164 template<class T>
165 inline void BoxLayoutData<T>::allocateGhostVector(const DataFactory<T>& factory, const IntVect& ghost)
166 {
167  if (this->m_callDelete == true)
168  {
169  for (unsigned int i=0; i<this->m_vector.size(); ++i)
170  {
171  delete this->m_vector[i];
172  this->m_vector[i] = NULL;
173  }
174 #if CH_USE_MEMORY_TRACKING
175  this->m_vector.bytes -= sizeof(T)*this->m_vector.size();
176 #endif
177  }
178 
179  this->m_callDelete = factory.callDelete();
180 
181  DataIterator it(this->dataIterator());
182 #if CH_USE_MEMORY_TRACKING
183  if (this->m_callDelete == true)
184  {
185  this->m_vector.bytes += sizeof(T)*it.size();
186  }
187 #endif
188  this->m_vector.resize(it.size(), NULL);
189 
190  for (; it.ok(); ++it)
191  {
192  unsigned int index = it().datInd();
193  Box abox = this->box(it());
194  abox.grow(ghost);
195  this->m_vector[index] = factory.create(abox, m_comps, it());
196  if (this->m_vector[index] == NULL)
197  {
198  MayDay::Error("OutOfMemory in BoxLayoutData::allocateGhostVector");
199  }
200  }
201 }
202 
203 template<class T>
204 inline void BoxLayoutData<T>::apply(void (*a_func)(const Box& box, int comps, T& t))
205 {
206  for (DataIterator it(this->dataIterator()); it.ok(); ++it)
207  {
208  a_func(this->box(it()), m_comps, *(this->m_vector[it().datInd()]));
209  }
210 }
211 
212 //======================================================================
213 template <class T>
215 {
216  define(a_original, interval);
217 }
218 
219 template <class T>
221 {
222  m_origPointer = a_original;
223  m_interval = interval;
224 }
225 
226 template <class T>
227 T* AliasDataFactory<T>::create(const Box& a_box, int ncomps, const DataIndex& a_dataInd) const
228 {
229  //CH_assert(this->box(a_dataInd) == a_box);
230  CH_assert(ncomps = m_interval.size());
231  T* rtn = new T(m_interval, m_origPointer->operator[](a_dataInd));
232  return rtn;
233 }
234 
235 template<class T>
236 void BoxLayoutData<T>::makeItSo(const Interval& a_srcComps,
237  const BoxLayoutData<T>& a_src,
238  BoxLayoutData<T>& a_dest,
239  const Interval& a_destComps,
240  const Copier& a_copier,
241  const LDOperator<T>& a_op) const
242 {
243  makeItSoBegin(a_srcComps, a_src, a_dest, a_destComps, a_copier, a_op);
244  makeItSoLocalCopy(a_srcComps, a_src, a_dest, a_destComps, a_copier, a_op);
245  makeItSoEnd(a_dest, a_destComps, a_op);
246 }
247 
248 template<class T>
250  const BoxLayoutData<T>& a_src,
251  BoxLayoutData<T>& a_dest,
252  const Interval& a_destComps,
253  const Copier& a_copier,
254  const LDOperator<T>& a_op) const
255 {
256  // The following five functions are nullOps in uniprocessor mode
257 
258 #ifdef CH_MPI
259 
260  allocateBuffers(a_src, a_srcComps,
261  a_dest, a_destComps,
262  a_copier,
263  a_op); //monkey with buffers, set up 'fromMe' and 'toMe' queues
264 
265 
266  writeSendDataFromMeIntoBuffers(a_src, a_srcComps, a_op);
267 
268  // If there is nothing to recv/send, don't go into these functions
269  // and allocate memory that will not be freed later. (ndk)
270  // The #ifdef CH_MPI is for the m_buff->m_toMe and m_buff->m_fromMe
271  {
272  CH_TIME("post messages");
273  this->numReceives = m_buff->m_toMe.size();
274  if (this->numReceives > 0)
275  {
276  postReceivesToMe(); // all non-blocking
277  }
278 
279  this->numSends = m_buff->m_fromMe.size();
280  if (this->numSends > 0)
281  {
282  postSendsFromMe(); // all non-blocking
283  }
284  }
285 #endif
286 
287 }
288 
289 template<class T>
291  const BoxLayoutData<T>& a_src,
292  BoxLayoutData<T>& a_dest,
293  const Interval& a_destComps,
294  const Copier& a_copier,
295  const LDOperator<T>& a_op) const
296 {
297 
298  CH_TIME("local copying");
299  for (CopyIterator it(a_copier, CopyIterator::LOCAL); it.ok(); ++it)
300  {
301  const MotionItem& item = it();
302  //const T& src = a_src[item.fromIndex];
303  //T& dest = a_dest[item.toIndex];
304  //int srcSize = src .size(item.fromRegion, a_srcComps);
305  //int destSize= dest.size(item.toRegion, a_destComps);
306  //if (srcSize != destSize) MayDay::Error("(srcSize != destSize) in makeItSo");
307  a_op.op(a_dest[item.toIndex], item.fromRegion,
308  a_destComps,
309  item.toRegion,
310  a_src[item.fromIndex],
311  a_srcComps);
312 
313  }
314 }
315 
316 
317 template<class T>
319  const Interval& a_destComps,
320  const LDOperator<T>& a_op) const
321 {
322  // Uncomment and Move this out of unpackReceivesToMe() (ndk)
323  completePendingSends(); // wait for sends from possible previous operation
324 
325  unpackReceivesToMe(a_dest, a_destComps, a_op); // nullOp in uniprocessor mode
326 
327 }
328 
329 
330 #ifndef CH_MPI
331 // uniprocessor version of all these nullop functions.
332 template<class T>
334 {
335 }
336 
337 template<class T>
339  const Interval& a_srcComps,
340  const BoxLayoutData<T>& a_dest,
341  const Interval& a_destComps,
342  const Copier& a_copier,
343  const LDOperator<T>& a_op
344  ) const
345 {
346 }
347 
348 template<class T>
350  const Interval& a_srcComps,
351  const LDOperator<T>& a_op) const
352 {
353 }
354 
355 template<class T>
357 {
358 }
359 
360 template<class T>
362 {
363 }
364 
365 template<class T>
367  const Interval& a_destComps,
368  const LDOperator<T>& a_op) const
369 {
370 }
371 
372 template<class T>
374  const Interval& a_destComps,
375  int ncomp,
376  const DataFactory<T>& factory,
377  const LDOperator<T>& a_op) const
378 {
379 }
380 
381 #else
382 
383 // MPI versions of the above codes.
384 
385 template<class T>
387 {
388  CH_TIME("completePendingSends");
389  if (this->numSends > 0)
390  {
391  m_sendStatus.resize(this->numSends);
392  int result = MPI_Waitall(this->numSends, &(m_sendRequests[0]), &(m_sendStatus[0]));
393  if (result != MPI_SUCCESS)
394  {
395  //hell if I know what to do about failed messaging here
396  }
397 
398 
399  }
400  this->numSends = 0;
401 }
402 
403 
404 template<class T>
406  const Interval& a_srcComps,
407  const BoxLayoutData<T>& a_dest,
408  const Interval& a_destComps,
409  const Copier& a_copier,
410  const LDOperator<T>& a_op) const
411 {
412  CH_TIME("MPI_allocateBuffers");
413  m_buff = &(((Copier&)a_copier).m_buffers);
414  if (m_buff->isDefined(a_srcComps.size()) && T::preAllocatable()<2) return;
415 
416  m_buff->m_ncomps = a_srcComps.size();
417 
418  m_buff->m_fromMe.resize(0);
419  m_buff->m_toMe.resize(0);
420  size_t sendBufferSize = 0;
421  size_t recBufferSize = 0;
422  // two versions of code here. one for preAllocatable T, one not.
423 
424  T dummy;
425  for (CopyIterator it(a_copier, CopyIterator::FROM); it.ok(); ++it)
426  {
427  const MotionItem& item = it();
428  CopierBuffer::bufEntry b;
429  b.item = &item;
430  b.size = a_op.size(a_src[item.fromIndex], item.fromRegion, a_srcComps);
431  sendBufferSize+=b.size;
432  b.procID = item.procID;
433  m_buff->m_fromMe.push_back(b);
434  }
435  sort(m_buff->m_fromMe.begin(), m_buff->m_fromMe.end());
436  for (CopyIterator it(a_copier, CopyIterator::TO); it.ok(); ++it)
437  {
438  const MotionItem& item = it();
439  CopierBuffer::bufEntry b;
440  b.item = &item;
441  if (T::preAllocatable() == 0)
442  {
443  b.size = a_op.size(dummy, item.fromRegion, a_destComps);
444  recBufferSize+=b.size;
445  }
446  else if (T::preAllocatable() == 1)
447  {
448  b.size = a_op.size(a_dest[item.toIndex], item.fromRegion, a_destComps);
449  recBufferSize+=b.size;
450  }
451  b.procID = item.procID;
452  m_buff->m_toMe.push_back(b);
453  }
454  sort(m_buff->m_toMe.begin(), m_buff->m_toMe.end());
455 
456  if (T::preAllocatable() == 2) // dynamic allocatable, need two pass
457  {
458  CH_TIME("MPI_ Phase 1 of 2 Phase: preAllocatable==2");
459  if (s_verbosity > 0) pout()<<"preAllocatable==2\n";
460 
461  // in the non-preallocatable case, I need to message the
462  // values for the m_buff->m_toMe[*].size
463  Vector<unsigned long> fdata;
464  Vector<unsigned long> tdata;
465  int count = 1;
466  int scount = 1;
467  if (m_buff->m_toMe.size() > 0)
468  {
469  tdata.resize(m_buff->m_toMe.size(), ULONG_MAX);
470  m_receiveRequests.resize(numProc()-1);
471  m_receiveStatus.resize(numProc()-1);
472  MPI_Request* Rptr = &(m_receiveRequests[0]);
473 
474  int lastProc = m_buff->m_toMe[0].procID;
475  int messageSize = 1;
476  unsigned long * dataPtr = &(tdata[0]);
477  int i = 1;
478 
479  for (;i<m_buff->m_toMe.size(); ++i)
480  {
481  CopierBuffer::bufEntry& b = m_buff->m_toMe[i];
482  if (b.procID == lastProc)
483  messageSize++;
484  else
485  {
486 
487  MPI_Irecv(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
488  1, Chombo_MPI::comm, Rptr);
489  Rptr++;
490 
491  lastProc = b.procID;
492  messageSize = 1;
493  dataPtr = &(tdata[i]);
494  count++;
495  }
496  }
497 
498  MPI_Irecv(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
499  1, Chombo_MPI::comm, Rptr );
500 
501 
502  }
503  if (m_buff->m_fromMe.size() > 0)
504  {
505  fdata.resize(m_buff->m_fromMe.size());
506  fdata[0]=m_buff->m_fromMe[0].size;
507  m_sendRequests.resize(numProc()-1);
508  m_sendStatus.resize(numProc()-1);
509  MPI_Request* Rptr = &(m_sendRequests[0]);
510 
511  int lastProc = m_buff->m_fromMe[0].procID;
512  int messageSize = 1;
513  unsigned long * dataPtr = &(fdata[0]);
514  int i = 1;
515  for (;i<m_buff->m_fromMe.size(); ++i)
516  {
517  fdata[i] = m_buff->m_fromMe[i].size;
518  CopierBuffer::bufEntry& b = m_buff->m_fromMe[i];
519  if (b.procID == lastProc)
520  messageSize++;
521  else
522  {
523 
524  MPI_Isend(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
525  1, Chombo_MPI::comm, Rptr);
526 
527 
528  Rptr++;
529  lastProc = b.procID;
530  messageSize = 1;
531  dataPtr = &(fdata[i]);
532  scount++;
533  }
534  }
535 
536  MPI_Isend(dataPtr, messageSize, MPI_UNSIGNED_LONG, lastProc,
537  1, Chombo_MPI::comm, Rptr);
538 
539 
540  }
541 
542  if (m_buff->m_toMe.size() > 0)
543  {
544 
545  int result = MPI_Waitall(count, &(m_receiveRequests[0]), &(m_receiveStatus[0]));
546  if (result != MPI_SUCCESS)
547  {
548  MayDay::Error("First pass of two-phase communication failed");
549  }
550 
551  for (int i=0; i<m_buff->m_toMe.size(); ++i)
552  {
553  CH_assert(tdata[i] != ULONG_MAX);
554  m_buff->m_toMe[i].size = tdata[i];
555  recBufferSize+= tdata[i];
556  }
557 
558 
559  }
560  if (m_buff->m_fromMe.size() > 0)
561  {
562 
563  int result = MPI_Waitall(scount, &(m_sendRequests[0]), &(m_sendStatus[0]));
564  if (result != MPI_SUCCESS)
565  {
566  MayDay::Error("First pass of two-phase communication failed");
567  }
568 
569  }
570  }
571 
572  // allocate send and receveive buffer space.
573 
574  if (sendBufferSize > m_buff->m_sendcapacity)
575  {
577  if (s_verbosity > 0) pout()<<"malloc send buffer "<<sendBufferSize<<std::endl;
578  (m_buff->m_sendbuffer) = mallocMT(sendBufferSize);
579  if ((m_buff->m_sendbuffer) == NULL)
580  {
581  MayDay::Error("Out of memory in BoxLayoutData::allocatebuffers");
582  }
583  m_buff->m_sendcapacity = sendBufferSize;
584  }
585 
586  if (recBufferSize > m_buff->m_reccapacity)
587  {
589  if (s_verbosity > 0) pout()<<"malloc receive buffer "<<recBufferSize<<std::endl;
590  m_buff->m_recbuffer = mallocMT(recBufferSize);
591  if (m_buff->m_recbuffer == NULL)
592  {
593  MayDay::Error("Out of memory in BoxLayoutData::allocatebuffers");
594  }
595  m_buff->m_reccapacity = recBufferSize;
596  }
597 
598  /*
599  pout()<<"\n";
600  for (int i=0; i<m_buff->m_fromMe.size(); i++)
601  pout()<<m_buff->m_fromMe[i].item->region<<"{"<<m_buff->m_fromMe[i].procID<<"}"<<" ";
602  pout() <<"::::";
603  for (int i=0; i<m_buff->m_toMe.size(); i++)
604  pout()<<m_buff->m_toMe[i].item->region<<"{"<<m_buff->m_toMe[i].procID<<"}"<<" ";
605  pout() << endl;
606  */
607 
608  char* nextFree = (char*)(m_buff->m_sendbuffer);
609  if (m_buff->m_fromMe.size() > 0)
610  {
611  for (unsigned int i=0; i<m_buff->m_fromMe.size(); ++i)
612  {
613  m_buff->m_fromMe[i].bufPtr = nextFree;
614  nextFree += m_buff->m_fromMe[i].size;
615  }
616  }
617 
618  nextFree = (char*)m_buff->m_recbuffer;
619  if (m_buff->m_toMe.size() > 0)
620  {
621  for (unsigned int i=0; i<m_buff->m_toMe.size(); ++i)
622  {
623  m_buff->m_toMe[i].bufPtr = nextFree;
624  nextFree += m_buff->m_toMe[i].size;
625  }
626  }
627 
628  // since fromMe and toMe are sorted based on procID, messages can now be grouped
629  // together on a per-processor basis.
630 
631 }
632 
633 template<class T>
635  const Interval& a_srcComps,
636  const LDOperator<T>& a_op) const
637 {
638  CH_TIME("write Data to buffers");
639  for (unsigned int i=0; i<m_buff->m_fromMe.size(); ++i)
640  {
641  const CopierBuffer::bufEntry& entry = m_buff->m_fromMe[i];
642  a_op.linearOut(a_src[entry.item->fromIndex], entry.bufPtr,
643  entry.item->fromRegion, a_srcComps);
644  }
645 }
646 
647 template<class T>
649 {
650  CH_TIME("post Sends");
651  // now we get the magic of message coalescence
652  // fromMe has already been sorted in the allocateBuffers() step.
653 
654  this->numSends = m_buff->m_fromMe.size();
655 
656  if (this->numSends > 1)
657  {
658  for (unsigned int i=m_buff->m_fromMe.size()-1; i>0; --i)
659  {
660  if (m_buff->m_fromMe[i].procID == m_buff->m_fromMe[i-1].procID)
661  {
662  this->numSends--;
663  m_buff->m_fromMe[i-1].size = m_buff->m_fromMe[i-1].size + m_buff->m_fromMe[i].size;
664  m_buff->m_fromMe[i].size = 0;
665  }
666  }
667  }
668  m_sendRequests.resize(this->numSends);
669  std::list<MPI_Request> extraRequests;
670 
671  unsigned int next=0;
672  long long maxSize = 0;
673  for (int i=0; i<this->numSends; ++i)
674  {
675  const CopierBuffer::bufEntry& entry = m_buff->m_fromMe[next];
676  char* buffer = (char*)entry.bufPtr;
677  size_t bsize = entry.size;
678  int idtag=0;
679  while (bsize > CH_MAX_MPI_MESSAGE_SIZE)
680  {
681  extraRequests.push_back(MPI_Request());
682  {
683  CH_TIME("MPI_Isend");
684  MPI_Isend(buffer, CH_MAX_MPI_MESSAGE_SIZE, MPI_BYTE, entry.procID,
685  idtag, Chombo_MPI::comm, &(extraRequests.back()));
686  }
687  maxSize = CH_MAX_MPI_MESSAGE_SIZE;
688  bsize -= CH_MAX_MPI_MESSAGE_SIZE;
689  buffer+=CH_MAX_MPI_MESSAGE_SIZE;
690  idtag++;
691  }
692  {
693  CH_TIME("MPI_Isend");
694  MPI_Isend(buffer, bsize, MPI_BYTE, entry.procID,
695  idtag, Chombo_MPI::comm, &(m_sendRequests[i]));
696  }
697  maxSize = Max<long long>(bsize, maxSize);
698  ++next;
699  while (next < m_buff->m_fromMe.size() && m_buff->m_fromMe[next].size == 0) ++next;
700  }
701  for (std::list<MPI_Request>::iterator it = extraRequests.begin(); it != extraRequests.end(); ++it)
702  {
703  m_sendRequests.push_back(*it);
704  }
705  this->numSends = m_sendRequests.size();
706 
707  CH_MaxMPISendSize = Max<long long>(CH_MaxMPISendSize, maxSize);
708 
709 }
710 
711 template<class T>
713 {
714  CH_TIME("post Receives");
715  this->numReceives = m_buff->m_toMe.size();
716 
717  if (this->numReceives > 1)
718  {
719  for (unsigned int i=m_buff->m_toMe.size()-1; i>0; --i)
720  {
721  if (m_buff->m_toMe[i].procID == m_buff->m_toMe[i-1].procID)
722  {
723  this->numReceives--;
724  m_buff->m_toMe[i-1].size += m_buff->m_toMe[i].size;
725  m_buff->m_toMe[i].size = 0;
726  }
727 
728  }
729  }
730  m_receiveRequests.resize(this->numReceives);
731  std::list<MPI_Request> extraRequests;
732  unsigned int next=0;
733  long long maxSize = 0;
734  for (int i=0; i<this->numReceives; ++i)
735  {
736  const CopierBuffer::bufEntry& entry = m_buff->m_toMe[next];
737  char* buffer = (char*)entry.bufPtr;
738  size_t bsize = entry.size;
739  int idtag=0;
740  while (bsize > CH_MAX_MPI_MESSAGE_SIZE)
741  {
742  extraRequests.push_back(MPI_Request());
743  {
744  CH_TIME("MPI_Irecv");
745  MPI_Irecv(buffer, CH_MAX_MPI_MESSAGE_SIZE, MPI_BYTE, entry.procID,
746  idtag, Chombo_MPI::comm, &(extraRequests.back()));
747  }
748  maxSize = CH_MAX_MPI_MESSAGE_SIZE;
749  bsize -= CH_MAX_MPI_MESSAGE_SIZE;
750  buffer+=CH_MAX_MPI_MESSAGE_SIZE;
751  idtag++;
752  }
753  {
754  CH_TIME("MPI_Irecv");
755  MPI_Irecv(buffer, bsize, MPI_BYTE, entry.procID,
756  idtag, Chombo_MPI::comm, &(m_receiveRequests[i]));
757  }
758  ++next;
759  maxSize = Max<long long>(bsize, maxSize);
760  while (next < m_buff->m_toMe.size() && m_buff->m_toMe[next].size == 0) ++next;
761  }
762  for (std::list<MPI_Request>::iterator it = extraRequests.begin(); it != extraRequests.end(); ++it)
763  {
764  m_receiveRequests.push_back(*it);
765  }
766  this->numReceives = m_receiveRequests.size();
767 
768  CH_MaxMPIRecvSize = Max<long long>(CH_MaxMPIRecvSize, maxSize);
769  //pout()<<"maxSize="<<maxSize<<" posted "<<this->numReceives<<" receives\n";
770 
771 }
772 
773 template<class T>
775  const Interval& a_destComps,
776  const LDOperator<T>& a_op) const
777 {
778 
779  CH_TIME("unpack messages");
780  if (this->numReceives > 0)
781  {
782  m_receiveStatus.resize(this->numReceives);
783  int result;
784  {
785  CH_TIME("MPI_Waitall");
786  result = MPI_Waitall(this->numReceives, &(m_receiveRequests[0]),
787  &(m_receiveStatus[0]));
788  }
789  if (result != MPI_SUCCESS)
790  {
791  //hell if I know what to do about failed messaging here
792  }
793 
794  for (unsigned int i=0; i<m_buff->m_toMe.size(); ++i)
795  {
796  const CopierBuffer::bufEntry& entry = m_buff->m_toMe[i];
797  a_op.linearIn(a_dest[entry.item->toIndex], entry.bufPtr, entry.item->toRegion, a_destComps);
798  }
799 
800 
801  }
802  this->numReceives = 0;
803 }
804 
805 template<class T>
807  const Interval& a_destComps,
808  int ncomp,
809  const DataFactory<T>& factory,
810 
811  const LDOperator<T>& a_op) const
812 {
813 
814  if (this->numReceives > 0)
815  {
816  m_receiveStatus.resize(this->numReceives);
817  int result;
818  {
819  CH_TIME("MPI_Waitall");
820  result = MPI_Waitall(this->numReceives, &(m_receiveRequests[0]),
821  &(m_receiveStatus[0]));
822  }
823  if (result != MPI_SUCCESS)
824  {
825  //hell if I know what to do about failed messaging here
826  }
827 
828  for (unsigned int i=0; i<m_buff->m_toMe.size(); ++i)
829  {
830  const CopierBuffer::bufEntry& entry = m_buff->m_toMe[i];
831  const MotionItem& item = *(entry.item);
832  RefCountedPtr<T> newT( factory.create(item.toRegion, ncomp, item.toIndex) );;
833 
834  a_op.linearIn(*newT, entry.bufPtr, item.toRegion, a_destComps);
835  a_dest[item.toIndex].push_back(newT);
836  }
837 
838 
839  }
840  this->numReceives = 0;
841 }
842 #endif
843 
844 template <class T>
846  LayoutData<Vector<RefCountedPtr<T> > >& a_dest,
847  const Interval& a_srcComps,
848  const ProblemDomain& a_domain,
849  const Copier& a_copier,
850  const DataFactory<T>& factory) const
851 {
852 
853  CH_assert(T::preAllocatable() == 0);
854  a_dest.define(a_destGrids);
855 
856  LDOperator<T> a_op;
857 
858  int ncomp = a_srcComps.size();
859  Interval destComps(0, ncomp-1);
860  allocateBuffers(*this, a_srcComps,
861  *this, destComps,
862  a_copier, a_op);
863 
864  writeSendDataFromMeIntoBuffers(*this, a_srcComps, a_op);
865 
866  // If there is nothing to recv/send, don't go into these functions
867  // and allocate memory that will not be freed later. (ndk)
868  // The #ifdef CH_MPI is for the m_buff->m_toMe and m_buff->m_fromMe
869 #ifdef CH_MPI
870  this->numReceives = m_buff->m_toMe.size();
871  if (this->numReceives > 0)
872  {
873  postReceivesToMe(); // all non-blocking
874  }
875 
876  this->numSends = m_buff->m_fromMe.size();
877  if (this->numSends > 0)
878  {
879  postSendsFromMe(); // all non-blocking
880  }
881 #endif
882 
883  // perform local copy
884  for (CopyIterator it(a_copier, CopyIterator::LOCAL); it.ok(); ++it)
885  {
886  const MotionItem& item = it();
887  RefCountedPtr<T> newT( factory.create(item.toRegion, ncomp, item.toIndex) );
888 
889  a_op.op(*newT, item.fromRegion,
890  destComps,
891  item.toRegion,
892  this->operator[](item.fromIndex),
893  a_srcComps);
894  a_dest[item.toIndex].push_back(newT);
895  }
896 
897  // Uncomment and Move this out of unpackReceivesToMe() (ndk)
898  completePendingSends(); // wait for sends from possible previous operation
899 
900  unpackReceivesToMe_append(a_dest, destComps, ncomp, factory, a_op); // nullOp in uniprocessor mode
901 }
902 
903 
904 template <class T>
906  LayoutData<Vector<RefCountedPtr<T> > >& a_dest,
907  const Interval& a_srcComps,
908  const ProblemDomain& a_domain,
909  const DataFactory<T>& factory) const
910 {
911  Copier copier;
912  copier.define(this->m_boxLayout, a_destGrids, a_domain, IntVect::Zero);
913 
914  generalCopyTo(a_destGrids, a_dest, a_srcComps, a_domain, copier, factory);
915 }
916 
917 
918 template <class T>
919 void BoxLayoutData<T>::addTo(const Interval& a_srcComps,
920  BoxLayoutData<T>& a_dest,
921  const Interval& a_destComps,
922  const ProblemDomain& a_domain) const
923 {
924  Copier copier;
925  copier.define(this->m_boxLayout, a_dest.m_boxLayout, a_domain, IntVect::Zero);
926  addTo(a_srcComps, a_dest, a_destComps, a_domain, copier);
927 }
928 
929 template <class T>
930 class LDaddOp : public LDOperator<T>
931 {
932 public:
933  virtual void op(T& dest,
934  const Box& RegionFrom,
935  const Interval& Cdest,
936  const Box& RegionTo,
937  const T& src,
938  const Interval& Csrc) const
939  {
940  dest.plus(src, RegionFrom, RegionTo, Csrc.begin(), Cdest.begin(), Cdest.size());
941  }
942  virtual void linearIn(T& arg, void* buf, const Box& R,
943  const Interval& comps) const
944  {
945  Real* buffer = (Real*)buf;
946 
947  ForAllXBNNnoindx(Real, arg, R, comps.begin(), comps.size())
948  {
949  argR+=*buffer;
950  buffer++;
951  } EndFor
952 
953  }
954 
955 };
956 
957 
958 template <class T>
959 void BoxLayoutData<T>::addTo(const Interval& a_srcComps,
960  BoxLayoutData<T>& a_dest,
961  const Interval& a_destComps,
962  const ProblemDomain& a_domain,
963  const Copier& a_copier) const
964 {
965  CH_TIME("addTo");
966  LDaddOp<T> addOp;
967  makeItSo(a_srcComps, *this, a_dest, a_destComps, a_copier, addOp);
968 }
969 
970 #include "NamespaceFooter.H"
971 #endif
std::ostream & pout()
Use this in place of std::cout for program output.
int m_comps
Definition: BoxLayoutData.H:341
CopierBuffer * m_buff
Definition: BoxLayoutData.H:419
virtual void define(const BoxLayout &boxes, int comps, const DataFactory< T > &factory=DefaultDataFactory< T >())
Definition: BoxLayoutDataI.H:83
bool m_callDelete
Definition: LayoutData.H:129
void define(BoxLayoutData< T > *a_original, const Interval &interval)
Definition: BoxLayoutDataI.H:220
A reference-counting handle class.
Definition: RefCountedPtr.H:66
#define freeMT(a_a)
Definition: memtrack.H:159
#define CH_assert(cond)
Definition: CHArray.H:37
void makeItSoEnd(BoxLayoutData< T > &a_dest, const Interval &a_destComps, const LDOperator< T > &a_op=LDOperator< T >()) const
Definition: BoxLayoutDataI.H:318
A class to facilitate interaction with physical boundary conditions.
Definition: ProblemDomain.H:130
Vector< T * > m_vector
Definition: LayoutData.H:122
void unpackReceivesToMe_append(LayoutData< Vector< RefCountedPtr< T > > > &a_dest, const Interval &a_destComps, int ncomp, const DataFactory< T > &factory, const LDOperator< T > &a_op) const
Definition: BoxLayoutDataI.H:373
int m_ncomps
Definition: Copier.H:67
A not-necessarily-disjoint collective of boxes.
Definition: BoxLayout.H:146
one dimensional dynamic array
Definition: Vector.H:52
void writeSendDataFromMeIntoBuffers(const BoxLayoutData< T > &a_src, const Interval &a_srcComps, const LDOperator< T > &a_op) const
Definition: BoxLayoutDataI.H:349
virtual ~BoxLayoutData()
Definition: BoxLayoutDataI.H:126
long long CH_MaxMPISendSize
int nComp() const
Definition: BoxLayoutData.H:258
Data that maintains a one-to-one mapping of T to the boxes in a BoxLayout.
Definition: LayoutData.H:46
A strange but true thing to make copying from one boxlayoutdata to another fast.
Definition: Copier.H:137
#define mallocMT(a_a)
Definition: memtrack.H:158
int size() const
Definition: DataIterator.H:168
long long CH_MaxMPIRecvSize
std::vector< bufEntry > m_fromMe
Definition: Copier.H:106
virtual bool callDelete() const
Definition: BoxLayoutData.H:43
Definition: Copier.H:341
void setVector(const BoxLayoutData< T > &da, const Interval &srcComps, const Interval &destComps)
Definition: BoxLayoutDataI.H:46
size_t m_sendcapacity
Definition: Copier.H:71
Definition: DataIterator.H:140
bool isDefined(int ncomps) const
Definition: Copier.H:64
void completePendingSends() const
Definition: BoxLayoutDataI.H:333
virtual void op(T &dest, const Box &RegionFrom, const Interval &Cdest, const Box &RegionTo, const T &src, const Interval &Csrc) const
Definition: BoxLayoutData.H:161
virtual void clear()
Definition: BoxLayoutDataI.H:148
unsigned int numProc()
number of parallel processes
Definition: Copier.H:342
Definition: Copier.H:30
void postReceivesToMe() const
Definition: BoxLayoutDataI.H:361
int size() const
Definition: Interval.H:64
BoxLayout m_boxLayout
Definition: LayoutData.H:116
void generalCopyTo(const BoxLayout &a_destGrids, LayoutData< Vector< RefCountedPtr< T > > > &a_dest, const Interval &a_interval, const ProblemDomain &a_domain, const DataFactory< T > &factory=DefaultDataFactory< T >()) const
General data copying operation.
Definition: BoxLayoutDataI.H:905
int procID
Definition: Copier.H:36
virtual T * create(const Box &box, int ncomps, const DataIndex &a_datInd) const
factory function. creates a new 'T' object
Definition: BoxLayoutDataI.H:32
virtual void linearOut(const T &arg, void *buf, const Box &R, const Interval &comps) const
Definition: BoxLayoutData.H:151
Definition: EBInterface.H:45
void resize(unsigned int isize)
Definition: Vector.H:323
virtual void apply(void(*a_Function)(const Box &box, int comps, T &t))
Definition: BoxLayoutDataI.H:204
DataIndex toIndex
Definition: Copier.H:33
size_t m_reccapacity
Definition: Copier.H:74
void * m_recbuffer
Definition: Copier.H:72
#define CH_TIME(name)
Definition: CH_Timer.H:59
Structure for passing component ranges in code.
Definition: Interval.H:23
void allocateGhostVector(const DataFactory< T > &factory, const IntVect &ghost=IntVect::Zero)
Definition: BoxLayoutDataI.H:165
virtual bool isDefined() const
Definition: BoxLayoutDataI.H:40
long long CH_MAX_MPI_MESSAGE_SIZE
void * m_sendbuffer
Definition: Copier.H:69
Interval interval() const
Definition: BoxLayoutData.H:264
virtual int size(const T &arg, const Box &b, const Interval &comps) const
Definition: BoxLayoutData.H:147
Data on a BoxLayout.
Definition: BoxLayoutData.H:91
static int s_verbosity
Definition: BoxLayoutData.H:338
virtual void linearIn(T &arg, void *buf, const Box &R, const Interval &comps) const
Definition: BoxLayoutDataI.H:942
double Real
Definition: REAL.H:33
void addTo(const Interval &a_srcComps, BoxLayoutData< T > &a_dest, const Interval &a_destComps, const ProblemDomain &a_domain) const
Definition: BoxLayoutDataI.H:919
virtual void define(const DisjointBoxLayout &dp, int comps, const IntVect &ghost=IntVect::Zero, const DataFactory< T > &a_factory=DefaultDataFactory< T >())
Definition: LevelDataI.H:70
void unpackReceivesToMe(BoxLayoutData< T > &a_dest, const Interval &a_destComps, const LDOperator< T > &a_op) const
Definition: BoxLayoutDataI.H:366
virtual void linearIn(T &arg, void *buf, const Box &R, const Interval &comps) const
Definition: BoxLayoutData.H:156
void makeItSoLocalCopy(const Interval &a_srcComps, const BoxLayoutData< T > &a_src, BoxLayoutData< T > &a_dest, const Interval &a_destComps, const Copier &a_copier, const LDOperator< T > &a_op=LDOperator< T >()) const
Definition: BoxLayoutDataI.H:290
Box toRegion
Definition: Copier.H:35
bool isClosed() const
Definition: BoxLayout.H:696
static void Error(const char *const a_msg=m_nullString, int m_exitCode=CH_DEFAULT_ERROR_CODE)
Print out message to cerr and exit with the specified exit code.
int begin() const
Definition: Interval.H:86
const BoxLayout & boxLayout() const
Definition: LayoutData.H:108
static const IntVect Zero
Definition: IntVect.H:627
void postSendsFromMe() const
Definition: BoxLayoutDataI.H:356
AliasDataFactory(BoxLayoutData< T > *a_original, const Interval &interval)
Definition: BoxLayoutDataI.H:214
A Rectangular Domain on an Integer Lattice.
Definition: Box.H:465
Definition: DataIndex.H:112
bool ok() const
Definition: Copier.H:391
bool m_isdefined
Definition: BoxLayoutData.H:342
An integer Vector in SpaceDim-dimensional space.
Definition: CHArray.H:42
DataIterator dataIterator() const
Definition: LayoutDataI.H:79
virtual T * create(const Box &box, int ncomps, const DataIndex &a_datInd) const =0
factory function. creates a new 'T' object
size_t size() const
Definition: Vector.H:177
Definition: Copier.H:340
Factory object to data members of a BoxLayoutData container.
Definition: BoxLayoutData.H:30
void makeItSoBegin(const Interval &a_srcComps, const BoxLayoutData< T > &a_src, BoxLayoutData< T > &a_dest, const Interval &a_destComps, const Copier &a_copier, const LDOperator< T > &a_op=LDOperator< T >()) const
Definition: BoxLayoutDataI.H:249
virtual T * create(const Box &box, int ncomps, const DataIndex &a_datInd) const
Definition: BoxLayoutDataI.H:227
Box & grow(int i)
grow functions
Definition: Box.H:2268
virtual bool ok() const
return true if this iterator is still in its Layout
Definition: LayoutIterator.H:110
Definition: BoxLayoutData.H:139
int end() const
Definition: Interval.H:91
virtual void define(const DisjointBoxLayout &a_level, const BoxLayout &a_dest, bool a_exchange=false, IntVect a_shift=IntVect::Zero)
Definition: BoxLayoutDataI.H:930
DataIndex fromIndex
Definition: Copier.H:33
Box box(const DataIndex &a_index) const
Definition: LayoutDataI.H:67
Box fromRegion
Definition: Copier.H:34
std::vector< bufEntry > m_toMe
Definition: Copier.H:107
Definition: Copier.H:335
void makeItSo(const Interval &a_srcComps, const BoxLayoutData< T > &a_src, BoxLayoutData< T > &a_dest, const Interval &a_destComps, const Copier &a_copier, const LDOperator< T > &a_op=LDOperator< T >()) const
Definition: BoxLayoutDataI.H:236
BoxLayoutData()
Definition: BoxLayoutDataI.H:101
virtual void op(T &dest, const Box &RegionFrom, const Interval &Cdest, const Box &RegionTo, const T &src, const Interval &Csrc) const
Definition: BoxLayoutDataI.H:933
void allocateBuffers(const BoxLayoutData< T > &a_src, const Interval &a_srcComps, const BoxLayoutData< T > &a_dest, const Interval &a_destComps, const Copier &a_copier, const LDOperator< T > &a_op) const
Definition: BoxLayoutDataI.H:338