FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
snl_fei_RecordCollection.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_sstream.hpp"
10 
11 #include "fei_FieldMask.hpp"
12 #include "fei_Record.hpp"
13 #include "snl_fei_RecordCollection.hpp"
14 #include "fei_SharedIDs.hpp"
15 
16 #undef fei_file
17 #define fei_file "snl_fei_RecordCollection.cpp"
18 #include "fei_ErrMacros.hpp"
19 
20 //----------------------------------------------------------------------------
22  : m_records(),
23  m_global_to_local(),
24  m_minID(99999999),
25  m_maxID(0),
26  localProc_(localProc),
27  debugOutput_(false),
28  dbgOut_(NULL)
29 {
30  m_records.reserve(2000);
31 }
32 
33 //----------------------------------------------------------------------------
34 snl_fei::RecordCollection::RecordCollection(const RecordCollection& src)
35  : m_records(src.m_records),
36  m_global_to_local(src.m_global_to_local),
37  m_minID(99999999),
38  m_maxID(0),
39  localProc_(src.localProc_),
40  debugOutput_(src.debugOutput_),
41  dbgOut_(src.dbgOut_)
42 {
43 }
44 
45 //----------------------------------------------------------------------------
47 {
48 }
49 
50 void snl_fei::RecordCollection::setIDMap(
51  const int* localIDs_begin, const int* localIDs_end,
52  const int* globalIDs_begin, const int* globalIDs_end)
53 {
54  int numLocal = localIDs_end - localIDs_begin;
55  int numGlobal = globalIDs_end - globalIDs_begin;
56  if (numLocal != numGlobal) {
57  throw std::runtime_error("RecordCollection::setIDMap ERROR, num local IDs must match num global IDs.");
58  }
59  m_global_to_local.clear();
60  m_records.resize(numLocal);
61  const int* localID_iter = localIDs_begin;
62  const int* globalID_iter = globalIDs_begin;
63  for(int i=0; i<numLocal; ++i) {
64  int lid = *localID_iter++;
65  int gid = *globalID_iter++;
66  m_records[lid].setID(gid);
67  m_records[lid].setOwnerProc(localProc_);
68  m_global_to_local.insert(std::make_pair(gid, lid));
69  }
70 }
71 
72 //----------------------------------------------------------------------------
73 void snl_fei::RecordCollection::initRecords(int numIDs, const int* IDs,
74  std::vector<fei::FieldMask*>& fieldMasks,
75  int* recordLocalIDs)
76 {
77  int maskID = 0;
78  fei::FieldMask* mask = NULL;
79  for(unsigned m=0; m<fieldMasks.size(); ++m) {
80  if (maskID == fieldMasks[m]->getMaskID()) {
81  mask = fieldMasks[m]; break;
82  }
83  }
84 
85  if (mask == NULL) {
86  mask = new fei::FieldMask();
87  maskID = mask->getMaskID();
88  fieldMasks.push_back(mask);
89  }
90 
91  for(int i=0; i<numIDs; ++i) {
92  if (m_minID > IDs[i]) m_minID = IDs[i];
93  if (m_maxID < IDs[i]) m_maxID = IDs[i];
94 
95  int local_id = -1;
96  std::map<int,int>::iterator iter = m_global_to_local.lower_bound(IDs[i]);
97  if (iter == m_global_to_local.end() || iter->first != IDs[i]) {
98  //record doesn't exist, so we'll add a new one.
99  local_id = m_records.size();
100  m_global_to_local.insert(iter, std::make_pair(IDs[i], local_id));
101  fei::Record<int> record;
102  record.setID(IDs[i]);
103  record.setFieldMask(mask);
104  record.setOwnerProc(-1);
105  m_records.push_back(record);
106  }
107  else {
108  local_id = iter->second;
109  }
110 
111  if (recordLocalIDs != NULL) recordLocalIDs[i] = local_id;
112  }
113 }
114 
115 //----------------------------------------------------------------------------
116 void snl_fei::RecordCollection::initRecords(int fieldID, int fieldSize,
117  int numIDs, const int* IDs,
118  std::vector<fei::FieldMask*>& fieldMasks,
119  int* recordLocalIDs)
120 {
121  int maskID = fei::FieldMask::calculateMaskID(1, &fieldID);
122  fei::FieldMask* mask = NULL;
123  for(unsigned m=0; m<fieldMasks.size(); ++m) {
124  if (maskID == fieldMasks[m]->getMaskID()) {
125  mask = fieldMasks[m]; break;
126  }
127  }
128 
129  if (mask == NULL) {
130  mask = new fei::FieldMask(1, &fieldID, &fieldSize);
131  maskID = mask->getMaskID();
132  fieldMasks.push_back(mask);
133  }
134 
135  int lastMaskID = maskID;
136  fei::FieldMask* lastMask = mask;
137 
138  for(int i=0; i<numIDs; ++i) {
139  if (m_minID > IDs[i]) m_minID = IDs[i];
140  if (m_maxID < IDs[i]) m_maxID = IDs[i];
141  int local_id;
142  std::map<int,int>::iterator iter = m_global_to_local.lower_bound(IDs[i]);
143  if (iter == m_global_to_local.end() || iter->first != IDs[i]) {
144  //record doesn't exist, so we'll add a new one.
145  local_id = m_records.size();
146  m_global_to_local.insert(iter, std::make_pair(IDs[i], local_id));
147  fei::Record<int> record;
148  record.setID(IDs[i]);
149  record.setFieldMask(mask);
150  record.setOwnerProc(-1);
151  m_records.push_back(record);
152 
153  if (recordLocalIDs != NULL) {
154  recordLocalIDs[i] = local_id;
155  }
156  }
157  else {
158  local_id = iter->second;
159  fei::Record<int>& record = m_records[local_id];
160 
161  if (recordLocalIDs != NULL) {
162  recordLocalIDs[i] = local_id;
163  }
164 
165  fei::FieldMask* thisMask = record.getFieldMask();
166  if (thisMask == NULL) {
167  record.setFieldMask(mask);
168  }
169 
170  int thisMaskID = record.getFieldMask()->getMaskID();
171 
172  if (maskID == thisMaskID || thisMask->hasFieldID(fieldID)) {
173  continue;
174  }
175 
176  if (lastMaskID == thisMaskID) {
177  record.setFieldMask(lastMask);
178  continue;
179  }
180 
181  int newMaskID = fei::FieldMask::calculateMaskID(*thisMask, fieldID);
182  if (lastMaskID == newMaskID) {
183  record.setFieldMask(lastMask);
184  continue;
185  }
186 
187  bool newMaskAlreadyExists = false;
188  for(unsigned m=0; m<fieldMasks.size(); ++m) {
189  if (newMaskID == fieldMasks[m]->getMaskID()) {
190  lastMask = fieldMasks[m];
191  lastMaskID = lastMask->getMaskID();
192  record.setFieldMask(lastMask);
193  newMaskAlreadyExists = true;
194  break;
195  }
196  }
197 
198  if (!newMaskAlreadyExists) {
199  fei::FieldMask* newmask = new fei::FieldMask(*record.getFieldMask());
200  newmask->addField(fieldID, fieldSize);
201  record.setFieldMask(newmask);
202  fieldMasks.push_back(newmask);
203  lastMask = newmask;
204  lastMaskID = lastMask->getMaskID();
205  }
206  }
207  }
208 }
209 
210 //----------------------------------------------------------------------------
211 void snl_fei::RecordCollection::setOwners_local()
212 {
213  for(size_t i=0; i<m_records.size(); ++i) {
214  fei::Record<int>& rec = m_records[i];
215  if (rec.getOwnerProc() == -1) rec.setOwnerProc(localProc_);
216  }
217 }
218 
219 //----------------------------------------------------------------------------
221 {
223  s_beg = sharedIDs.getSharedIDs().begin(),
224  s_end = sharedIDs.getSharedIDs().end(),
225  s_it;
226 
227  std::vector<int>& owningProcs = sharedIDs.getOwningProcs();
228 
229  int i=0;
230  for(i=0, s_it = s_beg; s_it != s_end; ++i, ++s_it) {
231  int sh_id = s_it->first;
232  fei::Record<int>* record = getRecordWithID(sh_id);
233  if (record == NULL) continue;
234 
235  int rec_owner = record->getOwnerProc();
236 
237 // if (rec_owner != -1 && rec_owner != owningProcs[i]) {
238 // std::cout<<record->getID()<<": owner="<<rec_owner<<" but lowest sharer="<<owningProcs[i]<<std::endl;
239 // }
240 
241  if (rec_owner != -1) owningProcs[i] = rec_owner;
242  else {
243  rec_owner = owningProcs[i];
244  record->setOwnerProc(rec_owner);
245  }
246 
247  if (debugOutput_) {
248  *dbgOut_ << "# setting ID " << (int)(record->getID())
249  << "'s owner to proc " << rec_owner << FEI_ENDL;
250  }
251  }
252 }
253 
255 {
256  std::map<int,int>::iterator iter = m_global_to_local.find(ID);
257 
258  if (iter == m_global_to_local.end()) {
259  return( NULL );
260  }
261 
262  return(&m_records[iter->second]);
263 }
264 
266 {
267  std::map<int,int>::const_iterator iter = m_global_to_local.find(ID);
268 
269  if (iter == m_global_to_local.end()) {
270  return( NULL );
271  }
272 
273  return(&m_records[iter->second]);
274 }
275 
276 int snl_fei::RecordCollection::getGlobalBlkIndex(int ID, int& globalBlkIndex)
277 {
278  fei::Record<int>* record = getRecordWithID(ID);
279  if (record == NULL) {
280  globalBlkIndex = -1;
281  ERReturn(-1);
282  }
283 
284  globalBlkIndex = record->getNumber();
285  return(0);
286 }
287 
288 //----------------------------------------------------------------------------
290  int fieldID,
291  int fieldSize,
292  int fieldOffset,
293  int whichComponentOfField,
294  const int* eqnNumbers)
295 {
296  fei::Record<int>* record = getRecordWithID(ID);
297  if (record == NULL) {
298  return -1;
299  }
300 
301  fei::FieldMask* mask = record->getFieldMask();
302  int offset = 0;
303  int err = mask->getFieldEqnOffset(fieldID, offset);
304  if (err != 0) {
305  return -1;
306  }
307 
308  const int* eqnNums = eqnNumbers + record->getOffsetIntoEqnNumbers();
309  if (eqnNums == NULL) {
310  FEI_OSTRINGSTREAM osstr;
311  osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR: null pointer,"
312  << " possibly because initComplete() hasn't been called yet?";
313  throw std::runtime_error(osstr.str());
314  }
315 
316  int globalIndex = -1;
317  if (fieldOffset > 0) {
318  globalIndex = eqnNums[offset + fieldOffset*fieldSize + whichComponentOfField];
319  }
320  else {
321  globalIndex = eqnNums[offset + whichComponentOfField];
322  }
323 
324  return(globalIndex);
325 }
326 
327 //----------------------------------------------------------------------------
329  int fieldID,
330  int fieldSize,
331  int fieldOffset,
332  int whichComponentOfField,
333  const int* eqnNumbers)
334 {
335  fei::Record<int>* record = getRecordWithLocalID(localID);
336  if (record == NULL) {
337  FEI_OSTRINGSTREAM osstr;
338  osstr << "snl_fei::RecordCollection::getGlobalIndexLocalID ERROR, no record with "
339  << "localID=" << localID;
340  throw std::runtime_error(osstr.str());
341  }
342 
343  fei::FieldMask* mask = record->getFieldMask();
344  int offset = 0;
345  int err = mask->getFieldEqnOffset(fieldID, offset);
346  if (err != 0) {
347  return -1;
348  }
349 
350  const int* eqnNums = eqnNumbers + record->getOffsetIntoEqnNumbers();
351  if (eqnNums == NULL) {
352  FEI_OSTRINGSTREAM osstr;
353  osstr << "snl_fei::RecordCollection::getGlobalIndex ERROR: null pointer,"
354  << " possibly because initComplete() hasn't been called yet?";
355  throw std::runtime_error(osstr.str());
356  }
357 
358  int globalIndex = -1;
359  if (fieldOffset > 0) {
360  globalIndex = eqnNums[offset + fieldOffset*fieldSize + whichComponentOfField];
361  }
362  else {
363  globalIndex = eqnNums[offset + whichComponentOfField];
364  }
365 
366  return(globalIndex);
367 }
GlobalIDType getNumber() const
std::vector< int > & getOwningProcs()
map_type & getSharedIDs()
int getOwnerProc() const
void setOwners_lowestSharing(fei::SharedIDs< int > &sharedIDs)
void setFieldMask(fei::FieldMask *fm)
int getGlobalIndex(int ID, int fieldID, int fieldSize, int fieldOffset, int whichComponentOfField, const int *eqnNumbers)
static int calculateMaskID(int numFields, const int *fieldIDs)
bool hasFieldID(int fieldID) const
void setOwnerProc(int owner)
void setID(const GlobalIDType &ID)
void addField(int fieldID, int fieldSize)
int getFieldEqnOffset(int fieldID, int &offset) const
GlobalIDType getID() const
void initRecords(int numIDs, const int *IDs, std::vector< fei::FieldMask * > &fieldMasks, int *recordLocalIDs=NULL)
int getOffsetIntoEqnNumbers() const
int getGlobalBlkIndex(int ID, int &globalBlkIndex)
fei::FieldMask * getFieldMask()
fei::Record< int > * getRecordWithID(int ID)
int getGlobalIndexLocalID(int localID, int fieldID, int fieldSize, int fieldOffset, int whichComponentOfField, const int *eqnNumbers)