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_global_to_local_map_(),
00060     doesSomeoneHaveMyMap(false),
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_global_to_local_map_(),
00073     doesSomeoneHaveMyMap(false),
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 //----------------------------------------------------------------------------
00086 void snl_fei::RecordCollection::initRecords(int numIDs, const int* IDs,
00087                                             std::vector<fei::FieldMask*>& fieldMasks,
00088                                             int* recordLocalIDs)
00089 {
00090   int maskID = 0;
00091   fei::FieldMask* mask = NULL;
00092   for(unsigned m=0; m<fieldMasks.size(); ++m) {
00093     if (maskID == fieldMasks[m]->getMaskID()) {
00094       mask = fieldMasks[m]; break;
00095     }
00096   }
00097 
00098   if (mask == NULL) {
00099     mask = new fei::FieldMask();
00100     maskID = mask->getMaskID();
00101     fieldMasks.push_back(mask);
00102   }
00103 
00104   
00105   syncFrom();
00106   for(int i=0; i<numIDs; ++i) {
00107     int local_id;
00108     fei::IndexType<int,int>::iterator iter = m_global_to_local.find(IDs[i]);
00109     if (iter == m_global_to_local.end() ) {
00110       //record doesn't exist, so we'll add a new one.
00111       local_id = m_records.size();
00112       m_global_to_local.insert(iter, std::make_pair(IDs[i], local_id));
00113       fei::Record<int> record;
00114       record.setID(IDs[i]);
00115       record.setFieldMask(mask);
00116       record.setOwnerProc(localProc_);
00117       m_records.push_back(record);
00118     }
00119     else {
00120       local_id = iter->second;
00121     }
00122 
00123     if (recordLocalIDs != NULL) recordLocalIDs[i] = local_id;
00124   }
00125   syncTo();
00126 }
00127 
00128 //----------------------------------------------------------------------------
00129 void snl_fei::RecordCollection::initRecords(int fieldID, int fieldSize,
00130                                               int numIDs, const int* IDs,
00131                                               std::vector<fei::FieldMask*>& fieldMasks,
00132                                               int* recordLocalIDs)
00133 {
00134   int maskID = fei::FieldMask::calculateMaskID(1, &fieldID);
00135   fei::FieldMask* mask = NULL;
00136   for(unsigned m=0; m<fieldMasks.size(); ++m) {
00137     if (maskID == fieldMasks[m]->getMaskID()) {
00138       mask = fieldMasks[m]; break;
00139     }
00140   }
00141 
00142   if (mask == NULL) {
00143     mask = new fei::FieldMask(1, &fieldID, &fieldSize);
00144     maskID = mask->getMaskID();
00145     fieldMasks.push_back(mask);
00146   }
00147 
00148   int lastMaskID = maskID;
00149   fei::FieldMask* lastMask = mask;
00150 
00151   syncFrom();
00152   for(int i=0; i<numIDs; ++i) {
00153     int local_id;
00154     fei::IndexType<int,int>::iterator iter = m_global_to_local.find(IDs[i]);
00155     if (iter == m_global_to_local.end() ) {
00156       //record doesn't exist, so we'll add a new one.
00157       local_id = m_records.size();
00158       m_global_to_local.insert(iter, std::make_pair(IDs[i], local_id));
00159       fei::Record<int> record;
00160       record.setID(IDs[i]);
00161       record.setFieldMask(mask);
00162       record.setOwnerProc(localProc_);
00163       m_records.push_back(record);
00164 
00165       if (recordLocalIDs != NULL) {
00166         recordLocalIDs[i] = local_id;
00167       }
00168     }
00169     else {
00170       local_id = iter->second;
00171       fei::Record<int>& record = m_records[local_id];
00172 
00173       if (recordLocalIDs != NULL) {
00174         recordLocalIDs[i] = local_id;
00175       }
00176 
00177       int thisMaskID = record.getFieldMask()->getMaskID();
00178 
00179       fei::FieldMask* thisMask = record.getFieldMask();
00180       if (maskID == thisMaskID || thisMask->hasFieldID(fieldID)) {
00181         continue;
00182       }
00183 
00184       if (lastMaskID == thisMaskID) {
00185         record.setFieldMask(lastMask);
00186        continue;
00187       }
00188 
00189       int newMaskID = fei::FieldMask::calculateMaskID(*thisMask, fieldID);
00190       if (lastMaskID == newMaskID) {
00191         record.setFieldMask(lastMask);
00192         continue;
00193       }
00194 
00195       bool newMaskAlreadyExists = false;
00196       for(unsigned m=0; m<fieldMasks.size(); ++m) {
00197         if (newMaskID == fieldMasks[m]->getMaskID()) {
00198           lastMask = fieldMasks[m];
00199           lastMaskID = lastMask->getMaskID();
00200           record.setFieldMask(lastMask);
00201           newMaskAlreadyExists = true;
00202           break;
00203         }
00204       }
00205 
00206       if (!newMaskAlreadyExists) {
00207         fei::FieldMask* newmask = new fei::FieldMask(*record.getFieldMask());
00208         newmask->addField(fieldID, fieldSize);
00209         record.setFieldMask(newmask);
00210         fieldMasks.push_back(newmask);
00211         lastMask = newmask;
00212         lastMaskID = lastMask->getMaskID();
00213       }
00214     }
00215   }
00216   syncTo();
00217 }
00218 
00219 //----------------------------------------------------------------------------
00220 void snl_fei::RecordCollection::
00221 setOwners_lowestSharing(fei::SharedIDs<int>& sharedIDs)
00222 {
00223   fei::SharedIDs<int>::map_type::iterator
00224     s_beg = sharedIDs.getSharedIDs().begin(),
00225     s_end = sharedIDs.getSharedIDs().end(),
00226     s_it;
00227 
00228   std::vector<int>& owningProcs = sharedIDs.getOwningProcs();
00229 
00230   int i=0;
00231   for(i=0, s_it = s_beg; s_it != s_end; ++i, ++s_it) {
00232     int sh_id = s_it->first;
00233     fei::Record<int>* record = getRecordWithID(sh_id);
00234     if (record == NULL) continue;
00235 
00236     int proc = owningProcs[i];
00237 
00238     if (debugOutput_) {
00239       *dbgOut_ << "#   setting ID " << (int)(record->getID())
00240                << "'s owner to proc " << proc << FEI_ENDL;
00241     }
00242 
00243     record->setOwnerProc(proc);
00244   }
00245 }
00246 
00247 fei::Record<int>* snl_fei::RecordCollection::getRecordWithID(int ID)
00248 {
00249   syncFrom();
00250   fei::IndexType<int,int>::iterator iter = m_global_to_local.find(ID);
00251 
00252   if (iter == m_global_to_local.end()) {
00253     return( NULL );
00254   }
00255 
00256   return(&m_records[iter->second]);
00257 }
00258 
00259 const fei::Record<int>* snl_fei::RecordCollection::getRecordWithID(int ID) const
00260 {
00261   syncFrom();
00262   fei::IndexType<int,int>::const_iterator iter = m_global_to_local.find(ID);
00263 
00264   if (iter == m_global_to_local.end()) {
00265     return( NULL );
00266   }
00267 
00268   return(&m_records[iter->second]);
00269 }
00270 
00271 int snl_fei::RecordCollection::getGlobalBlkIndex(int ID, int& globalBlkIndex)
00272 {
00273   fei::Record<int>* record = getRecordWithID(ID);
00274   if (record == NULL) {
00275     globalBlkIndex = -1;
00276     ERReturn(-1);
00277   }
00278 
00279   globalBlkIndex = record->getNumber();
00280   return(0);
00281 }
00282 
00283 //----------------------------------------------------------------------------
00284 int snl_fei::RecordCollection::getGlobalIndex(int ID,
00285                                               int fieldID,
00286                                               int fieldSize,
00287                                               int fieldOffset,
00288                                               int whichComponentOfField,
00289                                               const int* eqnNumbers)
00290 {
00291   fei::Record<int>* record = getRecordWithID(ID);
00292   if (record == NULL) {
00293     FEI_OSTRINGSTREAM osstr;
00294     osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR, no record with "
00295        << "ID=" << ID;
00296     throw std::runtime_error(osstr.str());
00297   }
00298 
00299   fei::FieldMask* mask = record->getFieldMask();
00300   int offset = 0;
00301   try {
00302     mask->getFieldEqnOffset(fieldID, offset);
00303   }
00304   catch (...) {
00305     FEI_OSTRINGSTREAM osstr;
00306     osstr << "failed to get eqn-offset for fieldID " << fieldID
00307           << " on record with ID " << ID << ".";
00308     throw std::runtime_error(osstr.str());
00309   }
00310 
00311   const int* eqnNums = eqnNumbers + record->getOffsetIntoEqnNumbers();
00312   if (eqnNums == NULL) {
00313     FEI_OSTRINGSTREAM osstr;
00314     osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR: null pointer,"
00315          << " possibly because initComplete() hasn't been called yet?";
00316     throw std::runtime_error(osstr.str());
00317   }
00318 
00319   int globalIndex = -1;
00320   if (fieldOffset > 0) {
00321     globalIndex = eqnNums[offset + fieldOffset*fieldSize + whichComponentOfField];
00322   }
00323   else {
00324     globalIndex = eqnNums[offset + whichComponentOfField];
00325   }
00326 
00327   return(globalIndex);
00328 }
00329 
00330 
00331 //----------------------------------------------------------------------------
00332 std::map<int,int>& snl_fei::RecordCollection::getGlobalToLocalMap() const 
00333 {       
00334   if (m_global_to_local.isStdMap()) 
00335     return(m_global_to_local.asMap(m_global_to_local_map_));
00336   m_global_to_local.resyncToMap(m_global_to_local_map_);
00337   return(m_global_to_local_map_ );
00338 }
00339 
00340 //----------------------------------------------------------------------------
00341 const std::map<int,int>& snl_fei::RecordCollection::getGlobalToLocalMap() 
00342 {
00343   if (m_global_to_local.isStdMap()) 
00344     return(m_global_to_local.asMap(m_global_to_local_map_));
00345       
00346   // This will cause a lot of work once this is set
00347   doesSomeoneHaveMyMap=true;
00348 
00349   m_global_to_local.resyncToMap(m_global_to_local_map_);
00350   return(m_global_to_local_map_ );
00351 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends