FEI Version of the Day
snl_fei_RecordMsgHandler.cpp
00001 /*--------------------------------------------------------------------*/
00002 /*    Copyright 2005 Sandia Corporation.                              */
00003 /*    Under the terms of Contract DE-AC04-94AL85000, there is a       */
00004 /*    non-exclusive license for use of this work by or on behalf      */
00005 /*    of the U.S. Government.  Export of this program may require     */
00006 /*    a license from the United States Government.                    */
00007 /*--------------------------------------------------------------------*/
00008 
00009 #include "fei_sstream.hpp"
00010 
00011 #include "snl_fei_RecordMsgHandler.hpp"
00012 #include "snl_fei_RecordCollection.hpp"
00013 #include "snl_fei_PointBlockMap.hpp"
00014 #include "fei_FieldMask.hpp"
00015 #include "fei_TemplateUtils.hpp"
00016 
00017 #undef fei_file
00018 #define fei_file "snl_fei_RecordMsgHandler.cpp"
00019 #include "fei_ErrMacros.hpp"
00020 
00021 snl_fei::RecordMsgHandler::RecordMsgHandler(int localProc,
00022               RecordCollection* recordCollection,
00023               snl_fei::PointBlockMap& ptBlkMap,
00024               std::vector<fei::FieldMask*>& fieldMasks,
00025               std::vector<int>& eqnNumbers)
00026   :sendPattern_(NULL),
00027    recvPattern_(NULL),
00028    recordCollection_(recordCollection),
00029    ptBlkMap_(ptBlkMap),
00030    fieldMasks_(fieldMasks),
00031    whichTask_(_FieldMasks_),
00032    sendProcs_(0, 32),
00033    recvProcs_(0, 32),
00034    eqnNumbers_(eqnNumbers),
00035    localProc_(localProc)
00036 {
00037 }
00038 
00039 snl_fei::RecordMsgHandler::~RecordMsgHandler()
00040 {
00041 }
00042 
00043 std::vector<int>& snl_fei::RecordMsgHandler::getSendProcs()
00044 {
00045   fei::copyKeysToVector(sendPattern_->getMap(), sendProcs_);
00046   return(sendProcs_);
00047 }
00048 
00049 std::vector<int>& snl_fei::RecordMsgHandler::getRecvProcs()
00050 {
00051   fei::copyKeysToVector(recvPattern_->getMap(), recvProcs_);
00052   return(recvProcs_);
00053 }
00054 
00055 int snl_fei::RecordMsgHandler::getSendMessageLength(int destProc,
00056                 int& messageLength)
00057 {
00058   if (sendPattern_ == NULL || recvPattern_ == NULL) ERReturn(-1);
00059 
00060   switch(whichTask_) {
00061   case _FieldMasks_:
00062     messageLength = localFieldMaskMessageSize(fieldMasks_);    break;
00063   case _MaskIDs_:
00064     messageLength = sendPattern_->getRow(destProc)->size();  break;
00065   case _EqnNumbers_:
00066     messageLength = eqnNumbersMsgLength(destProc);  break;
00067   default:
00068     std::abort();
00069   }
00070 
00071   return(0);
00072 }
00073 
00074 int snl_fei::RecordMsgHandler::getSendMessage(int destProc,
00075                 std::vector<int>& message)
00076 {
00077   switch(whichTask_) {
00078   case _FieldMasks_:
00079     CHK_ERR( packLocalFieldMasks(fieldMasks_, message) );    break;
00080   case _MaskIDs_:
00081     CHK_ERR( packMaskIDs(destProc, message) );  break;
00082   case _EqnNumbers_:
00083     CHK_ERR( packEqnNumbersMsg(destProc, message) );  break;
00084   default:
00085     std::abort();
00086   }
00087 
00088   return(0);
00089 }
00090 
00091 int snl_fei::RecordMsgHandler::processRecvMessage(int srcProc,
00092               std::vector<int>& message)
00093 {
00094   switch(whichTask_) {
00095   case _FieldMasks_:
00096     CHK_ERR( addFieldMasks(message, fieldMasks_) );    break;
00097   case _MaskIDs_:
00098     CHK_ERR( mergeMaskIDs(srcProc, message) );  break;
00099   case _EqnNumbers_:
00100     CHK_ERR( storeEqnNumbers(srcProc, message) );  break;
00101   default:
00102     std::abort();
00103   }
00104 
00105   return(0);
00106 }
00107 
00108 int snl_fei::RecordMsgHandler::
00109 localFieldMaskMessageSize(std::vector<fei::FieldMask*>& fieldMasks)
00110 {
00111   //msg-size will be 1+sum(numFields*3+2)
00112   int numLocalMasks = fieldMasks.size();
00113   int i, msgSize = 1;
00114   for(i=0; i<numLocalMasks; ++i) {
00115     msgSize += (fieldMasks[i]->getNumFields())*3+2;
00116   }
00117 
00118   return( msgSize );
00119 }
00120 
00121 int snl_fei::RecordMsgHandler::
00122 packLocalFieldMasks(std::vector<fei::FieldMask*>& fieldMasks,
00123         std::vector<int>& localFieldMasks)
00124 {
00125   int numLocalMasks = fieldMasks.size();
00126   int msgSize = 1;
00127   for(int ii=0; ii<numLocalMasks; ++ii) {
00128     msgSize += fieldMasks[ii]->getNumFields()*3+2;
00129   }
00130 
00131   localFieldMasks.resize(msgSize);
00132 
00133   int offset = 0;
00134   localFieldMasks[offset++] = fieldMasks.size();
00135   for(unsigned i=0; i<fieldMasks.size(); ++i) {
00136     int numFields = fieldMasks[i]->getNumFields();
00137     int numIndices = fieldMasks[i]->getNumIndices();
00138     localFieldMasks[offset++] = numFields;
00139     localFieldMasks[offset++] = numIndices;
00140 
00141     std::vector<int>& fieldIDs = fieldMasks[i]->getFieldIDs();
00142     std::vector<int>& fieldSizes = fieldMasks[i]->getFieldSizes();
00143 
00144     for(int j=0; j<numFields; ++j) {
00145       localFieldMasks[offset+j] = fieldIDs[j];
00146       localFieldMasks[offset+numFields+j] = fieldSizes[j];
00147     }
00148     offset += numFields*3;
00149   }
00150 
00151   return(0);
00152 }
00153 
00154 int snl_fei::RecordMsgHandler::
00155 addFieldMasks(std::vector<int>& msg, std::vector<fei::FieldMask*>& fieldMasks)
00156 {
00157   int offset = 0;
00158   int* msgPtr = &msg[0];
00159   int numMasks = msgPtr[offset++];
00160   for(int i=0; i<numMasks; ++i) {
00161     int numFields = msgPtr[offset++];
00162     int numIndices = msgPtr[offset++];
00163     int* fieldIDs = NULL;
00164     int* fieldSizes = NULL;
00165     if (numFields > 0) {
00166       fieldIDs = &(msgPtr[offset]);
00167       fieldSizes = &(msgPtr[offset+numFields]);
00168     }
00169 
00170     int maskID = fei::FieldMask::calculateMaskID(numFields, fieldIDs);
00171 
00172     bool maskAlreadyExists = false;
00173     for(unsigned j=0; j<fieldMasks.size(); ++j) {
00174       int existingMaskID = fieldMasks[j]->getMaskID();
00175       if (maskID == existingMaskID) {
00176   maskAlreadyExists = true; break;
00177       }
00178     }
00179 
00180     if (!maskAlreadyExists) {
00181       fei::FieldMask* newmask = new fei::FieldMask(numFields,
00182                  fieldIDs, fieldSizes);
00183       if (numFields < 1) {
00184   newmask->setNumIndices(numIndices);
00185       }
00186       fieldMasks.push_back(newmask);
00187     }
00188 
00189     offset += 3*numFields;
00190   }
00191 
00192   return(0);
00193 }
00194 
00195 int snl_fei::RecordMsgHandler::packMaskIDs(int destProc, std::vector<int>& msg)
00196 {
00197   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00198   int len = ids->size();
00199 
00200   msg.resize(len);
00201 
00202   fei::comm_map::row_type::const_iterator
00203     id_iter = ids->begin(),
00204     id_end = ids->end();
00205 
00206   int offset = 0;
00207   int* msgPtr = &msg[0];
00208 
00209   for(; id_iter != id_end; ++id_iter) {
00210     fei::Record<int>* rec = recordCollection_->getRecordWithID(*id_iter);
00211     if (rec == NULL) {
00212       FEI_OSTRINGSTREAM osstr;
00213       osstr << "RecordMsgHandler::packMaskIDs: proc " << localProc_
00214      << " failed to find ID " << *id_iter;
00215       throw std::runtime_error(osstr.str());
00216     }
00217 
00218     msgPtr[offset++] = rec->getFieldMask()->getMaskID();
00219   }
00220 
00221   return(0);
00222 }
00223 
00224 int snl_fei::RecordMsgHandler::mergeMaskIDs(int srcProc, std::vector<int>& msg)
00225 {
00226   fei::comm_map::row_type* ids = recvPattern_->getRow(srcProc);
00227 
00228   fei::comm_map::row_type::const_iterator
00229     id_iter = ids->begin(),
00230     id_end = ids->end();
00231 
00232   int offset = 0;
00233   int* msgPtr = &msg[0];
00234 
00235   for(; id_iter != id_end; ++id_iter) {
00236     int ID = *id_iter;
00237     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00238     if (rec == NULL) {
00239       ERReturn(-1);
00240     }
00241 
00242     int maskID = msgPtr[offset++];
00243 
00244     if (maskID != rec->getFieldMask()->getMaskID()) {
00245       //if the masks don't match, we need to add the fields from the
00246       //incoming-field-mask-id to our record's field-mask.
00247 
00248       //first, find the field-mask for 'maskID'
00249       fei::FieldMask* mask = NULL;
00250       for(unsigned fm=0; fm<fieldMasks_.size(); ++fm) {
00251   if (fieldMasks_[fm]->getMaskID() == maskID) mask = fieldMasks_[fm];
00252       }
00253       if (mask == NULL) {
00254   fei::console_out() << "mergeMaskIDs didn't find mask for maskID="
00255            << maskID<<FEI_ENDL;
00256   ERReturn(-1);
00257       }
00258 
00259       int numFields = mask->getNumFields();
00260       std::vector<int>& fieldIDs = mask->getFieldIDs();
00261       std::vector<int>& fieldSizes = mask->getFieldSizes();
00262 
00263       for(int nf=0; nf<numFields; ++nf) {
00264   recordCollection_->initRecords(fieldIDs[nf], fieldSizes[nf],
00265                1, &ID, fieldMasks_);
00266       }
00267     }
00268   }
00269 
00270   return(0);
00271 }
00272 
00273 int snl_fei::RecordMsgHandler::eqnNumbersMsgLength(int destProc)
00274 {
00275   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00276   fei::comm_map::row_type::const_iterator
00277     id_iter = ids->begin(),
00278     id_end = ids->end();
00279   int len = ids->size();
00280 
00281   len *= 3;
00282 
00283   for(; id_iter != id_end; ++id_iter) {
00284     int ID = *id_iter;
00285     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00286     if (rec == NULL) {
00287       ERReturn(-1);
00288     }
00289 
00290     len += rec->getFieldMask()->getNumIndices();
00291   }
00292 
00293   return(len);
00294 }
00295 
00296 int snl_fei::RecordMsgHandler::packEqnNumbersMsg(int destProc,
00297              std::vector<int>& msg)
00298 {
00299   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00300   int len = ids->size()*3;
00301   msg.resize(len);
00302   const int* eqnNumPtr = &eqnNumbers_[0];
00303 
00304   fei::comm_map::row_type::const_iterator
00305     id_iter = ids->begin(),
00306     id_end = ids->end();
00307   int offset = 0;
00308   for(; id_iter != id_end; ++id_iter) {
00309     int ID = *id_iter;
00310     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00311     if (rec == NULL) {
00312       ERReturn(-1);
00313     }
00314 
00315     len = rec->getFieldMask()->getNumIndices();
00316 
00317     msg[offset++] = ID;
00318     msg[offset++] = rec->getNumber();
00319     msg[offset++] = len;
00320 
00321     const int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
00322     for(int i=0; i<len; ++i) {
00323       msg.push_back(eqnNumbers[i]);
00324     }
00325   }
00326 
00327   return(0);
00328 }
00329 
00330 int snl_fei::RecordMsgHandler::storeEqnNumbers(int srcProc, std::vector<int>& msg)
00331 {
00332   int numIDs = recvPattern_->getRow(srcProc)->size();
00333   int offset = numIDs*3;
00334   int* msgPtr = &msg[0];
00335   int* eqnNumPtr = &eqnNumbers_[0];
00336   for(int i=0; i<numIDs; ++i) {
00337     int ID = msgPtr[i*3];
00338     int recNumber = msgPtr[i*3+1];
00339     int numEqns = msgPtr[i*3+2];
00340     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00341     if (rec == NULL) {
00342       ERReturn(-1);
00343     }
00344 
00345     rec->setNumber(recNumber);
00346     int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
00347     for(int eq=0; eq<numEqns; ++eq) {
00348       eqnNumbers[eq] = msgPtr[offset++];
00349       ptBlkMap_.setEqn(eqnNumbers[eq], recNumber, numEqns);
00350     }
00351   }
00352 
00353   return(0);
00354 }
00355 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends