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 #include "Ifpack_SerialTriDiSolver.h"
00043 #include "Ifpack_SerialTriDiMatrix.h"
00044 #include "Epetra_SerialDenseVector.h"
00045 #include <iostream>
00046
00047
00048 Ifpack_SerialTriDiSolver::Ifpack_SerialTriDiSolver()
00049 : Epetra_CompObject(),
00050 Epetra_BLAS(),
00051 Transpose_(false),
00052 Factored_(false),
00053 EstimateSolutionErrors_(false),
00054 SolutionErrorsEstimated_(false),
00055 Solved_(false),
00056 Inverted_(false),
00057 ReciprocalConditionEstimated_(false),
00058 RefineSolution_(false),
00059 SolutionRefined_(false),
00060 TRANS_('N'),
00061 N_(0),
00062 NRHS_(0),
00063 LDA_(0),
00064 LDAF_(0),
00065 LDB_(0),
00066 LDX_(0),
00067 INFO_(0),
00068 LWORK_(0),
00069 IPIV_(0),
00070 IWORK_(0),
00071 ANORM_(0.0),
00072 RCOND_(0.0),
00073 ROWCND_(0.0),
00074 COLCND_(0.0),
00075 AMAX_(0.0),
00076 Matrix_(0),
00077 LHS_(0),
00078 RHS_(0),
00079 Factor_(0),
00080 A_(0),
00081 FERR_(0),
00082 BERR_(0),
00083 AF_(0),
00084 WORK_(0),
00085 B_(0),
00086 X_(0)
00087 {
00088 InitPointers();
00089 ResetMatrix();
00090 ResetVectors();
00091 }
00092
00093 Ifpack_SerialTriDiSolver::~Ifpack_SerialTriDiSolver()
00094 {
00095 DeleteArrays();
00096 }
00097
00098 void Ifpack_SerialTriDiSolver::InitPointers()
00099 {
00100 IWORK_ = 0;
00101 FERR_ = 0;
00102 BERR_ = 0;
00103 Factor_ =0;
00104 Matrix_ =0;
00105 AF_ = 0;
00106 IPIV_ = 0;
00107 WORK_ = 0;
00108 INFO_ = 0;
00109 LWORK_ = 0;
00110 }
00111
00112 void Ifpack_SerialTriDiSolver::DeleteArrays()
00113 {
00114 if (IWORK_ != 0) {delete [] IWORK_;IWORK_ = 0;}
00115 if (FERR_ != 0) {delete [] FERR_; FERR_ = 0;}
00116 if (BERR_ != 0) {delete [] BERR_; BERR_ = 0;}
00117 if (Factor_ != Matrix_ && Factor_ != 0) {delete Factor_; Factor_ = 0;}
00118 if (Factor_ !=0) Factor_ = 0;
00119
00120 if (IPIV_ != 0) {delete [] IPIV_;IPIV_ = 0;}
00121 if (WORK_ != 0) {delete [] WORK_;WORK_ = 0;}
00122
00123 if (AF_ !=0) AF_ = 0;
00124
00125 INFO_ = 0;
00126 LWORK_ = 0;
00127 }
00128
00129 void Ifpack_SerialTriDiSolver::ResetMatrix()
00130 {
00131 DeleteArrays();
00132 ResetVectors();
00133 Matrix_ = 0;
00134 Factor_ = 0;
00135 Factored_ = false;
00136 Inverted_ = false;
00137 N_ = 0;
00138 LDA_ = 0;
00139 LDAF_ = 0;
00140 ANORM_ = -1.0;
00141 RCOND_ = -1.0;
00142 ROWCND_ = -1.0;
00143 COLCND_ = -1.0;
00144 AMAX_ = -1.0;
00145 A_ = 0;
00146
00147 }
00148
00149 int Ifpack_SerialTriDiSolver::SetMatrix(Ifpack_SerialTriDiMatrix & A_in) {
00150 ResetMatrix();
00151 Matrix_ = &A_in;
00152 Factor_ = &A_in;
00153 N_ = A_in.N();
00154 A_ = A_in.A();
00155 LDA_ = A_in.LDA();
00156 LDAF_ = LDA_;
00157 AF_ = A_in.A();
00158 return(0);
00159 }
00160
00161 void Ifpack_SerialTriDiSolver::ResetVectors()
00162 {
00163 LHS_ = 0;
00164 RHS_ = 0;
00165 B_ = 0;
00166 X_ = 0;
00167 ReciprocalConditionEstimated_ = false;
00168 SolutionRefined_ = false;
00169 Solved_ = false;
00170 SolutionErrorsEstimated_ = false;
00171 NRHS_ = 0;
00172 LDB_ = 0;
00173 LDX_ = 0;
00174 }
00175
00176 int Ifpack_SerialTriDiSolver::SetVectors(Epetra_SerialDenseMatrix & X_in, Epetra_SerialDenseMatrix & B_in)
00177 {
00178 if (B_in.N() != X_in.N()) EPETRA_CHK_ERR(-1);
00179 if (B_in.A()==0) EPETRA_CHK_ERR(-2);
00180 if (X_in.A()==0) EPETRA_CHK_ERR(-4);
00181
00182 ResetVectors();
00183 LHS_ = &X_in;
00184 RHS_ = &B_in;
00185 NRHS_ = B_in.N();
00186
00187 B_ = B_in.A();
00188 X_ = X_in.A();
00189 return(0);
00190 }
00191
00192 void Ifpack_SerialTriDiSolver::EstimateSolutionErrors(bool Flag) {
00193 EstimateSolutionErrors_ = Flag;
00194
00195 RefineSolution_ = RefineSolution_ || Flag;
00196 return;
00197 }
00198
00199 int Ifpack_SerialTriDiSolver::Factor(void) {
00200 if (Factored()) return(0);
00201 if (Inverted()) EPETRA_CHK_ERR(-100);
00202
00203 ANORM_ = Matrix_->OneNorm();
00204
00205
00206
00207
00208 Ifpack_SerialTriDiMatrix * F = Matrix_;
00209
00210 if (A_ == AF_)
00211 if (RefineSolution_ ) {
00212 Factor_ = new Ifpack_SerialTriDiMatrix(*Matrix_);
00213 F = Factor_;
00214 AF_ = Factor_->A();
00215 LDAF_ = Factor_->LDA();
00216 }
00217
00218 if (IPIV_==0) IPIV_ = new int[N_];
00219
00220 double * DL_ = F->DL();
00221 double * D_ = F->D();
00222 double * DU_ = F->DU();
00223 double * DU2_ = F->DU2();
00224
00225 lapack.GTTRF(N_, DL_, D_, DU_, DU2_, IPIV_, &INFO_);
00226
00227 Factored_ = true;
00228 double DN = N_;
00229 UpdateFlops( (N_ == 1)? 1. : 4*(DN-1) );
00230
00231 EPETRA_CHK_ERR(INFO_);
00232 return(0);
00233
00234 }
00235
00236
00237 int Ifpack_SerialTriDiSolver::Solve(void) {
00238 int ierr = 0;
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 if (B_==0) EPETRA_CHK_ERR(-3);
00250 if (X_==0) EPETRA_CHK_ERR(-4);
00251
00252 double DN = N_;
00253 double DNRHS = NRHS_;
00254 if (Inverted()) {
00255
00256 EPETRA_CHK_ERR(-101);
00257
00258 }
00259 else {
00260
00261 if (!Factored()) Factor();
00262
00263 if (B_!=X_) {
00264 *LHS_ = *RHS_;
00265 X_ = LHS_->A();
00266 }
00267
00268 Ifpack_SerialTriDiMatrix * F;
00269 if(A_ == AF_)
00270 F = Matrix_;
00271 else
00272 F = Factor_;
00273
00274 double * DL_ = F->DL();
00275 double * D_ = F->D();
00276 double * DU_ = F->DU();
00277 double * DU2_ = F->DU2();
00278
00279 lapack.GTTRS(TRANS_,N_,NRHS_,DL_,D_,DU_,DU2_,IPIV_,X_,N_,&INFO_);
00280
00281 if (INFO_!=0) EPETRA_CHK_ERR(INFO_);
00282 UpdateFlops(2.0*4*DN*DNRHS);
00283 Solved_ = true;
00284
00285 }
00286 int ierr1=0;
00287 if (RefineSolution_ && !Inverted()) ierr1 = ApplyRefinement();
00288 if (ierr1!=0) EPETRA_CHK_ERR(ierr1)
00289 else
00290 EPETRA_CHK_ERR(ierr);
00291
00292 return(0);
00293 }
00294
00295 int Ifpack_SerialTriDiSolver::ApplyRefinement(void)
00296 {
00297 std::cout<<" SerialTriDiSolver::ApplyRefinement this function is not supported"<<std::endl;
00298 EPETRA_CHK_ERR(-102);
00299 return(0);
00300 }
00301
00302
00303 int Ifpack_SerialTriDiSolver::Invert(void)
00304 {
00305 if (!Factored()) Factor();
00306
00307
00308 AllocateWORK();
00309
00310 lapack.GETRI ( N_, AF_, LDAF_, IPIV_, WORK_, LWORK_, &INFO_);
00311
00312 double DN = N_;
00313 UpdateFlops((DN*DN*DN));
00314 Inverted_ = true;
00315 Factored_ = false;
00316
00317 EPETRA_CHK_ERR(INFO_);
00318 return(0);
00319 }
00320
00321
00322 int Ifpack_SerialTriDiSolver::ReciprocalConditionEstimate(double & Value)
00323 {
00324 int ierr = 0;
00325 if (ReciprocalConditionEstimated()) {
00326 Value = RCOND_;
00327 return(0);
00328 }
00329
00330 if (ANORM_<0.0) ANORM_ = Matrix_->OneNorm();
00331 if (!Factored()) ierr = Factor();
00332 if (ierr!=0) EPETRA_CHK_ERR(ierr-2);
00333
00334 AllocateWORK();
00335 AllocateIWORK();
00336
00337 lapack.GECON( '1', N_, AF_, LDAF_, ANORM_, &RCOND_, WORK_, IWORK_, &INFO_);
00338 ReciprocalConditionEstimated_ = true;
00339 Value = RCOND_;
00340 UpdateFlops(2*N_*N_);
00341 EPETRA_CHK_ERR(INFO_);
00342 return(0);
00343 }
00344
00345 void Ifpack_SerialTriDiSolver::Print(std::ostream& os) const {
00346
00347 if (Matrix_!=0) os << "Solver Matrix" << std::endl << *Matrix_ << std::endl;
00348 if (Factor_!=0) os << "Solver Factored Matrix" << std::endl << *Factor_ << std::endl;
00349 if (LHS_ !=0) os << "Solver LHS" << std::endl << *LHS_ << std::endl;
00350 if (RHS_ !=0) os << "Solver RHS" << std::endl << *RHS_ << std::endl;
00351
00352 }