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_BlockJacobi_LinearProblem.h>
00030
00031 #include <Epetra_VbrMatrix.h>
00032 #include <Epetra_CrsGraph.h>
00033 #include <Epetra_Map.h>
00034 #include <Epetra_BlockMap.h>
00035 #include <Epetra_MultiVector.h>
00036 #include <Epetra_LinearProblem.h>
00037
00038 #include <Epetra_SerialDenseMatrix.h>
00039 #include <Epetra_SerialDenseVector.h>
00040 #include <Epetra_SerialDenseSVD.h>
00041
00042 #include <set>
00043
00044 using std::vector;
00045
00046 namespace EpetraExt {
00047
00048 LinearProblem_BlockJacobi::
00049 ~LinearProblem_BlockJacobi()
00050 {
00051 for( int i = 0; i < NumBlocks_; ++i )
00052 {
00053 if( SVDs_[i] ) delete SVDs_[i];
00054 else if( Inverses_[i] ) delete Inverses_[i];
00055
00056 if( RHSBlocks_[i] ) delete RHSBlocks_[i];
00057 }
00058
00059 if( NewProblem_ ) delete NewProblem_;
00060 if( NewMatrix_ ) delete NewMatrix_;
00061 }
00062
00063 LinearProblem_BlockJacobi::NewTypeRef
00064 LinearProblem_BlockJacobi::
00065 operator()( OriginalTypeRef orig )
00066 {
00067 origObj_ = &orig;
00068
00069 Epetra_VbrMatrix * OrigMatrix = dynamic_cast<Epetra_VbrMatrix*>( orig.GetMatrix() );
00070
00071 if( OrigMatrix->RowMap().DistributedGlobal() )
00072 { cout << "FAIL for Global!\n"; abort(); }
00073 if( OrigMatrix->IndicesAreGlobal() )
00074 { cout << "FAIL for Global Indices!\n"; abort(); }
00075
00076 NumBlocks_ = OrigMatrix->NumMyBlockRows();
00077
00078
00079 VbrBlocks_.resize(NumBlocks_);
00080 VbrBlockCnt_.resize(NumBlocks_);
00081 VbrBlockDim_.resize(NumBlocks_);
00082 VbrBlockIndices_.resize(NumBlocks_);
00083 for( int i = 0; i < NumBlocks_; ++i )
00084 {
00085 OrigMatrix->ExtractMyBlockRowView( i, VbrBlockDim_[i], VbrBlockCnt_[i], VbrBlockIndices_[i], VbrBlocks_[i] );
00086 }
00087
00088 SVDs_.resize(NumBlocks_);
00089 Inverses_.resize(NumBlocks_);
00090 for( int i = 0; i < NumBlocks_; ++i )
00091 {
00092 if( VbrBlockDim_[i] > 1 )
00093 {
00094 SVDs_[i] = new Epetra_SerialDenseSVD();
00095 SVDs_[i]->SetMatrix( *(VbrBlocks_[i][ VbrBlockCnt_[i]-1 ]) );
00096 SVDs_[i]->Factor();
00097 SVDs_[i]->Invert( rthresh_, athresh_ );
00098 Inverses_[i] = SVDs_[i]->InvertedMatrix();
00099 }
00100 else
00101 {
00102 SVDs_[i] = 0;
00103 double inv = 1. / (*(VbrBlocks_[i][ VbrBlockCnt_[i]-1 ]))(0,0);
00104 Inverses_[i] = new Epetra_SerialDenseMatrix( Copy, &inv, 1, 1, 1 );
00105 }
00106 }
00107
00108 if( verbose_ > 2 )
00109 {
00110 cout << "SVDs and Inverses!\n";
00111 for( int i = 0; i < NumBlocks_; ++i )
00112 {
00113 cout << "Block: " << i << " Size: " << VbrBlockDim_[i] << endl;
00114 if( SVDs_[i] ) SVDs_[i]->Print(cout);
00115 cout << *(Inverses_[i]) << endl;
00116 }
00117 }
00118
00119 Epetra_MultiVector * RHS = orig.GetRHS();
00120 double * A;
00121 int LDA;
00122 RHS->ExtractView( &A, &LDA );
00123 double * currLoc = A;
00124 RHSBlocks_.resize(NumBlocks_);
00125 for( int i = 0; i < NumBlocks_; ++i )
00126 {
00127 RHSBlocks_[i] = new Epetra_SerialDenseVector( View, currLoc, VbrBlockDim_[i] );
00128 currLoc += VbrBlockDim_[i];
00129 }
00130
00131 newObj_ = &orig;
00132
00133 return *newObj_;
00134 }
00135
00136 bool
00137 LinearProblem_BlockJacobi::
00138 fwd()
00139 {
00140 if( verbose_ > 2 )
00141 {
00142 cout << "-------------------\n";
00143 cout << "BlockJacobi\n";
00144 cout << "-------------------\n";
00145 }
00146
00147 double MinSV = 1e15;
00148 double MaxSV = 0.0;
00149
00150 multiset<double> SVs;
00151
00152 for( int i = 0; i < NumBlocks_; ++i )
00153 {
00154 if( VbrBlockDim_[i] > 1 )
00155 {
00156 SVDs_[i]->Factor();
00157 if( SVDs_[i]->S()[0] > MaxSV ) MaxSV = SVDs_[i]->S()[0];
00158 if( SVDs_[i]->S()[VbrBlockDim_[i]-1] < MinSV ) MinSV = SVDs_[i]->S()[VbrBlockDim_[i]-1];
00159 for( int j = 0; j < VbrBlockDim_[i]; ++j ) SVs.insert( SVDs_[i]->S()[j] );
00160 }
00161 else
00162 {
00163 SVs.insert(1.0);
00164 MaxSV = max( MaxSV, 1.0 );
00165 }
00166 }
00167
00168 multiset<double>::iterator iterSI = SVs.begin();
00169 multiset<double>::iterator endSI = SVs.end();
00170 int i = 0;
00171 if( verbose_ > 2 )
00172 {
00173 cout << endl;
00174 cout << "Singular Values\n";
00175 for( ; iterSI != endSI; ++iterSI, i++ ) cout << i << "\t" << *iterSI << endl;
00176 cout << endl;
00177 }
00178
00179 Epetra_VbrMatrix * OrigMatrix = dynamic_cast<Epetra_VbrMatrix*>( origObj_->GetMatrix() );
00180
00181 double abs_thresh = athresh_;
00182 double rel_thresh = rthresh_;
00183 if( thresholding_ == 1 )
00184 {
00185 abs_thresh = MaxSV * rel_thresh;
00186 rel_thresh = 0.0;
00187 }
00188
00189 for( int i = 0; i < NumBlocks_; ++i )
00190 {
00191 if( VbrBlockDim_[i] > 1 )
00192 SVDs_[i]->Invert( rel_thresh, abs_thresh );
00193 else
00194 (*Inverses_[i])(0,0) = 1./(*(VbrBlocks_[i][ VbrBlockCnt_[i]-1 ]))(0,0);
00195 }
00196
00197 for( int i = 0; i < NumBlocks_; ++i )
00198 {
00199 for( int j = 0; j < (VbrBlockCnt_[i]-1); ++j )
00200 {
00201 Epetra_SerialDenseMatrix tempMat( *(VbrBlocks_[i][j]) );
00202 VbrBlocks_[i][j]->Multiply( false, false, 1.0, *(Inverses_[i]), tempMat, 0.0 );
00203 }
00204
00205 Epetra_SerialDenseMatrix tempMat2( *(RHSBlocks_[i]) );
00206 RHSBlocks_[i]->Multiply( false, false, 1.0, *(Inverses_[i]), tempMat2, 0.0 );
00207
00208 if( verbose_ > 2 )
00209 {
00210 cout << "DiagBlock: " << i << endl;
00211 cout << *(VbrBlocks_[i][VbrBlockCnt_[i]-1]);
00212 cout << "RHSBlock: " << i << endl;
00213 cout << *(RHSBlocks_[i]);
00214 }
00215 }
00216
00217 if( verbose_ > 2 )
00218 {
00219 cout << "Block Jacobi'd Matrix!\n";
00220 if( removeDiag_ ) cout << *NewMatrix_ << endl;
00221 else cout << *(dynamic_cast<Epetra_VbrMatrix*>(origObj_->GetMatrix())) << endl;
00222 cout << "Block Jacobi'd RHS!\n";
00223 cout << *(origObj_->GetRHS());
00224 cout << endl;
00225 }
00226
00227 if( verbose_ > 0 )
00228 {
00229 cout << "Min Singular Value: " << MinSV << endl;
00230 cout << "Max Singular Value: " << MaxSV << endl;
00231 cout << "--------------------\n";
00232 }
00233
00234 return true;
00235 }
00236
00237 bool
00238 LinearProblem_BlockJacobi::
00239 rvs()
00240 {
00241 return true;
00242 }
00243
00244 }