9 #include <fei_CommUtils.hpp>
10 #include <fei_iostream.hpp>
11 #include <fei_impl_utils.hpp>
12 #include <fei_FillableMat.hpp>
13 #include <fei_CSRMat.hpp>
14 #include <fei_CSVec.hpp>
15 #include <fei_Graph.hpp>
16 #include <fei_Matrix.hpp>
17 #include <fei_Reducer.hpp>
20 namespace impl_utils {
24 const std::vector<int>& targets,
25 std::vector<int>& offsets)
27 offsets.assign(sources.size(), -1);
29 size_t ssize = sources.size(), tsize = targets.size();
30 size_t si = 0, ti = 0;
32 const int* sourcesptr = &sources[0];
33 const int* targetsptr = &targets[0];
35 while(si<ssize && ti<tsize) {
36 if (sourcesptr[si] == targetsptr[ti]) {
41 while(sourcesptr[si] < targetsptr[ti] && si<ssize) {
45 while(sourcesptr[si] > targetsptr[ti] && ti<tsize) {
52 size_t num_bytes_FillableMat(
const fei::FillableMat& mat)
54 int nrows = mat.getNumRows();
57 int num_chars_int = (2 + nrows*2 + nnz)*
sizeof(
int);
58 int num_chars_double = nnz*
sizeof(double);
60 return num_chars_int + num_chars_double;
64 void pack_FillableMat(
const fei::FillableMat& mat,
67 int nrows = mat.getNumRows();
70 int num_chars_int = (2 + nrows*2 + nnz)*
sizeof(
int);
72 int* intdata =
reinterpret_cast<int*
>(buffer);
73 double* doubledata =
reinterpret_cast<double*
>(buffer+num_chars_int);
78 intdata[ioffset++] = nrows;
79 intdata[ioffset++] = nnz;
81 int ioffsetcols = 2+nrows*2;
83 fei::FillableMat::const_iterator
87 for(; r_iter!=r_end; ++r_iter) {
88 int rowNumber = r_iter->first;
91 intdata[ioffset++] = rowNumber;
92 const int rowlen = row->size();
93 intdata[ioffset++] = rowlen;
95 const std::vector<int>& rowindices = row->indices();
96 const std::vector<double>& rowcoefs = row->coefs();
97 for(
int i=0; i<rowlen; ++i) {
98 intdata[ioffsetcols++] = rowindices[i];
99 doubledata[doffset++] = rowcoefs[i];
106 fei::FillableMat& mat,
107 bool clear_mat_on_entry,
108 bool overwrite_entries)
110 if (clear_mat_on_entry) {
114 if (buffer_end == buffer_begin) {
118 const int* intdata =
reinterpret_cast<const int*
>(buffer_begin);
120 int nrows = intdata[ioffset++];
121 int nnz = intdata[ioffset++];
123 int ioffsetcols = 2+nrows*2;
125 int num_chars_int = (2+nrows*2 + nnz)*
sizeof(
int);
126 const double* doubledata =
reinterpret_cast<const double*
>(buffer_begin+num_chars_int);
130 for(
int i=0; i<nrows; ++i) {
131 int row = intdata[ioffset++];
132 int rowlen = intdata[ioffset++];
134 for(
int j=0; j<rowlen; ++j) {
135 int col = intdata[ioffsetcols++];
136 double coef = doubledata[doffset++];
138 if (overwrite_entries) {
139 mat.putCoef(row, col, coef);
142 mat.sumInCoef(row, col, coef);
147 if (doffset != nnz) {
148 throw std::runtime_error(
"fei::impl_utils::unpack_FillableMat: failed, sizes don't agree.");
155 bool all_zeros =
true;
156 if (buffer_end == buffer_begin) {
160 const int* intdata =
reinterpret_cast<const int*
>(buffer_begin);
162 int nrows = intdata[ioffset++];
163 int nnz = intdata[ioffset++];
169 std::vector<double>& packed_coefs = mat.getPackedCoefs();
170 packed_coefs.resize(nnz);
172 int ioffsetcols = 2+nrows*2;
174 int num_chars_int = (2+nrows*2 + nnz)*
sizeof(
int);
175 const double* doubledata =
reinterpret_cast<const double*
>(buffer_begin+num_chars_int);
179 for(
int i=0; i<nrows; ++i) {
180 int row = intdata[ioffset++];
181 int rowlen = intdata[ioffset++];
186 for(
int j=0; j<rowlen; ++j) {
187 int col = intdata[ioffsetcols++];
188 double coef = doubledata[doffset];
189 if (coef != 0.0) all_zeros =
false;
191 packed_coefs[doffset++] = coef;
198 size_t num_bytes_indices_coefs(
const std::vector<int>& indices,
199 const std::vector<double>& coefs)
201 int num = indices.size();
202 int num_chars_int = (1+num)*
sizeof(
int);
203 int num_chars = num_chars_int + num*
sizeof(double);
207 void pack_indices_coefs(
const std::vector<int>& indices,
208 const std::vector<double>& coefs,
209 std::vector<char>& buffer,
212 if (indices.size() != coefs.size()) {
213 throw std::runtime_error(
"fei::impl_utils::pack_indices_coefs failed, sizes don't match.");
216 int num = indices.size();
217 int num_chars_int = (1+num)*
sizeof(
int);
218 int num_chars = num_chars_int + num*
sizeof(double);
220 buffer.resize(num_chars);
223 int* intdata =
reinterpret_cast<int*
>(&buffer[0]);
224 double* doubledata =
reinterpret_cast<double*
>(&buffer[0]+num_chars_int);
228 intdata[ioffset++] = num;
229 for(
int i=0; i<num; ++i) {
230 intdata[ioffset++] = indices[i];
231 doubledata[doffset++] = coefs[i];
235 void unpack_indices_coefs(
const std::vector<char>& buffer,
236 std::vector<int>& indices,
237 std::vector<double>& coefs)
239 if (buffer.size() == 0)
return;
241 const int* intdata =
reinterpret_cast<const int*
>(&buffer[0]);
243 int num = intdata[ioffset++];
244 int num_chars_int = (1+num)*
sizeof(
int);
245 const double* doubledata =
reinterpret_cast<const double*
>(&buffer[0]+num_chars_int);
251 for(
int i=0; i<num; ++i) {
252 indices[i] = intdata[ioffset++];
253 coefs[i] = doubledata[doffset++];
258 void separate_BC_eqns(
const fei::FillableMat& mat,
259 std::vector<int>& bcEqns,
260 std::vector<double>& bcVals)
262 fei::FillableMat::const_iterator
263 m_iter = mat.begin(),
266 for(; m_iter != m_end; ++m_iter) {
267 int eqn = m_iter->first;
270 std::vector<int>::iterator
271 iter = std::lower_bound(bcEqns.begin(), bcEqns.end(), eqn);
272 if (iter == bcEqns.end() || *iter != eqn) {
273 size_t offset = iter - bcEqns.begin();
274 bcEqns.insert(iter, eqn);
275 std::vector<double>::iterator viter = bcVals.begin();
278 double val = get_entry(*row, eqn);
279 bcVals.insert(viter, val);
282 fei::console_out() <<
"separate_BC_eqns ERROR, failed to find coef for eqn " << eqn;
290 void create_col_to_row_map(
const fei::FillableMat& mat,
291 std::multimap<int,int>& crmap)
295 if (mat.getNumRows() == 0)
return;
297 std::vector<int> rowNumbers;
300 fei::FillableMat::const_iterator
301 m_iter = mat.begin(),
304 for(; m_iter != m_end; ++m_iter) {
305 int rowNum = m_iter->first;
308 const std::vector<int>& rowindices = rowvec->indices();
310 for(
size_t i=0; i<rowindices.size(); ++i) {
311 int colNum = rowindices[i];
313 crmap.insert(std::make_pair(colNum, rowNum));
319 int remove_couplings(fei::FillableMat& mat)
321 int levelsOfCoupling = 0;
323 std::vector<int> rowNumbers;
326 bool finished =
false;
328 std::multimap<int,int> crmap;
329 create_col_to_row_map(mat, crmap);
331 typedef std::multimap<int,int>::iterator MM_Iter;
333 fei::FillableMat::iterator
334 m_iter = mat.begin(),
337 bool foundCoupling =
false;
338 for(; m_iter != m_end; ++m_iter) {
339 int rownum = m_iter->first;
343 std::pair<MM_Iter,MM_Iter> mmi = crmap.equal_range(rownum);
346 for(MM_Iter cri = mmi.first; cri != mmi.second; ++cri) {
347 int cri_row = cri->second;
349 fei::CSVec* frow = mat.create_or_getRow(cri_row);
351 double coef = get_entry(*frow,rownum);
353 remove_entry(*frow, rownum);
355 std::vector<int>& indices = mrow->indices();
356 std::vector<double>& coefs = mrow->coefs();
358 size_t rowlen = mrow->size();
359 for(
size_t ii=0; ii<rowlen; ++ii) {
363 int* indPtr = indices.empty() ? NULL : &indices[0];
364 double* coefPtr = coefs.empty() ? NULL : &coefs[0];
365 add_entries(*frow, rowlen, indPtr, coefPtr);
366 foundCoupling =
true;
370 if (foundCoupling ==
true) ++levelsOfCoupling;
371 else finished =
true;
374 if (levelsOfCoupling > 1) {
376 << levelsOfCoupling <<
" (Each level of coupling means that a slave DOF "
377 <<
"depends on a master which is itself a slave.) Behavior is not well "
378 <<
"understood for levelsOfCoupling greater than 1..."<<FEI_ENDL;
381 return levelsOfCoupling;
385 void global_union(MPI_Comm comm,
386 const fei::FillableMat& localMatrix,
387 fei::FillableMat& globalUnionMatrix)
389 globalUnionMatrix = localMatrix;
400 size_t num_bytes = num_bytes_FillableMat(localMatrix);
401 std::vector<char> localchardata(num_bytes);
403 pack_FillableMat(localMatrix, &localchardata[0]);
408 std::vector<int> recvdatalengths;
409 std::vector<char> recvdata;
410 int err =
fei::Allgatherv(comm, localchardata, recvdatalengths, recvdata);
412 throw std::runtime_error(
"fei::impl_utils::global_union: Allgatherv-int failed.");
417 bool clearMatOnEntry =
false;
418 bool overwriteEntries =
true;
421 for(
size_t p=0; p<recvdatalengths.size(); ++p) {
422 int len = recvdatalengths[p];
426 globalUnionMatrix, clearMatOnEntry, overwriteEntries);
434 void global_union(MPI_Comm comm,
437 globalUnionVec.indices().clear();
438 globalUnionVec.coefs().clear();
440 const std::vector<int>& localindices = localVec.indices();
441 const std::vector<double>& localcoefs = localVec.coefs();
443 std::vector<int> localintdata;
444 if (localindices.size() > 0) {
445 localintdata.assign(&localindices[0], &localindices[0]+localindices.size());
448 std::vector<double> localdoubledata;
449 if (localcoefs.size() > 0) {
450 localdoubledata.assign(&localcoefs[0], &localcoefs[0]+localcoefs.size());
456 std::vector<int> recvintdatalengths;
457 std::vector<int> recvintdata;
458 int err =
fei::Allgatherv(comm, localintdata, recvintdatalengths, recvintdata);
460 throw std::runtime_error(
"snl_fei::globalUnion csvec: Allgatherv-int failed.");
463 std::vector<int> recvdoubledatalengths;
464 std::vector<double> recvdoubledata;
465 err =
fei::Allgatherv(comm, localdoubledata, recvdoubledatalengths, recvdoubledata);
467 throw std::runtime_error(
"snl_fei::globalUnion csvec: Allgatherv-double failed.");
470 if (recvintdatalengths.size() != recvdoubledatalengths.size()) {
471 throw std::runtime_error(
"snl_fei::globalUnion csvec: inconsistent lengths from Allgatherv");
476 unsigned len = recvintdata.size();
478 int* recvintPtr = &recvintdata[0];
479 double* recvdoublePtr = &recvdoubledata[0];
481 for(
unsigned i=0; i<len; ++i) {
482 fei::put_entry(globalUnionVec, recvintPtr[i], recvdoublePtr[i]);
488 void translate_to_reduced_eqns(
const fei::Reducer& reducer,
fei::CSRMat& mat)
492 std::vector<int>& rowNumbers = srg.
rowNumbers;
493 for(
size_t i=0; i<rowNumbers.size(); ++i) {
494 rowNumbers[i] = reducer.translateToReducedEqn(rowNumbers[i]);
498 for(
size_t i=0; i<colIndices.size(); ++i) {
499 colIndices[i] = reducer.translateToReducedEqn(colIndices[i]);
504 void translate_to_reduced_eqns(
const fei::Reducer& reducer,
fei::CSVec& vec)
506 std::vector<int>& indices = vec.indices();
507 for(
size_t i=0; i<indices.size(); ++i) {
508 indices[i] = reducer.translateToReducedEqn(indices[i]);
515 const std::vector<int>& rowNumbers = inmat.getGraph().
rowNumbers;
516 const std::vector<int>& rowOffsets = inmat.getGraph().
rowOffsets;
519 for(
size_t i=0; i<rowNumbers.size(); ++i) {
520 int row = rowNumbers[i];
521 int offset = rowOffsets[i];
522 int rowlen = rowOffsets[i+1]-offset;
523 const int* indices = pckColInds.empty() ? NULL : &pckColInds[offset];
525 if (graph.
addIndices(row, rowlen, indices) != 0) {
526 throw std::runtime_error(
"fei::impl_utils::add_to_graph ERROR in graph.addIndices.");
534 const std::vector<int>& rowNumbers = inmat.getGraph().
rowNumbers;
535 const std::vector<int>& rowOffsets = inmat.getGraph().
rowOffsets;
537 const std::vector<double>& pckCoefs = inmat.getPackedCoefs();
539 for(
size_t i=0; i<rowNumbers.size(); ++i) {
540 int row = rowNumbers[i];
541 int offset = rowOffsets[i];
542 int rowlen = rowOffsets[i+1]-offset;
543 const int* indices = &pckColInds[offset];
544 const double* coefs = &pckCoefs[offset];
547 if (matrix.
sumIn(1, &row, rowlen, indices, &coefs, FEI_DENSE_ROW) != 0) {
548 throw std::runtime_error(
"fei::impl_utils::add_to_matrix ERROR in matrix.sumIn.");
552 if (matrix.
copyIn(1, &row, rowlen, indices, &coefs, FEI_DENSE_ROW) != 0) {
553 throw std::runtime_error(
"fei::impl_utils::add_to_matrix ERROR in matrix.copyIn.");
int Allgatherv(MPI_Comm comm, std::vector< T > &sendbuf, std::vector< int > &recvLengths, std::vector< T > &recvbuf)
bool unpack_CSRMat(const char *buffer_begin, const char *buffer_end, fei::CSRMat &mat)
std::vector< int > rowNumbers
void get_row_numbers(const FillableMat &mat, std::vector< int > &rows)
std::vector< int > packedColumnIndices
std::vector< int > rowOffsets
void find_offsets(const std::vector< int > &sources, const std::vector< int > &targets, std::vector< int > &offsets)
virtual int addIndices(int row, int len, const int *indices)=0
void unpack_FillableMat(const char *buffer_begin, const char *buffer_end, fei::FillableMat &mat, bool clear_mat_on_entry, bool overwrite_entries)
virtual int sumIn(int numRows, const int *rows, int numCols, const int *cols, const double *const *values, int format=0)=0
std::ostream & console_out()
int localProc(MPI_Comm comm)
virtual int copyIn(int numRows, const int *rows, int numCols, const int *cols, const double *const *values, int format=0)=0
int count_nnz(const FillableMat &mat)
int numProcs(MPI_Comm comm)