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