FEI Version of the Day
snl_fei_RecordMsgHandler.cpp
00001 /*
00002 // @HEADER
00003 // ************************************************************************
00004 //             FEI: Finite Element Interface to Linear Solvers
00005 //                  Copyright (2005) Sandia Corporation.
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the
00008 // U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Alan Williams (william@sandia.gov) 
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 */
00042 
00043 
00044 #include "fei_sstream.hpp"
00045 
00046 #include "snl_fei_RecordMsgHandler.hpp"
00047 #include "snl_fei_RecordCollection.hpp"
00048 #include "snl_fei_PointBlockMap.hpp"
00049 #include "fei_FieldMask.hpp"
00050 #include "fei_TemplateUtils.hpp"
00051 
00052 #undef fei_file
00053 #define fei_file "snl_fei_RecordMsgHandler.cpp"
00054 #include "fei_ErrMacros.hpp"
00055 
00056 snl_fei::RecordMsgHandler::RecordMsgHandler(int localProc,
00057               RecordCollection* recordCollection,
00058               snl_fei::PointBlockMap& ptBlkMap,
00059               std::vector<fei::FieldMask*>& fieldMasks,
00060               std::vector<int>& eqnNumbers)
00061   :sendPattern_(NULL),
00062    recvPattern_(NULL),
00063    recordCollection_(recordCollection),
00064    ptBlkMap_(ptBlkMap),
00065    fieldMasks_(fieldMasks),
00066    whichTask_(_FieldMasks_),
00067    sendProcs_(0, 32),
00068    recvProcs_(0, 32),
00069    eqnNumbers_(eqnNumbers),
00070    localProc_(localProc)
00071 {
00072 }
00073 
00074 snl_fei::RecordMsgHandler::~RecordMsgHandler()
00075 {
00076 }
00077 
00078 std::vector<int>& snl_fei::RecordMsgHandler::getSendProcs()
00079 {
00080   fei::copyKeysToVector(sendPattern_->getMap(), sendProcs_);
00081   return(sendProcs_);
00082 }
00083 
00084 std::vector<int>& snl_fei::RecordMsgHandler::getRecvProcs()
00085 {
00086   fei::copyKeysToVector(recvPattern_->getMap(), recvProcs_);
00087   return(recvProcs_);
00088 }
00089 
00090 int snl_fei::RecordMsgHandler::getSendMessageLength(int destProc,
00091                 int& messageLength)
00092 {
00093   if (sendPattern_ == NULL || recvPattern_ == NULL) ERReturn(-1);
00094 
00095   switch(whichTask_) {
00096   case _FieldMasks_:
00097     messageLength = localFieldMaskMessageSize(fieldMasks_);    break;
00098   case _MaskIDs_:
00099     messageLength = sendPattern_->getRow(destProc)->size();  break;
00100   case _EqnNumbers_:
00101     messageLength = eqnNumbersMsgLength(destProc);  break;
00102   default:
00103     std::abort();
00104   }
00105 
00106   return(0);
00107 }
00108 
00109 int snl_fei::RecordMsgHandler::getSendMessage(int destProc,
00110                 std::vector<int>& message)
00111 {
00112   switch(whichTask_) {
00113   case _FieldMasks_:
00114     CHK_ERR( packLocalFieldMasks(fieldMasks_, message) );    break;
00115   case _MaskIDs_:
00116     CHK_ERR( packMaskIDs(destProc, message) );  break;
00117   case _EqnNumbers_:
00118     CHK_ERR( packEqnNumbersMsg(destProc, message) );  break;
00119   default:
00120     std::abort();
00121   }
00122 
00123   return(0);
00124 }
00125 
00126 int snl_fei::RecordMsgHandler::processRecvMessage(int srcProc,
00127               std::vector<int>& message)
00128 {
00129   switch(whichTask_) {
00130   case _FieldMasks_:
00131     CHK_ERR( addFieldMasks(message, fieldMasks_) );    break;
00132   case _MaskIDs_:
00133     CHK_ERR( mergeMaskIDs(srcProc, message) );  break;
00134   case _EqnNumbers_:
00135     CHK_ERR( storeEqnNumbers(srcProc, message) );  break;
00136   default:
00137     std::abort();
00138   }
00139 
00140   return(0);
00141 }
00142 
00143 int snl_fei::RecordMsgHandler::
00144 localFieldMaskMessageSize(std::vector<fei::FieldMask*>& fieldMasks)
00145 {
00146   //msg-size will be 1+sum(numFields*3+2)
00147   int numLocalMasks = fieldMasks.size();
00148   int i, msgSize = 1;
00149   for(i=0; i<numLocalMasks; ++i) {
00150     msgSize += (fieldMasks[i]->getNumFields())*3+2;
00151   }
00152 
00153   return( msgSize );
00154 }
00155 
00156 int snl_fei::RecordMsgHandler::
00157 packLocalFieldMasks(std::vector<fei::FieldMask*>& fieldMasks,
00158         std::vector<int>& localFieldMasks)
00159 {
00160   int numLocalMasks = fieldMasks.size();
00161   int msgSize = 1;
00162   for(int ii=0; ii<numLocalMasks; ++ii) {
00163     msgSize += fieldMasks[ii]->getNumFields()*3+2;
00164   }
00165 
00166   localFieldMasks.resize(msgSize);
00167 
00168   int offset = 0;
00169   localFieldMasks[offset++] = fieldMasks.size();
00170   for(unsigned i=0; i<fieldMasks.size(); ++i) {
00171     int numFields = fieldMasks[i]->getNumFields();
00172     int numIndices = fieldMasks[i]->getNumIndices();
00173     localFieldMasks[offset++] = numFields;
00174     localFieldMasks[offset++] = numIndices;
00175 
00176     std::vector<int>& fieldIDs = fieldMasks[i]->getFieldIDs();
00177     std::vector<int>& fieldSizes = fieldMasks[i]->getFieldSizes();
00178 
00179     for(int j=0; j<numFields; ++j) {
00180       localFieldMasks[offset+j] = fieldIDs[j];
00181       localFieldMasks[offset+numFields+j] = fieldSizes[j];
00182     }
00183     offset += numFields*3;
00184   }
00185 
00186   return(0);
00187 }
00188 
00189 int snl_fei::RecordMsgHandler::
00190 addFieldMasks(std::vector<int>& msg, std::vector<fei::FieldMask*>& fieldMasks)
00191 {
00192   int offset = 0;
00193   int* msgPtr = &msg[0];
00194   int numMasks = msgPtr[offset++];
00195   for(int i=0; i<numMasks; ++i) {
00196     int numFields = msgPtr[offset++];
00197     int numIndices = msgPtr[offset++];
00198     int* fieldIDs = NULL;
00199     int* fieldSizes = NULL;
00200     if (numFields > 0) {
00201       fieldIDs = &(msgPtr[offset]);
00202       fieldSizes = &(msgPtr[offset+numFields]);
00203     }
00204 
00205     int maskID = fei::FieldMask::calculateMaskID(numFields, fieldIDs);
00206 
00207     bool maskAlreadyExists = false;
00208     for(unsigned j=0; j<fieldMasks.size(); ++j) {
00209       int existingMaskID = fieldMasks[j]->getMaskID();
00210       if (maskID == existingMaskID) {
00211   maskAlreadyExists = true; break;
00212       }
00213     }
00214 
00215     if (!maskAlreadyExists) {
00216       fei::FieldMask* newmask = new fei::FieldMask(numFields,
00217                  fieldIDs, fieldSizes);
00218       if (numFields < 1) {
00219   newmask->setNumIndices(numIndices);
00220       }
00221       fieldMasks.push_back(newmask);
00222     }
00223 
00224     offset += 3*numFields;
00225   }
00226 
00227   return(0);
00228 }
00229 
00230 int snl_fei::RecordMsgHandler::packMaskIDs(int destProc, std::vector<int>& msg)
00231 {
00232   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00233   int len = ids->size();
00234 
00235   msg.resize(len);
00236 
00237   fei::comm_map::row_type::const_iterator
00238     id_iter = ids->begin(),
00239     id_end = ids->end();
00240 
00241   int offset = 0;
00242   int* msgPtr = &msg[0];
00243 
00244   for(; id_iter != id_end; ++id_iter) {
00245     fei::Record<int>* rec = recordCollection_->getRecordWithID(*id_iter);
00246     if (rec == NULL) {
00247       FEI_OSTRINGSTREAM osstr;
00248       osstr << "RecordMsgHandler::packMaskIDs: proc " << localProc_
00249      << " failed to find ID " << *id_iter;
00250       throw std::runtime_error(osstr.str());
00251     }
00252 
00253     msgPtr[offset++] = rec->getFieldMask()->getMaskID();
00254   }
00255 
00256   return(0);
00257 }
00258 
00259 int snl_fei::RecordMsgHandler::mergeMaskIDs(int srcProc, std::vector<int>& msg)
00260 {
00261   fei::comm_map::row_type* ids = recvPattern_->getRow(srcProc);
00262 
00263   fei::comm_map::row_type::const_iterator
00264     id_iter = ids->begin(),
00265     id_end = ids->end();
00266 
00267   int offset = 0;
00268   int* msgPtr = &msg[0];
00269 
00270   for(; id_iter != id_end; ++id_iter) {
00271     int ID = *id_iter;
00272     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00273     if (rec == NULL) {
00274       ERReturn(-1);
00275     }
00276 
00277     int maskID = msgPtr[offset++];
00278 
00279     if (maskID != rec->getFieldMask()->getMaskID()) {
00280       //if the masks don't match, we need to add the fields from the
00281       //incoming-field-mask-id to our record's field-mask.
00282 
00283       //first, find the field-mask for 'maskID'
00284       fei::FieldMask* mask = NULL;
00285       for(unsigned fm=0; fm<fieldMasks_.size(); ++fm) {
00286   if (fieldMasks_[fm]->getMaskID() == maskID) mask = fieldMasks_[fm];
00287       }
00288       if (mask == NULL) {
00289   fei::console_out() << "mergeMaskIDs didn't find mask for maskID="
00290            << maskID<<FEI_ENDL;
00291   ERReturn(-1);
00292       }
00293 
00294       int numFields = mask->getNumFields();
00295       std::vector<int>& fieldIDs = mask->getFieldIDs();
00296       std::vector<int>& fieldSizes = mask->getFieldSizes();
00297 
00298       for(int nf=0; nf<numFields; ++nf) {
00299   recordCollection_->initRecords(fieldIDs[nf], fieldSizes[nf],
00300                1, &ID, fieldMasks_);
00301       }
00302     }
00303   }
00304 
00305   return(0);
00306 }
00307 
00308 int snl_fei::RecordMsgHandler::eqnNumbersMsgLength(int destProc)
00309 {
00310   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00311   fei::comm_map::row_type::const_iterator
00312     id_iter = ids->begin(),
00313     id_end = ids->end();
00314   int len = ids->size();
00315 
00316   len *= 3;
00317 
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 
00328   return(len);
00329 }
00330 
00331 int snl_fei::RecordMsgHandler::packEqnNumbersMsg(int destProc,
00332              std::vector<int>& msg)
00333 {
00334   fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
00335   int len = ids->size()*3;
00336   msg.resize(len);
00337   const int* eqnNumPtr = &eqnNumbers_[0];
00338 
00339   fei::comm_map::row_type::const_iterator
00340     id_iter = ids->begin(),
00341     id_end = ids->end();
00342   int offset = 0;
00343   for(; id_iter != id_end; ++id_iter) {
00344     int ID = *id_iter;
00345     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00346     if (rec == NULL) {
00347       ERReturn(-1);
00348     }
00349 
00350     len = rec->getFieldMask()->getNumIndices();
00351 
00352     msg[offset++] = ID;
00353     msg[offset++] = rec->getNumber();
00354     msg[offset++] = len;
00355 
00356     const int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
00357     for(int i=0; i<len; ++i) {
00358       msg.push_back(eqnNumbers[i]);
00359     }
00360   }
00361 
00362   return(0);
00363 }
00364 
00365 int snl_fei::RecordMsgHandler::storeEqnNumbers(int srcProc, std::vector<int>& msg)
00366 {
00367   int numIDs = recvPattern_->getRow(srcProc)->size();
00368   int offset = numIDs*3;
00369   int* msgPtr = &msg[0];
00370   int* eqnNumPtr = &eqnNumbers_[0];
00371   for(int i=0; i<numIDs; ++i) {
00372     int ID = msgPtr[i*3];
00373     int recNumber = msgPtr[i*3+1];
00374     int numEqns = msgPtr[i*3+2];
00375     fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
00376     if (rec == NULL) {
00377       ERReturn(-1);
00378     }
00379 
00380     rec->setNumber(recNumber);
00381     int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
00382     for(int eq=0; eq<numEqns; ++eq) {
00383       eqnNumbers[eq] = msgPtr[offset++];
00384       ptBlkMap_.setEqn(eqnNumbers[eq], recNumber, numEqns);
00385     }
00386   }
00387 
00388   return(0);
00389 }
00390 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends