OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
BareField.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  * This program was prepared by PSI.
7  * All rights in the program are reserved by PSI.
8  * Neither PSI nor the author(s)
9  * makes any warranty, express or implied, or assumes any liability or
10  * responsibility for the use of this software
11  *
12  * Visit www.amas.web.psi for more details
13  *
14  ***************************************************************************/
15 
16 // -*- C++ -*-
17 /***************************************************************************
18  *
19  * The IPPL Framework
20  *
21  *
22  * Visit http://people.web.psi.ch/adelmann/ for more details
23  *
24  ***************************************************************************/
25 
26 // include files
27 #include "Field/BareField.h"
28 #include "Field/BrickExpression.h"
30 #include "Message/Communicate.h"
31 #include "Message/GlobalComm.h"
32 #include "Message/Tags.h"
33 #include "Utility/Inform.h"
34 #include "Utility/Unique.h"
35 #include "Utility/IpplInfo.h"
36 //#include "Utility/IpplStats.h"
37 
38 #include <map>
39 #include <cstdlib>
40 
41 
43 //
44 // Copy ctor.
45 //
46 
47 template< class T, unsigned Dim >
49 : Layout( a.Layout ), // Copy the layout.
50  Gc( a.Gc ), // Copy the number of guard cells.
51  compressible_m( a.compressible_m ),
52  pinned(false) //UL: for pinned memory allocation
53 {
54 
55 
56 
57  // We assume the guard cells are peachy so clear the dirty flag.
59 
60  // Reserve space for the pointers to the LFields.
61  Locals_ac.reserve( a.size_if() );
62  // Loop over the LFields of the other array, creating LFields as we go.
63  for ( const_iterator_if a_i = a.begin_if(); a_i != a.end_if(); ++a_i )
64  {
65  // Create an LField with copy ctor.
66  LField<T,Dim> *lf = new LField<T,Dim>( *((*a_i).second) );
67  // Insert in the local list, hinting that it should go at the end.
69  typename ac_id_larray::value_type((*a_i).first,lf) );
70  }
71  // Tell the layout we are here.
72  getLayout().checkin( *this , Gc );
73  //INCIPPLSTAT(incBareFields);
74 }
75 
76 
78 //
79 // Destructor
80 //
81 
82 template< class T, unsigned Dim >
84 
85 
86  // must check out from our layout
87  if (Layout != 0) {
88  Layout->checkout(*this);
89  }
90 }
91 
92 
94 // Initialize the field, if it was constructed from the default constructor.
95 // This should NOT be called if the field was constructed by providing
96 // a FieldLayout.
97 
98 template< class T, unsigned Dim >
99 void
101 
102 
103 
104  // if our Layout has been previously set, we just ignore this request
105  if (Layout == 0) {
106  Layout = &l;
107  setup();
108  }
109 }
110 
111 //UL: for pinned memory allocation
112 template< class T, unsigned Dim >
113 void
115 
116 
117 
118  // if our Layout has been previously set, we just ignore this request
119  if (Layout == 0) {
120  Layout = &l;
121  pinned = p;
122  setup();
123  }
124 }
125 
126 template< class T, unsigned Dim >
127 void
129  const GuardCellSizes<Dim>& gc) {
130 
131 
132 
133  // if our Layout has been previously set, we just ignore this request
134  if (Layout == 0) {
135  Layout = &l;
136  Gc = gc;
137  setup();
138  }
139 }
140 
141 
143 //
144 // Using the data that has been initialized by the ctors,
145 // complete the construction by allocating the LFields.
146 //
147 
148 template< class T, unsigned Dim >
149 void
151 {
152 
153 
154 
155  // Make sure this FieldLayout can handle the number of GuardCells
156  // which we have here
157  if ( ! getLayout().fitsGuardCells(Gc)) {
158  ERRORMSG("Cannot construct IPPL BareField:" << endl);
159  ERRORMSG(" One or more vnodes is too small for the guard cells." << endl);
160  ERRORMSG(" Guard cell sizes = " << Gc << endl);
161  ERRORMSG(" FieldLayout = " << getLayout() << endl);
162  Ippl::abort();
163  }
164 
165  // We assume the guard cells are peachy so clear the dirty flag.
166  clearDirtyFlag();
167 
168  // Reserve space for the pointers to the LFields.
169  Locals_ac.reserve( getLayout().size_iv() );
170 
171  // Loop over all the Vnodes, creating an LField in each.
172  for (typename Layout_t::iterator_iv v_i=getLayout().begin_iv();
173  v_i != getLayout().end_iv();
174  ++v_i)
175  {
176  // Get the owned and guarded sizes.
177  const NDIndex<Dim> &owned = (*v_i).second->getDomain();
178  NDIndex<Dim> guarded = AddGuardCells( owned , Gc );
179 
180  // Get the global vnode number (ID number, value from 0 to nvnodes-1):
181  int vnode = (*v_i).second->getVnode();
182 
183  // Construct the LField for this Vnode.
184  //UL: for pinned memory allocation
185  LField<T, Dim> *lf;
186  if (pinned)
187  lf = new LField<T,Dim>( owned, guarded, vnode, pinned );
188  else
189  lf = new LField<T,Dim>( owned, guarded, vnode );
190 
191  // Put it in the list.
192  Locals_ac.insert( end_if(),
193  typename ac_id_larray::value_type((*v_i).first,lf));
194  }
195  // Tell the layout we are here.
196  getLayout().checkin( *this , Gc );
197  //INCIPPLSTAT(incBareFields);
198 }
199 
201 
202 //
203 // Print a BareField out.
204 //
205 
206 template< class T, unsigned Dim>
207 void
208 BareField<T,Dim>::write(std::ostream& out)
209 {
210 
211 
212 
213  // Inform dbgmsg(">>>>>>>> BareField::write", INFORM_ALL_NODES);
214  // dbgmsg << "Printing values for field at address = " << &(*this) << endl;
215 
216  // on remote nodes, we must send the subnodes LField's to node 0
218  if (Ippl::myNode() != 0) {
219  for ( iterator_if local = begin_if(); local != end_if() ; ++local) {
220  // Cache some information about this local field.
221  LField<T,Dim>& l = *((*local).second);
222  NDIndex<Dim>& lo = (NDIndex<Dim>&) l.getOwned();
223  typename LField<T,Dim>::iterator rhs(l.begin());
224 
225  // Build and send a message containing the owned LocalField data
226  if (Ippl::myNode() != 0) {
227  Message *mess = new Message();
228  lo.putMessage(*mess); // send the local domain of the LField
229  rhs.putMessage(*mess); // send the data itself
230  // dbgmsg << "Sending domain " << lo << " to node 0" << endl;
231  Ippl::Comm->send(mess, 0, tag);
232  }
233  }
234  } else { // now, on node 0, receive the remaining LField's ...
235  // put all the LField's in a big, uncompressed LField
236  LField<T,Dim> data(getDomain(), getDomain());
237  data.Uncompress();
238 
239  // first put in our local ones
240  for ( iterator_if local = begin_if(); local != end_if() ; ++local) {
241  // Cache some information about this local field.
242  LField<T,Dim>& l = *((*local).second);
243  NDIndex<Dim>& lo = (NDIndex<Dim>&) l.getOwned();
244  typename LField<T,Dim>::iterator rhs(l.begin());
245 
246  // put the local LField in our big LField
247  // dbgmsg << " Copying local domain " << lo << " from Lfield at ";
248  // dbgmsg << &l << ":" << endl;
249  typename LField<T,Dim>::iterator putloc = data.begin(lo);
250  typename LField<T,Dim>::iterator getloc = l.begin(lo);
251  for ( ; getloc != l.end() ; ++putloc, ++getloc ) {
252  // dbgmsg << " from " << &(*getloc) << " to " << &(*putloc);
253  // dbgmsg << ": " << *putloc << " = " << *getloc << endl;
254  *putloc = *getloc;
255  }
256  }
257 
258  // we expect to receive one message from each remote vnode
259  int remaining = getLayout().size_rdv();
260 
261  // keep receiving messages until they're all here
262  for ( ; remaining > 0; --remaining) {
263  // Receive the generic message.
264  int any_node = COMM_ANY_NODE;
265  Message *mess = Ippl::Comm->receive_block(any_node, tag);
266 
267  // Extract the domain size and LField iterator from the message
268  NDIndex<Dim> lo;
269  T compressed_data;
270  typename LField<T,Dim>::iterator rhs(compressed_data);
271  lo.getMessage(*mess);
272  rhs.getMessage(*mess);
273  // dbgmsg << "Received domain " << lo << " from " << any_node << endl;
274 
275  // put the received LField in our big LField
276  typename LField<T,Dim>::iterator putloc = data.begin(lo);
277  for (unsigned elems=lo.size(); elems > 0; ++putloc, ++rhs, --elems)
278  *putloc = *rhs;
279 
280  // Free the memory in the message.
281  delete mess;
282  }
283 
284  // finally, we can print the big LField out
285  out << data;
286  }
287 }
288 
289 
291 
292 //
293 // Fill all the guard cells, including all the necessary communication.
294 //
295 
296 template< class T, unsigned Dim >
297 void BareField<T,Dim>::fillGuardCells(bool reallyFill) const
298 {
299 
300  // This operation is logically const because the physical cells
301  // of the BareField are unaffected, so cast away const here.
302  BareField<T,Dim>& ncf = const_cast<BareField<T,Dim>&>(*this);
303 
304  // Only fill if we are supposed to.
305  if (!reallyFill)
306  return;
307 
308  // Make ourselves clean.
310 
311  // Only need to do work if we have non-zero GuardCellSizes
312  if (Gc == GuardCellSizes<Dim>())
313  return;
314 
315  // indicate we're doing another gc fill
316  //INCIPPLSTAT(incGuardCellFills);
317 
318  // iterators for looping through LField's of this BareField
319  iterator_if lf_i, lf_e = ncf.end_if();
320 
321  // ----------------------------------------
322  // First the send loop.
323  // Loop over all the local nodes and
324  // send data to the remote ones they overlap.
325  int nprocs = Ippl::getNodes();
326  if (nprocs > 1) {
327 
328  // Build a map of the messages we expect to receive.
329  typedef std::multimap< NDIndex<Dim> , LField<T,Dim>* , std::less<NDIndex<Dim> > > ac_recv_type;
330  ac_recv_type recv_ac;
331  bool* recvmsg = new bool[nprocs];
332 
333 
334 
335  // set up messages to be sent
336  Message** mess = new Message*[nprocs];
337  int iproc;
338  for (iproc=0; iproc<nprocs; ++iproc) {
339  mess[iproc] = NULL;
340  recvmsg[iproc] = false;
341  }
342 
343  // now do main loop over LFields, packing overlaps into proper messages
344  for (lf_i = ncf.begin_if(); lf_i != lf_e; ++lf_i) {
345 
346  // Cache some information about this local array.
347  LField<T,Dim> &lf = *((*lf_i).second);
348  const NDIndex<Dim> &lf_domain = lf.getAllocated();
349  // Find the remote ones that touch this LField's guard cells
350  typename Layout_t::touch_range_dv
351  rrange(ncf.getLayout().touch_range_rdv(lf_domain));
352  typename Layout_t::touch_iterator_dv rv_i;
353  for (rv_i = rrange.first; rv_i != rrange.second; ++rv_i) {
354  // Save the intersection and the LField it is for.
355  NDIndex<Dim> sub = lf_domain.intersect( (*rv_i).first );
356  typedef typename ac_recv_type::value_type value_type;
357  recv_ac.insert(value_type(sub,&lf));
358  // note who will be sending this data
359  int rnode = (*rv_i).second->getNode();
360  recvmsg[rnode] = true;
361  }
362 
363 
364 
365  const NDIndex<Dim>& lo = lf.getOwned();
366  // Loop over the remote domains which have guard cells
367  // that this local domain touches.
368  typename Layout_t::touch_range_dv
369  range( ncf.getLayout().touch_range_rdv(lo,ncf.getGC()) );
370  typename Layout_t::touch_iterator_dv remote_i;
371  for (remote_i = range.first; remote_i != range.second; ++remote_i) {
372  // Find the intersection.
373  NDIndex<Dim> intersection = lo.intersect( (*remote_i).first );
374  // Find out who owns this remote domain.
375  int rnode = (*remote_i).second->getNode();
376  // Create an LField iterator for this intersection region,
377  // and try to compress it.
378  // storage for LField compression
379  T compressed_value;
380  LFI msgval = lf.begin(intersection, compressed_value);
381  msgval.TryCompress();
382 
383  // Put intersection domain and field data into message
384  if (!mess[rnode]) mess[rnode] = new Message;
385  PAssert(mess[rnode]);
386  mess[rnode]->put(intersection); // puts Dim items in Message
387  mess[rnode]->put(msgval); // puts 3 items in Message
388  }
389 
390  }
391 
392  int remaining = 0;
393  for (iproc=0; iproc<nprocs; ++iproc)
394  if (recvmsg[iproc]) ++remaining;
395  delete [] recvmsg;
396 
397 
398 
399  // Get message tag.
401 
402  // Send all the messages.
403  for (iproc=0; iproc<nprocs; ++iproc) {
404  if (mess[iproc]) {
405  Ippl::Comm->send(mess[iproc], iproc, tag);
406  }
407  }
408 
409  delete [] mess;
410 
411  // ----------------------------------------
412  // Handle the local fills.
413  // Loop over all the local arrays.
414 
415  for (lf_i = ncf.begin_if(); lf_i != lf_e; ++lf_i)
416  {
417  // Cache some information about this LField.
418  LField<T,Dim> &lf = *(*lf_i).second;
419  const NDIndex<Dim>& la = lf.getAllocated();
420 
421  // Loop over all the other LFields to establish each LField's
422  // cache of overlaps.
423 
424  // This is an N*N operation, but the expectation is that this will
425  // pay off since we will reuse this cache quite often.
426 
427  if (!lf.OverlapCacheInitialized())
428  {
429  for (iterator_if rf_i = ncf.begin_if(); rf_i != ncf.end_if(); ++rf_i)
430  if ( rf_i != lf_i )
431  {
432  // Cache some info about this LField.
433  LField<T,Dim> &rf = *(*rf_i).second;
434  const NDIndex<Dim>& ro = rf.getOwned();
435 
436  // If the remote has info we want, then add it to our cache.
437  if ( la.touches(ro) )
438  lf.AddToOverlapCache(&rf);
439  }
440  }
441 
442  // We know at this point that the overlap cache is established.
443  // Use it.
444 
445  for (typename LField<T,Dim>::OverlapIterator rf_i = lf.BeginOverlap();
446  rf_i != lf.EndOverlap(); ++rf_i)
447  {
448  LField<T, Dim> &rf = *(*rf_i);
449  const NDIndex<Dim>& ro = rf.getOwned();
450 
451  bool c1 = lf.IsCompressed();
452  bool c2 = rf.IsCompressed();
453  bool c3 = *rf.begin() == *lf.begin();
454 
455  // If these are compressed we might not have to do any work.
456  if ( !( c1 && c2 && c3 ) )
457  {
458 
459 
460  // Find the intersection.
461  NDIndex<Dim> intersection = la.intersect(ro);
462 
463  // Build an iterator for the rhs.
464  LFI rhs = rf.begin(intersection);
465 
466  // Could we compress that?
467  if ( !(c1 && rhs.CanCompress(*lf.begin())) )
468  {
469  // Make sure the left is not compressed.
470  lf.Uncompress();
471 
472  // Nope, we really have to copy.
473  LFI lhs = lf.begin(intersection);
474  // And do the assignment.
476  }
477 
478 
479  }
480  }
481  }
482 
483 
484  // ----------------------------------------
485  // Receive all the messages.
486 
487  while (remaining>0) {
488  // Receive the next message.
489  int any_node = COMM_ANY_NODE;
490 
491  Message* rmess = Ippl::Comm->receive_block(any_node,tag);
492  PAssert(rmess);
493  --remaining;
494 
495 
496  // Determine the number of domains being sent
497  int ndoms = rmess->size() / (Dim + 3);
498  for (int idom=0; idom<ndoms; ++idom) {
499  // Extract the intersection domain from the message.
500  NDIndex<Dim> intersection;
501  intersection.getMessage(*rmess);
502 
503  // Extract the rhs iterator from it.
504  T compressed_value;
505  LFI rhs(compressed_value);
506  rhs.getMessage(*rmess);
507 
508  // Find the LField it is destined for.
509  typename ac_recv_type::iterator hit = recv_ac.find( intersection );
510  PAssert( hit != recv_ac.end() );
511  // Build the lhs brick iterator.
512  LField<T,Dim> &lf = *(*hit).second;
513  // Check and see if we really have to do this.
514  if ( !(rhs.IsCompressed() && lf.IsCompressed() &&
515  (*rhs == *lf.begin())) )
516  {
517  // Yep. gotta do it.
518  lf.Uncompress();
519  LFI lhs = lf.begin(intersection);
520  // Do the assignment.
522  }
523 
524  // Take that entry out of the receive list.
525  recv_ac.erase( hit );
526  }
527  delete rmess;
528  }
529 
530  }
531  else { // single-node case
532  // ----------------------------------------
533  // Handle the local fills.
534  // Loop over all the local arrays.
535 
536  for (lf_i = ncf.begin_if(); lf_i != lf_e; ++lf_i)
537  {
538  // Cache some information about this LField.
539  LField<T,Dim> &lf = *(*lf_i).second;
540  const NDIndex<Dim>& la = lf.getAllocated();
541 
542  // Loop over all the other LFields to establish each LField's
543  // cache of overlaps.
544 
545  // This is an N*N operation, but the expectation is that this will
546  // pay off since we will reuse this cache quite often.
547 
548  if (!lf.OverlapCacheInitialized())
549  {
550  for (iterator_if rf_i = ncf.begin_if(); rf_i != ncf.end_if(); ++rf_i)
551  if ( rf_i != lf_i )
552  {
553  // Cache some info about this LField.
554  LField<T,Dim> &rf = *(*rf_i).second;
555  const NDIndex<Dim>& ro = rf.getOwned();
556 
557  // If the remote has info we want, then add it to our cache.
558  if ( la.touches(ro) )
559  lf.AddToOverlapCache(&rf);
560  }
561  }
562 
563  // We know at this point that the overlap cache is established.
564  // Use it.
565 
566  for (typename LField<T,Dim>::OverlapIterator rf_i = lf.BeginOverlap();
567  rf_i != lf.EndOverlap(); ++rf_i)
568  {
569  LField<T, Dim> &rf = *(*rf_i);
570  const NDIndex<Dim>& ro = rf.getOwned();
571 
572  bool c1 = lf.IsCompressed();
573  bool c2 = rf.IsCompressed();
574  bool c3 = *rf.begin() == *lf.begin();
575 
576  // If these are compressed we might not have to do any work.
577  if ( !( c1 && c2 && c3 ) )
578  {
579 
580 
581  // Find the intersection.
582  NDIndex<Dim> intersection = la.intersect(ro);
583 
584  // Build an iterator for the rhs.
585  LFI rhs = rf.begin(intersection);
586 
587  // Could we compress that?
588  if ( !(c1 && rhs.CanCompress(*lf.begin())) )
589  {
590  // Make sure the left is not compressed.
591  lf.Uncompress();
592 
593  // Nope, we really have to copy.
594  LFI lhs = lf.begin(intersection);
595  // And do the assignment.
597  }
598 
599 
600  }
601  }
602  }
603 
604  }
605  return;
606 }
607 
609 
610 //
611 // Fill guard cells with a constant value.
612 // This is typically used to zero out the guard cells before a scatter.
613 //
614 
615 template <class T, unsigned Dim>
616 void BareField<T,Dim>::setGuardCells(const T& val) const
617 {
618  // profiling macros
619 
620 
621 
622  // if there are no guard cells, we can just return
623  if (Gc == GuardCellSizes<Dim>())
624  return;
625 
626  // this member function is logically const, so cast away const-ness
627  BareField<T,Dim>& ncf = const_cast<BareField<T,Dim>&>(*this);
628 
629  // loop over our LFields and set guard cell values
630  iterator_if lf_i, lf_e = ncf.end_if();
631  for (lf_i = ncf.begin_if(); lf_i != lf_e; ++lf_i) {
632  // Get this LField
633  LField<T,Dim>& lf = *((*lf_i).second);
634 
635  // Quick test to see if we can avoid doing any work.
636  // If this LField is compressed and already contains
637  // the value that is being assigned to the guard cells,
638  // then we can just move on to the next LField.
639  if (lf.IsCompressed() && lf.getCompressedData() == val)
640  continue;
641 
642  // OK, we really have to fill the guard cells, so get
643  // the domains we will be working with.
644  const NDIndex<Dim>& adom = lf.getAllocated();
645  const NDIndex<Dim>& odom = lf.getOwned();
646  NDIndex<Dim> dom = odom; // initialize working domain to Owned
647 
648  // create a compressed LField with the same allocated domain
649  // containing the value to be assigned to the guard cells
650  LField<T,Dim> rf(odom,adom);
651  rf.Compress(val);
652 
653  // Uncompress LField to be filled and get some iterators
654  lf.Uncompress();
655  LFI lhs, rhs;
656 
657  // now loop over dimensions and fill guard cells along each
658  for (unsigned int idim = 0; idim < Dim; ++idim) {
659  // set working domain to left guards in this dimension
660  dom[idim] = Index(adom[idim].first(),
661  adom[idim].first() + Gc.left(idim) - 1);
662  if (!dom[idim].empty()) {
663  // Set iterators over working domain and do assignment
664  lhs = lf.begin(dom);
665  rhs = rf.begin(dom);
667  }
668 
669  // Set working domain to right guards in this dimension
670  dom[idim] = Index(adom[idim].last() - Gc.right(idim) + 1,
671  adom[idim].last());
672  if (!dom[idim].empty()) {
673  // Set iterators over working domain and do assignment
674  lhs = lf.begin(dom);
675  rhs = rf.begin(dom);
677  }
678 
679  // Adjust working domain along this direction
680  // in preparation for working on next dimension.
681  dom[idim] = adom[idim];
682  }
683  }
684 
685  // let's set the dirty flag, since we have modified guard cells.
686  ncf.setDirtyFlag();
687 
688  return;
689 }
690 
692 
693 //
694 // Accumulate guard cells into real cells, including necessary communication.
695 //
696 
697 template <class T, unsigned Dim>
699 {
700 
701  // Only need to do work if we have non-zero GuardCellSizes
702  if (Gc == GuardCellSizes<Dim>())
703  return;
704 
705  // iterators for looping through LField's of this BareField
706  iterator_if lf_i, lf_e = end_if();
707 
708  // ----------------------------------------
709  // First the send loop.
710  // Loop over all the local nodes and
711  // send data to the remote ones they overlap.
712  int nprocs = Ippl::getNodes();
713  if (nprocs > 1) {
714 
715  // Build a map of the messages we expect to receive.
716  typedef std::multimap< NDIndex<Dim> , LField<T,Dim>* , std::less<NDIndex<Dim> > > ac_recv_type;
717  ac_recv_type recv_ac;
718  bool* recvmsg = new bool[nprocs];
719 
720 
721 
722  // set up messages to be sent
723  Message** mess = new Message*[nprocs];
724  int iproc;
725  for (iproc=0; iproc<nprocs; ++iproc) {
726  mess[iproc] = NULL;
727  recvmsg[iproc] = false;
728  }
729 
730  // now do main loop over LFields, packing overlaps into proper messages
731  for (lf_i = begin_if(); lf_i != lf_e; ++lf_i) {
732 
733  // Cache some information about this local array.
734  LField<T,Dim> &lf = *((*lf_i).second);
735  const NDIndex<Dim>& lo = lf.getOwned();
736  // Find the remote ones with guard cells touching this LField
737  typename Layout_t::touch_range_dv
738  rrange( getLayout().touch_range_rdv(lo,Gc) );
739  typename Layout_t::touch_iterator_dv rv_i;
740  for (rv_i = rrange.first; rv_i != rrange.second; ++rv_i) {
741  // Save the intersection and the LField it is for.
742  NDIndex<Dim> sub = lo.intersect( (*rv_i).first );
743  recv_ac.insert(typename ac_recv_type::value_type(sub,&lf));
744  // note who will be sending this data
745  int rnode = (*rv_i).second->getNode();
746  recvmsg[rnode] = true;
747  }
748 
749 
750 
751  const NDIndex<Dim> &lf_domain = lf.getAllocated();
752  // Loop over the remote domains that touch this local
753  // domain's guard cells
754  typename Layout_t::touch_range_dv
755  range(getLayout().touch_range_rdv(lf_domain));
756  typename Layout_t::touch_iterator_dv remote_i;
757  for (remote_i = range.first; remote_i != range.second; ++remote_i) {
758  // Find the intersection.
759  NDIndex<Dim> intersection = lf_domain.intersect( (*remote_i).first );
760  // Find out who owns this remote domain.
761  int rnode = (*remote_i).second->getNode();
762  // Create an LField iterator for this intersection region,
763  // and try to compress it.
764  // storage for LField compression
765  T compressed_value;
766  LFI msgval = lf.begin(intersection, compressed_value);
767  msgval.TryCompress();
768 
769  // Put intersection domain and field data into message
770  if (!mess[rnode]) mess[rnode] = new Message;
771  PAssert(mess[rnode]);
772  mess[rnode]->put(intersection); // puts Dim items in Message
773  mess[rnode]->put(msgval); // puts 3 items in Message
774  }
775 
776  }
777 
778  int remaining = 0;
779  for (iproc=0; iproc<nprocs; ++iproc)
780  if (recvmsg[iproc]) ++remaining;
781  delete [] recvmsg;
782 
783 
784 
785  // Get message tag.
787 
788  // Send all the messages.
789  for (iproc=0; iproc<nprocs; ++iproc) {
790  if (mess[iproc]) {
791  Ippl::Comm->send(mess[iproc], iproc, tag);
792  }
793  }
794 
795  delete [] mess;
796 
797  // ----------------------------------------
798  // Handle the local fills.
799  // Loop over all the local arrays.
800 
801  for (lf_i=begin_if(); lf_i != lf_e; ++lf_i)
802  {
803  // Cache some information about this LField.
804  LField<T,Dim> &lf = *(*lf_i).second;
805  const NDIndex<Dim>& la = lf.getAllocated();
806 
807  // Loop over all the other LFields to establish each LField's
808  // cache of overlaps.
809 
810  // This is an N*N operation, but the expectation is that this will
811  // pay off since we will reuse this cache quite often.
812 
813  if (!lf.OverlapCacheInitialized())
814  {
815  for (iterator_if rf_i = begin_if(); rf_i != end_if(); ++rf_i)
816  if ( rf_i != lf_i )
817  {
818  // Cache some info about this LField.
819  LField<T,Dim> &rf = *(*rf_i).second;
820  const NDIndex<Dim>& ro = rf.getOwned();
821 
822  // If the remote has info we want, then add it to our cache.
823  if ( la.touches(ro) )
824  lf.AddToOverlapCache(&rf);
825  }
826  }
827 
828  // We know at this point that the overlap cache is established.
829  // Use it.
830 
831  for (typename LField<T,Dim>::OverlapIterator rf_i = lf.BeginOverlap();
832  rf_i != lf.EndOverlap(); ++rf_i)
833  {
834  LField<T, Dim> &rf = *(*rf_i);
835  const NDIndex<Dim>& ro = rf.getOwned();
836 
837 
838 
839  // Find the intersection.
840  NDIndex<Dim> intersection = la.intersect(ro);
841 
842  // Build iterator for lf guard cells
843  LFI lhs = lf.begin(intersection);
844 
845  // check if we can skip accumulation
846  if ( !lhs.CanCompress(T()) ) {
847 
848  // Make sure the right side is not compressed.
849  rf.Uncompress();
850 
851  // Build iterator for rf real cells
852  LFI rhs = rf.begin(intersection);
853 
854  // And do the accumulation
856  }
857 
858  }
859  }
860 
861 
862  // ----------------------------------------
863  // Receive all the messages.
864 
865  while (remaining>0) {
866  // Receive the next message.
867  int any_node = COMM_ANY_NODE;
868 
869  Message* rmess = Ippl::Comm->receive_block(any_node,tag);
870  PAssert(rmess);
871  --remaining;
872 
873 
874  // Determine the number of domains being sent
875  int ndoms = rmess->size() / (Dim + 3);
876  for (int idom=0; idom<ndoms; ++idom) {
877  // Extract the intersection domain from the message.
878  NDIndex<Dim> intersection;
879  intersection.getMessage(*rmess);
880 
881  // Extract the rhs iterator from it.
882  T compressed_value;
883  LFI rhs(compressed_value);
884  rhs.getMessage(*rmess);
885 
886  // Find the LField it is destined for.
887  typename ac_recv_type::iterator hit = recv_ac.find( intersection );
888  PAssert( hit != recv_ac.end() );
889 
890  // Build the lhs brick iterator.
891  LField<T,Dim> &lf = *(*hit).second;
892 
893  // Make sure LField is uncompressed
894  lf.Uncompress();
895  LFI lhs = lf.begin(intersection);
896 
897  // Do the accumulation
899 
900  // Take that entry out of the receive list.
901  recv_ac.erase( hit );
902  }
903  delete rmess;
904  }
905 
906  }
907  else { // single-node case
908  // ----------------------------------------
909  // Handle the local fills.
910  // Loop over all the local arrays.
911 
912  for (lf_i=begin_if(); lf_i != lf_e; ++lf_i)
913  {
914  // Cache some information about this LField.
915  LField<T,Dim> &lf = *(*lf_i).second;
916  const NDIndex<Dim>& la = lf.getAllocated();
917 
918  // Loop over all the other LFields to establish each LField's
919  // cache of overlaps.
920 
921  // This is an N*N operation, but the expectation is that this will
922  // pay off since we will reuse this cache quite often.
923 
924  if (!lf.OverlapCacheInitialized())
925  {
926  for (iterator_if rf_i = begin_if(); rf_i != end_if(); ++rf_i)
927  if ( rf_i != lf_i )
928  {
929  // Cache some info about this LField.
930  LField<T,Dim> &rf = *(*rf_i).second;
931  const NDIndex<Dim>& ro = rf.getOwned();
932 
933  // If the remote has info we want, then add it to our cache.
934  if ( la.touches(ro) )
935  lf.AddToOverlapCache(&rf);
936  }
937  }
938 
939  // We know at this point that the overlap cache is established.
940  // Use it.
941 
942  for (typename LField<T,Dim>::OverlapIterator rf_i = lf.BeginOverlap();
943  rf_i != lf.EndOverlap(); ++rf_i)
944  {
945  LField<T, Dim> &rf = *(*rf_i);
946  const NDIndex<Dim>& ro = rf.getOwned();
947 
948 
949 
950  // Find the intersection.
951  NDIndex<Dim> intersection = la.intersect(ro);
952 
953  // Build iterator for lf guard cells
954  LFI lhs = lf.begin(intersection);
955 
956  // Check if we can skip accumulation
957  if ( !lhs.CanCompress(T()) ) {
958  // Make sure rf is not compressed.
959  rf.Uncompress();
960 
961  // Build iterator for rf real cells
962  LFI rhs = rf.begin(intersection);
963 
964  // And do the accumulation
966  }
967 
968  }
969  }
970 
971  }
972 
973  // since we just modified real cell values, set dirty flag if using
974  // deferred guard cell fills
975  setDirtyFlag();
976  // fill guard cells now, unless we are deferring
977  fillGuardCellsIfNotDirty();
978  // try to compress the final result
979  Compress();
980 
981  return;
982 }
983 
985 
986 //
987 // Tell a BareField to compress itself.
988 // Just loop over all of the local fields and tell them to compress.
989 //
990 template<class T, unsigned Dim>
992 {
993 
994 
995 
996  if (!compressible_m) return;
997 
998  // This operation is logically const, so cast away const here
999  BareField<T,Dim>& ncf = const_cast<BareField<T,Dim>&>(*this);
1000  for (iterator_if lf_i = ncf.begin_if(); lf_i != ncf.end_if(); ++lf_i)
1001  (*lf_i).second->TryCompress(isDirty());
1002 }
1003 
1004 template<class T, unsigned Dim>
1006 {
1007 
1008 
1009 
1010  // This operation is logically const, so cast away const here
1011  BareField<T,Dim>& ncf = const_cast<BareField<T,Dim>&>(*this);
1012  for (iterator_if lf_i = ncf.begin_if(); lf_i != ncf.end_if(); ++lf_i)
1013  (*lf_i).second->Uncompress();
1014 }
1015 
1016 //
1017 // Look at all the local fields and calculate the
1018 // fraction of all the elements that are compressed.
1019 //
1020 template<class T, unsigned Dim>
1022 {
1023 
1024 
1025 
1026  // elements[0] = total elements
1027  // elements[1] = compressed elements
1028  double elements[2] = { 0.0, 0.0};
1029  // Loop over all of the local fields.
1030  for (const_iterator_if lf_i=begin_if(); lf_i != end_if(); ++lf_i)
1031  {
1032  // Get a reference to the current local field.
1033  LField<T,Dim> &lf = *(*lf_i).second;
1034  // Get the size of this one.
1035  double s = lf.getOwned().size();
1036  // Add that up.
1037  elements[0] += s;
1038  // If it is compressed...
1039  if ( lf.IsCompressed() )
1040  // Add that amount to the compressed total.
1041  elements[1] += s;
1042  }
1043  // Make some space to put the global sum of each of the above.
1044  double reduced_elements[2] = { 0.0, 0.0};
1045  // Do the global reduction.
1046  reduce(elements,elements+2,reduced_elements,OpAddAssign());
1047  // Return the fraction.
1048  return reduced_elements[1]/reduced_elements[0];
1049 }
1050 
1051 
1053 template<class T, unsigned Dim>
1055 {
1056 
1057 
1058 
1059  // Cast to the proper type of FieldLayout.
1060  Layout_t *newLayout = (Layout_t *)( userlist );
1061 
1062  // Build a new temporary field on the new layout.
1063  BareField<T,Dim> tempField( *newLayout, Gc );
1064 
1065  // Copy our data over to the new layout.
1066  tempField = *this;
1067 
1068  // Copy back the pointers to the new local fields.
1069  Locals_ac = tempField.Locals_ac;
1070 
1071  //INCIPPLSTAT(incRepartitions);
1072 }
1073 
1074 
1076 // Tell the subclass that the FieldLayout is being deleted, so
1077 // don't use it anymore
1078 template<class T, unsigned Dim>
1080 {
1081 
1082 
1083 
1084  // just set our layout pointer to NULL; if we try to do anything more
1085  // with this object, other than delete it, a core dump is likely
1086  if (Layout != 0 && Layout->get_Id() == userlist->getUserListID()) {
1087  // the ID refers to this layout, so get rid of it. It is possible
1088  // the ID refers to some other object, in which case we do not want
1089  // to cast away our Layout object.
1090  Layout = 0;
1091  } else {
1092  // for now, print a warning, until other types of FieldLayoutUser's
1093  // are set up to register with a FieldLayout ... but in general,
1094  // this is OK and this warning should be removed
1095  WARNMSG("BareField: notified of unknown UserList being deleted.");
1096  WARNMSG(endl);
1097  }
1098 }
1099 
1100 // a simple true-false template used to select which loop to implement
1101 // in the BareField::localElement body
1102 template<unsigned Dim, bool exists>
1104 };
1105 
1106 // 1, 2, 3, and N Dimensional functions
1107 template <class T>
1108 inline
1109 T* PtrOffset(T* ptr, const NDIndex<1U>& pos, const NDIndex<1U>& alloc,
1111  T* newptr = ptr + pos[0].first() - alloc[0].first();
1112  return newptr;
1113 }
1114 
1115 template <class T>
1116 inline
1117 T* PtrOffset(T* ptr, const NDIndex<2U>& pos, const NDIndex<2U>& alloc,
1119  T* newptr = ptr + pos[0].first() - alloc[0].first() +
1120  alloc[0].length() * ( pos[1].first() - alloc[1].first() );
1121  return newptr;
1122 }
1123 
1124 template <class T>
1125 inline
1126 T* PtrOffset(T* ptr, const NDIndex<3U>& pos, const NDIndex<3U>& alloc,
1128  T* newptr = ptr + pos[0].first() - alloc[0].first() +
1129  alloc[0].length() * ( pos[1].first() - alloc[1].first() +
1130  alloc[1].length() * ( pos[2].first() - alloc[2].first() ) );
1131  return newptr;
1132 }
1133 
1134 template <class T, unsigned Dim>
1135 inline
1136 T* PtrOffset(T* ptr, const NDIndex<Dim>& pos, const NDIndex<Dim>& alloc,
1138  T* newptr = ptr;
1139  int n=1;
1140  for (unsigned int d=0; d<Dim; ++d) {
1141  newptr += n * (pos[d].first() - alloc[d].first());
1142  n *= alloc[d].length();
1143  }
1144  return newptr;
1145 }
1146 
1147 
1149 // Get a ref to a single element of the Field; if it is not local to our
1150 // processor, print an error and exit. This allows the user to provide
1151 // different index values on each node, instead of using the same element
1152 // and broadcasting to all nodes.
1153 template<class T, unsigned Dim>
1155 {
1156 
1157 
1158 
1159 
1160  // Instead of checking to see if the user has asked for one element,
1161  // we will just use the first element specified for each dimension.
1162 
1163  // Is this element here?
1164  // Try and find it in the local BareFields.
1165  const_iterator_if lf_i = begin_if();
1166  const_iterator_if lf_end = end_if();
1167  for ( ; lf_i != lf_end ; ++lf_i ) {
1168  LField<T,Dim>& lf(*(*lf_i).second);
1169  // End-point "contains" OK since "owned" is unit stride.
1170  // was before CK fix: if ( lf.getOwned().contains( Indexes ) ) {
1171  if ( lf.getAllocated().contains( Indexes ) ) {
1172  // Found it ... first uncompress, then get a pointer to the
1173  // requested element.
1174  lf.Uncompress();
1175  // return *(lf.begin(Indexes));
1176  // instead of building an iterator, just find the value
1177  NDIndex<Dim> alloc = lf.getAllocated();
1178  T* pdata = PtrOffset(lf.getP(), Indexes, alloc,
1179  LFieldDimTag<Dim,(Dim<=3)>());
1180  return *pdata;
1181  }
1182  }
1183 
1184  // if we're here, we did not find it ... it must not be local
1185  ERRORMSG("BareField::localElement: attempt to access non-local index ");
1186  ERRORMSG(Indexes << " on node " << Ippl::myNode() << endl);
1187  ERRORMSG("Occurred in a BareField with layout = " << getLayout() << endl);
1188  ERRORMSG("Calling abort ..." << endl);
1189  Ippl::abort();
1190  return *((*((*(begin_if())).second)).begin());
1191 }
1192 
1193 
1195 //
1196 // Get a single value and return it in the given storage. Whichever
1197 // node owns the value must broadcast it to the other nodes.
1198 //
1200 template <class T, unsigned int Dim>
1201 void BareField<T,Dim>::getsingle(const NDIndex<Dim>& Indexes, T& r) const
1202 {
1203 
1204 
1205 
1206  // Instead of checking to see if the user has asked for one element,
1207  // we will just use the first element specified for each dimension.
1208 
1209  // Check to see if the point is in the boundary conditions.
1210  // Check for: The point is not in the owned domain, but it is in that
1211  // domain augmented with the boundary condition size.
1212  // If so, use a different algorithm.
1213  if ( (!Indexes.touches(Layout->getDomain())) &&
1214  Indexes.touches(AddGuardCells(Layout->getDomain(),Gc)) ) {
1215  getsingle_bc(Indexes,r);
1216  return;
1217  }
1218 
1219  // create a tag for send/receives if necessary
1221 
1222  // Is it here? Try and find it in the LFields
1223  const_iterator_if lf_end = end_if();
1224  for (const_iterator_if lf_i = begin_if(); lf_i != lf_end ; ++lf_i) {
1225  if ( (*lf_i).second->getOwned().contains( Indexes ) ) {
1226  // Found it.
1227  // Get a pointer to the requested element.
1228  LField<T,Dim>& lf( *(*lf_i).second );
1229  typename LField<T,Dim>::iterator lp = lf.begin(Indexes);
1230 
1231  // Get the requested data.
1232  r = *lp;
1233 
1234  // Broadcast it if we're running in parallel
1235  if (Ippl::getNodes() > 1) {
1236  Message *mess = new Message;
1237  ::putMessage(*mess, r);
1238  Ippl::Comm->broadcast_others(mess, tag);
1239  }
1240 
1241  return;
1242  }
1243  }
1244 
1245  // If we're here, we didn't find it: It is remote. Wait for a message.
1246  if (Ippl::getNodes() > 1) {
1247  int any_node = COMM_ANY_NODE;
1248  Message *mess = Ippl::Comm->receive_block(any_node,tag);
1249  ::getMessage(*mess, r);
1250  delete mess;
1251  }
1252  else {
1253  // we did not find it, and we only have one node, so this must be
1254  // an error.
1255  ERRORMSG("Illegal single-value index " << Indexes);
1256  ERRORMSG(" in BareField::getsingle()" << endl);
1257  }
1258 }
1259 
1261 
1262 //
1263 // Get a single value from the BareField when we know that the
1264 // value is in the boundary condition area.
1265 // We use a more robust but slower algorithm here because there could
1266 // be redundancy.
1267 //
1268 
1269 template<class T, unsigned D>
1270 void
1271 BareField<T,D>::getsingle_bc(const NDIndex<D>& Indexes, T& r) const
1272 {
1273  // We will look through everything to find who is the authority
1274  // for the data. We look through the locals to see if we have it,
1275  // and we look through the remotes to see if someone else has it.
1276  // The lowest numbered processor is the authority.
1277  int authority_proc = -1;
1278 
1279  // Look through all the locals to try and find it.
1280  // Loop over all the LFields.
1281  const_iterator_if lf_end = end_if();
1282  for (const_iterator_if lf_i = begin_if(); lf_i != lf_end ; ++lf_i) {
1283  // Is it in this LField?
1284  if ( (*lf_i).second->getAllocated().contains( Indexes ) ) {
1285  // Found it. As far as we know now, this is the authority proc.
1286  authority_proc = Ippl::myNode();
1287 
1288  // Get the requested data.
1289  LField<T,D>& lf( *(*lf_i).second );
1290  typename LField<T,D>::iterator lp = lf.begin(Indexes);
1291  r = *lp;
1292 
1293  // If we're not the only guy on the block, go on to find the remotes.
1294  if (Ippl::getNodes() > 1)
1295  break;
1296 
1297  // Otherwise, we're done.
1298  return;
1299  }
1300  }
1301 
1302  // Look through all the remotes to see who else has it.
1303  // Loop over all the remote LFields that touch Indexes.
1304  typename FieldLayout<D>::touch_range_dv range =
1305  Layout->touch_range_rdv(Indexes,Gc);
1306  for (typename FieldLayout<D>::touch_iterator_dv p=range.first;
1307  p!=range.second;++p)
1308  // See if anybody has a lower processor number.
1309  if ( authority_proc > (*p).second->getNode() )
1310  // Someone else is the authority.
1311  authority_proc = (*p).second->getNode();
1312 
1313  // create a tag for the broadcast.
1315 
1316  if ( authority_proc == Ippl::myNode() ) {
1317  // If we're the authority, broadcast.
1318  Message *mess = new Message;
1319  ::putMessage(*mess, r);
1320  Ippl::Comm->broadcast_others(mess, tag);
1321  }
1322  else {
1323  // If someone else is the authority, receive the message.
1324  Message *mess = Ippl::Comm->receive_block(authority_proc,tag);
1325  ::getMessage(*mess, r);
1326  delete mess;
1327  }
1328 
1329 }
1330 
1331 /***************************************************************************
1332  * $RCSfile: BareField.cpp,v $ $Author: adelmann $
1333  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:26 $
1334  * IPPL_VERSION_ID: $Id: BareField.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $
1335  ***************************************************************************/
elements
Definition: IndexMap.cpp:163
T * value_type(const SliceIterator< T > &)
const unsigned Dim
T * PtrOffset(T *ptr, const NDIndex< 1U > &pos, const NDIndex< 1U > &alloc, LFieldDimTag< 1U, true >)
Definition: BareField.hpp:1109
NDIndex< Dim > AddGuardCells(const NDIndex< Dim > &idx, const GuardCellSizes< Dim > &g)
const int COMM_ANY_NODE
Definition: Communicate.h:40
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
void putMessage(Message &m, const T &t)
Definition: Message.h:549
void getMessage(Message &m, T &t)
Definition: Message.h:572
#define F_GETSINGLE_TAG
Definition: Tags.h:50
#define F_TAG_CYCLE
Definition: Tags.h:53
#define F_GUARD_CELLS_TAG
Definition: Tags.h:44
#define F_WRITE_TAG
Definition: Tags.h:45
std::complex< double > a
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define WARNMSG(msg)
Definition: IpplInfo.h:349
#define PAssert(c)
Definition: PAssert.h:102
std::string::iterator iterator
Definition: MSLang.h:16
bool CanCompress(const T &) const
Message & getMessage(Message &m)
Message & getMessage(Message &m)
Definition: NDIndex.h:138
unsigned size() const
bool touches(const NDIndex< Dim > &) const
Message & putMessage(Message &m) const
Definition: NDIndex.h:130
NDIndex< Dim > intersect(const NDIndex< Dim > &) const
void getsingle_bc(const NDIndex< Dim > &, T &) const
Definition: BareField.hpp:1271
void setDirtyFlag()
Definition: BareField.h:117
T & localElement(const NDIndex< Dim > &) const
Definition: BareField.hpp:1154
void accumGuardCells()
Definition: BareField.hpp:698
void getsingle(const NDIndex< Dim > &, T &) const
Definition: BareField.hpp:1201
GuardCellSizes< Dim > Gc
Definition: BareField.h:343
const GuardCellSizes< Dim > & getGC() const
Definition: BareField.h:146
iterator_if begin_if()
Definition: BareField.h:100
virtual void notifyUserOfDelete(UserList *)
Definition: BareField.hpp:1079
void setup()
Definition: BareField.hpp:150
ac_id_larray::const_iterator const_iterator_if
Definition: BareField.h:93
ac_id_larray::iterator iterator_if
Definition: BareField.h:92
void Uncompress() const
Definition: BareField.hpp:1005
void Compress() const
Definition: BareField.hpp:991
ac_id_larray Locals_ac
Definition: BareField.h:331
virtual void Repartition(UserList *)
Definition: BareField.hpp:1054
void clearDirtyFlag()
Definition: BareField.h:118
iterator_if end_if()
Definition: BareField.h:101
void setGuardCells(const T &) const
Definition: BareField.hpp:616
virtual void fillGuardCells(bool reallyFill=true) const
Definition: BareField.hpp:297
void initialize(Layout_t &)
Definition: BareField.hpp:100
double CompressedFraction() const
Definition: BareField.hpp:1021
Layout_t & getLayout() const
Definition: BareField.h:131
void write(std::ostream &)
Definition: BareField.hpp:208
Definition: LField.h:58
void Compress()
Definition: LField.h:161
T * getP()
Definition: LField.h:100
void AddToOverlapCache(LField< T, Dim > *newCacheItem)
Definition: LField.h:188
bool IsCompressed() const
Definition: LField.h:134
const NDIndex< Dim > & getOwned() const
Definition: LField.h:99
T & getCompressedData()
Definition: LField.h:179
std::vector< LField< T, Dim > * >::iterator OverlapIterator
Definition: LField.h:196
const iterator & end() const
Definition: LField.h:111
const NDIndex< Dim > & getAllocated() const
Definition: LField.h:98
const iterator & begin() const
Definition: LField.h:110
void Uncompress(bool fill_domain=true)
Definition: LField.h:172
OverlapIterator BeginOverlap()
Definition: LField.h:198
OverlapIterator EndOverlap()
Definition: LField.h:199
bool OverlapCacheInitialized()
Definition: LField.h:186
touch_range_dv touch_range_rdv(const NDIndex< Dim > &domain, const GuardCellSizes< Dim > &gc=gc0()) const
Definition: FieldLayout.h:780
std::pair< touch_iterator_dv, touch_iterator_dv > touch_range_dv
Definition: FieldLayout.h:77
void checkin(FieldLayoutUser &f, const GuardCellSizes< Dim > &gc=gc0())
ac_id_vnodes::iterator iterator_iv
Definition: FieldLayout.h:73
virtual void apply()
Definition: Index.h:237
bool send(Message *, int node, int tag, bool delmsg=true)
virtual int broadcast_others(Message *, int, bool delmsg=true)
Message * receive_block(int &node, int &tag)
size_t size() const
Definition: Message.h:292
Message & put(const T &val)
Definition: Message.h:406
int next_tag(int t, int s=1000)
Definition: TagMaker.h:39
static void abort(const char *=0)
Definition: IpplInfo.cpp:616
static int getNodes()
Definition: IpplInfo.cpp:670
static int myNode()
Definition: IpplInfo.cpp:691
static Communicate * Comm
Definition: IpplInfo.h:84
ID_t getUserListID() const
Definition: UserList.cpp:54
void reserve(size_type n)
Definition: vmap.h:125
iterator end()
Definition: vmap.h:108
std::pair< typename Unique::type, my_auto_ptr< LField< T, Dim > > > value_type
Definition: vmap.h:64
std::pair< iterator, bool > insert(const value_type &x)
Definition: vmap.hpp:73