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