FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fei_Lookup_Impl.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_macros.hpp>
10 
11 #include <fei_Lookup_Impl.hpp>
12 
13 #include <fei_VectorSpace.hpp>
14 
15 #include <snl_fei_Utils.hpp>
16 #include <fei_TemplateUtils.hpp>
17 #include <fei_CommUtils.hpp>
18 
19 #include <snl_fei_Constraint.hpp>
20 
21 #include <snl_fei_SubdMsgHandler.hpp>
22 
23 #undef fei_file
24 #define fei_file "fei_Lookup_Impl.cpp"
25 #include <fei_ErrMacros.hpp>
26 
27 //----------------------------------------------------------------------------
29  int nodeIDType)
30  : matGraph_(matGraph),
31  ptBlkMap_(NULL),
32  vspace_(),
33  nodeIDType_(nodeIDType),
34  nodenumPairs_(),
35  eqnnumPairs_(),
36  nodenumSubdomainDB_(),
37  databasesBuilt_(false),
38  fieldIDs_(),
39  fieldSizes_(),
40  elemBlockIDs_(0, 4),
41  fieldIDs_2D_(),
42  workspace_()
43 {
44  vspace_ = matGraph_->getRowSpace();
45  ptBlkMap_ = vspace_->getPointBlockMap();
46 
47  int err = buildDatabases();
48  if (err != 0) {
49  voidERReturn;
50  }
51 }
52 
53 //----------------------------------------------------------------------------
55 {
56  fei::destroyValues(nodenumSubdomainDB_);
57  nodenumSubdomainDB_.clear();
58 }
59 
60 //----------------------------------------------------------------------------
61 int fei::Lookup_Impl::getEqnNumber(int nodeNumber, int fieldID)
62 {
63  std::map<int,fei::Record<int>*>::iterator
64  nnp_iter = nodenumPairs_.find(nodeNumber);
65 
66  if (nnp_iter == nodenumPairs_.end()) return(-1);
67 
68  fei::Record<int>* node = (*nnp_iter).second;
69 
70  std::vector<int>& eqnNums = vspace_->getEqnNumbers();
71  int* eqnNumbers = eqnNums.size() > 0 ? &eqnNums[0] : NULL;
72  if (eqnNumbers == NULL) {
73  throw std::runtime_error("Fatal error in fei::Lookup_Impl::getEqnNumber");
74  }
75  eqnNumbers += node->getOffsetIntoEqnNumbers();
76  int offset = -1;
77  int err = node->getFieldMask()->getFieldEqnOffset(fieldID, offset);
78  if (err == 0) {
79  return(eqnNumbers[offset]);
80  }
81 
82  return -1;
83 }
84 
85 //----------------------------------------------------------------------------
87 {
88  std::map<int,fei::Record<int>*>::iterator
89  enp_iter = eqnnumPairs_.find(eqnNumber);
90 
91  if (enp_iter == eqnnumPairs_.end()) return(-1);
92 
93  fei::Record<int>* node = (*enp_iter).second;
94 
95  return( node->getNumber() );
96 }
97 
98 //----------------------------------------------------------------------------
99 int fei::Lookup_Impl::getAssociatedNodeID(int eqnNumber)
100 {
101  std::map<int,fei::Record<int>*>::iterator
102  enp_iter = eqnnumPairs_.find(eqnNumber);
103 
104  if (enp_iter == eqnnumPairs_.end()) return(-1);
105 
106  fei::Record<int>* node = (*enp_iter).second;
107 
108  return( node->getID() );
109 }
110 
111 //----------------------------------------------------------------------------
113 {
114  std::map<int,fei::Record<int>*>::iterator
115  enp_iter = eqnnumPairs_.find(eqnNumber);
116 
117  if (enp_iter == eqnnumPairs_.end()) return(-1);
118 
119  fei::Record<int>* node = (*enp_iter).second;
120 
121  fei::FieldMask* fm = node->getFieldMask();
122  const std::vector<int>& fieldIDs = fm->getFieldIDs();
123  const std::vector<int>& fieldSizes = fm->getFieldSizes();
124 
125  const std::vector<int>& eqnNumbers = vspace_->getEqnNumbers();
126 
127  int baseEqnOffset = node->getOffsetIntoEqnNumbers();
128  int numNodalEqns = fm->getNumIndices();
129 
130  if (baseEqnOffset + numNodalEqns > (int)eqnNumbers.size()) {
131  throw std::runtime_error("fei::Lookup_Impl::getAssociatedFieldID ERROR, nodal eqn offset out of range.");
132  }
133 
134  int offset = 0;
135  int eqn = eqnNumbers[baseEqnOffset];
136  while(eqn < eqnNumber && offset < numNodalEqns) {
137  eqn = eqnNumbers[baseEqnOffset + ++offset];
138  }
139 
140  if (eqn != eqnNumber) {
141  throw std::runtime_error("fei::Lookup_Impl::getAssociatedFieldID ERROR, eqnNumber not found");
142  }
143 
144  int fieldSize_total = 0;
145  for(size_t i=0; i<fieldSizes.size(); ++i) {
146  fieldSize_total += fieldSizes[i];
147  if (fieldSize_total > offset) {
148  return fieldIDs[i];
149  }
150  }
151 
152  return -1;
153 }
154 
155 //----------------------------------------------------------------------------
157 {
158  std::map<int,std::vector<int>* >::iterator
159  nns_iter = nodenumSubdomainDB_.find(nodeNumber);
160  if (nns_iter != nodenumSubdomainDB_.end()) {
161  return( true );
162  }
163 
164  std::map<int,fei::Record<int>*>::iterator
165  nnp_iter = nodenumPairs_.find(nodeNumber);
166 
167  return(nnp_iter != nodenumPairs_.end() ? true : false);
168 }
169 
170 //----------------------------------------------------------------------------
171 int fei::Lookup_Impl::getOffsetIntoBlkEqn(int blkEqn, int ptEqn)
172 {
173  //assume blkEqn is a node-number, for now.
174  std::map<int,fei::Record<int>*>::iterator
175  nnp_iter = nodenumPairs_.find(blkEqn);
176 
177  if (nnp_iter == nodenumPairs_.end()) return(-1);
178 
179  fei::Record<int>* node = (*nnp_iter).second;
180 
181  int eqn = vspace_->getEqnNumbers()[node->getOffsetIntoEqnNumbers()];
182  return(ptEqn - eqn);
183 }
184 
185 //----------------------------------------------------------------------------
186 int fei::Lookup_Impl::buildDatabases()
187 {
188  if (databasesBuilt_) return(0);
189 
190  snl_fei::RecordCollection* collection = NULL;
191  int err = vspace_->getRecordCollection(nodeIDType_, collection);
192  if (err != 0) {
193  //probably means that vspace_ doesn't have 'nodeIDType_', so we'll skip the
194  //rest of this function. It's not a problem if vspace_ doesn't have nodeIDType_.
195  return(0);
196  }
197 
198  std::vector<int>& vspcEqnNumbers = vspace_->getEqnNumbers();
199 
200  std::vector<fei::Record<int> >& rvec = collection->getRecords();
201 
202  for(size_t i=0; i<rvec.size(); ++i) {
203  fei::Record<int>* node = &rvec[i];
204 
205  std::pair<int,fei::Record<int>* > int_node_pair(node->getNumber(), node);
206 
207  nodenumPairs_.insert(int_node_pair);
208 
209  int numEqns = node->getFieldMask()->getNumIndices();
210  int* eqnNumbers = &vspcEqnNumbers[0]
211  + node->getOffsetIntoEqnNumbers();
212 
213  for(int eq=0; eq<numEqns; ++eq) {
214  std::pair<int,fei::Record<int>* > eqn_node_pair(eqnNumbers[eq], node);
215  eqnnumPairs_.insert(eqn_node_pair);
216  }
217  }
218 
219  MPI_Comm comm = matGraph_->getRowSpace()->getCommunicator();
220 
221  int numLocalLagrangeConstraints = matGraph_->getLagrangeConstraints().size();
222 
223  int numGlobalLagrangeConstraints = 0;
224  fei::GlobalSum(comm, numLocalLagrangeConstraints, numGlobalLagrangeConstraints);
225 
226  bool noconstraints = numGlobalLagrangeConstraints<1 ? true : false;
227 
228  fei::SharedIDs<int> subdomainIDs;
229  fei::SharedIDs<int>& sharedIDs = vspace_->getSharedIDs(nodeIDType_);
230 
231  if (noconstraints == false) {
232  snl_fei::SubdMsgHandler subdmsghndlr(collection, &sharedIDs, &subdomainIDs);
233 
234  if (vspace_->ownerPatterns_.size() > 0 && vspace_->sharerPatterns_.size() > 0) {
235  subdmsghndlr.setSendPattern(vspace_->ownerPatterns_.find(nodeIDType_)->second);
236  subdmsghndlr.setRecvPattern(vspace_->sharerPatterns_.find(nodeIDType_)->second);
237  CHK_ERR( fei::exchange(comm, &subdmsghndlr) );
238  }
239 
240  //Now the subdomainIDs object contains a mapping from each shared ID to a
241  //list of processors that have that ID in their local subdomain.
242  //So what we'll do next is run through the list of IDs in subdomainIDs and
243  //for each ID, store the corresponding node-number in a database together
244  //with a pointer to a list (vector) of the subdomain-processors.
245  }
246  else {
247  subdomainIDs = sharedIDs;
248  }
249 
250  int local_proc = fei::localProc(comm);
251 
252  fei::SharedIDs<int>::map_type& sdIDTable = subdomainIDs.getSharedIDs();
254  sd_iter = sdIDTable.begin(),
255  sd_end = sdIDTable.end();
256 
257  for(int i=0; sd_iter != sd_end; ++i, ++sd_iter) {
258  int id = sd_iter->first;
259  std::set<int>& procList = sd_iter->second;
260 
261  fei::Record<int>* node = collection->getRecordWithID(id);
262  if (node == NULL) {
263  ERReturn(-1);
264  }
265 
266  std::vector<int>* newarray = new std::vector<int>;
267  std::set<int>::const_iterator
268  p_iter = procList.begin(), p_end = procList.end();
269 
270  for(; p_iter != p_end; ++p_iter) {
271  int proc = *p_iter;
272  newarray->push_back(proc);
273  }
274 
275  if (node->isInLocalSubdomain_) {
276  fei::sortedListInsert(local_proc, *newarray);
277  }
278 
279  nodenumSubdomainDB_.insert(std::pair<int,std::vector<int>*>(node->getNumber(), newarray));
280  }
281 
282  databasesBuilt_ = true;
283  return(0);
284 }
285 
int GlobalSum(MPI_Comm comm, std::vector< T > &local, std::vector< T > &global)
GlobalIDType getNumber() const
Definition: fei_Record.hpp:58
int sortedListInsert(const T &item, std::vector< T > &list)
std::map< T, std::set< int > > map_type
map_type & getSharedIDs()
Lookup_Impl(fei::SharedPtr< fei::MatrixGraph > matGraph, int nodeIDType)
int getAssociatedFieldID(int eqnNumber)
int getAssociatedNodeNumber(int eqnNumber)
std::vector< fei::Record< int > > & getRecords()
int getNumIndices() const
virtual fei::SharedPtr< fei::VectorSpace > getRowSpace()=0
std::vector< int > & getFieldSizes()
std::vector< int > & getFieldIDs()
snl_fei::PointBlockMap * getPointBlockMap()
int localProc(MPI_Comm comm)
int getEqnNumber(int nodeNumber, int fieldID)
int getFieldEqnOffset(int fieldID, int &offset) const
GlobalIDType getID() const
Definition: fei_Record.hpp:46
bool isInLocalElement(int nodeNumber)
void destroyValues(MAP_TYPE &map_obj)
int getOffsetIntoEqnNumbers() const
Definition: fei_Record.hpp:126
fei::FieldMask * getFieldMask()
Definition: fei_Record.hpp:106
fei::Record< int > * getRecordWithID(int ID)
int getOffsetIntoBlkEqn(int blkEqn, int ptEqn)
bool isInLocalSubdomain_
Definition: fei_Record.hpp:162