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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "Ifpack_ConfigDefs.h"
00044 #include "Ifpack_SILU.h"
00045 #ifdef HAVE_IFPACK_SUPERLU
00046
00047 #include "Ifpack_CondestType.h"
00048 #include "Epetra_ConfigDefs.h"
00049 #include "Epetra_Comm.h"
00050 #include "Epetra_Map.h"
00051 #include "Epetra_RowMatrix.h"
00052 #include "Epetra_Vector.h"
00053 #include "Epetra_MultiVector.h"
00054 #include "Epetra_CrsGraph.h"
00055 #include "Epetra_CrsMatrix.h"
00056 #include "Teuchos_ParameterList.hpp"
00057 #include "Teuchos_RefCountPtr.hpp"
00058
00059
00060 extern "C" {int dfill_diag(int n, NCformat *Astore);}
00061
00062 using Teuchos::RefCountPtr;
00063 using Teuchos::rcp;
00064
00065 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00066 # include "Teuchos_TimeMonitor.hpp"
00067 #endif
00068
00069
00070 Ifpack_SILU::Ifpack_SILU(Epetra_RowMatrix* Matrix_in) :
00071 A_(rcp(Matrix_in,false)),
00072 Comm_(Matrix_in->Comm()),
00073 UseTranspose_(false),
00074 NumMyDiagonals_(0),
00075 DropTol_(1e-4),
00076 FillTol_(1e-2),
00077 FillFactor_(10.0),
00078 DropRule_(9),
00079 Condest_(-1.0),
00080 IsInitialized_(false),
00081 IsComputed_(false),
00082 NumInitialize_(0),
00083 NumCompute_(0),
00084 NumApplyInverse_(0),
00085 InitializeTime_(0.0),
00086 ComputeTime_(0.0),
00087 ApplyInverseTime_(0.0),
00088 Time_(Comm()),
00089 etree_(0),
00090 perm_r_(0),
00091 perm_c_(0)
00092 {
00093 Teuchos::ParameterList List;
00094 SetParameters(List);
00095 SY_.Store=0;
00096 }
00097
00098
00099
00100
00101 void Ifpack_SILU::Destroy()
00102 {
00103 if(IsInitialized_){
00104
00105 StatFree(&stat_);
00106
00107 Destroy_CompCol_Permuted(&SAc_);
00108 Destroy_SuperNode_Matrix(&SL_);
00109 Destroy_CompCol_Matrix(&SU_);
00110
00111
00112 Destroy_SuperMatrix_Store(&SA_);
00113 if(SY_.Store) Destroy_SuperMatrix_Store(&SY_);
00114 SY_.Store=0;
00115
00116
00117 delete [] etree_;etree_=0;
00118 delete [] perm_r_;perm_r_=0;
00119 delete [] perm_c_;perm_c_=0;
00120 }
00121 }
00122
00123
00124 int Ifpack_SILU::SetParameters(Teuchos::ParameterList& List)
00125 {
00126 DropTol_=List.get("fact: drop tolerance",DropTol_);
00127 FillTol_=List.get("fact: zero pivot threshold",FillTol_);
00128 FillFactor_=List.get("fact: maximum fill factor",FillFactor_);
00129 DropRule_=List.get("fact: silu drop rule",DropRule_);
00130
00131
00132 sprintf(Label_, "IFPACK SILU (drop=%d, zpv=%f, ffact=%f, rthr=%f)",
00133 DropRule(),FillTol(),FillFactor(),DropTol());
00134 return(0);
00135 }
00136
00137
00138 template<typename int_type>
00139 int Ifpack_SILU::TInitialize()
00140 {
00141
00142 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00143 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_SILU::Initialize");
00144 #endif
00145
00146 Time_.ResetStartTime();
00147
00148
00149 Destroy();
00150
00151 IsInitialized_ = false;
00152
00153 Epetra_CrsMatrix* CrsMatrix;
00154 CrsMatrix = dynamic_cast<Epetra_CrsMatrix*>(&*A_);
00155
00156 if(CrsMatrix && CrsMatrix->RowMap().SameAs(CrsMatrix->ColMap()) && CrsMatrix->IndicesAreContiguous()){
00157
00158 Aover_=rcp(CrsMatrix,false);
00159 }
00160 else if(CrsMatrix && CrsMatrix->IndicesAreContiguous()){
00161
00162 int size = A_->MaxNumEntries();
00163 int N=A_->NumMyRows();
00164 Aover_ = rcp(new Epetra_CrsMatrix(Copy,A_->RowMatrixRowMap(), size));
00165 std::vector<int_type> Indices(size);
00166 std::vector<double> Values(size);
00167
00168 int i,j,ct,*rowptr,*colind;
00169 double *values;
00170 IFPACK_CHK_ERR(CrsMatrix->ExtractCrsDataPointers(rowptr,colind,values));
00171
00172
00173 for(i=0;i<N;i++){
00174 for(j=rowptr[i],ct=0;j<rowptr[i+1];j++){
00175 if(colind[j]<N){
00176 Indices[ct]= (int_type) CrsMatrix->GCID64(colind[j]);
00177 Values[ct]=values[j];
00178 ct++;
00179 }
00180 }
00181 Aover_->InsertGlobalValues((int_type) CrsMatrix->GRID64(i),ct,&Values[0],&Indices[0]);
00182 }
00183 IFPACK_CHK_ERR(Aover_->FillComplete(CrsMatrix->RowMap(),CrsMatrix->RowMap()));
00184 }
00185 else{
00186
00187 int size = A_->MaxNumEntries();
00188 Aover_ = rcp(new Epetra_CrsMatrix(Copy,A_->RowMatrixRowMap(), size));
00189 if (Aover_.get() == 0) IFPACK_CHK_ERR(-5);
00190
00191 std::vector<int> Indices1(size);
00192 std::vector<int_type> Indices2(size);
00193 std::vector<double> Values1(size),Values2(size);
00194
00195
00196
00197 int N=A_->NumMyRows();
00198 for (int i = 0 ; i < N ; ++i) {
00199 int NumEntries;
00200 int_type GlobalRow = (int_type) A_->RowMatrixRowMap().GID64(i);
00201 IFPACK_CHK_ERR(A_->ExtractMyRowCopy(i, size, NumEntries,
00202 &Values1[0], &Indices1[0]));
00203
00204
00205 int ct=0;
00206 for (int j=0; j < NumEntries ; ++j) {
00207 if(Indices1[j] < N){
00208 Indices2[ct] = (int_type) A_->RowMatrixColMap().GID64(Indices1[j]);
00209 Values2[ct]=Values1[j];
00210 ct++;
00211 }
00212 }
00213 IFPACK_CHK_ERR(Aover_->InsertGlobalValues(GlobalRow,ct,
00214 &Values2[0],&Indices2[0]));
00215 }
00216 IFPACK_CHK_ERR(Aover_->FillComplete(A_->RowMatrixRowMap(),A_->RowMatrixRowMap()));
00217 }
00218
00219
00220 Aover_->OptimizeStorage();
00221 Graph_=rcp(const_cast<Epetra_CrsGraph*>(&Aover_->Graph()),false);
00222
00223 IsInitialized_ = true;
00224 NumInitialize_++;
00225 InitializeTime_ += Time_.ElapsedTime();
00226
00227 return(0);
00228 }
00229
00230 int Ifpack_SILU::Initialize() {
00231 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00232 if(A_->RowMatrixRowMap().GlobalIndicesInt()) {
00233 return TInitialize<int>();
00234 }
00235 else
00236 #endif
00237 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00238 if(A_->RowMatrixRowMap().GlobalIndicesLongLong()) {
00239 return TInitialize<long long>();
00240 }
00241 else
00242 #endif
00243 throw "Ifpack_SILU::Initialize: GlobalIndices type unknown for A_";
00244 }
00245
00246
00247
00248 int Ifpack_SILU::Compute()
00249 {
00250
00251 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00252 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_SILU::Compute");
00253 #endif
00254
00255 if (!IsInitialized())
00256 IFPACK_CHK_ERR(Initialize());
00257
00258 Time_.ResetStartTime();
00259 IsComputed_ = false;
00260
00261
00262 StatInit(&stat_);
00263 ilu_set_default_options(&options_);
00264 options_.ILU_DropTol=DropTol_;
00265 options_.ILU_FillTol=FillTol_;
00266 options_.ILU_DropRule=DropRule_;
00267 options_.ILU_FillFactor=FillFactor_;
00268
00269
00270 int *rowptr,*colind;
00271 double *values;
00272 IFPACK_CHK_ERR(Aover_->ExtractCrsDataPointers(rowptr,colind,values));
00273 int N=Aover_->NumMyRows();
00274
00275
00276 dCreate_CompCol_Matrix(&SA_,N,N,Aover_->NumMyNonzeros(),
00277 values,colind,rowptr,SLU_NC,SLU_D,SLU_GE);
00278
00279
00280
00281 dfill_diag(N, (NCformat*)SA_.Store);
00282
00283
00284 etree_=new int [N];
00285 perm_r_=new int[N];
00286 perm_c_=new int[N];
00287
00288
00289 int permc_spec=options_.ColPerm;
00290 if ( permc_spec != MY_PERMC && options_.Fact == DOFACT )
00291 get_perm_c(permc_spec,&SA_,perm_c_);
00292
00293
00294 sp_preorder(&options_, &SA_, perm_c_, etree_, &SAc_);
00295
00296
00297 int panel_size = sp_ienv(1);
00298 int relax = sp_ienv(2);
00299 int info=0;
00300 dgsitrf(&options_,&SAc_,relax,panel_size,etree_,NULL,0,perm_c_,perm_r_,&SL_,&SU_,&stat_,&info);
00301 if(info<0) IFPACK_CHK_ERR(info);
00302
00303 IsComputed_ = true;
00304 NumCompute_++;
00305 ComputeTime_ += Time_.ElapsedTime();
00306 return 0;
00307 }
00308
00309
00310
00311 int Ifpack_SILU::Solve(bool Trans, const Epetra_MultiVector& X,
00312 Epetra_MultiVector& Y) const
00313 {
00314
00315 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00316 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_SILU::ApplyInverse - Solve");
00317 #endif
00318
00319 if (!IsComputed())
00320 IFPACK_CHK_ERR(-3);
00321 int nrhs=X.NumVectors();
00322 int N=A_->NumMyRows();
00323
00324
00325 Y=X;
00326
00327
00328
00329 if(SY_.Store) Destroy_SuperMatrix_Store(&SY_);
00330 SY_.Store=0;
00331 dCreate_Dense_Matrix(&SY_,N,nrhs,Y[0],N,SLU_DN,SLU_D,SLU_GE);
00332
00333 int info;
00334 dgstrs(TRANS,&SL_,&SU_,perm_c_,perm_r_,&SY_,&stat_,&info);
00335 if(!info) IFPACK_CHK_ERR(info);
00336
00337 return(info);
00338 }
00339
00340
00341
00342 int Ifpack_SILU::Multiply(bool Trans, const Epetra_MultiVector& X,
00343 Epetra_MultiVector& Y) const
00344 {
00345
00346 if (!IsComputed())
00347 IFPACK_CHK_ERR(-1);
00348
00349 return(0);
00350 }
00351
00352
00353
00354 int Ifpack_SILU::ApplyInverse(const Epetra_MultiVector& X,
00355 Epetra_MultiVector& Y) const
00356 {
00357
00358 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00359 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_SILU::ApplyInverse");
00360 #endif
00361
00362 if (!IsComputed())
00363 IFPACK_CHK_ERR(-3);
00364
00365 if (X.NumVectors() != Y.NumVectors())
00366 IFPACK_CHK_ERR(-2);
00367
00368 Time_.ResetStartTime();
00369
00370
00371
00372 Teuchos::RefCountPtr< const Epetra_MultiVector > Xcopy;
00373 if (X.Pointers()[0] == Y.Pointers()[0])
00374 Xcopy = Teuchos::rcp( new Epetra_MultiVector(X) );
00375 else
00376 Xcopy = Teuchos::rcp( &X, false );
00377
00378 IFPACK_CHK_ERR(Solve(Ifpack_SILU::UseTranspose(), *Xcopy, Y));
00379
00380 ++NumApplyInverse_;
00381 ApplyInverseTime_ += Time_.ElapsedTime();
00382
00383 return(0);
00384
00385 }
00386
00387
00388 double Ifpack_SILU::Condest(const Ifpack_CondestType CT,
00389 const int MaxIters, const double Tol,
00390 Epetra_RowMatrix* Matrix_in)
00391 {
00392
00393 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00394 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_SILU::Condest");
00395 #endif
00396
00397 if (!IsComputed())
00398 return(-1.0);
00399
00400 Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
00401
00402 return(Condest_);
00403 }
00404
00405
00406 std::ostream&
00407 Ifpack_SILU::Print(std::ostream& os) const
00408 {
00409 if (!Comm().MyPID()) {
00410 os << endl;
00411 os << "================================================================================" << endl;
00412 os << "Ifpack_SILU: " << Label() << endl << endl;
00413 os << "Dropping rule = "<< DropRule() << endl;
00414 os << "Zero pivot thresh = "<< FillTol() << endl;
00415 os << "Max fill factor = "<< FillFactor() << endl;
00416 os << "Drop tolerance = "<< DropTol() << endl;
00417 os << "Condition number estimate = " << Condest() << endl;
00418 os << "Global number of rows = " << A_->NumGlobalRows64() << endl;
00419 if (IsComputed_) {
00420
00421 int fnnz=0;
00422 if(SL_.Store) fnnz+=((SCformat*)SL_.Store)->nnz;
00423 if(SU_.Store) fnnz+=((NCformat*)SU_.Store)->nnz;
00424 int lufill=fnnz - A_->NumMyRows();
00425 os << "No. of nonzeros in L+U = "<< lufill<<endl;
00426 os << "Fill ratio: nnz(F)/nnz(A) = "<<(double)lufill / (double)A_->NumMyNonzeros()<<endl;
00427 }
00428 os << endl;
00429 os << "Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
00430 os << "----- ------- -------------- ------------ --------" << endl;
00431 os << "Initialize() " << std::setw(5) << NumInitialize()
00432 << " " << std::setw(15) << InitializeTime()
00433 << " 0.0 0.0" << endl;
00434 os << "Compute() " << std::setw(5) << NumCompute()
00435 << " " << std::setw(15) << ComputeTime()
00436 << " " << std::setw(15) << 1.0e-6 * ComputeFlops();
00437 if (ComputeTime() != 0.0)
00438 os << " " << std::setw(15) << 1.0e-6 * ComputeFlops() / ComputeTime() << endl;
00439 else
00440 os << " " << std::setw(15) << 0.0 << endl;
00441 os << "ApplyInverse() " << std::setw(5) << NumApplyInverse()
00442 << " " << std::setw(15) << ApplyInverseTime()
00443 << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops();
00444 if (ApplyInverseTime() != 0.0)
00445 os << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops() / ApplyInverseTime() << endl;
00446 else
00447 os << " " << std::setw(15) << 0.0 << endl;
00448 os << "================================================================================" << endl;
00449 os << endl;
00450 }
00451
00452 return(os);
00453 }
00454
00455 #endif