FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
snl_fei_RecordMsgHandler.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 "snl_fei_RecordMsgHandler.hpp"
12 #include "snl_fei_RecordCollection.hpp"
13 #include "snl_fei_PointBlockMap.hpp"
14 #include "fei_FieldMask.hpp"
15 #include "fei_TemplateUtils.hpp"
16 
17 #undef fei_file
18 #define fei_file "snl_fei_RecordMsgHandler.cpp"
19 #include "fei_ErrMacros.hpp"
20 
22  RecordCollection* recordCollection,
23  snl_fei::PointBlockMap& ptBlkMap,
24  std::vector<fei::FieldMask*>& fieldMasks,
25  std::vector<int>& eqnNumbers)
26  :sendPattern_(NULL),
27  recvPattern_(NULL),
28  recordCollection_(recordCollection),
29  ptBlkMap_(ptBlkMap),
30  fieldMasks_(fieldMasks),
31  whichTask_(_FieldMasks_),
32  sendProcs_(0, 32),
33  recvProcs_(0, 32),
34  eqnNumbers_(eqnNumbers),
35  localProc_(localProc)
36 {
37 }
38 
40 {
41 }
42 
44 {
45  fei::copyKeysToVector(sendPattern_->getMap(), sendProcs_);
46  return(sendProcs_);
47 }
48 
50 {
51  fei::copyKeysToVector(recvPattern_->getMap(), recvProcs_);
52  return(recvProcs_);
53 }
54 
56  int& messageLength)
57 {
58  if (sendPattern_ == NULL || recvPattern_ == NULL) ERReturn(-1);
59 
60  switch(whichTask_) {
61  case _FieldMasks_:
62  messageLength = localFieldMaskMessageSize(fieldMasks_); break;
63  case _MaskIDs_:
64  messageLength = sendPattern_->getRow(destProc)->size(); break;
65  case _EqnNumbers_:
66  messageLength = eqnNumbersMsgLength(destProc); break;
67  default:
68  std::abort();
69  }
70 
71  return(0);
72 }
73 
75  std::vector<int>& message)
76 {
77  switch(whichTask_) {
78  case _FieldMasks_:
79  CHK_ERR( packLocalFieldMasks(fieldMasks_, message) ); break;
80  case _MaskIDs_:
81  CHK_ERR( packMaskIDs(destProc, message) ); break;
82  case _EqnNumbers_:
83  CHK_ERR( packEqnNumbersMsg(destProc, message) ); break;
84  default:
85  std::abort();
86  }
87 
88  return(0);
89 }
90 
92  std::vector<int>& message)
93 {
94  switch(whichTask_) {
95  case _FieldMasks_:
96  CHK_ERR( addFieldMasks(message, fieldMasks_) ); break;
97  case _MaskIDs_:
98  CHK_ERR( mergeMaskIDs(srcProc, message) ); break;
99  case _EqnNumbers_:
100  CHK_ERR( storeEqnNumbers(srcProc, message) ); break;
101  default:
102  std::abort();
103  }
104 
105  return(0);
106 }
107 
108 int snl_fei::RecordMsgHandler::
109 localFieldMaskMessageSize(std::vector<fei::FieldMask*>& fieldMasks)
110 {
111  //msg-size will be 1+sum(numFields*3+2)
112  int numLocalMasks = fieldMasks.size();
113  int i, msgSize = 1;
114  for(i=0; i<numLocalMasks; ++i) {
115  msgSize += (fieldMasks[i]->getNumFields())*3+2;
116  }
117 
118  return( msgSize );
119 }
120 
121 int snl_fei::RecordMsgHandler::
122 packLocalFieldMasks(std::vector<fei::FieldMask*>& fieldMasks,
123  std::vector<int>& localFieldMasks)
124 {
125  int numLocalMasks = fieldMasks.size();
126  int msgSize = 1;
127  for(int ii=0; ii<numLocalMasks; ++ii) {
128  msgSize += fieldMasks[ii]->getNumFields()*3+2;
129  }
130 
131  localFieldMasks.resize(msgSize);
132 
133  int offset = 0;
134  localFieldMasks[offset++] = fieldMasks.size();
135  for(unsigned i=0; i<fieldMasks.size(); ++i) {
136  int numFields = fieldMasks[i]->getNumFields();
137  int numIndices = fieldMasks[i]->getNumIndices();
138  localFieldMasks[offset++] = numFields;
139  localFieldMasks[offset++] = numIndices;
140 
141  std::vector<int>& fieldIDs = fieldMasks[i]->getFieldIDs();
142  std::vector<int>& fieldSizes = fieldMasks[i]->getFieldSizes();
143 
144  for(int j=0; j<numFields; ++j) {
145  localFieldMasks[offset+j] = fieldIDs[j];
146  localFieldMasks[offset+numFields+j] = fieldSizes[j];
147  }
148  offset += numFields*3;
149  }
150 
151  return(0);
152 }
153 
154 int snl_fei::RecordMsgHandler::
155 addFieldMasks(std::vector<int>& msg, std::vector<fei::FieldMask*>& fieldMasks)
156 {
157  int offset = 0;
158  int* msgPtr = &msg[0];
159  int numMasks = msgPtr[offset++];
160  for(int i=0; i<numMasks; ++i) {
161  int numFields = msgPtr[offset++];
162  int numIndices = msgPtr[offset++];
163  int* fieldIDs = NULL;
164  int* fieldSizes = NULL;
165  if (numFields > 0) {
166  fieldIDs = &(msgPtr[offset]);
167  fieldSizes = &(msgPtr[offset+numFields]);
168  }
169 
170  int maskID = fei::FieldMask::calculateMaskID(numFields, fieldIDs);
171 
172  bool maskAlreadyExists = false;
173  for(unsigned j=0; j<fieldMasks.size(); ++j) {
174  int existingMaskID = fieldMasks[j]->getMaskID();
175  if (maskID == existingMaskID) {
176  maskAlreadyExists = true; break;
177  }
178  }
179 
180  if (!maskAlreadyExists) {
181  fei::FieldMask* newmask = new fei::FieldMask(numFields,
182  fieldIDs, fieldSizes);
183  if (numFields < 1) {
184  newmask->setNumIndices(numIndices);
185  }
186  fieldMasks.push_back(newmask);
187  }
188 
189  offset += 3*numFields;
190  }
191 
192  return(0);
193 }
194 
195 int snl_fei::RecordMsgHandler::packMaskIDs(int destProc, std::vector<int>& msg)
196 {
197  fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
198  int len = ids->size();
199 
200  msg.resize(len);
201 
202  fei::comm_map::row_type::const_iterator
203  id_iter = ids->begin(),
204  id_end = ids->end();
205 
206  int offset = 0;
207  int* msgPtr = &msg[0];
208 
209  for(; id_iter != id_end; ++id_iter) {
210  fei::Record<int>* rec = recordCollection_->getRecordWithID(*id_iter);
211  if (rec == NULL) {
212  FEI_OSTRINGSTREAM osstr;
213  osstr << "RecordMsgHandler::packMaskIDs: proc " << localProc_
214  << " failed to find ID " << *id_iter;
215  throw std::runtime_error(osstr.str());
216  }
217 
218  msgPtr[offset++] = rec->getFieldMask()->getMaskID();
219  }
220 
221  return(0);
222 }
223 
224 int snl_fei::RecordMsgHandler::mergeMaskIDs(int srcProc, std::vector<int>& msg)
225 {
226  fei::comm_map::row_type* ids = recvPattern_->getRow(srcProc);
227 
228  fei::comm_map::row_type::const_iterator
229  id_iter = ids->begin(),
230  id_end = ids->end();
231 
232  int offset = 0;
233  int* msgPtr = &msg[0];
234 
235  for(; id_iter != id_end; ++id_iter) {
236  int ID = *id_iter;
237  fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
238  if (rec == NULL) {
239  ERReturn(-1);
240  }
241 
242  int maskID = msgPtr[offset++];
243 
244  if (maskID != rec->getFieldMask()->getMaskID()) {
245  //if the masks don't match, we need to add the fields from the
246  //incoming-field-mask-id to our record's field-mask.
247 
248  //first, find the field-mask for 'maskID'
249  fei::FieldMask* mask = NULL;
250  for(unsigned fm=0; fm<fieldMasks_.size(); ++fm) {
251  if (fieldMasks_[fm]->getMaskID() == maskID) mask = fieldMasks_[fm];
252  }
253  if (mask == NULL) {
254  fei::console_out() << "mergeMaskIDs didn't find mask for maskID="
255  << maskID<<FEI_ENDL;
256  ERReturn(-1);
257  }
258 
259  int numFields = mask->getNumFields();
260  std::vector<int>& fieldIDs = mask->getFieldIDs();
261  std::vector<int>& fieldSizes = mask->getFieldSizes();
262 
263  for(int nf=0; nf<numFields; ++nf) {
264  recordCollection_->initRecords(fieldIDs[nf], fieldSizes[nf],
265  1, &ID, fieldMasks_);
266  }
267  }
268  }
269 
270  return(0);
271 }
272 
273 int snl_fei::RecordMsgHandler::eqnNumbersMsgLength(int destProc)
274 {
275  fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
276  fei::comm_map::row_type::const_iterator
277  id_iter = ids->begin(),
278  id_end = ids->end();
279  int len = ids->size();
280 
281  len *= 3;
282 
283  for(; id_iter != id_end; ++id_iter) {
284  int ID = *id_iter;
285  fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
286  if (rec == NULL) {
287  ERReturn(-1);
288  }
289 
290  len += rec->getFieldMask()->getNumIndices();
291  }
292 
293  return(len);
294 }
295 
296 int snl_fei::RecordMsgHandler::packEqnNumbersMsg(int destProc,
297  std::vector<int>& msg)
298 {
299  fei::comm_map::row_type* ids = sendPattern_->getRow(destProc);
300  int len = ids->size()*3;
301  msg.resize(len);
302  const int* eqnNumPtr = &eqnNumbers_[0];
303 
304  fei::comm_map::row_type::const_iterator
305  id_iter = ids->begin(),
306  id_end = ids->end();
307  int offset = 0;
308  for(; id_iter != id_end; ++id_iter) {
309  int ID = *id_iter;
310  fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
311  if (rec == NULL) {
312  ERReturn(-1);
313  }
314 
315  len = rec->getFieldMask()->getNumIndices();
316 
317  msg[offset++] = ID;
318  msg[offset++] = rec->getNumber();
319  msg[offset++] = len;
320 
321  const int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
322  for(int i=0; i<len; ++i) {
323  msg.push_back(eqnNumbers[i]);
324  }
325  }
326 
327  return(0);
328 }
329 
330 int snl_fei::RecordMsgHandler::storeEqnNumbers(int srcProc, std::vector<int>& msg)
331 {
332  int numIDs = recvPattern_->getRow(srcProc)->size();
333  int offset = numIDs*3;
334  int* msgPtr = &msg[0];
335  int* eqnNumPtr = &eqnNumbers_[0];
336  for(int i=0; i<numIDs; ++i) {
337  int ID = msgPtr[i*3];
338  int recNumber = msgPtr[i*3+1];
339  int numEqns = msgPtr[i*3+2];
340  fei::Record<int>* rec = recordCollection_->getRecordWithID(ID);
341  if (rec == NULL) {
342  ERReturn(-1);
343  }
344 
345  rec->setNumber(recNumber);
346  int* eqnNumbers = eqnNumPtr+rec->getOffsetIntoEqnNumbers();
347  for(int eq=0; eq<numEqns; ++eq) {
348  eqnNumbers[eq] = msgPtr[offset++];
349  ptBlkMap_.setEqn(eqnNumbers[eq], recNumber, numEqns);
350  }
351  }
352 
353  return(0);
354 }
355 
GlobalIDType getNumber() const
void setNumber(const GlobalIDType &num)
std::vector< int > & getRecvProcs()
int processRecvMessage(int srcProc, std::vector< int > &message)
int getNumIndices() const
void setNumIndices(int numInd)
std::vector< int > & getSendProcs()
void copyKeysToVector(const MAP_TYPE &map_obj, std::vector< int > &keyvector)
size_t getNumFields() const
static int calculateMaskID(int numFields, const int *fieldIDs)
std::vector< int > & getFieldSizes()
RecordMsgHandler(int localProc, RecordCollection *recordCollection, snl_fei::PointBlockMap &ptBlkMap, std::vector< fei::FieldMask * > &fieldMasks, std::vector< int > &eqnNumbers)
std::vector< int > & getFieldIDs()
int getSendMessage(int destProc, std::vector< int > &message)
std::ostream & console_out()
int getSendMessageLength(int destProc, int &messageLength)
int getOffsetIntoEqnNumbers() const
fei::FieldMask * getFieldMask()