src/Utility/FieldDebugPrint.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 // include files
00027 #include "Utility/FieldDebugPrint.h"
00028 #include "Profile/Profiler.h"
00029 #include "Field/BrickExpression.h"
00030 #include "Field/GuardCellSizes.h"
00031 #include "Utility/IpplInfo.h"
00032 #include "Utility/PAssert.h"
00033 #include "Message/Communicate.h"
00034 #include "Message/Message.h"
00035 
00036 #ifdef IPPL_USE_STANDARD_HEADERS
00037 #include <iomanip>
00038 using namespace std;
00039 #else
00040 #include <iomanip.h>
00041 #endif
00042 
00043 // debugging macro
00044 #ifdef IPPL_PRINTDEBUG
00045 #define FDPDBG(x) x
00046 #else
00047 #define FDPDBG(x)
00048 #endif
00049 
00050 
00051 // Print out the data for a given field, using it's whole domain
00052 template<class T, unsigned Dim>
00053 void FieldDebugPrint<T,Dim>::print(BareField<T,Dim>& F,
00054                                    Inform& out, bool allnodes) {
00055   NDIndex<Dim> domain;
00056   if (PrintBC)
00057     domain = AddGuardCells(F.getDomain(), F.getGuardCellSizes());
00058   else
00059     domain = F.getDomain();
00060   print(F, domain, out, allnodes);
00061 }
00062 
00063 
00064 // print out the data for a given field, using it's whole domain
00065 template<class T, unsigned Dim>
00066 void FieldDebugPrint<T,Dim>::print(BareField<T,Dim>& F, bool allnodes) {
00067   NDIndex<Dim> domain;
00068   if (PrintBC)
00069     domain = AddGuardCells(F.getDomain(), F.getGuardCellSizes());
00070   else
00071     domain = F.getDomain();
00072   Inform out("");
00073   print(F, domain, out, allnodes);
00074 }
00075 
00076 
00077 // print out the data for a given field and domain
00078 template<class T, unsigned Dim>
00079 void FieldDebugPrint<T,Dim>::print(BareField<T,Dim>& F,
00080                                    const NDIndex<Dim>& view, bool allnodes) {
00081   Inform out("");
00082   print(F, view, out, allnodes);
00083 }
00084 
00085 
00086 // print out the data for a given field and domain
00087 template<class T, unsigned Dim>
00088 void FieldDebugPrint<T,Dim>::print(BareField<T,Dim>& F,
00089                                    const NDIndex<Dim>& view,
00090                                    Inform& out,
00091                                    bool allnodes) {
00092   TAU_TYPE_STRING(taustr, CT(*this) + " void (" + CT(F) + ", " + CT(view) +
00093                   ", " + CT(out) + ", " + CT(allnodes) + " )");
00094   TAU_PROFILE("FieldDebugPrint::print()", taustr,
00095               TAU_UTILITY | TAU_FIELD | TAU_IO);
00096 
00097   // a debug Inform object
00098   FDPDBG(Inform dbgmsg("FieldDebugPrint", INFORM_ALL_NODES));
00099   FDPDBG(dbgmsg << "Printing domain " << view);
00100   FDPDBG(dbgmsg << " for a Field with total domain " << F.getDomain() << endl);
00101   FDPDBG(dbgmsg << "Involving all nodes? " << allnodes << endl);
00102 
00103   // generate a new communication tag, if necessary
00104   int tag;
00105   if (allnodes) {
00106     tag = Ippl::Comm->next_tag(FP_GATHER_TAG, FP_TAG_CYCLE);
00107     FDPDBG(dbgmsg << "Using tag = " << tag << endl);
00108   }
00109 
00110   // determine the maximum domain of the field
00111   NDIndex<Dim> domain;
00112   if (PrintBC)
00113     domain = AddGuardCells(F.getDomain(), F.getGuardCellSizes());
00114   else
00115     domain = F.getDomain();
00116   FDPDBG(dbgmsg << "Maximum domain of the field (possibly with GC's) = ");
00117   FDPDBG(dbgmsg << domain << endl);
00118 
00119   // check that the view is contained inside of the Field's domain
00120   if(!domain.contains(view)) {
00121     ERRORMSG("FieldPrint::print - the domain of the field: " << domain<<endl);
00122     ERRORMSG(" must contain the selected view: " << view << endl);
00123     return;
00124   }
00125 
00126   // In order to print this stuff right, we need to make sure the
00127   // guard cells are filled.  But we can only do this if this is
00128   // being called by all the nodes, since it requires communication.
00129   if (allnodes && F.isDirty()) {
00130     FDPDBG(dbgmsg << "Filling guard cells first." << endl);
00131     F.fillGuardCells();
00132   }
00133 
00134   // create an LField to store the information for the view, and
00135   // an LField to indicate which elements we actually have (they might
00136   // not be available if we're printing out from the debugger without
00137   // any communication).  Start off initially saying we do not have
00138   // any data.
00139   typedef typename LField<T,Dim>::iterator LFI;
00140   typedef typename LField<bool,Dim>::iterator BLFI;
00141   typedef PETE_Scalar<bool> BPS;
00142   LField<T,Dim> myLField(view,view);
00143   LField<bool,Dim> availLField(view,view);
00144   BPS trueitem(true);
00145   BPS falseitem(false);
00146   BLFI blhs = availLField.begin();
00147   BrickExpression<Dim,BLFI,BPS,OpAssign>(blhs,falseitem).apply();
00148 
00149   // create an iterator for looping over local vnodes
00150   typename BareField<T,Dim>::iterator_if local;
00151 
00152   // If we're printing involving all the nodes, send data from local vnodes to
00153   // node zero and have that node print.  If we're doing this on individual
00154   // nodes, just have that node fill in the data it has, and print that
00155   // (which does not require any communication).
00156   if (allnodes) {
00157     // Loop over all the local nodes and send the intersecting data to the
00158     // parent node
00159     if (Ippl::myNode() != 0) {
00160       // prepare a message to send to parent node
00161       Message *mess = new Message();
00162       int datahere;
00163       // put data for each local LField in the message
00164       for (local = F.begin_if(); local != F.end_if(); ++local) {
00165         // find the intersection of this lfield with the view, and put data in
00166         // message.
00167         LField<T,Dim> &l = *(*local).second;
00168         NDIndex<Dim>& lo = (NDIndex<Dim>&) l.getAllocated();
00169         if (view.touches(lo)) {
00170           datahere = 1;
00171           NDIndex<Dim> intersection = lo.intersect(view);
00172           FDPDBG(dbgmsg << "Node " << Ippl::myNode() << " sending domain ");
00173           FDPDBG(dbgmsg << intersection << " to node 0." << endl);
00174           T compressed_data;
00175           LFI rhs = l.begin(intersection, compressed_data);
00176           rhs.TryCompress();
00177 	  ::putMessage(*mess, datahere);
00178           intersection.putMessage(*mess);
00179           rhs.putMessage(*mess);
00180         }
00181       }
00182 
00183       // Send the message.
00184       datahere = 0;
00185       ::putMessage(*mess, datahere);
00186       Ippl::Comm->send(mess, 0, tag);
00187     } else {
00188       // Receive all the messages, one from each node.
00189       for (int remaining = Ippl::getNodes() - 1; remaining > 0; --remaining) {
00190         // Receive the generic message.
00191         int any_node = COMM_ANY_NODE;
00192         Message *mess = Ippl::Comm->receive_block(any_node, tag);
00193         PAssert(mess != 0);
00194 
00195         // keep getting blocks until we're done with the message
00196         int datahere;
00197         ::getMessage(*mess, datahere);
00198         while (datahere != 0) {
00199           // Extract the intersection domain from the message.
00200           NDIndex<Dim> localBlock;
00201           localBlock.getMessage(*mess);
00202           FDPDBG(dbgmsg << "Parent receiving domain " << localBlock);
00203           FDPDBG(dbgmsg << " from node " << any_node << endl);
00204 
00205           // Extract the rhs iterator from it.
00206           T compressed_value;
00207           LFI rhs(compressed_value);
00208           rhs.getMessage(*mess);
00209 
00210           // copy the data into our local LField
00211           myLField.Uncompress();
00212           availLField.Uncompress();
00213           LFI lhs = myLField.begin(localBlock);
00214           BrickExpression<Dim,LFI,LFI,OpAssign>(lhs,rhs).apply();
00215           BLFI blhs = availLField.begin(localBlock);
00216           BrickExpression<Dim,BLFI,BPS,OpAssign>(blhs,trueitem).apply();
00217 
00218           // see if there is another block
00219 	  ::getMessage(*mess, datahere);
00220         }
00221 
00222         // done with the message now
00223         delete mess;
00224       }
00225     }
00226   }
00227 
00228   // Now that we have populated the localfield with the view, we print.
00229   // Only print on node 0, or on all the nodes if allnodes = false.
00230   if (!allnodes || Ippl::myNode() == 0) {
00231 
00232     // TJW 1/22/1999
00233 
00234     // To make this correct with defergcfill=true and allnodes=false (to avoid
00235     // inconsistent/unset guard element values being output as physical
00236     // elements, do this in two stages. The first fills the single LField
00237     // based on intersections with Allocated domains, which can put some
00238     // inconsistent/unset guard-element values into physical element
00239     // locations. The second fills the single LField based on intersections
00240     // with Owned domains, which will overwrite those bogus values with
00241     // correct values from owned physical elements in the original BareField's
00242     // LFields. There is undoubtably a more efficient way to achieve this end,
00243     // but do it this way for now, to fix the bug:
00244     
00245     // TJW: First stage: intersect with Allocated:
00246 
00247     // first need to copy all local blocks into the single LField
00248     for (local = F.begin_if(); local != F.end_if(); ++local) {
00249       // find the intersection of this lfield with the view
00250       LField<T,Dim> &l = *(*local).second;
00251       NDIndex<Dim>& lo = (NDIndex<Dim>&) l.getAllocated();
00252       if (view.touches(lo)) {
00253         myLField.Uncompress();
00254         availLField.Uncompress();
00255         NDIndex<Dim> intersection = lo.intersect(view);
00256         FDPDBG(dbgmsg << "Node "<<Ippl::myNode()<<" copying local domain ");
00257         FDPDBG(dbgmsg << intersection << " into local LField storage."<<endl);
00258         LFI lhs = myLField.begin(intersection);
00259         LFI rhs = l.begin(intersection);
00260         BrickExpression<Dim,LFI,LFI,OpAssign>(lhs,rhs).apply();
00261         BLFI blhs = availLField.begin(intersection);
00262         BrickExpression<Dim,BLFI,BPS,OpAssign>(blhs,trueitem).apply();
00263       }
00264     }
00265 
00266     // TJW: Second stage: intersect with Owned:
00267 
00268     // first need to copy all local blocks into the single LField
00269     for (local = F.begin_if(); local != F.end_if(); ++local) {
00270       // find the intersection of this lfield with the view
00271       LField<T,Dim> &l = *(*local).second;
00272       NDIndex<Dim>& lo = (NDIndex<Dim>&) l.getOwned();
00273       if (view.touches(lo)) {
00274         myLField.Uncompress();
00275         availLField.Uncompress();
00276         NDIndex<Dim> intersection = lo.intersect(view);
00277         FDPDBG(dbgmsg << "Node "<<Ippl::myNode()<<" copying local domain ");
00278         FDPDBG(dbgmsg << intersection << " into local LField storage."<<endl);
00279         LFI lhs = myLField.begin(intersection);
00280         LFI rhs = l.begin(intersection);
00281         BrickExpression<Dim,LFI,LFI,OpAssign>(lhs,rhs).apply();
00282         BLFI blhs = availLField.begin(intersection);
00283         BrickExpression<Dim,BLFI,BPS,OpAssign>(blhs,trueitem).apply();
00284       }
00285     }
00286 
00287     FDPDBG(dbgmsg << "Finished assembling data; now printing." << endl);
00288 
00289     // finally, we can print
00290     out << "~~~~~~~~ field slice ";
00291     for (unsigned int pd=0; pd < Dim; ++pd) {
00292       out << (pd == 0 ? "(" : ", ");
00293       out << view[pd].first() << ":" << view[pd].last();
00294       out << ":" << view[pd].stride();
00295     }
00296     out << ") ~~~~~~~~" << endl;
00297     if(Scientific)
00298       out.setf(ios::scientific);
00299 
00300     int i0, i1, i2;
00301     LFI liter = myLField.begin();
00302     BLFI bliter = availLField.begin();
00303     switch(Dim) {
00304     case 1:
00305       for (i0=0; i0 < view[0].length(); ++i0, ++liter, ++bliter)
00306         printelem(*bliter, *liter, i0, out);
00307       out << endl;
00308       break;
00309 
00310     case 2:
00311       for (i1=0; i1 < view[1].length(); ++i1) {
00312         out << "--------------------------------------------------J = ";
00313         out << view[1].first() + i1 << endl;
00314         for (i0=0; i0 < view[0].length(); ++i0, ++liter, ++bliter)
00315           printelem(*bliter, *liter, i0, out);
00316         out << endl;
00317         out << endl;
00318       }
00319       break;
00320 
00321     case 3:
00322       for (i2=0; i2 < view[2].length(); ++i2) {
00323         out << "==================================================K = ";
00324         out << view[2].first() + i2 << endl;
00325         for (i1=0; i1 < view[1].length(); ++i1) {
00326           out << "--------------------------------------------------J = ";
00327           out << view[1].first() + i1 << endl;
00328           for (i0=0; i0 < view[0].length(); ++i0, ++liter, ++bliter)
00329             printelem(*bliter, *liter, i0, out);
00330           out << endl;
00331           out << endl;
00332         }
00333       }
00334       break;
00335 
00336     default:
00337       ERRORMSG("bad Dimension \"" << Dim << "\" in FieldDebugPrint::print()");
00338       ERRORMSG(endl);
00339       Ippl::abort();
00340     }
00341   }
00342 }
00343 
00344 
00345 // print a single value to the screen
00346 template<class T, unsigned Dim>
00347 void FieldDebugPrint<T,Dim>::printelem(bool isavail, T &val,
00348                                        unsigned int i0, Inform& out) {
00349   if (DataPrecision > 0)
00350     out << setprecision(DataPrecision);
00351   if (DataWidth > 0)
00352     out << setw(DataWidth);
00353   if(Scientific)
00354     out.setf(ios::scientific);
00355   if (isavail)
00356     out << val;
00357   else
00358     out << '-';
00359   if (CarReturn > 0 && ((i0+1) % CarReturn) == 0)
00360     out << endl;
00361   else
00362     out << " ";
00363 }
00364 
00365   
00366 /***************************************************************************
00367  * $RCSfile: FieldDebugPrint.cpp,v $   $Author: adelmann $
00368  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00369  * IPPL_VERSION_ID: $Id: FieldDebugPrint.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00370  ***************************************************************************/

Generated on Mon Jan 16 13:23:58 2006 for IPPL by  doxygen 1.4.6