47 #ifdef HAVE_FEI_AZTECOO
57 #define AZTEC_MPI AZTEC_MPI
73 #define ADMSR_LOCAL_ROW_ALLOC_LEN(localRow) 1+bindx[localRow+1]-bindx[localRow]
75 #define ADMSR_LOCAL_ROW_LEN(localRow) 1+rowLengths_[localRow]
77 namespace fei_trilinos {
83 localOffset_(map->localOffset()),
84 localSize_(map->localSize()),
87 arraysAllocated_(false),
92 N_update_(map->localSize()),
110 AztecDMSR_Matrix::AztecDMSR_Matrix(
const AztecDMSR_Matrix& src)
111 : isFilled_(src.isFilled_),
112 isAllocated_(src.isAllocated_),
113 localOffset_(src.localOffset_),
114 localSize_(src.localSize_),
117 arraysAllocated_(src.arraysAllocated_),
121 nnzeros_(src.nnzeros_),
122 N_update_(src.N_update_),
127 azTransformed_(src.azTransformed_)
129 expand_array(tmp_array_, tmp_array_len_, src.tmp_array_len_);
130 expand_array(dtmp_array_, dtmp_array_len_, src.dtmp_array_len_);
135 rowLengths_[i] = src.rowLengths_[i];
141 if (isAllocated_ && nnzeros_ > 0) {
142 val =
new double[nnzeros_+1];
143 bindx =
new int[nnzeros_+1];
145 for(
int i=0; i<nnzeros_+1; ++i) {
147 bindx[i] = src.bindx[i];
151 AZ_set_MSR(Amat_, bindx, val, amap_->data_org, 0, NULL, AZ_LOCAL);
157 AztecDMSR_Matrix::~AztecDMSR_Matrix()
159 if (arraysAllocated_) {
164 arraysAllocated_ =
false;
167 if (dtmp_array_)
delete [] dtmp_array_; dtmp_array_ = NULL;
170 delete [] rowLengths_;
175 if (azTransformed_) {
176 azTransformed_ =
false;
179 AZ_matrix_destroy(&Amat_);
183 isAllocated_ =
false;
184 arraysAllocated_ =
false;
186 if (tmp_array_len_ > 0) {
187 delete [] tmp_array_;
194 void AztecDMSR_Matrix::expand_array(
int*& array,
int& arraylen,
int newlen)
196 if (arraylen < newlen) {
198 array =
new int[newlen];
199 for(
int i=0; i<newlen; ++i) array[i] = -999;
205 void AztecDMSR_Matrix::expand_array(
double*& array,
int& arraylen,
int newlen)
207 if (arraylen < newlen) {
209 array =
new double[newlen];
210 for(
int i=0; i<newlen; ++i) array[i] = -999.9;
216 void AztecDMSR_Matrix::scale(
double scalar)
218 if (scalar == 1.0)
return;
221 for(
int i=0; i<nnzeros_+1; ++i) {
228 void AztecDMSR_Matrix::matvec(
const Aztec_LSVector& x,
229 Aztec_LSVector& y)
const
237 int *proc_config = amap_->getProcConfig();
239 double *b = (
double*)x.startPointer();
240 double *c = (
double*)y.startPointer();
242 AZ_MSR_matvec_mult(b, c, Amat_, proc_config);
249 void AztecDMSR_Matrix::put(
double s)
252 for(
int i=0; i<bindx[N_update_]; i++) val[i] = s;
255 fei::console_out() <<
"AztecDMSR_Matrix::put - ERROR, can't do put until allocated"
262 int AztecDMSR_Matrix::rowLength(
int row)
const
268 if(amap_->inUpdate(thisRow,localRow)){
269 return(ADMSR_LOCAL_ROW_ALLOC_LEN(localRow));
273 <<
" not in local update set." <<
FEI_ENDL;
280 int AztecDMSR_Matrix::setDiagEntry(
int row,
double value)
284 if(!amap_->inUpdate(thisRow,localRow)){
286 <<
" not in local update set." <<
FEI_ENDL;
290 val[localRow] = value;
295 double AztecDMSR_Matrix::getDiagEntry(
int row)
const
299 if(!amap_->inUpdate(thisRow,localRow)){
301 <<
" not in local update set." <<
FEI_ENDL;
302 abort();
return val[0];
305 return(val[localRow]);
309 int AztecDMSR_Matrix::getOffDiagRowPointers(
int row,
int*& colIndices,
311 int& offDiagRowLength)
315 if(!amap_->inUpdate(thisRow,localRow)){
316 fei::console_out() <<
"AztecDMSR_Matrix::getOffDiagRowPointers: ERROR - row " << row
317 <<
" not in local update set." <<
FEI_ENDL;
321 offDiagRowLength = rowLengths_[localRow];
322 if (isFilled_) offDiagRowLength = ADMSR_LOCAL_ROW_ALLOC_LEN(localRow)-1;
323 int start = bindx[localRow];
324 colIndices = &(bindx[start]);
325 coefs = &(val[start]);
331 void AztecDMSR_Matrix::getRow(
int row,
341 bool foundDiagonal =
false;
343 int j, localRow, itmp;
347 if(!amap_->inUpdate(thisRow,localRow)){
349 <<
" not in local update set." <<
FEI_ENDL;
354 int start = bindx[localRow];
355 int end = bindx[localRow+1]-1;
358 for(
int i=start; i<=end; i++){
360 colInd[j] = amap_->getTransformedEqn(bindx[i]);
362 if (colInd[j]==row) {
366 coefs[j] = val[localRow];
371 foundDiagonal =
true;
377 coefs[j] = val[localRow];
386 int AztecDMSR_Matrix::putRow(
int row,
int len,
const double *coefs,
394 int j, localRow, globalColIndex;
398 if (!amap_->inUpdate(thisRow,localRow)){
400 <<
" not in local update set." <<
FEI_ENDL;
404 int offDiagRowLen = rowLengths_[localRow];
405 int rowAllocLen = ADMSR_LOCAL_ROW_ALLOC_LEN(localRow);
406 if (isFilled_) offDiagRowLen = rowAllocLen - 1;
407 int offDiagRowAllocLen = rowAllocLen - 1;
409 if (len > rowAllocLen) {
414 int jLimit = bindx[localRow+1] - 1;
415 int jStart = bindx[localRow];
416 int* colInds = &(bindx[jStart]);
417 int colStart = *colInds;
418 double* rowCoefs = &(val[jStart]);
420 for(
int i=0; i<len; i++){
421 if (colInd[i] == row){
422 val[localRow] = coefs[i];
430 int colIndex = colStart;
432 while (j <= jLimit) {
433 globalColIndex = amap_->getTransformedEqn(colIndex);
435 if (globalColIndex == col)
break;
437 colIndex = bindx[++j];
447 <<
" find col. index " << colInd[i] <<
" in "
456 int insertPoint = -1;
457 int index = fei::binarySearch<int>(col, colInds, offDiagRowLen, insertPoint);
459 if (index >= offDiagRowAllocLen){
461 <<
"row " << row <<
", colInd["<<i<<
"] " << colInd[i]
462 <<
", index = " << index <<
FEI_ENDL;
467 rowCoefs[index] = coefs[i];
470 int tmp = offDiagRowLen;
471 int err = insert(col, insertPoint, colInds,
472 tmp, offDiagRowAllocLen);
473 err += insert(coefs[i], insertPoint, rowCoefs,
474 offDiagRowLen, offDiagRowAllocLen);
477 <<
"value for index " << col <<
" to row " << row <<
FEI_ENDL;
480 rowLengths_[localRow]++;
489 int AztecDMSR_Matrix::sumIntoRow(
int numRows,
const int* rows,
490 int numCols,
const int *colInd,
491 const double*
const* coefs)
493 if (numRows == 0 || numCols == 0)
return(0);
497 for(
int i=0; i<numRows; ++i) {
498 err = sumIntoRow(rows[i], numCols, coefs[i], colInd);
499 if (err != 0)
return(err);
509 for(
int i=0; i<numRows; ++i) {
512 if (!amap_->inUpdate(row, localRow)) {
514 <<
" not in local update set [" << amap_->getUpdate()[0] <<
" ... "
515 << amap_->getUpdate()[N_update_-1] <<
"]." <<
FEI_ENDL;
519 int rowlen = bindx[localRow+1]-bindx[localRow];
520 if (maxRowLen < rowlen) maxRowLen = rowlen;
523 if (maxRowLen+2*numCols > tmp_array_len_) {
524 expand_array(tmp_array_, tmp_array_len_, maxRowLen+2*numCols);
527 int* incols = &tmp_array_[maxRowLen];
528 int* indirect = incols+numCols;
530 for(
int jj=0; jj<numCols; ++jj) {
531 incols[jj] = colInd[jj];
535 fei::insertion_sort_with_companions<int>(numCols, incols, indirect);
539 for(
int i=0; i<numRows; ++i) {
541 if (!amap_->inUpdate(row, localRow)) {
543 <<
" not in local update set [" << amap_->getUpdate()[0] <<
" ... "
544 << amap_->getUpdate()[N_update_-1] <<
"]." <<
FEI_ENDL;
548 int jStart = bindx[localRow];
549 double* rowCoefs = val+jStart;
550 int* rowColInds = bindx+jStart;
551 int rowLen= bindx[localRow+1]-jStart;
553 for(
int jj=0; jj<rowLen; ++jj) {
554 tmp_array_[jj] = amap_->getTransformedEqn(rowColInds[jj]);
557 const double* coefs_i = coefs[i];
560 int incol = incols[inoffset];
561 while (incol == row) {
562 val[localRow] += coefs_i[indirect[inoffset++]];
563 if (inoffset >= numCols)
break;
564 incol = incols[inoffset];
567 if (inoffset >= numCols)
continue;
571 int rowOffset = fei::binarySearch<int>(incol, tmp_array_, rowLen);
574 <<
"row " << row <<
", col not found: "
579 rowCoefs[rowOffset++] += coefs_i[indirect[inoffset++]];
582 if (inoffset>0 && incols[inoffset] == incols[inoffset-1]) --rowOffset;
584 while(inoffset < numCols) {
585 incol = incols[inoffset];
588 val[localRow] += coefs_i[indirect[inoffset++]];
592 while(tmp_array_[rowOffset] != incol) {
594 if (rowOffset >= rowLen) {
596 << incol <<
" not found in row " << row <<
FEI_ENDL;
601 rowCoefs[rowOffset++] += coefs_i[indirect[inoffset++]];
602 if (inoffset>0 && incols[inoffset] == incols[inoffset-1]) --rowOffset;
610 int AztecDMSR_Matrix::sumIntoRow(
int row,
int len,
const double *coefs,
618 int localRow, thisRow = row ;
620 if (!amap_->inUpdate(thisRow,localRow)) {
622 <<
" not in local update set." <<
FEI_ENDL;
626 int jLimit = bindx[localRow+1] - 1;
627 int jStart = bindx[localRow];
628 int jLen = jLimit-jStart+1;
629 int* colInds = &(bindx[jStart]);
630 double* rowCoefs = &(val[jStart]);
633 if (jLen+len > tmp_array_len_) {
634 expand_array(tmp_array_, tmp_array_len_, jLen+len);
635 expand_array(dtmp_array_, dtmp_array_len_, len);
637 for(
int jj=0; jj<jLen; ++jj) {
638 tmp_array_[jj] = amap_->getTransformedEqn(colInds[jj]);
641 int* incols = &tmp_array_[jLen];
643 for(
int jj=0; jj<len; ++jj) {
644 int col = colInd[jj];
646 val[localRow] += coefs[jj];
650 dtmp_array_[doffs++] = coefs[jj];
653 fei::insertion_sort_with_companions<double>(doffs, incols, dtmp_array_);
656 int offset = fei::binarySearch<int>(incols[ioffset], tmp_array_, jLen);
659 <<
"row " << row <<
", col not found: "
664 rowCoefs[offset++] += dtmp_array_[ioffset++];
665 if (incols[ioffset] == tmp_array_[offset-1]) --offset;
667 while(ioffset < doffs) {
668 int incol = incols[ioffset];
670 while(tmp_array_[offset] != incol) {
672 if (offset >= jLen) {
674 << incols[ioffset] <<
" not found in row " << row <<
FEI_ENDL;
678 rowCoefs[offset++] += dtmp_array_[ioffset++];
679 if (incols[ioffset] == tmp_array_[offset-1]) --offset;
687 int rowAllocLen = ADMSR_LOCAL_ROW_ALLOC_LEN(localRow);
688 int offDiagRowLen = isFilled_ ? rowAllocLen - 1 : rowLengths_[localRow];
689 int offDiagRowAllocLen = rowAllocLen - 1;
691 for(
int i=0; i<len; i++){
692 if (colInd[i] == row){
693 val[localRow] += coefs[i];
699 int insertPoint = -1;
700 int index = fei::binarySearch<int>(col, colInds, offDiagRowLen, insertPoint);
703 rowCoefs[index] += coefs[i];
706 int tmp = offDiagRowLen;
707 int err = insert(col, insertPoint, colInds,
708 tmp, offDiagRowAllocLen);
709 err += insert(coefs[i], insertPoint, rowCoefs,
710 offDiagRowLen, offDiagRowAllocLen);
713 <<
"value for index " << col <<
" to row " << row <<
FEI_ENDL;
716 rowLengths_[localRow]++;
724 int AztecDMSR_Matrix::addScaledMatrix(
double scalar,
725 const AztecDMSR_Matrix& source)
727 if (N_update_ != source.N_update_ ||
728 nnzeros_ != source.nnzeros_ ||
729 isFilled_ != source.isFilled_) {
730 fei::console_out() <<
"AztecDMSR_Matrix::addScaledMatrix ERROR, not compatible"
735 const double* src_val = source.val;
737 for(i=0; i<N_update_; ++i) {
738 val[i] += scalar*src_val[i];
744 for(i=N_update_+1; i<nnzeros_+1; ++i) {
745 val[i] += src_val[i];
749 for(i=N_update_+1; i<nnzeros_+1; ++i) {
750 val[i] += scalar*src_val[i];
758 int AztecDMSR_Matrix::insert(
int item,
int offset,
int* list,
759 int& len,
int allocLen)
761 if (len >= allocLen)
return(-1);
763 for(
int i=len; i>offset; i--) list[i] = list[i-1];
772 int AztecDMSR_Matrix::insert(
double item,
int offset,
double* list,
773 int& len,
int allocLen)
775 if (len >= allocLen)
return(-1);
777 for(
int i=len; i>offset; i--) list[i] = list[i-1];
786 void AztecDMSR_Matrix::getDiagonal(Aztec_LSVector& diagVector)
const {
792 double *pdv = (
double*)diagVector.startPointer();
794 for(
int i=0; i<N_update_; i++){
800 void AztecDMSR_Matrix::allocate(
int *rowLengths)
813 for(i=0; i<N_update_; i++){
814 if (rowLengths[i] < 0) {
815 messageAbort(
"allocate: negative row length");
817 nnzeros_ += rowLengths[i] + 1;
823 bindx =
new int[nnzeros_+1];
828 val =
new double[nnzeros_+1];
830 arraysAllocated_ =
true;
832 for(i=0; i<nnzeros_+1; i++){
837 bindx[0] = N_update_+1;
839 for(i=0; i<N_update_; i++){
840 bindx[i+1] = bindx[i] + rowLengths[i];
841 if (bindx[i+1] < 0) {
842 messageAbort(
"allocate: bindx row length negative.");
847 val[N_update_] = 0.0;
849 AZ_set_MSR(Amat_, bindx, val,amap_->data_org, 0, NULL, AZ_LOCAL);
856 void AztecDMSR_Matrix::allocate(
int *rowLengths,
857 const int*
const* colIndices)
859 allocate(rowLengths);
862 int offset = N_update_+1;
863 for(
int i=0; i<N_update_; ++i) {
864 const int* row_cols = colIndices[i];
865 int row_len = rowLengths[i];
866 rowLengths_[i] = row_len-1;
870 for(
int j=0; j<row_len; ++j) {
871 col = row_cols[coffset++];
873 if (col == localOffset_+i) {
874 col = row_cols[coffset++];
877 if (col <= prev_col) {
878 messageAbort(
"allocate: column-indices not sorted.");
883 bindx[offset++] = col;
889 double AztecDMSR_Matrix::rowMax(
int row)
const {
893 if(!amap_->inUpdate(row,localRow)){
895 <<
" not in local update set." <<
FEI_ENDL;
899 max = fabs(val[localRow]);
901 for(
int i=bindx[localRow]; i<bindx[localRow+1]; i++)
902 if(fabs(val[i])>max)max = fabs(val[i]);
908 void AztecDMSR_Matrix::fillComplete() {
914 if (isFilled_ || azTransformed_) {
916 azTransformed_ =
true;
920 int *proc_config = amap_->getProcConfig();
925 int globalSize = amap_->globalSize();
926 for(
int i=N_update_+1; i<nnzeros_+1; i++) {
927 if (bindx[i] < 0 || bindx[i] >= globalSize) {
928 fei::console_out() <<
"AztecDMSR_Matrix: ERROR, bindx["<<i<<
"]: " << bindx[i]
929 <<
", globalSize: " << globalSize <<
FEI_ENDL;
931 MPI_Comm thisComm = amap_->getCommunicator();
937 AZ_transform(proc_config, &amap_->external, bindx, val,
938 amap_->getUpdate(), &amap_->update_index,
939 &amap_->extern_index, &amap_->data_org, N_update_,
940 dummy, dummy, dummy, &dummy, AZ_MSR_MATRIX);
953 AZ_set_MSR(Amat_, bindx, val, amap_->data_org, 0, NULL, AZ_LOCAL);
955 amap_->orderingUpdate.resize(N_update_);
956 for(
int ii=0; ii<N_update_; ii++) {
957 amap_->orderingUpdate[amap_->update_index[ii]] = ii;
960 amap_->az_transformed =
true;
961 azTransformed_ =
true;
968 void AztecDMSR_Matrix::copyStructure(AztecDMSR_Matrix& source)
975 nnzeros_ = source.nnzeros_;
977 if (arraysAllocated_) {
980 arraysAllocated_ =
false;
983 val =
new double[nnzeros_+1];
984 bindx =
new int[nnzeros_+1];
987 for(i=0; i<nnzeros_+1; i++) {
989 bindx[i] = source.bindx[i];
992 for(i=0; i<N_update_; ++i) rowLengths_[i] = source.rowLengths_[i];
994 amap_ = source.amap_;
996 AZ_set_MSR(Amat_, bindx, val, amap_->data_org, 0, NULL, AZ_LOCAL);
998 isFilled_ = source.isFilled_;
999 azTransformed_ = source.azTransformed_;
1001 arraysAllocated_ =
true;
1006 bool AztecDMSR_Matrix::readFromFile(
const char *filename)
1024 FILE *mfp = fopen(filename,
"r");
1027 fei::console_out() <<
"AztecDMSR_Matrix::readFromFile - couldn't open matrix file."
1032 if (strstr(filename,
".mtx") == NULL) {
1033 fei::console_out() <<
"AztecDMSR_Matrix::readFromFile: filename doesn't contain "
1034 <<
"'.mtx'. File should be a MatrixMarket file." <<
FEI_ENDL;
1039 fgets(line,128,mfp);
1040 }
while(strchr(line,
'%'));
1044 fgets(line,128,mfp);
1045 }
while(strchr(line,
'%'));
1050 sscanf(line,
"%d %d %le",&i,&j,&value);
1052 if(amap_->inUpdate(i, dummy)) {
1053 if (putRow(i, 1, &value, &j) != 0)
return(
false);
1062 bool AztecDMSR_Matrix::writeToFile(
const char *fileName)
const
1071 int numProcs = amap_->getProcConfig()[AZ_N_procs];
1072 int thisProc = amap_->getProcConfig()[AZ_node];
1076 int localNNZ = nnzeros_;
1077 int globalNNZ = localNNZ;
1079 MPI_Comm thisComm = amap_->getCommunicator();
1080 MPI_Allreduce(&localNNZ, &globalNNZ, 1, MPI_INT, MPI_SUM, thisComm);
1090 if (p == thisProc) {
1093 if (masterRank == thisProc) {
1095 file = fopen(fileName,
"w");
1100 int n = amap_->globalSize();
1101 fprintf(file,
"%d %d %d\n",n, n, globalNNZ);
1105 file = fopen(fileName,
"a");
1109 for(
int i=0; i<N_update_; i++){
1110 int row = localOffset_+i;
1113 if (!amap_->inUpdate(row, localRow))
return(
false);
1115 int offDiagRowLen = ADMSR_LOCAL_ROW_LEN(localRow) - 1;
1116 if (isFilled_) offDiagRowLen = ADMSR_LOCAL_ROW_ALLOC_LEN(localRow) - 1;
1117 int* colInds = &(bindx[bindx[localRow]]);
1118 double* coefs = &(val[bindx[localRow]]);
1120 bool wroteDiagonal =
false;
1121 for(
int j=0; j<offDiagRowLen; j++) {
1122 int col = colInds[j];
1123 int globalCol = col;
1125 globalCol = amap_->getTransformedEqn(col);
1128 if (globalCol >= row && !wroteDiagonal) {
1129 fprintf(file,
"%d %d %20.13e\n", row, row,
1131 wroteDiagonal =
true;
1134 fprintf(file,
"%d %d %20.13e\n", row, globalCol, coefs[j]);
1136 if (!wroteDiagonal) {
1137 fprintf(file,
"%d %d %20.13e\n", row, row,
1139 wroteDiagonal =
true;
1150 void AztecDMSR_Matrix::messageAbort(
const char* mesg) {
std::ostream & console_out()
int numProcs(MPI_Comm comm)