FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fei_NodeDatabase.cpp
1 /*--------------------------------------------------------------------*/
2 /* Copyright 2005 Sandia Corporation. */
3 /* Under the terms of Contract DE-AC04-94AL85000, there is a */
4 /* non-exclusive license for use of this work by or on behalf */
5 /* of the U.S. Government. Export of this program may require */
6 /* a license from the United States Government. */
7 /*--------------------------------------------------------------------*/
8 
9 #include <fei_NodeDatabase.hpp>
10 
11 #include <fei_CommUtils.hpp>
12 #include <fei_NodeDescriptor.hpp>
13 #include <fei_NodeCommMgr.hpp>
14 
15 #include <fei_macros.hpp>
16 #include <fei_TemplateUtils.hpp>
17 #undef fei_file
18 #define fei_file "fei_NodeDatabase.cpp"
19 
20 #include <fei_ErrMacros.hpp>
21 
22 //------------------------------------------------------------------------------
23 NodeDatabase::NodeDatabase(std::map<int,int>* fieldDatabase,
24  NodeCommMgr* nodeCommMgr)
25  : nodePtrs_(),
26  eqnNumbers_(0), eqnNodeIndices_(),
27  nodeIDs_(),
28  nodeNumbers_(),
29  synchronized_(false),
30  need_to_alloc_and_sync_(true),
31  fieldDB_(fieldDatabase),
32  nodeCommMgr_(nodeCommMgr),
33  numLocalNodes_(0),
34  firstLocalNodeNumber_(-1), lastLocalNodeNumber_(-1),
35  nodePool_()
36 {
37 }
38 
39 //------------------------------------------------------------------------------
41 {
42  deleteMemory();
43 }
44 
45 //------------------------------------------------------------------------------
46 void NodeDatabase::deleteMemory()
47 {
48  for(size_t i=0; i<nodePtrs_.size(); ++i) {
49  nodePool_.destroy(nodePtrs_[i]);
50  nodePool_.deallocate(nodePtrs_[i], 1);
51  }
52 }
53 
54 //------------------------------------------------------------------------------
55 int NodeDatabase::getNodeWithID(GlobalID nodeID, const NodeDescriptor*& node) const
56 {
57  int index = getIndexOfID(nodeID);
58  if (index < 0) {
59  //fei::console_out() << "FEI NodeDatabase: node " << (int)nodeID << " not found."<<FEI_ENDL;
60  return(-1);
61  }
62 
63  node = nodePtrs_[index];
64  return(0);
65 }
66 
67 //------------------------------------------------------------------------------
68 int NodeDatabase::getNodeWithID(GlobalID nodeID, NodeDescriptor*& node)
69 {
70  int index = getIndexOfID(nodeID);
71  if (index < 0) {
72  //fei::console_out() << "FEI NodeDatabase: node " << (int)nodeID << " not found."<<FEI_ENDL;
73  return(-1);
74  }
75 
76  node = nodePtrs_[index];
77  return(0);
78 }
79 
80 //------------------------------------------------------------------------------
81 int NodeDatabase::getNodeWithNumber(int nodeNumber, const NodeDescriptor*& node) const
82 {
83  if (!synchronized_) ERReturn(-1);
84 
85  std::map<int,int>::const_iterator iter = nodeNumbers_.find(nodeNumber);
86  if (iter == nodeNumbers_.end()) {
87  // The node wasn't found, return a NULL ptr.
88  node = NULL;
89  // Indicate that the node is NULL.
90  return -1;
91  }
92 
93  int index = iter->second;
94  node = nodePtrs_[index];
95 
96  return(0);
97 }
98 
99 //------------------------------------------------------------------------------
100 int NodeDatabase::getNodeWithEqn(int eqnNumber, const NodeDescriptor*& node) const
101 {
102  int insertPoint = -1;
103  int index = fei::binarySearch(eqnNumber, eqnNumbers_, insertPoint);
104 
105  if (index >= 0) {
106  node = nodePtrs_[eqnNodeIndices_[index]];
107  }
108  else if (insertPoint > 0) {
109  node = nodePtrs_[eqnNodeIndices_[insertPoint-1]];
110  }
111  else {
112  //We only reach this line if insertPoint==0, which means the specified
113  //eqnNumber lies below the equation-number for the first node in our list.
114  //In other words, we don't have the requested node.
115  return(-1);
116  }
117 
118  //Now let's make sure that the specified equation is less than or equal to
119  //this node's last equation.
120 
121  int numNodeFields = node->getNumFields();
122  if (numNodeFields <= 0) return(-1);
123 
124  int lastFieldOnNode = node->getFieldIDList()[numNodeFields-1];
125 
126  int lastFieldSize = (*fieldDB_)[lastFieldOnNode];
127 
128  int lastEqnOnNode = node->getFieldEqnNumbers()[numNodeFields-1] +
129  lastFieldSize - 1;
130 
131  if (eqnNumber <= lastEqnOnNode) return(0);
132 
133  return(-1);
134 }
135 
136 //------------------------------------------------------------------------------
137 void NodeDatabase::getNodeAtIndex(int i, const NodeDescriptor*& node) const
138 {
139  int nnodes = nodePtrs_.size();
140  if (i>=0 && i < nnodes) {
141  node = nodePtrs_[i];
142  }
143  else {
144  node = NULL;
145  }
146 }
147 
148 //------------------------------------------------------------------------------
150 {
151  int nnodes = nodePtrs_.size();
152  if (i>=0 && i < nnodes) {
153  node = nodePtrs_[i];
154  }
155  else {
156  node = NULL;
157  }
158 }
159 
160 //------------------------------------------------------------------------------
161 int NodeDatabase::countLocalNodalEqns(int localRank)
162 {
163  int numEqns = 0;
164 
165  for(size_t i=0; i<nodePtrs_.size(); i++) {
166  NodeDescriptor* node = nodePtrs_[i];
167 
168  if (node->getOwnerProc() == localRank) {
169  int numFields = node->getNumFields();
170  const int* fieldIDList = node->getFieldIDList();
171 
172  for(int j=0; j<numFields; j++) {
173  int numParams = (*fieldDB_)[fieldIDList[j]];
174 
175  numEqns += numParams;
176  }
177  }
178  }
179 
180  return(numEqns);
181 }
182 
183 //------------------------------------------------------------------------------
185 {
186  int numLocal = 0;
187  for(size_t i=0; i<nodePtrs_.size(); i++) {
188  if (nodePtrs_[i]->getOwnerProc() == localRank) numLocal++;
189  }
190 
191  return(numLocal);
192 }
193 
194 //------------------------------------------------------------------------------
195 int NodeDatabase::getIndexOfID(GlobalID nodeID) const
196 {
197  std::map<GlobalID,int>::const_iterator
198  iter = nodeIDs_.find(nodeID);
199 
200  if (iter == nodeIDs_.end()) return(-1);
201 
202  return( iter->second );
203 }
204 
205 //------------------------------------------------------------------------------
206 int NodeDatabase::initNodeID(GlobalID nodeID)
207 {
208  static NodeDescriptor dummyNode;
209 
210  int index = nodeIDs_.size();
211  std::map<GlobalID,int>::iterator
212  iter = nodeIDs_.lower_bound(nodeID);
213 
214  if (iter == nodeIDs_.end() || iter->first != nodeID) {
215  nodeIDs_.insert(iter, std::make_pair(nodeID,index));
216 
217  NodeDescriptor* nodePtr = nodePool_.allocate(1);
218  nodePool_.construct(nodePtr, dummyNode);
219 
220  nodePtr->setGlobalNodeID(nodeID);
221 
222  nodePtrs_.push_back(nodePtr);
223 
224  need_to_alloc_and_sync_ = true;
225  }
226 
227  return(0);
228 }
229 
230 //------------------------------------------------------------------------------
231 int NodeDatabase::initNodeIDs(GlobalID* nodeIDs, int numNodes)
232 {
233  static NodeDescriptor dummyNode;
234 
235  for(int i=0; i<numNodes; i++) {
236  initNodeID(nodeIDs[i]);
237  }
238 
239  return(0);
240 }
241 
242 //------------------------------------------------------------------------------
243 int NodeDatabase::synchronize(int firstLocalNodeNumber,
244  int firstLocalEqn,
245  int localRank,
246  MPI_Comm comm)
247 {
248  eqnNumbers_.reserve(nodePtrs_.size());
249  eqnNodeIndices_.reserve(nodePtrs_.size());
250 
251  eqnNumbers_.resize(0);
252  eqnNodeIndices_.resize(0);
253 
254  firstLocalNodeNumber_ = firstLocalNodeNumber;
255  int nodeNumber = firstLocalNodeNumber;
256  int numEqns = 0;
257 
258  nodeNumbers_.clear();
259 
260  numLocalNodes_ = 0;
261  std::map<GlobalID,int>::iterator
262  iter = nodeIDs_.begin(), iter_end = nodeIDs_.end();
263 
264  for(; iter!=iter_end; ++iter) {
265  int i = iter->second;
266  NodeDescriptor* node = NULL;
267  getNodeAtIndex(i, node);
268  if (node==NULL) continue;
269 
270  int numFields = node->getNumFields();
271  const int* fieldIDList = node->getFieldIDList();
272 
273  int numNodalDOF = 0;
274  int firstEqnNumber, eqnNumber;
275 
276  for(int j=0; j<numFields; j++) {
277  int numFieldParams = (*fieldDB_)[fieldIDList[j]];
278  numNodalDOF += numFieldParams;
279 
280  if (node->getOwnerProc() == localRank) {
281  eqnNumber = firstLocalEqn + numEqns;
282  if (j==0) firstEqnNumber = eqnNumber;
283 
284  numEqns += numFieldParams;
285 
286  node->setFieldEqnNumber(fieldIDList[j], eqnNumber);
287  }
288  }
289 
290  if (node->getOwnerProc() == localRank) {
291  node->setNodeNumber(nodeNumber++);
292  numLocalNodes_++;
293 
294  int insertPoint = fei::sortedListInsert(firstEqnNumber, eqnNumbers_);
295  if (insertPoint == -2) ERReturn(-2);
296  if (insertPoint >= 0) eqnNodeIndices_.insert(eqnNodeIndices_.begin()+insertPoint, i);
297  }
298 
299  node->setNumNodalDOF(numNodalDOF);
300 
301  int thisNodeNumber = node->getNodeNumber();
302  nodeNumbers_.insert(std::make_pair(thisNodeNumber, i));
303  }
304 
305  lastLocalNodeNumber_ = nodeNumber - 1;
306 
307  // next, have the node comm manager get the field IDs and
308  // equation numbers for all of the nodes that we know about but don't
309  // own. i.e., the remotely-owned shared nodes.
310  // Again, we'll get the nodeNumber info for those nodes while we're at it.
311  //
312  CHK_ERR( nodeCommMgr_->exchangeEqnInfo() );
313 
314  //Now finish up by inserting equation-numbers for shared nodes into our
315  //eqnNumbers_ and eqnNodeIndices_ lists, for future lookups...
316 
317  int numSharedNodes = nodeCommMgr_->getNumSharedNodes();
318  for(int i=0; i<numSharedNodes; i++) {
319  NodeDescriptor& node = nodeCommMgr_->getSharedNodeAtIndex(i);
320  GlobalID nodeID = node.getGlobalNodeID();
321  int index = getIndexOfID(nodeID);
322  int nDOF = node.getNumNodalDOF();
323  if (nDOF <= 0) {
324  continue;
325  //FEI_COUT << "localRank " << localRank << ", node "<<nodeID<<" has nDOF=" << nDOF<<FEI_ENDL;
326  //ERReturn(-1);
327  }
328  int firstEqn = node.getFieldEqnNumbers()[0];
329  int insertPoint = fei::sortedListInsert(firstEqn, eqnNumbers_);
330  if (insertPoint == -2) ERReturn(-2);
331  if (insertPoint >= 0) eqnNodeIndices_.insert(eqnNodeIndices_.begin()+insertPoint, index);
332 
333  int thisNodeNumber = node.getNodeNumber();
334  nodeNumbers_.insert(std::make_pair(thisNodeNumber, index));
335  }
336 
337  synchronized_ = true;
338  need_to_alloc_and_sync_ = false;
339 
340  return(0);
341 }
342 
343 //------------------------------------------------------------------------------
344 int NodeDatabase::getAssociatedNodeNumber(int eqnNumber)
345 {
346  int insertPoint = -1;
347  int index = fei::binarySearch(eqnNumber, eqnNumbers_, insertPoint);
348 
349  if (index >= 0) {
350  return( nodePtrs_[eqnNodeIndices_[index]]->getNodeNumber() );
351  }
352 
353  if (insertPoint > 0) {
354  NodeDescriptor& node = *(nodePtrs_[eqnNodeIndices_[insertPoint-1]]);
355  const int* fieldEqnNumbers = node.getFieldEqnNumbers();
356  const int* fieldIDList = node.getFieldIDList();
357  int numFields = node.getNumFields();
358 
359  int lastEqn = fieldEqnNumbers[numFields-1];
360 
361  int fieldSize = -1;
362  std::map<int,int>::const_iterator f_iter
363  = fieldDB_->find(fieldIDList[numFields-1]);
364  if (f_iter == fieldDB_->end()) ERReturn(-1);
365  fieldSize = (*f_iter).second;
366 
367  //if eqnNumber is inside the range of eqn-numbers assocated with this node,
368  //then return this node's node-number
369  if (eqnNumber >= fieldEqnNumbers[0] && (lastEqn+fieldSize - 1) >= eqnNumber) {
370  return( node.getNodeNumber() );
371  }
372  }
373 
374  //if we get to here, then we don't know how to locate the node with this
375  //eqn-number...
376  return(-1);
377 }
378 
379 //------------------------------------------------------------------------------
380 int NodeDatabase::getAssociatedFieldID(int eqnNumber)
381 {
382  int insertPoint = -1;
383  int index = fei::binarySearch(eqnNumber, eqnNumbers_, insertPoint);
384 
385  int index2 = index;
386  if (index2 < 0) index2 = insertPoint-1;
387 
388  if (index2 < 0) ERReturn(-1);
389 
390  NodeDescriptor& node = *(nodePtrs_[eqnNodeIndices_[index2]]);
391 
392  const int* fieldEqnNumbers = node.getFieldEqnNumbers();
393  const int* fieldIDList = node.getFieldIDList();
394  int numFields = node.getNumFields();
395 
396  int lastEqn = fieldEqnNumbers[numFields-1];
397 
398  int fieldSize = -1;
399  std::map<int,int>::const_iterator f_iter
400  = fieldDB_->find(fieldIDList[numFields-1]);
401  if (f_iter == fieldDB_->end()) ERReturn(-1);
402  fieldSize = (*f_iter).second;
403 
404  //if eqnNumber is outside the range of eqn-numbers that are associated with
405  //this node, then we're in trouble...
406  if (eqnNumber < fieldEqnNumbers[0] || eqnNumber > lastEqn+fieldSize) {
407  ERReturn(-1);
408  }
409 
410  //ok, so we're ready to figure out which fieldID eqnNumber is associated with.
411  for(int i=0; i<numFields-1; i++) {
412  if (eqnNumber >= fieldEqnNumbers[i] && eqnNumber < fieldEqnNumbers[i+1]) {
413  return(fieldIDList[i]);
414  }
415  }
416 
417  //if we get to here, then eqnNumber is associated with the last fieldID on the
418  //node.
419  return(fieldIDList[numFields-1]);
420 }
virtual ~NodeDatabase()
int sortedListInsert(const T &item, std::vector< T > &list)
int countLocalNodeDescriptors(int localRank)
int getNodeWithNumber(int nodeNumber, const NodeDescriptor *&node) const
int initNodeID(GlobalID nodeID)
int binarySearch(const T &item, const T *list, int len)
int getNodeWithEqn(int eqnNumber, const NodeDescriptor *&node) const
int synchronize(int firstLocalNodeNumber, int firstLocalEqn, int localRank, MPI_Comm comm)
NodeDatabase(std::map< int, int > *fieldDatabase, NodeCommMgr *nodeCommMgr)
int getIndexOfID(GlobalID nodeID) const
void getNodeAtIndex(int i, const NodeDescriptor *&node) const
int countLocalNodalEqns(int localRank)
int getAssociatedFieldID(int eqnNumber)
int getAssociatedNodeNumber(int eqnNumber)
int getNodeWithID(GlobalID nodeID, const NodeDescriptor *&node) const
int initNodeIDs(GlobalID *nodeIDs, int numNodes)