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     std::vector<int>& fieldInstances = fieldMasks[i]->getFieldInstances();
00144 
00145     for(int j=0; j<numFields; ++j) {
00146       localFieldMasks[offset+j] = fieldIDs[j];
00147       localFieldMasks[offset+numFields+j] = fieldSizes[j];
00148       localFieldMasks[offset+numFields*2+j] = fieldInstances[j];
00149     }
00150     offset += numFields*3;
00151   }
00152 
00153   return(0);
00154 }
00155 
00156 int snl_fei::RecordMsgHandler::
00157 addFieldMasks(std::vector<int>& msg, std::vector<fei::FieldMask*>& fieldMasks)
00158 {
00159   int offset = 0;
00160   int* msgPtr = &msg[0];
00161   int numMasks = msgPtr[offset++];
00162   for(int i=0; i<numMasks; ++i) {
00163     int numFields = msgPtr[offset++];
00164     int numIndices = msgPtr[offset++];
00165     int* fieldIDs = NULL;
00166     int* fieldSizes = NULL;
00167     int* fieldInstances = NULL;
00168     if (numFields > 0) {
00169       fieldIDs = &(msgPtr[offset]);
00170       fieldSizes = &(msgPtr[offset+numFields]);
00171       fieldInstances = &(msgPtr[offset+numFields*2]);
00172     }
00173 
00174     int maskID = fei::FieldMask::calculateMaskID(numFields,
00175                  fieldIDs,
00176                  fieldInstances);
00177 
00178     bool maskAlreadyExists = false;
00179     for(unsigned j=0; j<fieldMasks.size(); ++j) {
00180       int existingMaskID = fieldMasks[j]->getMaskID();
00181       if (maskID == existingMaskID) {
00182   maskAlreadyExists = true; break;
00183       }
00184     }
00185 
00186     if (!maskAlreadyExists) {
00187       fei::FieldMask* newmask = new fei::FieldMask(numFields,
00188                  fieldIDs,
00189                  fieldSizes,
00190                  fieldInstances);
00191       if (numFields < 1) {
00192   newmask->setNumIndices(numIndices);
00193       }
00194       fieldMasks.push_back(newmask);
00195     }
00196 
00197     offset += 3*numFields;
00198   }
00199 
00200   return(0);
00201 }
00202 
00203 int snl_fei::RecordMsgHandler::packMaskIDs(int destProc, std::vector<int>& msg)
00204 {
00205   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00206   int len = ids->size();
00207 
00208   msg.resize(len);
00209 
00210   fei::comm_map::row_type::const_iterator
00211     id_iter = ids->begin(),
00212     id_end = ids->end();
00213 
00214   int offset = 0;
00215   int* msgPtr = &msg[0];
00216 
00217   for(; id_iter != id_end; ++id_iter) {
00218     fei::Record<int>* rec = recordCollection_->getRecordWithID(*id_iter);
00219     if (rec == NULL) {
00220       FEI_OSTRINGSTREAM osstr;
00221       osstr << "RecordMsgHandler::packMaskIDs: proc " << localProc_
00222      << " failed to find ID " << *id_iter;
00223       throw std::runtime_error(osstr.str());
00224     }
00225 
00226     msgPtr[offset++] = rec->getFieldMask()->getMaskID();
00227   }
00228 
00229   return(0);
00230 }
00231 
00232 int snl_fei::RecordMsgHandler::mergeMaskIDs(int srcProc, std::vector<int>& msg)
00233 {
00234   fei::comm_map::row_type* ids = recvPattern_->getRow(srcProc);
00235 
00236   fei::comm_map::row_type::const_iterator
00237     id_iter = ids->begin(),
00238     id_end = ids->end();
00239 
00240   int offset = 0;
00241   int* msgPtr = &msg[0];
00242 
00243   for(; id_iter != id_end; ++id_iter) {
00244     int ID = *id_iter;
00245     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00246     if (rec == NULL) {
00247       ERReturn(-1);
00248     }
00249 
00250     int maskID = msgPtr[offset++];
00251 
00252     if (maskID != rec->getFieldMask()->getMaskID()) {
00253       //if the masks don't match, we need to add the fields from the
00254       //incoming-field-mask-id to our record's field-mask.
00255 
00256       //first, find the field-mask for 'maskID'
00257       fei::FieldMask* mask = NULL;
00258       for(unsigned fm=0; fm<fieldMasks_.size(); ++fm) {
00259   if (fieldMasks_[fm]->getMaskID() == maskID) mask = fieldMasks_[fm];
00260       }
00261       if (mask == NULL) {
00262   FEI_CERR << "mergeMaskIDs didn't find mask for maskID="
00263            << maskID<<FEI_ENDL;
00264   ERReturn(-1);
00265       }
00266 
00267       int numFields = mask->getNumFields();
00268       std::vector<int>& fieldIDs = mask->getFieldIDs();
00269       std::vector<int>& fieldSizes = mask->getFieldSizes();
00270       std::vector<int>& fieldInstances = mask->getFieldInstances();
00271 
00272       for(int nf=0; nf<numFields; ++nf) {
00273   recordCollection_->initRecords(fieldIDs[nf], fieldSizes[nf],
00274                fieldInstances[nf],
00275                1, &ID, fieldMasks_);
00276       }
00277     }
00278   }
00279 
00280   return(0);
00281 }
00282 
00283 int snl_fei::RecordMsgHandler::eqnNumbersMsgLength(int destProc)
00284 {
00285   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00286   fei::comm_map::row_type::const_iterator
00287     id_iter = ids->begin(),
00288     id_end = ids->end();
00289   int len = ids->size();
00290 
00291   len *= 3;
00292 
00293   for(; id_iter != id_end; ++id_iter) {
00294     int ID = *id_iter;
00295     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00296     if (rec == NULL) {
00297       ERReturn(-1);
00298     }
00299 
00300     len += rec->getFieldMask()->getNumIndices();
00301   }
00302 
00303   return(len);
00304 }
00305 
00306 int snl_fei::RecordMsgHandler::packEqnNumbersMsg(int destProc,
00307              std::vector<int>& msg)
00308 {
00309   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00310   int len = ids->size()*3;
00311   msg.resize(len);
00312   const int* eqnNumPtr = &eqnNumbers_[0];
00313 
00314   fei::comm_map::row_type::const_iterator
00315     id_iter = ids->begin(),
00316     id_end = ids->end();
00317   int offset = 0;
00318   for(; id_iter != id_end; ++id_iter) {
00319     int ID = *id_iter;
00320     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00321     if (rec == NULL) {
00322       ERReturn(-1);
00323     }
00324 
00325     len = rec->getFieldMask()->getNumIndices();
00326 
00327     msg[offset++] = ID;
00328     msg[offset++] = rec->getNumber();
00329     msg[offset++] = len;
00330 
00331     const int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
00332     for(int i=0; i<len; ++i) {
00333       msg.push_back(eqnNumbers[i]);
00334     }
00335   }
00336 
00337   return(0);
00338 }
00339 
00340 int snl_fei::RecordMsgHandler::storeEqnNumbers(int srcProc, std::vector<int>& msg)
00341 {
00342   int numIDs = recvPattern_->getRow(srcProc)->size();
00343   int offset = numIDs*3;
00344   int* msgPtr = &msg[0];
00345   int* eqnNumPtr = &eqnNumbers_[0];
00346   for(int i=0; i<numIDs; ++i) {
00347     int ID = msgPtr[i*3];
00348     int recNumber = msgPtr[i*3+1];
00349     int numEqns = msgPtr[i*3+2];
00350     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00351     if (rec == NULL) {
00352       ERReturn(-1);
00353     }
00354 
00355     rec->setNumber(recNumber);
00356     int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
00357     for(int eq=0; eq<numEqns; ++eq) {
00358       eqnNumbers[eq] = msgPtr[offset++];
00359       ptBlkMap_.setEqn(eqnNumbers[eq], recNumber, numEqns);
00360     }
00361   }
00362 
00363   return(0);
00364 }
00365 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends