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