FEI Version of the Day
snl_fei_RecordCollection.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 "fei_FieldMask.hpp"
00012 #include "fei_Record.hpp"
00013 #include "snl_fei_RecordCollection.hpp"
00014 #include "fei_SharedIDs.hpp"
00015 
00016 #undef fei_file
00017 #define fei_file "snl_fei_RecordCollection.cpp"
00018 #include "fei_ErrMacros.hpp"
00019 
00020 //----------------------------------------------------------------------------
00021 snl_fei::RecordCollection::RecordCollection(int localProc)
00022   : m_records(),
00023     m_global_to_local(),
00024     m_minID(99999999),
00025     m_maxID(0),
00026     localProc_(localProc),
00027     debugOutput_(false),
00028     dbgOut_(NULL)
00029 {
00030   m_records.reserve(2000);
00031 }
00032 
00033 //----------------------------------------------------------------------------
00034 snl_fei::RecordCollection::RecordCollection(const RecordCollection& src)
00035   : m_records(src.m_records),
00036     m_global_to_local(src.m_global_to_local),
00037     m_minID(99999999),
00038     m_maxID(0),
00039     localProc_(src.localProc_),
00040     debugOutput_(src.debugOutput_),
00041     dbgOut_(src.dbgOut_)
00042 {
00043 }
00044 
00045 //----------------------------------------------------------------------------
00046 snl_fei::RecordCollection::~RecordCollection()
00047 {
00048 }
00049 
00050 void snl_fei::RecordCollection::setIDMap(
00051           const int* localIDs_begin, const int* localIDs_end,
00052           const int* globalIDs_begin, const int* globalIDs_end)
00053 {
00054   int numLocal = localIDs_end - localIDs_begin;
00055   int numGlobal = globalIDs_end - globalIDs_begin;
00056   if (numLocal != numGlobal) {
00057     throw std::runtime_error("RecordCollection::setIDMap ERROR, num local IDs must match num global IDs.");
00058   }
00059   m_global_to_local.clear();
00060   m_records.resize(numLocal);
00061   const int* localID_iter = localIDs_begin;
00062   const int* globalID_iter = globalIDs_begin;
00063   for(int i=0; i<numLocal; ++i) {
00064     int lid = *localID_iter++;
00065     int gid = *globalID_iter++;
00066     m_records[lid].setID(gid);
00067     m_records[lid].setOwnerProc(localProc_);
00068     m_global_to_local.insert(std::make_pair(gid, lid));
00069   }
00070 }
00071 
00072 //----------------------------------------------------------------------------
00073 void snl_fei::RecordCollection::initRecords(int numIDs, const int* IDs,
00074                                             std::vector<fei::FieldMask*>& fieldMasks,
00075                                             int* recordLocalIDs)
00076 {
00077   int maskID = 0;
00078   fei::FieldMask* mask = NULL;
00079   for(unsigned m=0; m<fieldMasks.size(); ++m) {
00080     if (maskID == fieldMasks[m]->getMaskID()) {
00081       mask = fieldMasks[m]; break;
00082     }
00083   }
00084 
00085   if (mask == NULL) {
00086     mask = new fei::FieldMask();
00087     maskID = mask->getMaskID();
00088     fieldMasks.push_back(mask);
00089   }
00090 
00091   for(int i=0; i<numIDs; ++i) {
00092     if (m_minID > IDs[i]) m_minID = IDs[i];
00093     if (m_maxID < IDs[i]) m_maxID = IDs[i];
00094 
00095     int local_id = -1;
00096     std::map<int,int>::iterator iter = m_global_to_local.lower_bound(IDs[i]);
00097     if (iter == m_global_to_local.end() || iter->first != IDs[i]) {
00098       //record doesn't exist, so we'll add a new one.
00099       local_id = m_records.size();
00100       m_global_to_local.insert(iter, std::make_pair(IDs[i], local_id));
00101       fei::Record<int> record;
00102       record.setID(IDs[i]);
00103       record.setFieldMask(mask);
00104       record.setOwnerProc(-1);
00105       m_records.push_back(record);
00106     }
00107     else {
00108       local_id = iter->second;
00109     }
00110 
00111     if (recordLocalIDs != NULL) recordLocalIDs[i] = local_id;
00112   }
00113 }
00114 
00115 //----------------------------------------------------------------------------
00116 void snl_fei::RecordCollection::initRecords(int fieldID, int fieldSize,
00117                                               int numIDs, const int* IDs,
00118                                               std::vector<fei::FieldMask*>& fieldMasks,
00119                                               int* recordLocalIDs)
00120 {
00121   int maskID = fei::FieldMask::calculateMaskID(1, &fieldID);
00122   fei::FieldMask* mask = NULL;
00123   for(unsigned m=0; m<fieldMasks.size(); ++m) {
00124     if (maskID == fieldMasks[m]->getMaskID()) {
00125       mask = fieldMasks[m]; break;
00126     }
00127   }
00128 
00129   if (mask == NULL) {
00130     mask = new fei::FieldMask(1, &fieldID, &fieldSize);
00131     maskID = mask->getMaskID();
00132     fieldMasks.push_back(mask);
00133   }
00134 
00135   int lastMaskID = maskID;
00136   fei::FieldMask* lastMask = mask;
00137 
00138   for(int i=0; i<numIDs; ++i) {
00139     if (m_minID > IDs[i]) m_minID = IDs[i];
00140     if (m_maxID < IDs[i]) m_maxID = IDs[i];
00141     int local_id;
00142     std::map<int,int>::iterator iter = m_global_to_local.lower_bound(IDs[i]);
00143     if (iter == m_global_to_local.end() || iter->first != IDs[i]) {
00144       //record doesn't exist, so we'll add a new one.
00145       local_id = m_records.size();
00146       m_global_to_local.insert(iter, std::make_pair(IDs[i], local_id));
00147       fei::Record<int> record;
00148       record.setID(IDs[i]);
00149       record.setFieldMask(mask);
00150       record.setOwnerProc(-1);
00151       m_records.push_back(record);
00152 
00153       if (recordLocalIDs != NULL) {
00154         recordLocalIDs[i] = local_id;
00155       }
00156     }
00157     else {
00158       local_id = iter->second;
00159       fei::Record<int>& record = m_records[local_id];
00160 
00161       if (recordLocalIDs != NULL) {
00162         recordLocalIDs[i] = local_id;
00163       }
00164 
00165       fei::FieldMask* thisMask = record.getFieldMask();
00166       if (thisMask == NULL) {
00167         record.setFieldMask(mask);
00168       }
00169 
00170       int thisMaskID = record.getFieldMask()->getMaskID();
00171 
00172       if (maskID == thisMaskID || thisMask->hasFieldID(fieldID)) {
00173         continue;
00174       }
00175 
00176       if (lastMaskID == thisMaskID) {
00177         record.setFieldMask(lastMask);
00178        continue;
00179       }
00180 
00181       int newMaskID = fei::FieldMask::calculateMaskID(*thisMask, fieldID);
00182       if (lastMaskID == newMaskID) {
00183         record.setFieldMask(lastMask);
00184         continue;
00185       }
00186 
00187       bool newMaskAlreadyExists = false;
00188       for(unsigned m=0; m<fieldMasks.size(); ++m) {
00189         if (newMaskID == fieldMasks[m]->getMaskID()) {
00190           lastMask = fieldMasks[m];
00191           lastMaskID = lastMask->getMaskID();
00192           record.setFieldMask(lastMask);
00193           newMaskAlreadyExists = true;
00194           break;
00195         }
00196       }
00197 
00198       if (!newMaskAlreadyExists) {
00199         fei::FieldMask* newmask = new fei::FieldMask(*record.getFieldMask());
00200         newmask->addField(fieldID, fieldSize);
00201         record.setFieldMask(newmask);
00202         fieldMasks.push_back(newmask);
00203         lastMask = newmask;
00204         lastMaskID = lastMask->getMaskID();
00205       }
00206     }
00207   }
00208 }
00209 
00210 //----------------------------------------------------------------------------
00211 void snl_fei::RecordCollection::setOwners_local()
00212 {
00213   for(size_t i=0; i<m_records.size(); ++i) {
00214     fei::Record<int>& rec = m_records[i];
00215     if (rec.getOwnerProc() == -1) rec.setOwnerProc(localProc_);
00216   }
00217 }
00218 
00219 //----------------------------------------------------------------------------
00220 void snl_fei::RecordCollection::setOwners_lowestSharing(fei::SharedIDs<int>& sharedIDs)
00221 {
00222   fei::SharedIDs<int>::map_type::iterator
00223     s_beg = sharedIDs.getSharedIDs().begin(),
00224     s_end = sharedIDs.getSharedIDs().end(),
00225     s_it;
00226 
00227   std::vector<int>& owningProcs = sharedIDs.getOwningProcs();
00228 
00229   int i=0;
00230   for(i=0, s_it = s_beg; s_it != s_end; ++i, ++s_it) {
00231     int sh_id = s_it->first;
00232     fei::Record<int>* record = getRecordWithID(sh_id);
00233     if (record == NULL) continue;
00234  
00235     int rec_owner = record->getOwnerProc();
00236 
00237 //    if (rec_owner != -1 && rec_owner != owningProcs[i]) {
00238 //      std::cout<<record->getID()<<": owner="<<rec_owner<<" but lowest sharer="<<owningProcs[i]<<std::endl;
00239 //    }
00240 
00241     if (rec_owner != -1) owningProcs[i] = rec_owner;
00242     else {
00243       rec_owner = owningProcs[i];
00244       record->setOwnerProc(rec_owner);
00245     }
00246 
00247     if (debugOutput_) {
00248       *dbgOut_ << "#   setting ID " << (int)(record->getID())
00249                << "'s owner to proc " << rec_owner << FEI_ENDL;
00250     }
00251   }
00252 }
00253 
00254 fei::Record<int>* snl_fei::RecordCollection::getRecordWithID(int ID)
00255 {
00256   std::map<int,int>::iterator iter = m_global_to_local.find(ID);
00257 
00258   if (iter == m_global_to_local.end()) {
00259     return( NULL );
00260   }
00261 
00262   return(&m_records[iter->second]);
00263 }
00264 
00265 const fei::Record<int>* snl_fei::RecordCollection::getRecordWithID(int ID) const
00266 {
00267   std::map<int,int>::const_iterator iter = m_global_to_local.find(ID);
00268 
00269   if (iter == m_global_to_local.end()) {
00270     return( NULL );
00271   }
00272 
00273   return(&m_records[iter->second]);
00274 }
00275 
00276 int snl_fei::RecordCollection::getGlobalBlkIndex(int ID, int& globalBlkIndex)
00277 {
00278   fei::Record<int>* record = getRecordWithID(ID);
00279   if (record == NULL) {
00280     globalBlkIndex = -1;
00281     ERReturn(-1);
00282   }
00283 
00284   globalBlkIndex = record->getNumber();
00285   return(0);
00286 }
00287 
00288 //----------------------------------------------------------------------------
00289 int snl_fei::RecordCollection::getGlobalIndex(int ID,
00290                                               int fieldID,
00291                                               int fieldSize,
00292                                               int fieldOffset,
00293                                               int whichComponentOfField,
00294                                               const int* eqnNumbers)
00295 {
00296   fei::Record<int>* record = getRecordWithID(ID);
00297   if (record == NULL) {
00298     FEI_OSTRINGSTREAM osstr;
00299     osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR, no record with "
00300        << "ID=" << ID;
00301     throw std::runtime_error(osstr.str());
00302   }
00303 
00304   fei::FieldMask* mask = record->getFieldMask();
00305   int offset = 0;
00306   try {
00307     mask->getFieldEqnOffset(fieldID, offset);
00308   }
00309   catch (...) {
00310     FEI_OSTRINGSTREAM osstr;
00311     osstr << "failed to get eqn-offset for fieldID " << fieldID
00312           << " on record with ID " << ID << ".";
00313     throw std::runtime_error(osstr.str());
00314   }
00315 
00316   const int* eqnNums = eqnNumbers + record->getOffsetIntoEqnNumbers();
00317   if (eqnNums == NULL) {
00318     FEI_OSTRINGSTREAM osstr;
00319     osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR: null pointer,"
00320          << " possibly because initComplete() hasn't been called yet?";
00321     throw std::runtime_error(osstr.str());
00322   }
00323 
00324   int globalIndex = -1;
00325   if (fieldOffset > 0) {
00326     globalIndex = eqnNums[offset + fieldOffset*fieldSize + whichComponentOfField];
00327   }
00328   else {
00329     globalIndex = eqnNums[offset + whichComponentOfField];
00330   }
00331 
00332   return(globalIndex);
00333 }
00334 
00335 //----------------------------------------------------------------------------
00336 int snl_fei::RecordCollection::getGlobalIndexLocalID(int localID,
00337                                               int fieldID,
00338                                               int fieldSize,
00339                                               int fieldOffset,
00340                                               int whichComponentOfField,
00341                                               const int* eqnNumbers)
00342 {
00343   fei::Record<int>* record = getRecordWithLocalID(localID);
00344   if (record == NULL) {
00345     FEI_OSTRINGSTREAM osstr;
00346     osstr << "snl_fei::RecordCollection::getGlobalIndexLocalID ERROR, no record with "
00347        << "localID=" << localID;
00348     throw std::runtime_error(osstr.str());
00349   }
00350 
00351   fei::FieldMask* mask = record->getFieldMask();
00352   int offset = 0;
00353   try {
00354     mask->getFieldEqnOffset(fieldID, offset);
00355   }
00356   catch (...) {
00357     FEI_OSTRINGSTREAM osstr;
00358     osstr << "failed to get eqn-offset for fieldID " << fieldID
00359           << " on record with localID " << localID << ".";
00360     throw std::runtime_error(osstr.str());
00361   }
00362 
00363   const int* eqnNums = eqnNumbers + record->getOffsetIntoEqnNumbers();
00364   if (eqnNums == NULL) {
00365     FEI_OSTRINGSTREAM osstr;
00366     osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR: null pointer,"
00367          << " possibly because initComplete() hasn't been called yet?";
00368     throw std::runtime_error(osstr.str());
00369   }
00370 
00371   int globalIndex = -1;
00372   if (fieldOffset > 0) {
00373     globalIndex = eqnNums[offset + fieldOffset*fieldSize + whichComponentOfField];
00374   }
00375   else {
00376     globalIndex = eqnNums[offset + whichComponentOfField];
00377   }
00378 
00379   return(globalIndex);
00380 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends