Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

src/DataSource/ACLVISPtclBaseDataSource.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 "DataSource/ACLVISPtclBaseDataSource.h"
00028 #include "DataSource/ACLVISOperations.h"
00029 #include "DataSource/ACLVISDataConnect.h"
00030 #include "DataSource/PtclAttribDataSource.h"
00031 #include "Particle/ParticleBase.h"
00032 #include "Message/Communicate.h"
00033 #include "Utility/IpplInfo.h"
00034 #include "Utility/Pstring.h"
00035 #include "Profile/Profiler.h"
00036 
00037 
00039 // constructor: name, connection method, transfer method, pbase
00040 template<class PLayout>
00041 ACLVISParticleBaseDataSource<PLayout>::ACLVISParticleBaseDataSource(const
00042                                                                     char *nm,
00043          DataConnect *dc, int tm, ParticleBase<PLayout>& PB)
00044   : ParticleBaseDataSource(nm, dc, tm, &PB), MyParticleBase(PB),
00045     IDMap(&IDMapA), NewIDMap(&IDMapB)
00046 {
00047 
00048   TAU_TYPE_STRING(taustr, "void (char *, DataConnect *, int, " + CT(PB));
00049   TAU_PROFILE("ACLVISParticleBaseDataSource::ACLVISParticleBaseDataSource()", 
00050               taustr, TAU_VIZ);
00051 
00052   // make sure we do not have a ParticleBase with positions greater than
00053   // 3 dimensions
00054   CTAssert(PLayout::Dimension < 4);
00055 
00056   // then check to make sure we're not trying to make a connection that we
00057   // don't support in this class
00058   string filestring = "aclvis";
00059   if (string(dc->ID()) != filestring) {
00060     ERRORMSG("Illegal DataConnect object for ACLVIS Data Object." << endl);
00061     ACLVISConnection = 0;
00062     Connection = 0;
00063   } else if (tm != DataSource::OUTPUT) {
00064     ERRORMSG("ACLVIS data connections may only be of type OUTPUT." << endl);
00065     ACLVISConnection = 0;
00066     Connection = 0;
00067   } else {
00068     ACLVISConnection = dynamic_cast<ACLVISDataConnect *>(dc);
00069     checkin();
00070   }
00071 }
00072 
00073 
00075 // destructor
00076 template<class PLayout>
00077 ACLVISParticleBaseDataSource<PLayout>::~ACLVISParticleBaseDataSource() {
00078   TAU_TYPE_STRING(taustr, CT(*this) + " void ()" );
00079   TAU_PROFILE("ACLVISParticleBaseDataSource::~ACLVISParticleBaseDataSource()", 
00080     taustr, TAU_VIZ);
00081 }
00082 
00083 
00085 // make a connection using the given attribute.  Return success.
00086 template<class PLayout>
00087 bool ACLVISParticleBaseDataSource<PLayout>::connect_attrib(
00088            ParticleAttribDataSource *pa) {
00089   TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleAttribDataSource * )");
00090   TAU_PROFILE("ACLVISParticleBaseDataSource::connect_attrib()", 
00091     taustr, TAU_VIZ);
00092 
00093   // on parent node, establish connection to ACLVIS for this base+attrib pair
00094   if (getConnection()->onConnectNode() && connected())
00095     // call ACLVIS API to register this data object
00096     ACLVISConnection->getConnection()->connect((void *)pa,
00097                        (char *)(pa->name()),
00098                        (ReadParticleTool *)(pa->getConnectStorage()),
00099                        ParticleDataType);
00100 
00101   return ParticleBaseDataSource::connect_attrib(pa);
00102 }
00103 
00104 
00106 // disconnect from the external agency the connection involving this
00107 // particle base and the given attribute.  Return success.
00108 template<class PLayout>
00109 bool ACLVISParticleBaseDataSource<PLayout>::disconnect_attrib(
00110            ParticleAttribDataSource *pa) {
00111   TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleAttribDataSource * )");
00112   TAU_PROFILE("ACLVISParticleBaseDataSource::disconnect_attrib()", 
00113     taustr, TAU_VIZ);
00114 
00115   // on parent node, remove connection to ACLVIS for this base+attrib pair
00116   if (getConnection()->onConnectNode() && connected())
00117 #ifdef IPPL_LUX
00118     ACLVISConnection->getConnection()->disconnect((char *)(pa->name()));
00119 #else
00120     ACLVISConnection->getConnection()->disconnect((void *)pa);
00121 #endif
00122 
00123   return ParticleBaseDataSource::disconnect_attrib(pa);
00124 }
00125 
00126 
00128 // check to see if the given ParticleAttrib is in this ParticleBase's
00129 // list of registered attributes.  Return true if this is so.
00130 template<class PLayout>
00131 bool ACLVISParticleBaseDataSource<PLayout>::has_attrib(
00132             ParticleAttribBase *pa) {
00133   TAU_TYPE_STRING(taustr, CT(*this) + " bool (ParticleAttribDataSource * )");
00134   TAU_PROFILE("ACLVISParticleBaseDataSource::has_attrib()", 
00135     taustr, TAU_VIZ);
00136 
00137   // go through the list of registered attributes in our ParticleBase ...
00138   typename ParticleBase<PLayout>::attrib_iterator attr=MyParticleBase.begin();
00139   typename ParticleBase<PLayout>::attrib_iterator endattr=MyParticleBase.end();
00140   for ( ; attr != endattr; ++attr)
00141     if (pa == *attr)
00142       return true;
00143 
00144   // if here, not found
00145   return false;
00146 }
00147 
00148 
00150 // Indicate to the receiver that we're allowing them time to manipulate the
00151 // data (e.g., for a viz program, to rotate it, change representation, etc.)
00152 // This should only return when the manipulation is done.
00153 template<class PLayout>
00154 void ACLVISParticleBaseDataSource<PLayout>::interact(const char *str) {
00155   TAU_TYPE_STRING(taustr, CT(*this) +  " void ()" );
00156   TAU_PROFILE("ACLVISParticleBaseDataSource::interact()", taustr, TAU_VIZ);
00157 
00158   // on parent node, hand off control to ACLVIS API.  If a command string
00159   // is given, instead call the viz API function to execute it as an
00160   // interactive command.
00161   if (getConnection()->onConnectNode() && connected()) {
00162     if (str != 0 && *str != 0) {
00163 #ifndef IPPL_LUX
00164       ACLVISConnection->getConnection()->InterpretCommand(str);
00165 #endif
00166     } else {
00167 #ifdef IPPL_LUX
00168       ACLVISConnection->getConnection()->Interact();
00169 #else
00170       ACLVISConnection->getConnection()->Interact(1);
00171 #endif
00172     }
00173   }
00174 }
00175 
00176 
00178 // Update the object, that is, make sure the receiver of the data has a
00179 // current and consistent snapshot of the current state.  Return success.
00180 template<class PLayout>
00181 bool ACLVISParticleBaseDataSource<PLayout>::update() {
00182   TAU_TYPE_STRING(taustr, CT(*this) +  " bool ()" );
00183   TAU_PROFILE("ACLVISParticleBaseDataSource::update()", taustr, TAU_VIZ);
00184 
00185   //Inform dbgmsg("APB::update", INFORM_ALL_NODES);
00186   //dbgmsg << "Starting update on node " << Ippl::myNode() << endl;
00187 
00188   // only need to do update if we have connected attribs
00189   if (begin_attrib() == end_attrib())
00190     return true;
00191 
00192   // get the next tag for communication
00193   int n, tag = Ippl::Comm->next_tag(DS_PB_TAG, DS_CYCLE);
00194   unsigned N = Ippl::getNodes();
00195   unsigned myN = Ippl::myNode();
00196   unsigned locN = MyParticleBase.getLocalNum();
00197   unsigned totN = MyParticleBase.getTotalNum();
00198   unsigned currIndx = 0;
00199 
00200   typename AttribList_t::iterator attr;
00201   typename AttribList_t::iterator endattr;
00202 
00203   // clear out the id list
00204   NewIDMap->erase(NewIDMap->begin(), NewIDMap->end());
00205 
00206   // when running in parallel, we must send all data to parent nodes
00207   //dbgmsg << "About to send all the messages out ..." << endl;
00208   for (n=0; n < getConnection()->getNodes(); ++n) {
00209     if (myN != n) {
00210       // put number of local particles into message
00211       Message *msg = new Message;
00212       msg->put(locN);
00213 
00214       if (locN > 0) {
00215         // put position and ID data into a message
00216         MyParticleBase.R.putMessage(*msg, locN, 0);
00217         MyParticleBase.ID.putMessage(*msg, locN, 0);
00218 
00219         // put attribute data into a message
00220         for (attr=begin_attrib(), endattr=end_attrib();
00221              attr != endattr;
00222              ++attr)
00223           (*attr)->putMessage(msg);
00224       }
00225 
00226       // send the data to parent
00227       //dbgmsg << "Sending " << locN << " particles to node " << n << endl;
00228       Ippl::Comm->send(msg, n, tag);
00229     }
00230   }
00231 
00232   // on the parent nodes, put in our own data and the data from other
00233   // nodes
00234   //dbgmsg << "About to receive in all the messages ..." << endl;
00235   if (getConnection()->onConnectNode()) {
00236 
00237     // on master nodes, prepare all the attributes for new data
00238     for (attr=begin_attrib(),endattr=end_attrib(); attr!=endattr; ++attr)
00239       (*attr)->prepare_data(true, totN);
00240 
00241     // process a message or local data from each node
00242     for (n=0; n < N; ++n) {
00243       if (myN == n) {
00244         // put in local data
00245         if (locN > 0) {
00246           //dbgmsg << "Inserting local data ..." << endl;
00247           for (attr=begin_attrib(),endattr=end_attrib();attr!=endattr;++attr){
00248             (*attr)->insert_data(locN, currIndx, 0);
00249             insert_pos(locN, currIndx, &(MyParticleBase.R[0]),
00250                        &(MyParticleBase.ID[0]), *attr);
00251           }
00252         }
00253 
00254         // increment index, which indicates where the next particles go
00255         currIndx += locN;
00256 
00257       } else {
00258         // now receive message from current other node
00259         Message *msg = Ippl::Comm->receive_block(n, tag);
00260         unsigned remN;
00261         msg->get(remN);
00262 
00263         // extract attrib data into agency-specific data structure
00264         if (remN > 0) {
00265           // get coordinate attribute from message
00266           typename PLayout::SingleParticlePos_t* posdata =
00267             (typename PLayout::SingleParticlePos_t *)(msg->remove());
00268           typename PLayout::Index_t* iddata =
00269             (typename PLayout::Index_t *)(msg->remove());
00270 
00271           // get non-position attribute data from message, and put all the
00272           // data into the ACLVIS data structures
00273           //dbgmsg<<"Inserting remote data from node " << n << " ..." << endl;
00274           for (attr=begin_attrib(),endattr=end_attrib();attr!=endattr;++attr){
00275             (*attr)->insert_data(remN, currIndx, msg);
00276             insert_pos(remN, currIndx, posdata, iddata, *attr);
00277           }
00278 
00279           // free the memory used to store position and ID values
00280           free(static_cast<void *>(posdata));
00281           free(static_cast<void *>(iddata));
00282 
00283           // increment index, which indicates where the next particles go
00284           currIndx += remN;
00285         }
00286 
00287         // we're done with this node
00288         delete msg;
00289       }
00290     }
00291 
00292     // tell ACLVIS API there is new data
00293     for (attr=begin_attrib(),endattr=end_attrib(); attr!=endattr; ++attr) {
00294       // on parent node, call ACLVIS API to update data for each attrib.
00295       (*attr)->prepare_data(false, totN);
00296 #ifdef IPPL_LUX
00297       ACLVISConnection->getConnection()->update((char *)((*attr)->name()));
00298 #else
00299       ACLVISConnection->getConnection()->update((void *)(*attr));
00300 #endif
00301     }
00302   }
00303 
00304   // swap ID lists
00305   IDMap_t *tmpmap = IDMap;
00306   IDMap = NewIDMap;
00307   NewIDMap = tmpmap;
00308 
00309   // report success
00310   return true;
00311 }
00312 
00313 
00315 // copy data out of the given coordinates iterator into the data structure
00316 // for the given ParticleAttribDataSource which represents the agency-
00317 // specific storage.  Arguments = number of particles, starting index,
00318 // pointer to value, pointer to ID's, and ParticleAttribDataSource
00319 template<class PLayout>
00320 void ACLVISParticleBaseDataSource<PLayout>::insert_pos(
00321                       unsigned N, unsigned sIndx,
00322                       typename PLayout::SingleParticlePos_t* data,
00323                       typename PLayout::Index_t* iddata,
00324                       ParticleAttribDataSource* pa) {
00325   TAU_TYPE_STRING(taustr, "void (unsigned, unsigned, " + CT(data) 
00326     + ", ParticleAttribDataSource *" );
00327   TAU_PROFILE("ACLVISParticleBaseDataSource::insert_pos()", taustr, TAU_VIZ);
00328 
00329   //  Inform dbgmsg("APB::insert_pos", INFORM_ALL_NODES);
00330 
00331   // get ACLVIS data storage location for particle coordinates
00332   ReadParticleTool *vizdata =
00333     static_cast<ReadParticleTool *>(pa->getConnectStorage());
00334 
00335   // copy in the data from the storage
00336   unsigned maxIndx = sIndx + N;
00337   for ( ; sIndx < maxIndx; ++sIndx, ++data, ++iddata) {
00338     // set position for the Nth particle
00339     ACLVISTraits<ReadParticleTool, typename PLayout::SingleParticlePos_t>::
00340       setCoord(vizdata, sIndx, *data);
00341 
00342     // find where this particle was located during the last update
00343     typename IDMap_t::iterator idloc = IDMap->find(*iddata);
00344     int prevloc = (-1);
00345     if (idloc != IDMap->end())
00346       prevloc = (*idloc).second;
00347 
00348     // set ID information for the Nth particle
00349     ACLVISTraits<ReadParticleTool, typename PLayout::Index_t>::
00350       setID(vizdata, sIndx, prevloc);
00351 
00352     // save where this item is located in the list
00353     (*NewIDMap)[*iddata] = sIndx;
00354 
00355     //    dbgmsg << "  Inserted particle position " << sIndx << " = ";
00356     //    dbgmsg << *data << " with ID = " << prevloc << endl;
00357   }
00358 }
00359 
00360 
00361 /***************************************************************************
00362  * $RCSfile: ACLVISPtclBaseDataSource.cpp,v $   $Author: adelmann $
00363  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:24 $
00364  * IPPL_VERSION_ID: $Id: ACLVISPtclBaseDataSource.cpp,v 1.1.1.1 2003/01/23 07:40:24 adelmann Exp $ 
00365  ***************************************************************************/

Generated on Fri Nov 2 01:25:55 2007 for IPPL by doxygen 1.3.5