fei_NodeDatabase.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_NodeDatabase.hpp>
00010 
00011 #include <fei_CommUtils.hpp>
00012 #include <fei_NodeDescriptor.hpp>
00013 #include <fei_NodeCommMgr.hpp>
00014 
00015 #include <fei_macros.hpp>
00016 #include <fei_TemplateUtils.hpp>
00017 #undef fei_file
00018 #define fei_file "fei_NodeDatabase.cpp"
00019 
00020 #include <fei_ErrMacros.hpp>
00021 
00022 //------------------------------------------------------------------------------
00023 NodeDatabase::NodeDatabase(std::map<int,int>* fieldDatabase,
00024                            NodeCommMgr* nodeCommMgr)
00025   : nodePtrs_(),
00026     eqnNumbers_(0), eqnNodeIndices_(),
00027     nodeIDs_(),
00028     nodeNumbers_(),
00029     synchronized_(false),
00030     need_to_alloc_and_sync_(true),
00031     fieldDB_(fieldDatabase),
00032     nodeCommMgr_(nodeCommMgr),
00033     numLocalNodes_(0),
00034     firstLocalNodeNumber_(-1), lastLocalNodeNumber_(-1),
00035     nodePool_()
00036 {
00037 }
00038 
00039 //------------------------------------------------------------------------------
00040 NodeDatabase::~NodeDatabase()
00041 {
00042   deleteMemory();
00043 }
00044 
00045 //------------------------------------------------------------------------------
00046 void NodeDatabase::deleteMemory()
00047 {
00048   for(size_t i=0; i<nodePtrs_.size(); ++i) {
00049     nodePool_.destroy(nodePtrs_[i]);
00050     nodePool_.deallocate(nodePtrs_[i], 1);
00051   }
00052 }
00053 
00054 //------------------------------------------------------------------------------
00055 int NodeDatabase::getNodeWithID(GlobalID nodeID, const NodeDescriptor*& node) const
00056 {
00057   int index = getIndexOfID(nodeID);
00058   if (index < 0) {
00059     //FEI_CERR << "FEI NodeDatabase: node " << (int)nodeID << " not found."<<FEI_ENDL;
00060     return(-1);
00061   }
00062 
00063   node = nodePtrs_[index];
00064   return(0);
00065 }
00066 
00067 //------------------------------------------------------------------------------
00068 int NodeDatabase::getNodeWithID(GlobalID nodeID, NodeDescriptor*& node)
00069 {
00070   int index = getIndexOfID(nodeID);
00071   if (index < 0) {
00072     //FEI_CERR << "FEI NodeDatabase: node " << (int)nodeID << " not found."<<FEI_ENDL;
00073     return(-1);
00074   }
00075 
00076   node = nodePtrs_[index];
00077   return(0);
00078 }
00079 
00080 //------------------------------------------------------------------------------
00081 int NodeDatabase::getNodeWithNumber(int nodeNumber, const NodeDescriptor*& node) const
00082 {
00083   if (!synchronized_) ERReturn(-1);
00084 
00085   std::map<int,int>::const_iterator iter = nodeNumbers_.find(nodeNumber);
00086   if (iter == nodeNumbers_.end()) {
00087     ERReturn(-1);
00088   }
00089 
00090   int index = iter->second;
00091   node = nodePtrs_[index];
00092 
00093   return(0);
00094 }
00095 
00096 //------------------------------------------------------------------------------
00097 int NodeDatabase::getNodeWithEqn(int eqnNumber, const NodeDescriptor*& node) const
00098 {
00099   int insertPoint = -1;
00100   int index = fei::binarySearch(eqnNumber, eqnNumbers_, insertPoint);
00101 
00102   if (index >= 0) {
00103     node = nodePtrs_[eqnNodeIndices_[index]];
00104   }
00105   else if (insertPoint > 0) {
00106     node = nodePtrs_[eqnNodeIndices_[insertPoint-1]];
00107   }
00108   else {
00109     //We only reach this line if insertPoint==0, which means the specified
00110     //eqnNumber lies below the equation-number for the first node in our list.
00111     //In other words, we don't have the requested node.
00112     return(-1);
00113   }
00114 
00115   //Now let's make sure that the specified equation is less than or equal to
00116   //this node's last equation.
00117 
00118   int numNodeFields = node->getNumFields();
00119   if (numNodeFields <= 0) return(-1);
00120 
00121   int lastFieldOnNode = node->getFieldIDList()[numNodeFields-1];
00122 
00123   int lastFieldSize = (*fieldDB_)[lastFieldOnNode];
00124 
00125   int lastEqnOnNode = node->getFieldEqnNumbers()[numNodeFields-1] +
00126             lastFieldSize - 1;
00127 
00128   if (eqnNumber <= lastEqnOnNode) return(0);
00129 
00130   return(-1);
00131 }
00132 
00133 //------------------------------------------------------------------------------
00134 int NodeDatabase::getNodeAtIndex(int i, const NodeDescriptor*& node) const
00135 {
00136   //For performance reasons, we will assume that the caller is providing a
00137   //valid in-range index, and will forego the safety check:
00138 
00139   node = nodePtrs_[i];
00140   return(0);
00141 }
00142 
00143 //------------------------------------------------------------------------------
00144 int NodeDatabase::getNodeAtIndex(int i, NodeDescriptor*& node)
00145 {
00146   //For performance reasons, we will assume that the caller is providing a
00147   //valid in-range index, and will forego the safety check:
00148 
00149   node = nodePtrs_[i];
00150   return(0);
00151 }
00152 
00153 //------------------------------------------------------------------------------
00154 int NodeDatabase::countLocalNodalEqns(int localRank)
00155 {
00156   int numEqns = 0;
00157 
00158   for(size_t i=0; i<nodePtrs_.size(); i++) {
00159     NodeDescriptor* node = nodePtrs_[i];
00160 
00161     if (node->getOwnerProc() == localRank) {
00162       int numFields = node->getNumFields();
00163       const int* fieldIDList = node->getFieldIDList();
00164 
00165       for(int j=0; j<numFields; j++) {
00166         int numParams =        (*fieldDB_)[fieldIDList[j]];
00167 
00168         numEqns += numParams;
00169       }
00170     }
00171   }
00172 
00173   return(numEqns);
00174 }
00175 
00176 //------------------------------------------------------------------------------
00177 int NodeDatabase::countLocalNodeDescriptors(int localRank)
00178 {
00179   int numLocal = 0;
00180   for(size_t i=0; i<nodePtrs_.size(); i++) {
00181     if (nodePtrs_[i]->getOwnerProc() == localRank) numLocal++;
00182   }
00183 
00184   return(numLocal);
00185 }
00186 
00187 //------------------------------------------------------------------------------
00188 int NodeDatabase::getIndexOfID(GlobalID nodeID) const
00189 {
00190   std::map<GlobalID,int>::const_iterator
00191     iter = nodeIDs_.find(nodeID);
00192 
00193   if (iter == nodeIDs_.end()) return(-1);
00194 
00195   return( iter->second );
00196 }
00197 
00198 //------------------------------------------------------------------------------
00199 int NodeDatabase::initNodeID(GlobalID nodeID)
00200 {
00201   static NodeDescriptor dummyNode;
00202 
00203   int index = nodeIDs_.size();
00204   std::map<GlobalID,int>::iterator
00205     iter = nodeIDs_.lower_bound(nodeID);
00206 
00207   if (iter == nodeIDs_.end() || iter->first != nodeID) {
00208     nodeIDs_.insert(iter, std::make_pair(nodeID,index));
00209 
00210     NodeDescriptor* nodePtr = nodePool_.allocate(1);
00211     nodePool_.construct(nodePtr, dummyNode);
00212 
00213     nodePtr->setGlobalNodeID(nodeID);
00214 
00215     nodePtrs_.push_back(nodePtr);
00216 
00217     need_to_alloc_and_sync_ = true;
00218   }
00219 
00220   return(0);
00221 }
00222 
00223 //------------------------------------------------------------------------------
00224 int NodeDatabase::initNodeIDs(GlobalID* nodeIDs, int numNodes)
00225 {
00226   static NodeDescriptor dummyNode;
00227 
00228   for(int i=0; i<numNodes; i++) {
00229     initNodeID(nodeIDs[i]);
00230   }
00231 
00232   return(0);
00233 }
00234 
00235 //------------------------------------------------------------------------------
00236 int NodeDatabase::synchronize(int firstLocalNodeNumber,
00237                               int firstLocalEqn,
00238                               int localRank,
00239                               MPI_Comm comm)
00240 {
00241   eqnNumbers_.reserve(nodePtrs_.size());
00242   eqnNodeIndices_.reserve(nodePtrs_.size());
00243 
00244   eqnNumbers_.resize(0);
00245   eqnNodeIndices_.resize(0);
00246 
00247   firstLocalNodeNumber_ = firstLocalNodeNumber;
00248   int nodeNumber = firstLocalNodeNumber;
00249   int numEqns = 0;
00250   
00251   nodeNumbers_.clear();
00252 
00253   numLocalNodes_ = 0;
00254   std::map<GlobalID,int>::iterator
00255     iter = nodeIDs_.begin(), iter_end = nodeIDs_.end();
00256 
00257   for(; iter!=iter_end; ++iter) {
00258     int i = iter->second;
00259     NodeDescriptor* node = NULL;
00260     CHK_ERR( getNodeAtIndex(i, node) );
00261 
00262     int numFields = node->getNumFields();
00263     const int* fieldIDList = node->getFieldIDList();
00264 
00265     int numNodalDOF = 0;
00266     int firstEqnNumber, eqnNumber;
00267 
00268     for(int j=0; j<numFields; j++) {
00269       int numFieldParams = (*fieldDB_)[fieldIDList[j]];
00270       numNodalDOF += numFieldParams;
00271 
00272       if (node->getOwnerProc() == localRank) {
00273         eqnNumber = firstLocalEqn + numEqns;
00274         if (j==0) firstEqnNumber = eqnNumber;
00275 
00276         numEqns += numFieldParams;
00277 
00278         node->setFieldEqnNumber(fieldIDList[j], eqnNumber);
00279       }
00280     }
00281 
00282     if (node->getOwnerProc() == localRank) {
00283       node->setNodeNumber(nodeNumber++);
00284       numLocalNodes_++;
00285 
00286       int insertPoint = fei::sortedListInsert(firstEqnNumber, eqnNumbers_);
00287       if (insertPoint == -2) ERReturn(-2);
00288       if (insertPoint >= 0) eqnNodeIndices_.insert(eqnNodeIndices_.begin()+insertPoint, i);
00289     }
00290 
00291     node->setNumNodalDOF(numNodalDOF);
00292 
00293     int thisNodeNumber = node->getNodeNumber();
00294     nodeNumbers_.insert(std::make_pair(thisNodeNumber, i));
00295   }
00296 
00297   lastLocalNodeNumber_ = nodeNumber - 1;
00298 
00299   //  next, have the node comm manager get the field IDs and 
00300   //  equation numbers for all of the nodes that we know about but don't
00301   //  own. i.e., the remotely-owned shared nodes.
00302   //  Again, we'll get the nodeNumber info for those nodes while we're at it.
00303   //
00304   CHK_ERR( nodeCommMgr_->exchangeEqnInfo() );
00305 
00306   //Now finish up by inserting equation-numbers for shared nodes into our
00307   //eqnNumbers_ and eqnNodeIndices_ lists, for future lookups...
00308 
00309   int numSharedNodes = nodeCommMgr_->getNumSharedNodes();
00310   for(int i=0; i<numSharedNodes; i++) {
00311     NodeDescriptor& node = nodeCommMgr_->getSharedNodeAtIndex(i);
00312     GlobalID nodeID = node.getGlobalNodeID();
00313     int index = getIndexOfID(nodeID);
00314     int nDOF = node.getNumNodalDOF();
00315     if (nDOF <= 0) {
00316       FEI_COUT << "localRank " << localRank << ", node "<<nodeID<<" has nDOF="
00317            << nDOF<<FEI_ENDL;
00318       ERReturn(-1);
00319     }
00320     int firstEqn = node.getFieldEqnNumbers()[0];
00321     int insertPoint = fei::sortedListInsert(firstEqn, eqnNumbers_);
00322     if (insertPoint == -2) ERReturn(-2);
00323     if (insertPoint >= 0) eqnNodeIndices_.insert(eqnNodeIndices_.begin()+insertPoint, index);
00324 
00325     int thisNodeNumber = node.getNodeNumber();
00326     nodeNumbers_.insert(std::make_pair(thisNodeNumber, index));
00327   }
00328 
00329   synchronized_ = true;
00330   need_to_alloc_and_sync_ = false;
00331 
00332   return(0);
00333 }
00334 
00335 //------------------------------------------------------------------------------
00336 int NodeDatabase::getAssociatedNodeNumber(int eqnNumber)
00337 {
00338   int insertPoint = -1;
00339   int index = fei::binarySearch(eqnNumber, eqnNumbers_, insertPoint);
00340 
00341   if (index >= 0) {
00342     return( nodePtrs_[eqnNodeIndices_[index]]->getNodeNumber() );
00343   }
00344 
00345   if (insertPoint > 0) {
00346     NodeDescriptor& node = *(nodePtrs_[eqnNodeIndices_[insertPoint-1]]);
00347     const int* fieldEqnNumbers = node.getFieldEqnNumbers();
00348     const int* fieldIDList = node.getFieldIDList();
00349     int numFields = node.getNumFields();
00350 
00351     int lastEqn = fieldEqnNumbers[numFields-1];
00352 
00353     int fieldSize = -1;
00354     std::map<int,int>::const_iterator f_iter
00355       = fieldDB_->find(fieldIDList[numFields-1]);
00356     if (f_iter == fieldDB_->end()) ERReturn(-1);
00357     fieldSize = (*f_iter).second;
00358 
00359     //if eqnNumber is inside the range of eqn-numbers assocated with this node,
00360     //then return this node's node-number
00361     if (eqnNumber >= fieldEqnNumbers[0] && (lastEqn+fieldSize - 1) >= eqnNumber) {
00362       return( node.getNodeNumber() );
00363     }
00364   }
00365 
00366   //if we get to here, then we don't know how to locate the node with this
00367   //eqn-number...
00368   return(-1);
00369 }
00370 
00371 //------------------------------------------------------------------------------
00372 int NodeDatabase::getAssociatedFieldID(int eqnNumber)
00373 {
00374   int insertPoint = -1;
00375   int index = fei::binarySearch(eqnNumber, eqnNumbers_, insertPoint);
00376 
00377   int index2 = index;
00378   if (index2 < 0) index2 = insertPoint-1;
00379 
00380   if (index2 < 0) ERReturn(-1);
00381 
00382   NodeDescriptor& node = *(nodePtrs_[eqnNodeIndices_[index2]]);
00383 
00384   const int* fieldEqnNumbers = node.getFieldEqnNumbers();
00385   const int* fieldIDList = node.getFieldIDList();
00386   int numFields = node.getNumFields();
00387 
00388   int lastEqn = fieldEqnNumbers[numFields-1];
00389 
00390   int fieldSize = -1;
00391   std::map<int,int>::const_iterator f_iter
00392     = fieldDB_->find(fieldIDList[numFields-1]);
00393   if (f_iter == fieldDB_->end()) ERReturn(-1);
00394   fieldSize = (*f_iter).second;
00395 
00396   //if eqnNumber is outside the range of eqn-numbers that are associated with
00397   //this node, then we're in trouble...
00398   if (eqnNumber < fieldEqnNumbers[0] || eqnNumber > lastEqn+fieldSize) {
00399     ERReturn(-1);
00400   }
00401 
00402   //ok, so we're ready to figure out which fieldID eqnNumber is associated with.
00403   for(int i=0; i<numFields-1; i++) {
00404     if (eqnNumber >= fieldEqnNumbers[i] && eqnNumber < fieldEqnNumbers[i+1]) {
00405       return(fieldIDList[i]);
00406     }
00407   }
00408 
00409   //if we get to here, then eqnNumber is associated with the last fieldID on the
00410   //node.
00411   return(fieldIDList[numFields-1]);
00412 }

Generated on Tue Jul 13 09:27:45 2010 for FEI by  doxygen 1.4.7