|
IFPACK Development
|
00001 //@HEADER 00002 // *********************************************************************** 00003 // 00004 // Ifpack: Object-Oriented Algebraic Preconditioner Package 00005 // Copyright (2002) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 00028 00029 #include "Ifpack_OverlapSolveObject.h" 00030 #include "Epetra_Comm.h" 00031 #include "Epetra_Map.h" 00032 #include "Epetra_CrsGraph.h" 00033 #include "Epetra_CrsMatrix.h" 00034 #include "Epetra_Vector.h" 00035 #include "Epetra_MultiVector.h" 00036 #include "Epetra_Flops.h" 00037 00038 //============================================================================== 00039 Ifpack_OverlapSolveObject::Ifpack_OverlapSolveObject(char * Label, const Epetra_Comm & Comm) 00040 : Label_(Label), 00041 L_(0), 00042 UseLTrans_(false), 00043 D_(0), 00044 U_(0), 00045 UseUTrans_(false), 00046 UseTranspose_(false), 00047 Comm_(Comm), 00048 Condest_(-1.0), 00049 OverlapMode_(Zero) 00050 { 00051 } 00052 00053 //============================================================================== 00054 Ifpack_OverlapSolveObject::Ifpack_OverlapSolveObject(const Ifpack_OverlapSolveObject & Source) 00055 : Label_(Source.Label_), 00056 L_(Source.L_), 00057 UseLTrans_(Source.UseLTrans_), 00058 D_(Source.D_), 00059 U_(Source.U_), 00060 UseUTrans_(Source.UseUTrans_), 00061 UseTranspose_(Source.UseTranspose_), 00062 Comm_(Source.Comm_), 00063 Condest_(Source.Condest_), 00064 OverlapMode_(Source.OverlapMode_) 00065 { 00066 } 00067 //============================================================================== 00068 Ifpack_OverlapSolveObject::~Ifpack_OverlapSolveObject(){ 00069 } 00070 //============================================================================== 00071 //============================================================================= 00072 int Ifpack_OverlapSolveObject::Solve(bool Trans, const Epetra_MultiVector& X, 00073 Epetra_MultiVector& Y) const { 00074 // 00075 // This function finds Y such that LDU Y = X or U(trans) D L(trans) Y = X for multiple RHS 00076 // 00077 00078 // First generate X and Y as needed for this function 00079 Epetra_MultiVector * X1 = 0; 00080 Epetra_MultiVector * Y1 = 0; 00081 EPETRA_CHK_ERR(SetupXY(Trans, X, Y, X1, Y1)); 00082 00083 bool Upper = true; 00084 bool Lower = false; 00085 bool UnitDiagonal = true; 00086 00087 if (!Trans) { 00088 00089 EPETRA_CHK_ERR(L_->Solve(Lower, Trans, UnitDiagonal, *X1, *Y1)); 00090 EPETRA_CHK_ERR(Y1->Multiply(1.0, *D_, *Y1, 0.0)); // y = D*y (D_ has inverse of diagonal) 00091 EPETRA_CHK_ERR(U_->Solve(Upper, Trans, UnitDiagonal, *Y1, *Y1)); // Solve Uy = y 00092 if (L_->Exporter()!=0) {EPETRA_CHK_ERR(Y.Export(*Y1,*L_->Exporter(), OverlapMode_));} // Export computed Y values if needed 00093 } 00094 else { 00095 EPETRA_CHK_ERR(U_->Solve(Upper, Trans, UnitDiagonal, *X1, *Y1)); // Solve Uy = y 00096 EPETRA_CHK_ERR(Y1->Multiply(1.0, *D_, *Y1, 0.0)); // y = D*y (D_ has inverse of diagonal) 00097 EPETRA_CHK_ERR(L_->Solve(Lower, Trans, UnitDiagonal, *Y1, *Y1)); 00098 if (U_->Importer()!=0) {EPETRA_CHK_ERR(Y.Export(*Y1,*U_->Importer(), OverlapMode_));} // Export computed Y values if needed 00099 } 00100 00101 return(0); 00102 } 00103 //============================================================================= 00104 int Ifpack_OverlapSolveObject::Multiply(bool Trans, const Epetra_MultiVector& X, 00105 Epetra_MultiVector& Y) const { 00106 // 00107 // This function finds X such that LDU Y = X or U(trans) D L(trans) Y = X for multiple RHS 00108 // 00109 00110 // First generate X and Y as needed for this function 00111 Epetra_MultiVector * X1 = 0; 00112 Epetra_MultiVector * Y1 = 0; 00113 EPETRA_CHK_ERR(SetupXY(Trans, X, Y, X1, Y1)); 00114 00115 if (!Trans) { 00116 EPETRA_CHK_ERR(U_->Multiply(Trans, *X1, *Y1)); // 00117 EPETRA_CHK_ERR(Y1->Update(1.0, *X1, 1.0)); // Y1 = Y1 + X1 (account for implicit unit diagonal) 00118 EPETRA_CHK_ERR(Y1->ReciprocalMultiply(1.0, *D_, *Y1, 0.0)); // y = D*y (D_ has inverse of diagonal) 00119 Epetra_MultiVector Y1temp(*Y1); // Need a temp copy of Y1 00120 EPETRA_CHK_ERR(L_->Multiply(Trans, Y1temp, *Y1)); 00121 EPETRA_CHK_ERR(Y1->Update(1.0, Y1temp, 1.0)); // (account for implicit unit diagonal) 00122 if (L_->Exporter()!=0) {EPETRA_CHK_ERR(Y.Export(*Y1,*L_->Exporter(), OverlapMode_));} // Export computed Y values if needed 00123 } 00124 else { 00125 00126 EPETRA_CHK_ERR(L_->Multiply(Trans, *X1, *Y1)); 00127 EPETRA_CHK_ERR(Y1->Update(1.0, *X1, 1.0)); // Y1 = Y1 + X1 (account for implicit unit diagonal) 00128 EPETRA_CHK_ERR(Y1->ReciprocalMultiply(1.0, *D_, *Y1, 0.0)); // y = D*y (D_ has inverse of diagonal) 00129 Epetra_MultiVector Y1temp(*Y1); // Need a temp copy of Y1 00130 EPETRA_CHK_ERR(U_->Multiply(Trans, Y1temp, *Y1)); 00131 EPETRA_CHK_ERR(Y1->Update(1.0, Y1temp, 1.0)); // (account for implicit unit diagonal) 00132 if (L_->Exporter()!=0) {EPETRA_CHK_ERR(Y.Export(*Y1,*L_->Exporter(), OverlapMode_));} 00133 } 00134 return(0); 00135 } 00136 //========================================================================= 00137 int Ifpack_OverlapSolveObject::SetupXY(bool Trans, 00138 const Epetra_MultiVector& Xin, const Epetra_MultiVector& Yin, 00139 Epetra_MultiVector * & Xout, Epetra_MultiVector * & Yout) const { 00140 00141 // Generate an X and Y suitable for performing Solve() and Multiply() methods 00142 00143 if (Xin.NumVectors()!=Yin.NumVectors()) EPETRA_CHK_ERR(-1); // Return error: X and Y not the same size 00144 00145 //cout << "Xin = " << Xin << endl; 00146 Xout = (Epetra_MultiVector *) &Xin; 00147 Yout = (Epetra_MultiVector *) &Yin; 00148 return(0); 00149 } 00150 //============================================================================= 00151 int Ifpack_OverlapSolveObject::Condest(bool Trans, double & ConditionNumberEstimate) const { 00152 00153 if (Condest_>=0.0) { 00154 ConditionNumberEstimate = Condest_; 00155 return(0); 00156 } 00157 // Create a vector with all values equal to one 00158 Epetra_Vector Ones(U_->DomainMap()); 00159 Epetra_Vector OnesResult(L_->RangeMap()); 00160 Ones.PutScalar(1.0); 00161 00162 EPETRA_CHK_ERR(Solve(Trans, Ones, OnesResult)); // Compute the effect of the solve on the vector of ones 00163 EPETRA_CHK_ERR(OnesResult.Abs(OnesResult)); // Make all values non-negative 00164 EPETRA_CHK_ERR(OnesResult.MaxValue(&ConditionNumberEstimate)); // Get the maximum value across all processors 00165 Condest_ = ConditionNumberEstimate; // Save value for possible later calls 00166 return(0); 00167 }
1.7.4