FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
snl_fei_Utils.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 <limits>
12 #include <cmath>
13 #include <stdexcept>
14 
15 #include <snl_fei_Utils.hpp>
16 #include "fei_Record.hpp"
17 #include <fei_MatrixGraph.hpp>
18 #include <fei_SparseRowGraph.hpp>
19 #include <fei_Matrix_Impl.hpp>
20 #include <fei_ParameterSet.hpp>
21 
22 #include <fei_CommUtils.hpp>
23 #include <fei_TemplateUtils.hpp>
24 #include <fei_CSVec.hpp>
25 #include <fei_chk_mpi.hpp>
26 
27 #undef fei_file
28 #define fei_file "snl_fei_Utils.cpp"
29 #include <fei_ErrMacros.hpp>
30 
31 //----------------------------------------------------------------------------
32 const char* snl_fei::getParam(const char* key,
33  int numParams,
34  const char* const* paramStrings)
35 {
36  int foundOffset = -1;
37  return( getParam(key, numParams, paramStrings, foundOffset) );
38 }
39 
40 //----------------------------------------------------------------------------
41 const char* snl_fei::getParamValue(const char* key,
42  int numParams,
43  const char* const* paramStrings,
44  char separator)
45 {
46  const char* param = getParam(key, numParams, paramStrings);
47 
48  return( param != NULL ? skipSeparator(param, separator) : NULL );
49 }
50 
51 //----------------------------------------------------------------------------
52 const char* snl_fei::getParamValue(const char* key,
53  int numParams,
54  const char* const* paramStrings,
55  int& foundOffset,
56  char separator)
57 {
58  const char* param = getParam(key, numParams, paramStrings, foundOffset);
59 
60  return( param != NULL ? skipSeparator(param, separator) : NULL );
61 }
62 
63 //----------------------------------------------------------------------------
64 int snl_fei::getIntParamValue(const char* key,
65  int numParams,
66  const char*const* params,
67  int& paramValue)
68 {
69  const char* tempstr = getParamValue(key, numParams, params);
70  if (tempstr==NULL) return(-1);
71 
72  std::string strg(tempstr);
73  FEI_ISTRINGSTREAM isstr(strg);
74  isstr >> paramValue;
75  return( isstr.fail() ? -1 : 0 );
76 }
77 
78 //----------------------------------------------------------------------------
79 int snl_fei::getDoubleParamValue(const char* key,
80  int numParams,
81  const char*const* params,
82  double& paramValue)
83 {
84  const char* tempstr = getParamValue(key, numParams, params);
85  if (tempstr==NULL) return(-1);
86 
87  std::string strg(tempstr);
88  FEI_ISTRINGSTREAM isstr(strg);
89  isstr >> paramValue;
90  return( isstr.fail() ? -1 : 0 );
91 }
92 
93 //----------------------------------------------------------------------------
94 int snl_fei::getDoubleParamValue(const char* key,
95  std::vector<std::string>& params,
96  double& paramValue)
97 {
98  const char* tempstr = getParamValue(key, params);
99  if (tempstr==NULL) return(-1);
100 
101  std::string strg(tempstr);
102  FEI_ISTRINGSTREAM isstr(strg);
103  isstr >> paramValue;
104  return( isstr.fail() ? -1 : 0 );
105 }
106 
107 //----------------------------------------------------------------------------
108 const char* snl_fei::getParam(const char* key,
109  int numParams,
110  const char* const* paramStrings,
111  int& foundOffset)
112 {
113  const char* returnPtr = NULL;
114  foundOffset = -1;
115 
116  //if the search-key is null, or if the list of strings to be searched is null,
117  //or if the number of strings to be searched is null, then return now.
118  //
119  if (key == NULL || paramStrings == NULL || numParams == 0) {
120  return(returnPtr);
121  }
122 
123  unsigned keyLen = strlen(key);
124 
125  for(int i=numParams-1; i>=0; --i) {
126  const char* paramStr = paramStrings[i];
127 
128  //if the i-th paramString is null, skip it.
129  if (paramStr == NULL) continue;
130 
131  unsigned paramStr_len = leading_substring_length(paramStr);
132  if (paramStr_len != keyLen) continue;
133 
134  if (strncmp(key, paramStr, keyLen) == 0) {
135  returnPtr = paramStr;
136  foundOffset = i;
137  return(returnPtr);
138  }
139  }
140 
141  return(returnPtr);
142 }
143 
144 //----------------------------------------------------------------------------
145 const char* snl_fei::getParam(const char* key,
146  std::vector<std::string>& params,
147  int& foundOffset)
148 {
149  std::vector<std::string>::iterator
150  p_iter = params.begin(),
151  p_end = params.end();
152 
153  int offset = 0;
154  for(; p_iter != p_end; ++p_iter, ++offset) {
155  std::string& pstr = *p_iter;
156  int ssize = pstr.size();
157  if (ssize < 1) continue;
158 
159  std::string::size_type i = pstr.find(key);
160  if (i == 0) {
161  foundOffset = offset;
162  return( pstr.c_str() );
163  }
164  }
165 
166  return( NULL );
167 }
168 
169 //----------------------------------------------------------------------------
170 const char* snl_fei::getParamValue(const char* key,
171  std::vector<std::string>& params,
172  char separator)
173 {
174  int offset = 0;
175  return( skipSeparator( getParam(key, params, offset), separator) );
176 }
177 
178 //----------------------------------------------------------------------------
179 void snl_fei::separate_string(const char* input_string,
180  const char* substring,
181  const char*& before_substring,
182  int& len_before_substring,
183  const char*& after_substring,
184  int& len_after_substring)
185 {
186  if (input_string == NULL) {
187  before_substring = NULL;
188  len_before_substring = 0;
189  after_substring = NULL;
190  len_after_substring = 0;
191  return;
192  }
193 
194  int len_input_string = strlen(input_string);
195  before_substring = input_string;
196 
197  if (substring == NULL) {
198  len_before_substring = len_input_string;
199  after_substring = NULL;
200  len_after_substring = 0;
201  return;
202  }
203 
204  int len_substring = strlen(substring);
205 
206  const char* s1 = strstr(input_string, substring);
207  if (s1 == NULL) {
208  len_before_substring = len_input_string;
209  after_substring = NULL;
210  len_after_substring = 0;
211  return;
212  }
213 
214  after_substring = skipSeparator(s1, substring[len_substring-1]);
215  len_before_substring = s1 - input_string;
216  len_after_substring = len_input_string - len_before_substring - len_substring;
217 }
218 
219 //----------------------------------------------------------------------------
220 int snl_fei::storeNamedAttribute(const char* name,
221  void* attribute,
222  std::vector<char*>& attributeNames,
223  std::vector<void*>& attributes)
224 {
225  int offset = -1;
226  const char* foundname = attributeNames.empty() ?
227  0 : snl_fei::getParam(name, attributeNames.size(),
228  &(attributeNames[0]), offset);
229 
230  if (foundname != 0) {
231  attributes[offset] = attribute;
232  }
233  else {
234  char* newname = new char[strlen(name)+1];
235  strcpy(newname, name);
236  attributeNames.push_back(newname);
237  attributes.push_back(attribute);
238  }
239 
240  return(0);
241 }
242 
243 //----------------------------------------------------------------------------
244 void* snl_fei::retrieveNamedAttribute(const char* name,
245  std::vector<char*>& attributeNames,
246  std::vector<void*>& attributes)
247 {
248  int offset = -1;
249  const char* foundname = attributeNames.empty() ?
250  0 : snl_fei::getParam(name, attributeNames.size(),
251  &(attributeNames[0]), offset);
252 
253  void* returnVal = NULL;
254 
255  if (foundname != 0) {
256  returnVal = attributes[offset];
257  }
258  else {
259  return( returnVal );
260  }
261 
262  return( returnVal );
263 }
264 
265 //----------------------------------------------------------------------------
266 unsigned snl_fei::leading_substring_length(const char* string)
267 {
268  if (string == NULL) {
269  return(0);
270  }
271 
272  const char* lastchar = string;
273  unsigned len = 0;
274 
275  while(*lastchar != ' ' && *lastchar != '\t' && *lastchar != '\0') {
276  ++len;
277  ++lastchar;
278  }
279 
280  return(len);
281 }
282 
283 //----------------------------------------------------------------------------
284 const char* snl_fei::skipSeparator(const char* paramString,
285  char separator)
286 {
287  if (paramString == NULL) return(NULL);
288 
289  const char* result = strchr(paramString, separator);
290 
291  if (result == NULL) return(result);
292 
293  //allow for the possibility that separator is repeated
294  while(result[0] == separator) result++;
295 
296  return( result );
297 }
298 
299 //----------------------------------------------------------------------------
300 int snl_fei::mergeStringLists(char**& strings,
301  int& numStrings,
302  const char*const* stringsToMerge,
303  int numStringsToMerge)
304 {
305  int i;
306  if (numStrings == 0) {
307  strings = new char*[numStringsToMerge];
308 
309  for(i=0; i<numStringsToMerge; ++i){
310  strings[i] = new char[strlen(stringsToMerge[i])+1];
311 
312  strcpy(strings[i], stringsToMerge[i]);
313  }
314 
315  numStrings = numStringsToMerge;
316  }
317  else {
318  int numMerged = 0;
319  bool* merged = new bool[numStringsToMerge];
320  for(i=0; i<numStringsToMerge; ++i) {
321  const char* temp;
322  const char* temp2;
323  int len_temp, len_temp2;
324  separate_string(stringsToMerge[i], " ",
325  temp, len_temp, temp2, len_temp2);
326  std::string strtemp(temp, len_temp);
327  int foundOffset = -1;
328  const char* matchingString =
329  snl_fei::getParam(strtemp.c_str(), numStrings, strings, foundOffset);
330  if (matchingString != NULL) {
331  int len = strlen(stringsToMerge[i])+1;
332  delete [] strings[foundOffset];
333  strings[foundOffset] = new char[len];
334  strcpy(strings[foundOffset], stringsToMerge[i]);
335  merged[i] = true;
336  ++numMerged;
337  }
338  else merged[i] = false;
339  }
340 
341  if (numMerged == numStringsToMerge) {
342  delete [] merged;
343  return(0);
344  }
345 
346  char** newStrings = new char*[numStrings+numStringsToMerge-numMerged];
347  for(i=0; i<numStrings; ++i) {
348  newStrings[i] = strings[i];
349  }
350  int offset = numStrings;
351  for(i=0; i<numStringsToMerge; ++i) {
352  if (!merged[i]) {
353  int len = strlen(stringsToMerge[i])+1;
354  newStrings[offset] = new char[len];
355  strcpy(newStrings[offset++], stringsToMerge[i]);
356  }
357  }
358  delete [] merged;
359 
360  delete [] strings;
361  strings = newStrings;
362  numStrings+= numStringsToMerge-numMerged;
363  }
364 
365  return(0);
366 }
367 
368 //----------------------------------------------------------------------------
369 int snl_fei::resolveConflictingCRs(fei::MatrixGraph& matrixGraph,
370  fei::Matrix& bcEqns,
371  const std::vector<int>& bcEqnNumbers)
372 {
373  int numLagrangeConstraints = matrixGraph.getLocalNumLagrangeConstraints();
374  if (numLagrangeConstraints < 1) {
375  return(0);
376  }
377 
378  double coefs[3];
379  int indices[3];
380  indices[0] = 0;
381  indices[1] = 1;
382  indices[2] = 2;
383  coefs[0] = 1.0;
384  coefs[1] = 0.0;
385  coefs[2] = 1.0;
386 
387  double* coefPtr = &(coefs[0]);
388  int* indicesPtr = &(indices[0]);
389 
390  double fei_eps = 1.e-49;
391 
392  std::vector<int> cr_indices;
393  std::map<int,Constraint<fei::Record<int>*>*>& lagrangeConstraints =
394  matrixGraph.getLagrangeConstraints();
395 
396  std::map<int,Constraint<fei::Record<int>*>*>::const_iterator
397  cr_iter = lagrangeConstraints.begin(),
398  cr_end = lagrangeConstraints.end();
399 
400  while(cr_iter != cr_end) {
401  Constraint<fei::Record<int>*>* cr = (*cr_iter).second;
402 
403  CHK_ERR( matrixGraph.getConstraintConnectivityIndices(cr, cr_indices) );
404 
405  std::vector<double>& weights = cr->getMasterWeights();
406  double* weightsPtr = &weights[0];
407 
408  int len = cr_indices.size();
409  int* cr_indPtr = &(cr_indices[0]);
410  for(int j=0; j<len; ++j) {
411  if (std::abs(weightsPtr[j] + 1.0) > fei_eps) continue;
412 
413  int eqn = cr_indPtr[j];
414  if (fei::binarySearch(eqn, bcEqnNumbers) > -1) {
415  int cr_eqn = cr->getEqnNumber();
416 
417  CHK_ERR( bcEqns.copyIn(1, &cr_eqn, 3, indicesPtr,
418  (double**)(&coefPtr)) );
419  }
420  }
421  ++cr_iter;
422  }
423 
424  return(0);
425 }
426 
427 //----------------------------------------------------------------------------
428 int snl_fei::gatherRemoteEssBCs(fei::CSVec& essBCs,
429  fei::SparseRowGraph* remoteGraph,
430  fei::Matrix& matrix)
431 {
432  std::vector<int>& rrowOffs = remoteGraph->rowOffsets;
433  std::vector<int>& rcols = remoteGraph->packedColumnIndices;
434 
435  int numEssEqns = essBCs.size();
436  if (numEssEqns > 0) {
437  int* essEqns = &(essBCs.indices()[0]);
438  double* coefs = &(essBCs.coefs()[0]);
439 
440  if (rrowOffs.size() > 0 && rcols.size() > 0) {
441 
442  int* rowOffsPtr = &(rrowOffs[0]);
443  int* rcolsPtr = &(rcols[0]);
444 
445  for(int j=0; j<numEssEqns; ++j) {
446 
447  int eqn = essEqns[j];
448 
449  for(unsigned i=0; i<rrowOffs.size()-1; ++i) {
450  int len = rowOffsPtr[i+1]-rowOffsPtr[i];
451  int* colsPtr = &(rcolsPtr[rowOffsPtr[i]]);
452 
453  if (fei::binarySearch(eqn, colsPtr, len) > -1) {
454  double coef = coefs[j];
455  double* coefPtr = &coef;
456 
457  for(int k=0; k<len; ++k) {
458  CHK_ERR( matrix.copyIn(1, &(colsPtr[k]),
459  1, &(eqn), &coefPtr) );
460  }
461  }
462  }
463  }
464  }
465  }
466 
467  CHK_ERR( matrix.gatherFromOverlap(false) );
468 
469  return(0);
470 }
471 
473 snl_fei::mergeSparseRowGraphs(const fei::SparseRowGraph* srg1,
474  const fei::SparseRowGraph* srg2)
475 {
477 
478  int numrows = srg1->rowNumbers.size() + srg2->rowNumbers.size();
479  int nnz = srg1->packedColumnIndices.size() + srg2->packedColumnIndices.size();
480 
481  newgraph->rowNumbers.resize(numrows);
482  newgraph->rowOffsets.resize(numrows+1);
483  newgraph->packedColumnIndices.resize(nnz);
484 
485  std::map<int,int> rowmap;
486 
487  for(unsigned i=0; i<srg1->rowNumbers.size(); ++i) {
488  int rowlen = srg1->rowOffsets[i+1]-srg1->rowOffsets[i];
489  rowmap.insert(std::make_pair(srg1->rowNumbers[i], rowlen));
490  }
491 
492  for(unsigned i=0; i<srg2->rowNumbers.size(); ++i) {
493  int rowlen = srg2->rowOffsets[i+1]-srg2->rowOffsets[i];
494  rowmap.insert(std::make_pair(srg2->rowNumbers[i], rowlen));
495  }
496 
497  std::map<int,int>::iterator
498  r_iter = rowmap.begin(),
499  r_end = rowmap.end();
500 
501  int offset = 0;
502  for(unsigned i=0; r_iter != r_end; ++r_iter, ++i) {
503  newgraph->rowNumbers[i] = r_iter->first;
504  int rowlen = r_iter->second;
505  newgraph->rowOffsets[i] = offset;
506  offset += rowlen;
507  r_iter->second = i;
508  }
509  newgraph->rowOffsets[numrows] = offset;
510 
511  for(unsigned i=0; i<srg1->rowNumbers.size(); ++i) {
512  r_iter = rowmap.find(srg1->rowNumbers[i]);
513 
514  int newcoloffset = newgraph->rowOffsets[r_iter->second];
515 
516  int jbegin = srg1->rowOffsets[i];
517  int jend = srg1->rowOffsets[i+1];
518  for(int j=jbegin; j<jend; ++j) {
519  newgraph->packedColumnIndices[newcoloffset++] =
520  srg1->packedColumnIndices[j];
521  }
522  }
523 
524  for(unsigned i=0; i<srg2->rowNumbers.size(); ++i) {
525  r_iter = rowmap.find(srg2->rowNumbers[i]);
526 
527  int newcoloffset = newgraph->rowOffsets[r_iter->second];
528 
529  int jbegin = srg2->rowOffsets[i];
530  int jend = srg2->rowOffsets[i+1];
531  for(int j=jbegin; j<jend; ++j) {
532  newgraph->packedColumnIndices[newcoloffset++] =
533  srg2->packedColumnIndices[j];
534  }
535  }
536 
537  return(newgraph);
538 }
539 
540 void snl_fei::copy2DBlockDiagToColumnContig(int numBlocks,
541  const int* blockSizes,
542  const double*const* values2d,
543  int format,
544  double* colcontigvalues)
545 {
546  int i, j, k, offset, coffset;
547 
548  switch(format) {
549  case FEI_BLOCK_DIAGONAL_ROW:
550  offset = 0;
551  coffset = 0;
552  for(i=0; i<numBlocks; ++i) {
553  int bsize = blockSizes[i];
554  for(j=0; j<bsize; ++j) {
555  for(k=0; k<bsize; ++k) {
556  colcontigvalues[coffset+j*bsize+k] = values2d[offset+j][k];
557  }
558  }
559  offset += bsize;
560  coffset += bsize*bsize;
561  }
562  break;
563  default:
564  FEI_OSTRINGSTREAM osstr;
565  osstr << "copy2DBlockDiagToColumnContig ERROR, format="<<format
566  << " not recognized.";
567  throw std::runtime_error(osstr.str());
568  }
569 }
570 
571 void snl_fei::copy2DToColumnContig(int numrows,
572  int numcols,
573  const double*const* values2d,
574  int format,
575  double* colcontigvalues)
576 {
577  int i, j;
578 
579  switch(format) {
580 
581  case FEI_DENSE_ROW:
582  for(i=0; i<numrows; ++i) {
583  for(j=0; j<numcols; ++j) {
584  colcontigvalues[j*numrows+i] = values2d[i][j];
585  }
586  }
587  break;
588 
589  case FEI_DENSE_COL:
590  for(j=0; j<numcols; ++j) {
591  for(i=0; i<numrows; ++i) {
592  colcontigvalues[j*numrows+i] = values2d[j][i];
593  }
594  }
595  break;
596 
597  default:
598  FEI_OSTRINGSTREAM osstr;
599  osstr << "copy2DToColumnContig ERROR, format="<<format<<" not recognized.";
600  throw std::runtime_error(osstr.str());
601  }
602 }
std::vector< int > rowNumbers
virtual int getConstraintConnectivityIndices(ConstraintType *cr, std::vector< int > &globalIndices)=0
std::vector< int > packedColumnIndices
std::vector< int > rowOffsets
virtual std::map< int, ConstraintType * > & getLagrangeConstraints()=0
int binarySearch(const T &item, const T *list, int len)
virtual int copyIn(int numRows, const int *rows, int numCols, const int *cols, const double *const *values, int format=0)=0
virtual int getLocalNumLagrangeConstraints() const =0
virtual int gatherFromOverlap(bool accumulate=true)=0