00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <EpetraExt_BTF_LinearProblem.h>
00030
00031 #include <Epetra_CrsMatrix.h>
00032 #include <Epetra_VbrMatrix.h>
00033 #include <Epetra_CrsGraph.h>
00034 #include <Epetra_Map.h>
00035 #include <Epetra_BlockMap.h>
00036 #include <Epetra_MultiVector.h>
00037 #include <Epetra_LinearProblem.h>
00038
00039 #include <set>
00040
00041 using std::vector;
00042 using std::map;
00043 using std::set;
00044
00045 #define MATTRANS_F77 F77_FUNC(mattrans,MATTRANS)
00046 #define GENBTF_F77 F77_FUNC(genbtf,GENBTF)
00047
00048 extern "C" {
00049 extern void MATTRANS_F77( int*, int*, int*, int*, int*, int* );
00050 extern void GENBTF_F77( int*, int*, int*, int*, int*, int*, int*, int*, int*,
00051 int*, int*, int*, int*, int*, int*, int*, int*, int*,
00052 int*, int*, int* );
00053 }
00054
00055 namespace EpetraExt {
00056
00057 LinearProblem_BTF::
00058 ~LinearProblem_BTF()
00059 {
00060 deleteNewObjs_();
00061 }
00062
00063 void
00064 LinearProblem_BTF::
00065 deleteNewObjs_()
00066 {
00067 if( NewProblem_ ) delete NewProblem_;
00068
00069 if( NewMatrix_ ) delete NewMatrix_;
00070
00071 if( NewLHS_ ) delete NewLHS_;
00072 if( NewRHS_ ) delete NewRHS_;
00073
00074 if( NewMap_ ) delete NewMap_;
00075
00076 for( int i = 0; i < Blocks_.size(); ++i )
00077 for( int j = 0; j < Blocks_[i].size(); ++j )
00078 delete Blocks_[i][j];
00079 }
00080
00081 LinearProblem_BTF::NewTypeRef
00082 LinearProblem_BTF::
00083 operator()( OriginalTypeRef orig )
00084 {
00085 changedLP_ = false;
00086
00087
00088 if( &orig == origObj_ && NewProblem_ )
00089 {
00090 int * indices;
00091 double * values;
00092 int currCnt;
00093 int numRows = OrigMatrix_->NumMyRows();
00094
00095 for( int i = 0; i < numRows; ++i )
00096 if( ZeroElements_[i].size() )
00097 {
00098 int loc = 0;
00099 OrigMatrix_->ExtractMyRowView( i, currCnt, values, indices );
00100 for( int j = 0; j < currCnt; ++j )
00101 if( ZeroElements_[i].count( indices[j] ) )
00102 {
00103 if( values[j] > threshold_ ) changedLP_ = true;
00104 ++loc;
00105 }
00106 }
00107
00108
00109
00110
00111 if( changedLP_ )
00112 deleteNewObjs_();
00113 else
00114 return *newObj_;
00115 }
00116
00117 origObj_ = &orig;
00118
00119 OrigMatrix_ = dynamic_cast<Epetra_CrsMatrix*>(orig.GetMatrix());
00120 OrigLHS_ = orig.GetLHS();
00121 OrigRHS_ = orig.GetRHS();
00122
00123 if( OrigMatrix_->RowMap().DistributedGlobal() )
00124 { cout << "FAIL for Global!\n"; abort(); }
00125 if( OrigMatrix_->IndicesAreGlobal() )
00126 { cout << "FAIL for Global Indices!\n"; abort(); }
00127
00128 int n = OrigMatrix_->NumMyRows();
00129 int nnz = OrigMatrix_->NumMyNonzeros();
00130
00131
00132
00133
00134
00135
00136 vector<int> ia(n+1,0);
00137 int maxEntries = OrigMatrix_->MaxNumEntries();
00138 vector<int> ja_tmp(maxEntries);
00139 vector<double> jva_tmp(maxEntries);
00140 vector<int> ja(nnz);
00141 int cnt;
00142
00143 const Epetra_BlockMap & OldRowMap = OrigMatrix_->RowMap();
00144 const Epetra_BlockMap & OldColMap = OrigMatrix_->ColMap();
00145 Epetra_CrsGraph strippedGraph( Copy, OldRowMap, OldColMap, 0 );
00146 ZeroElements_.resize(n);
00147
00148 for( int i = 0; i < n; ++i )
00149 {
00150 ZeroElements_[i].clear();
00151 OrigMatrix_->ExtractMyRowCopy( i, maxEntries, cnt, &jva_tmp[0], &ja_tmp[0] );
00152 ia[i+1] = ia[i];
00153 for( int j = 0; j < cnt; ++j )
00154 {
00155 if( fabs(jva_tmp[j]) > threshold_ )
00156 ja[ ia[i+1]++ ] = ja_tmp[j];
00157 else
00158 ZeroElements_[i].insert( ja_tmp[j] );
00159 }
00160
00161 int new_cnt = ia[i+1] - ia[i];
00162 strippedGraph.InsertMyIndices( i, new_cnt, &ja[ ia[i] ] );
00163 }
00164 nnz = ia[n];
00165 strippedGraph.FillComplete();
00166
00167 if( verbose_ > 2 )
00168 {
00169 cout << "Stripped Graph\n";
00170 cout << strippedGraph;
00171 }
00172
00173 vector<int> iat(n+1,0);
00174 vector<int> jat(nnz);
00175 for( int i = 0; i < n; ++i )
00176 for( int j = ia[i]; j < ia[i+1]; ++j )
00177 ++iat[ ja[j]+1 ];
00178 for( int i = 0; i < n; ++i )
00179 iat[i+1] += iat[i];
00180 for( int i = 0; i < n; ++i )
00181 for( int j = ia[i]; j < ia[i+1]; ++j )
00182 jat[ iat[ ja[j] ]++ ] = i;
00183 for( int i = 0; i < n; ++i )
00184 iat[n-i] = iat[n-i-1];
00185 iat[0] = 0;
00186
00187
00188 for( int i = 0; i < n+1; ++i ) ++ia[i];
00189 for( int i = 0; i < nnz; ++i ) ++ja[i];
00190 for( int i = 0; i < n+1; ++i ) ++iat[i];
00191 for( int i = 0; i < nnz; ++i ) ++jat[i];
00192
00193 if( verbose_ > 2 )
00194 {
00195 cout << "-----------------------------------------\n";
00196 cout << "CRS Format Graph\n";
00197 cout << "-----------------------------------------\n";
00198 for( int i = 0; i < n; ++i )
00199 {
00200 cout << i+1 << ": " << ia[i+1] << ": ";
00201 for( int j = ia[i]-1; j<ia[i+1]-1; ++j )
00202 cout << " " << ja[j];
00203 cout << endl;
00204 }
00205 cout << "-----------------------------------------\n";
00206 }
00207
00208 if( verbose_ > 2 )
00209 {
00210 cout << "-----------------------------------------\n";
00211 cout << "CCS Format Graph\n";
00212 cout << "-----------------------------------------\n";
00213 for( int i = 0; i < n; ++i )
00214 {
00215 cout << i+1 << ": " << iat[i+1] << ": ";
00216 for( int j = iat[i]-1; j<iat[i+1]-1; ++j )
00217 cout << " " << jat[j];
00218 cout << endl;
00219 }
00220 cout << "-----------------------------------------\n";
00221 }
00222
00223 vector<int> w(10*n);
00224
00225 vector<int> rowperm(n);
00226 vector<int> colperm(n);
00227
00228
00229 int nhrows, nhcols, hrzcmp;
00230
00231 int nsrows, sqcmpn;
00232
00233 int nvrows, nvcols, vrtcmp;
00234
00235 vector<int> rcmstr(n+1);
00236 vector<int> ccmstr(n+1);
00237
00238 int msglvl = 0;
00239 int output = 6;
00240
00241 GENBTF_F77( &n, &n, &iat[0], &jat[0], &ia[0], &ja[0], &w[0],
00242 &rowperm[0], &colperm[0], &nhrows, &nhcols,
00243 &hrzcmp, &nsrows, &sqcmpn, &nvrows, &nvcols, &vrtcmp,
00244 &rcmstr[0], &ccmstr[0], &msglvl, &output );
00245
00246
00247 for( int i = 0; i < n; ++i )
00248 {
00249 --rowperm[i];
00250 --colperm[i];
00251 }
00252 for( int i = 0; (i<n+1) && (rcmstr[i]!=n+1); ++i )
00253 {
00254 --rcmstr[i];
00255 --ccmstr[i];
00256 }
00257
00258 if( verbose_ > 0 )
00259 {
00260 cout << "-----------------------------------------\n";
00261 cout << "BTF Output\n";
00262 cout << "-----------------------------------------\n";
00263
00264
00265
00266 if( hrzcmp )
00267 {
00268 cout << "Num Horizontal: Rows, Cols, Comps\n";
00269 cout << nhrows << "\t" << nhcols << "\t" << hrzcmp << endl;
00270 }
00271 cout << "Num Square: Rows, Comps\n";
00272 cout << nsrows << "\t" << sqcmpn << endl;
00273 if( vrtcmp )
00274 {
00275 cout << "Num Vertical: Rows, Cols, Comps\n";
00276 cout << nvrows << "\t" << nvcols << "\t" << vrtcmp << endl;
00277 }
00278
00279
00280
00281
00282 }
00283
00284 if( hrzcmp || vrtcmp )
00285 {
00286 cout << "FAILED! hrz cmp's:" << hrzcmp << " vrtcmp: " << vrtcmp << endl;
00287 exit(0);
00288 }
00289
00290 rcmstr[sqcmpn] = n;
00291
00292
00293
00294 vector<int> rowperm_t( n );
00295 vector<int> colperm_t( n );
00296 for( int i = 0; i < n; ++i )
00297 {
00298 rowperm_t[i] = rowperm[i];
00299 colperm_t[i] = colperm[i];
00300 }
00301
00302
00303
00304 OldGlobalElements_.resize(n);
00305 OldRowMap.MyGlobalElements( &OldGlobalElements_[0] );
00306
00307 vector<int> newDomainElements( n );
00308 vector<int> newRangeElements( n );
00309 for( int i = 0; i < n; ++i )
00310 {
00311 newDomainElements[ i ] = OldGlobalElements_[ rowperm_t[i] ];
00312 newRangeElements[ i ] = OldGlobalElements_[ colperm_t[i] ];
00313 }
00314
00315
00316 Blocks_.resize( sqcmpn );
00317 BlockDim_.resize( sqcmpn );
00318 for( int i = 0; i < sqcmpn; ++i )
00319 {
00320 BlockDim_[i] = rcmstr[i+1]-rcmstr[i];
00321 for( int j = rcmstr[i]; j < rcmstr[i+1]; ++j )
00322 {
00323 BlockRowMap_[ newDomainElements[j] ] = i;
00324 SubBlockRowMap_[ newDomainElements[j] ] = j-rcmstr[i];
00325 BlockColMap_[ newRangeElements[j] ] = i;
00326 SubBlockColMap_[ newRangeElements[j] ] = j-rcmstr[i];
00327 }
00328 }
00329
00330 if( verbose_ > 2 )
00331 {
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 int MinSize = 1000000000;
00346 int MaxSize = 0;
00347 for( int i = 0; i < sqcmpn; ++i )
00348 {
00349 if( MinSize > BlockDim_[i] ) MinSize = BlockDim_[i];
00350 if( MaxSize < BlockDim_[i] ) MaxSize = BlockDim_[i];
00351 }
00352 cout << "Min Block Size: " << MinSize << " " << "Max Block Size: " << MaxSize << endl;
00353 }
00354
00355 vector<int> myBlockElements( sqcmpn );
00356 for( int i = 0; i < sqcmpn; ++i ) myBlockElements[i] = i;
00357 NewMap_ = new Epetra_BlockMap( sqcmpn, sqcmpn, &myBlockElements[0], &BlockDim_[0], 0, OldRowMap.Comm() );
00358
00359 if( verbose_ > 2 )
00360 {
00361 cout << "New Block Map!\n";
00362 cout << *NewMap_;
00363 }
00364
00365
00366 vector< set<int> > crsBlocks( sqcmpn );
00367 BlockCnt_.resize( sqcmpn );
00368 int maxLength = strippedGraph.MaxNumIndices();
00369 vector<int> sIndices( maxLength );
00370 int currLength;
00371 for( int i = 0; i < n; ++i )
00372 {
00373 strippedGraph.ExtractGlobalRowCopy( OldGlobalElements_[i], maxLength, currLength, &sIndices[0] );
00374 for( int j = 0; j < currLength; ++j )
00375 crsBlocks[ BlockRowMap_[ OldGlobalElements_[i] ] ].insert( BlockColMap_[ sIndices[j] ] );
00376 }
00377
00378 for( int i = 0; i < sqcmpn; ++i )
00379 {
00380 BlockCnt_[i] = crsBlocks[i].size();
00381 Blocks_[i].resize( BlockCnt_[i] );
00382 }
00383
00384 NewBlockRows_.resize( sqcmpn );
00385 for( int i = 0; i < sqcmpn; ++i )
00386 {
00387 NewBlockRows_[i] = vector<int>( crsBlocks[i].begin(), crsBlocks[i].end() );
00388 for( int j = 0; j < BlockCnt_[i]; ++j )
00389 {
00390 Blocks_[i][j] = new Epetra_SerialDenseMatrix();
00391 Blocks_[i][j]->Shape( BlockDim_[i], BlockDim_[ NewBlockRows_[i][j] ] );
00392 }
00393 }
00394
00395
00396 NewLHS_ = new Epetra_MultiVector( *NewMap_, 1 );
00397 NewRHS_ = new Epetra_MultiVector( *NewMap_, 1 );
00398
00399 maxLength = OrigMatrix_->MaxNumEntries();
00400 vector<int> indices( maxLength );
00401 vector<double> values( maxLength );
00402 for( int i = 0; i < n; ++i )
00403 {
00404 int BlockRow = BlockRowMap_[ OldGlobalElements_[i] ];
00405 int SubBlockRow = SubBlockRowMap_[ OldGlobalElements_[i] ];
00406 OrigMatrix_->ExtractGlobalRowCopy( OldGlobalElements_[i], maxLength, currLength, &values[0], &indices[0] );
00407 for( int j = 0; j < currLength; ++j )
00408 {
00409 int BlockCol = BlockColMap_[ indices[j] ];
00410 int SubBlockCol = SubBlockColMap_[ indices[j] ];
00411 for( int k = 0; k < BlockCnt_[BlockRow]; ++k )
00412 if( BlockCol == NewBlockRows_[BlockRow][k] )
00413 {
00414 if( values[j] > threshold_ )
00415 {
00416
00417
00418 (*(Blocks_[BlockRow][k]))(SubBlockRow,SubBlockCol) = values[j];
00419 break;
00420 }
00421 else
00422 ZeroElements_[i].erase( OrigMatrix_->RowMap().LID( indices[j] ) );
00423 }
00424 }
00425
00426
00427 NewRHS_->ReplaceGlobalValue( BlockRow, SubBlockRow, 0, (*OrigRHS_)[0][i] );
00428 }
00429
00430 if( verbose_ > 2 )
00431 {
00432 cout << "Zero Elements: \n";
00433 cout << "--------------\n";
00434 int cnt = 0;
00435 for( int i = 0; i < n; ++i )
00436 {
00437 set<int>::iterator iterSI = ZeroElements_[i].begin();
00438 set<int>::iterator endSI = ZeroElements_[i].end();
00439 for( ; iterSI != endSI; ++iterSI )
00440 {
00441 cout << " " << *iterSI;
00442 ++cnt;
00443 }
00444 cout << endl;
00445 }
00446 cout << "ZE Cnt: " << cnt << endl;
00447 cout << "--------------\n";
00448 }
00449
00450
00451 NewMatrix_ = new Epetra_VbrMatrix( View, *NewMap_, &BlockCnt_[0] );
00452 for( int i = 0; i < sqcmpn; ++i )
00453 {
00454 NewMatrix_->BeginInsertGlobalValues( i, BlockCnt_[i], &(NewBlockRows_[i])[0] );
00455 for( int j = 0; j < BlockCnt_[i]; ++j )
00456 NewMatrix_->SubmitBlockEntry( *(Blocks_[i][j]) );
00457 NewMatrix_->EndSubmitEntries();
00458 }
00459 NewMatrix_->FillComplete();
00460
00461 if( verbose_ > 2 )
00462 {
00463 cout << "New Block Matrix!\n";
00464 cout << *NewMatrix_;
00465 cout << "New Block LHS!\n";
00466 cout << *NewLHS_;
00467 cout << "New Block RHS!\n";
00468 cout << *NewRHS_;
00469 }
00470
00471
00472 NewProblem_ = new Epetra_LinearProblem( NewMatrix_, NewLHS_, NewRHS_ );
00473 newObj_ = NewProblem_;
00474
00475 if( verbose_ ) cout << "-----------------------------------------\n";
00476
00477 return *newObj_;
00478 }
00479
00480 bool
00481 LinearProblem_BTF::
00482 fwd()
00483 {
00484
00485 int NumBlockRows = BlockDim_.size();
00486 for( int i = 0; i < NumBlockRows; ++i )
00487 {
00488 int NumBlocks = BlockCnt_[i];
00489 for( int j = 0; j < NumBlocks; ++j )
00490 {
00491 int Size = BlockDim_[i] * BlockDim_[ NewBlockRows_[i][j] ];
00492 double * p = Blocks_[i][j]->A();
00493 for( int k = 0; k < Size; ++k ) *p++ = 0.0;
00494 }
00495 }
00496
00497 int maxLength = OrigMatrix_->MaxNumEntries();
00498 int n = OldGlobalElements_.size();
00499 int currLength;
00500 vector<int> indices( maxLength );
00501 vector<double> values( maxLength );
00502 for( int i = 0; i < n; ++i )
00503 {
00504 int BlockRow = BlockRowMap_[ OldGlobalElements_[i] ];
00505 int SubBlockRow = SubBlockRowMap_[ OldGlobalElements_[i] ];
00506 OrigMatrix_->ExtractGlobalRowCopy( OldGlobalElements_[i], maxLength, currLength, &values[0], &indices[0] );
00507 for( int j = 0; j < currLength; ++j )
00508 {
00509 if( fabs(values[j]) > threshold_ )
00510 {
00511 int BlockCol = BlockColMap_[ indices[j] ];
00512 int SubBlockCol = SubBlockColMap_[ indices[j] ];
00513 for( int k = 0; k < BlockCnt_[BlockRow]; ++k )
00514 if( BlockCol == NewBlockRows_[BlockRow][k] )
00515 {
00516 (*(Blocks_[BlockRow][k]))(SubBlockRow,SubBlockCol) = values[j];
00517 break;
00518 }
00519 }
00520 }
00521
00522 NewRHS_->ReplaceGlobalValue( BlockRow, SubBlockRow, 0, (*OrigRHS_)[0][i] );
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 return true;
00538 }
00539
00540 bool
00541 LinearProblem_BTF::
00542 rvs()
00543 {
00544
00545 int rowCnt = OrigLHS_->MyLength();
00546 for( int i = 0; i < rowCnt; ++i )
00547 {
00548 int BlockCol = BlockColMap_[ OldGlobalElements_[i] ];
00549 int SubBlockCol = SubBlockColMap_[ OldGlobalElements_[i] ];
00550 (*OrigLHS_)[0][i] = (*NewLHS_)[0][ NewMap_->FirstPointInElement(BlockCol) + SubBlockCol ];
00551 }
00552
00553 return true;
00554 }
00555
00556 }