|
EpetraExt
Development
|
00001 //@HEADER 00002 // *********************************************************************** 00003 // 00004 // EpetraExt: Epetra Extended - Linear Algebra Services Package 00005 // Copyright (2011) Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 //@HEADER 00041 00042 #include <EpetraExt_BlockJacobi_LinearProblem.h> 00043 00044 #include <Epetra_VbrMatrix.h> 00045 #include <Epetra_CrsGraph.h> 00046 #include <Epetra_Map.h> 00047 #include <Epetra_BlockMap.h> 00048 #include <Epetra_MultiVector.h> 00049 #include <Epetra_LinearProblem.h> 00050 00051 #include <Epetra_SerialDenseMatrix.h> 00052 #include <Epetra_SerialDenseVector.h> 00053 #include <Epetra_SerialDenseSVD.h> 00054 00055 #include <set> 00056 00057 using std::vector; 00058 00059 namespace EpetraExt { 00060 00061 LinearProblem_BlockJacobi:: 00062 ~LinearProblem_BlockJacobi() 00063 { 00064 for( int i = 0; i < NumBlocks_; ++i ) 00065 { 00066 if( SVDs_[i] ) delete SVDs_[i]; 00067 else if( Inverses_[i] ) delete Inverses_[i]; 00068 00069 if( RHSBlocks_[i] ) delete RHSBlocks_[i]; 00070 } 00071 00072 if( NewProblem_ ) delete NewProblem_; 00073 if( NewMatrix_ ) delete NewMatrix_; 00074 } 00075 00076 LinearProblem_BlockJacobi::NewTypeRef 00077 LinearProblem_BlockJacobi:: 00078 operator()( OriginalTypeRef orig ) 00079 { 00080 origObj_ = &orig; 00081 00082 Epetra_VbrMatrix * OrigMatrix = dynamic_cast<Epetra_VbrMatrix*>( orig.GetMatrix() ); 00083 00084 if( OrigMatrix->RowMap().DistributedGlobal() ) 00085 { std::cout << "FAIL for Global!\n"; abort(); } 00086 if( OrigMatrix->IndicesAreGlobal() ) 00087 { std::cout << "FAIL for Global Indices!\n"; abort(); } 00088 00089 NumBlocks_ = OrigMatrix->NumMyBlockRows(); 00090 00091 //extract serial dense matrices from vbr matrix 00092 VbrBlocks_.resize(NumBlocks_); 00093 VbrBlockCnt_.resize(NumBlocks_); 00094 VbrBlockDim_.resize(NumBlocks_); 00095 VbrBlockIndices_.resize(NumBlocks_); 00096 for( int i = 0; i < NumBlocks_; ++i ) 00097 { 00098 OrigMatrix->ExtractMyBlockRowView( i, VbrBlockDim_[i], VbrBlockCnt_[i], VbrBlockIndices_[i], VbrBlocks_[i] ); 00099 } 00100 00101 SVDs_.resize(NumBlocks_); 00102 Inverses_.resize(NumBlocks_); 00103 for( int i = 0; i < NumBlocks_; ++i ) 00104 { 00105 if( VbrBlockDim_[i] > 1 ) 00106 { 00107 SVDs_[i] = new Epetra_SerialDenseSVD(); 00108 SVDs_[i]->SetMatrix( *(VbrBlocks_[i][ VbrBlockCnt_[i]-1 ]) ); 00109 SVDs_[i]->Factor(); 00110 SVDs_[i]->Invert( rthresh_, athresh_ ); 00111 Inverses_[i] = SVDs_[i]->InvertedMatrix(); 00112 } 00113 else 00114 { 00115 SVDs_[i] = 0; 00116 double inv = 1. / (*(VbrBlocks_[i][ VbrBlockCnt_[i]-1 ]))(0,0); 00117 Inverses_[i] = new Epetra_SerialDenseMatrix( Copy, &inv, 1, 1, 1 ); 00118 } 00119 } 00120 00121 if( verbose_ > 2 ) 00122 { 00123 std::cout << "SVDs and Inverses!\n"; 00124 for( int i = 0; i < NumBlocks_; ++i ) 00125 { 00126 std::cout << "Block: " << i << " Size: " << VbrBlockDim_[i] << std::endl; 00127 if( SVDs_[i] ) SVDs_[i]->Print(std::cout); 00128 std::cout << *(Inverses_[i]) << std::endl; 00129 } 00130 } 00131 00132 Epetra_MultiVector * RHS = orig.GetRHS(); 00133 double * A; 00134 int LDA; 00135 RHS->ExtractView( &A, &LDA ); 00136 double * currLoc = A; 00137 RHSBlocks_.resize(NumBlocks_); 00138 for( int i = 0; i < NumBlocks_; ++i ) 00139 { 00140 RHSBlocks_[i] = new Epetra_SerialDenseVector( View, currLoc, VbrBlockDim_[i] ); 00141 currLoc += VbrBlockDim_[i]; 00142 } 00143 00144 newObj_ = &orig; 00145 00146 return *newObj_; 00147 } 00148 00149 bool 00150 LinearProblem_BlockJacobi:: 00151 fwd() 00152 { 00153 if( verbose_ > 2 ) 00154 { 00155 std::cout << "-------------------\n"; 00156 std::cout << "BlockJacobi\n"; 00157 std::cout << "-------------------\n"; 00158 } 00159 00160 double MinSV = 1e15; 00161 double MaxSV = 0.0; 00162 00163 std::multiset<double> SVs; 00164 00165 for( int i = 0; i < NumBlocks_; ++i ) 00166 { 00167 if( VbrBlockDim_[i] > 1 ) 00168 { 00169 SVDs_[i]->Factor(); 00170 if( SVDs_[i]->S()[0] > MaxSV ) MaxSV = SVDs_[i]->S()[0]; 00171 if( SVDs_[i]->S()[VbrBlockDim_[i]-1] < MinSV ) MinSV = SVDs_[i]->S()[VbrBlockDim_[i]-1]; 00172 for( int j = 0; j < VbrBlockDim_[i]; ++j ) SVs.insert( SVDs_[i]->S()[j] ); 00173 } 00174 else 00175 { 00176 SVs.insert(1.0); 00177 MaxSV = std::max( MaxSV, 1.0 ); 00178 } 00179 } 00180 00181 std::multiset<double>::iterator iterSI = SVs.begin(); 00182 std::multiset<double>::iterator endSI = SVs.end(); 00183 int i = 0; 00184 if( verbose_ > 2 ) 00185 { 00186 std::cout << std::endl; 00187 std::cout << "Singular Values\n"; 00188 for( ; iterSI != endSI; ++iterSI, i++ ) std::cout << i << "\t" << *iterSI << std::endl; 00189 std::cout << std::endl; 00190 } 00191 00192 Epetra_VbrMatrix * OrigMatrix = dynamic_cast<Epetra_VbrMatrix*>( origObj_->GetMatrix() ); 00193 00194 double abs_thresh = athresh_; 00195 double rel_thresh = rthresh_; 00196 if( thresholding_ == 1 ) 00197 { 00198 abs_thresh = MaxSV * rel_thresh; 00199 rel_thresh = 0.0; 00200 } 00201 00202 for( int i = 0; i < NumBlocks_; ++i ) 00203 { 00204 if( VbrBlockDim_[i] > 1 ) 00205 SVDs_[i]->Invert( rel_thresh, abs_thresh ); 00206 else 00207 (*Inverses_[i])(0,0) = 1./(*(VbrBlocks_[i][ VbrBlockCnt_[i]-1 ]))(0,0); 00208 } 00209 00210 for( int i = 0; i < NumBlocks_; ++i ) 00211 { 00212 for( int j = 0; j < (VbrBlockCnt_[i]-1); ++j ) 00213 { 00214 Epetra_SerialDenseMatrix tempMat( *(VbrBlocks_[i][j]) ); 00215 VbrBlocks_[i][j]->Multiply( false, false, 1.0, *(Inverses_[i]), tempMat, 0.0 ); 00216 } 00217 00218 Epetra_SerialDenseMatrix tempMat2( *(RHSBlocks_[i]) ); 00219 RHSBlocks_[i]->Multiply( false, false, 1.0, *(Inverses_[i]), tempMat2, 0.0 ); 00220 00221 if( verbose_ > 2 ) 00222 { 00223 std::cout << "DiagBlock: " << i << std::endl; 00224 std::cout << *(VbrBlocks_[i][VbrBlockCnt_[i]-1]); 00225 std::cout << "RHSBlock: " << i << std::endl; 00226 std::cout << *(RHSBlocks_[i]); 00227 } 00228 } 00229 00230 if( verbose_ > 2 ) 00231 { 00232 std::cout << "Block Jacobi'd Matrix!\n"; 00233 if( removeDiag_ ) std::cout << *NewMatrix_ << std::endl; 00234 else std::cout << *(dynamic_cast<Epetra_VbrMatrix*>(origObj_->GetMatrix())) << std::endl; 00235 std::cout << "Block Jacobi'd RHS!\n"; 00236 std::cout << *(origObj_->GetRHS()); 00237 std::cout << std::endl; 00238 } 00239 00240 if( verbose_ > 0 ) 00241 { 00242 std::cout << "Min Singular Value: " << MinSV << std::endl; 00243 std::cout << "Max Singular Value: " << MaxSV << std::endl; 00244 std::cout << "--------------------\n"; 00245 } 00246 00247 return true; 00248 } 00249 00250 bool 00251 LinearProblem_BlockJacobi:: 00252 rvs() 00253 { 00254 return true; 00255 } 00256 00257 } //namespace EpetraExt
1.7.6.1