IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_SerialTriDiMatrix.cpp
00001 
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //               Epetra: Linear Algebra Services Package
00006 //                 Copyright 2011 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ************************************************************************
00041 //@HEADER
00042 
00043 #include "Ifpack_SerialTriDiMatrix.h"
00044 #include "Epetra_Util.h"
00045 
00046 //=============================================================================
00047 Ifpack_SerialTriDiMatrix::Ifpack_SerialTriDiMatrix(bool set_object_label)
00048   : Epetra_CompObject(),
00049     Epetra_Object(-1, false),
00050     N_(0),
00051     A_Copied_(false),
00052     CV_(Copy),
00053     A_(0),
00054     UseTranspose_(false)
00055 {
00056   if (set_object_label) {
00057     SetLabel("Epetra::SerialTriDiMatrix");
00058   }
00059 }
00060 
00061 //=============================================================================
00062 Ifpack_SerialTriDiMatrix::Ifpack_SerialTriDiMatrix(int NumRowCol,
00063                                                    bool set_object_label)
00064   : Epetra_CompObject(),
00065     Epetra_Object(-1, false),
00066     N_(NumRowCol),
00067     A_Copied_(false),
00068     CV_(Copy),
00069     A_(0),
00070     UseTranspose_(false)
00071 {
00072   if (set_object_label) {
00073     SetLabel("Epetra::SerialTriDiMatrix");
00074   }
00075   if(NumRowCol < 0)
00076     throw ReportError("NumRows = " + toString(NumRowCol) + ". Should be >= 0", -1);
00077 
00078   int errorcode = Shape(NumRowCol);
00079   if(errorcode != 0)
00080     throw ReportError("Shape returned non-zero value", errorcode);
00081 }
00082 
00083 //=============================================================================
00084 Ifpack_SerialTriDiMatrix::Ifpack_SerialTriDiMatrix(Epetra_DataAccess CV_in, double* A_in,
00085                                                    int NumRowCol,
00086                                                    bool set_object_label)
00087   : Epetra_CompObject(),
00088     Epetra_Object(-1, false),
00089     N_(NumRowCol),
00090     A_Copied_(false),
00091     CV_(CV_in),
00092     A_(A_in),
00093     UseTranspose_(false)
00094 {
00095   if (set_object_label) {
00096     SetLabel("Epetra::SerialTriDiMatrix");
00097   }
00098   if(A_in == 0)
00099     throw ReportError("Null pointer passed as A parameter.", -3);
00100   if(NumRowCol < 0)
00101     throw ReportError("NumRowCol = " + toString(NumRowCol) + ". Should be >= 0", -1);
00102 
00103   if (CV_in == Copy) {
00104     const int newsize = (N_ == 1) ? 1 : 4*(N_-1);
00105     if (newsize > 0) {
00106       A_ = new double[newsize];
00107       CopyMat(A_in, N_, A_, N_);
00108       A_Copied_ = true;
00109       DL_ = A_;
00110       D_  = DL_+(N_-1);
00111       DU_ = D_ + N_;
00112       DU2_ = DU_ + (N_-1);
00113     }
00114     else {
00115       A_ = 0;
00116     }
00117   }
00118 }
00119 //=============================================================================
00120 Ifpack_SerialTriDiMatrix::Ifpack_SerialTriDiMatrix(const Ifpack_SerialTriDiMatrix& Source)
00121   : Epetra_CompObject(Source),
00122     N_(Source.N_),
00123     LDA_(Source.LDA_),
00124     A_Copied_(false),
00125     CV_(Source.CV_),
00126     UseTranspose_(false)
00127 {
00128   SetLabel(Source.Label());
00129   if(CV_ == Copy) {
00130     const int newsize =  (N_ == 1)? 1 : 4*(N_-1);
00131     if(newsize > 0) {
00132       A_ = new double[newsize];
00133       CopyMat(Source.A_, Source.N() , A_, N_);
00134       A_Copied_ = true;
00135       DL_ = A_;
00136       D_  = DL_+(N_-1);
00137       DU_ = D_ + N_;
00138       DU2_ = DU_ + (N_-1);
00139     }
00140     else {
00141       A_ = 0;
00142     }
00143   }
00144 }
00145 
00146 //=============================================================================
00147 int Ifpack_SerialTriDiMatrix::Reshape(int NumRows, int NumCols) {
00148     if(NumRows < 0 || NumCols < 0)
00149       return(-1);
00150     if(NumRows != NumCols)
00151       return(-1);
00152 
00153     double* A_tmp = 0;
00154     const int newsize = (N_ == 1)? 1 : 4*(N_-1);
00155     if(newsize > 0) {
00156         // Allocate space for new matrix
00157         A_tmp = new double[newsize];
00158         for (int k = 0; k < newsize; k++)
00159             A_tmp[k] = 0.0; // Zero out values
00160         if (A_ != 0)
00161           CopyMat(A_, N_, A_tmp, NumRows); // Copy principal submatrix of A to new A
00162         
00163   }
00164   CleanupData(); // Get rid of anything that might be already allocated
00165   N_ = NumCols;
00166   if(newsize > 0) {
00167     A_ = A_tmp; // Set pointer to new A
00168     A_Copied_ = true;
00169   }
00170 
00171   DL_ = A_;
00172   D_ = A_+(N_-1);
00173   DU_ = D_+N_;
00174   DU2_ = DU_+(N_-1);
00175 
00176   return(0);
00177 }
00178 //=============================================================================
00179 int Ifpack_SerialTriDiMatrix::Shape(int NumRowCol) {
00180     if(NumRowCol < 0 || NumRowCol < 0)
00181         return(-1);
00182 
00183   CleanupData(); // Get rid of anything that might be already allocated
00184   N_ = NumRowCol;
00185   LDA_ = N_;
00186   const int newsize = (N_ == 1)? 1 : 4*(N_-1);
00187   if(newsize > 0) {
00188     A_ = new double[newsize];
00189     for (int k = 0; k < newsize; k++)
00190       A_[k] = 0.0; // Zero out values
00191     A_Copied_ = true;
00192   }
00193   // set the pointers
00194   DL_ = A_;
00195   D_ = A_+(N_-1);
00196   DU_ = D_+N_;
00197   DU2_ = DU_+(N_-1);
00198 
00199   return(0);
00200 }
00201 //=============================================================================
00202 Ifpack_SerialTriDiMatrix::~Ifpack_SerialTriDiMatrix()
00203 {
00204 
00205   CleanupData();
00206 
00207 }
00208 //=============================================================================
00209 void Ifpack_SerialTriDiMatrix::CleanupData()
00210 {
00211   if (A_)
00212     delete [] A_;
00213     A_ = DL_ = D_ = DU_ = DU2_ =  0;
00214     A_Copied_ = false;
00215     N_ = 0;
00216 }
00217 //=============================================================================
00218 Ifpack_SerialTriDiMatrix& Ifpack_SerialTriDiMatrix::operator = (const Ifpack_SerialTriDiMatrix& Source) {
00219   if(this == &Source)
00220         return(*this); // Special case of source same as target
00221     if((CV_ == View) && (Source.CV_ == View) && (A_ == Source.A_))
00222         return(*this); // Special case of both are views to same data.
00223 
00224     if(std::strcmp(Label(), Source.Label()) != 0)
00225         throw ReportError("operator= type mismatch (lhs = " + std::string(Label()) +
00226       ", rhs = " + std::string(Source.Label()) + ").", -5);
00227     
00228     if(Source.CV_ == View) {
00229         if(CV_ == Copy) { // C->V only
00230             CleanupData();
00231             CV_ = View;
00232         }
00233         N_ = Source.N_;
00234         A_ = Source.A_;
00235         DL_ = Source.DL_;
00236         D_ = Source.D_;
00237         DU_ = Source.DU_;
00238         DU2_ = Source.DU2_;
00239     }
00240     else {
00241         if(CV_ == View) { // V->C
00242             CV_ = Copy;
00243             N_ = Source.N_;
00244             const int newsize = 4*N_ - 4;
00245             if(newsize > 0) {
00246                 A_ = new double[newsize];
00247                 DL_ = A_;
00248                 D_ = A_+(N_-1);
00249                 DU_ = D_+N_;
00250                 DU2_ = DU_+(N_-1);
00251                 A_Copied_ = true;
00252             }
00253             else {
00254                 A_ = 0;
00255                 DL_ = D_ = DU_ = DU2_ = 0;
00256                 A_Copied_ = false;
00257             }
00258         }
00259         else { // C->C
00260             if(Source.N_ == N_) { // we don't need to reallocate
00261                 N_ = Source.N_;
00262             }
00263             else { // we need to allocate more space (or less space)
00264                 CleanupData();
00265                 N_ = Source.N_;
00266                 const int newsize = (N_ == 1)? 1 : 4*(N_-1);
00267                 if(newsize > 0) {
00268                     A_ = new double[newsize];
00269                     DL_ = A_;
00270                     D_ = A_+(N_-1);
00271                     DU_ = D_+N_;
00272                     DU2_ = DU_+(N_-1);
00273                     A_Copied_ = true;
00274                 }
00275             }
00276         }
00277         CopyMat(Source.A_, Source.N(), A_, N_); // V->C and C->C
00278     }
00279     
00280   return(*this);
00281 }
00282 
00283 
00284 //=============================================================================
00285 bool Ifpack_SerialTriDiMatrix::operator==(const Ifpack_SerialTriDiMatrix& rhs) const
00286 {
00287   if (N_ != rhs.N_) return(false);
00288 
00289   const double* A_tmp = A_;
00290   const double* rhsA = rhs.A_;
00291 
00292   const int size = (N_ == 1)? 1 : 4*(N_-1);
00293 
00294   for(int j=0; j<size; ++j) {
00295     if (std::abs(A_tmp[j] - rhsA[j]) > Epetra_MinDouble) {
00296       return(false);
00297     }
00298   }
00299 
00300   return(true);
00301 }
00302 
00303 //=============================================================================
00304 Ifpack_SerialTriDiMatrix& Ifpack_SerialTriDiMatrix::operator+= ( const Ifpack_SerialTriDiMatrix & Source) {
00305     if (N() != Source.N())
00306         throw ReportError("Column dimension of source = " + toString(Source.N()) +
00307                                             " is different than column dimension of target = " + toString(N()), -2);
00308 
00309     CopyMat(Source.A(), Source.N(), A(), N(),true);
00310   return(*this);
00311 }
00312 //=============================================================================
00313 void Ifpack_SerialTriDiMatrix::CopyMat(const double* Source,
00314                        int nrowcol,
00315                                        double* Target,
00316                        int tN,
00317                                        bool add)
00318 {
00319   int lmax = EPETRA_MIN(nrowcol,tN);
00320   if (add) {
00321     // do this in 4 passes
00322     for(int j=0; j<lmax; ++j) {      
00323       Target[(tN-1)+j] += Source[(nrowcol-1)+j];  //D      
00324       if(j<tN-1) {
00325     Target[j] += Source[j];  // DL
00326     Target[(tN-1)+tN + j] += Source[(nrowcol-1)+ nrowcol + j]; // DU
00327       }
00328       if(j<tN-2) Target[(tN-1)*2 + tN + j] += Source[ (nrowcol-1)*2 +nrowcol  + j]; // DU2
00329     }
00330   }
00331   else {  
00332     for(int j=0; j<lmax; ++j) {
00333       Target[(tN-1)+j] = Source[(nrowcol-1)+j];  //D      
00334       if(j<tN-1) {
00335     Target[j] = Source[j];  // DL
00336     Target[(tN-1)+tN + j] = Source[(nrowcol-1)+ nrowcol + j]; // DU
00337       }
00338       if(j<tN-2) Target[(tN-1)*2 + tN + j] = Source[ (nrowcol-1)*2 +nrowcol  + j]; // DU2
00339     }
00340   }
00341   return;
00342 }
00343 //=============================================================================
00344 double Ifpack_SerialTriDiMatrix::NormOne() const {
00345   int i;
00346   double anorm = 0.0;
00347   double * ptr  = A_;
00348   double sum=0.0;
00349   
00350   const int size = (N_ == 1)? 1 : 4*(N_-1);
00351 
00352   for (i=0; i<size; i++) sum += std::abs(*ptr++);
00353   
00354   anorm = EPETRA_MAX(anorm, sum);
00355   UpdateFlops((double)size );
00356   return(anorm);
00357 }
00358 //=============================================================================
00359 double Ifpack_SerialTriDiMatrix::NormInf() const {
00360   return NormOne();
00361 
00362 }
00363 //=============================================================================
00364 int Ifpack_SerialTriDiMatrix::Scale(double ScalarA) {
00365 
00366   int i;
00367 
00368   double * ptr = A_;
00369 
00370   const int size = (N_ == 1)? 1 : 4*(N_-1);
00371 
00372   for (i=0; i<size ; i++) { *ptr = ScalarA * (*ptr); ptr++; }
00373  
00374   UpdateFlops((double)N_*(double)N_);
00375   return(0);
00376 
00377 }
00378 
00379 // //=========================================================================
00380 int Ifpack_SerialTriDiMatrix::Multiply (char TransA, char TransB, double ScalarAB,
00381                     const Ifpack_SerialTriDiMatrix& A_in,
00382                     const Ifpack_SerialTriDiMatrix& B,
00383                     double ScalarThis ) {
00384   throw ReportError("Ifpack_SerialTriDiMatrix::Multiply not implimented ",-2);
00385   return(-1);
00386 
00387 }
00388 
00389 //=========================================================================
00390 
00391 int Ifpack_SerialTriDiMatrix::Random() {
00392   
00393   Epetra_Util util;
00394   double* arrayPtr = A_;
00395   const int size = (N_ == 1)? 1 : 4*(N_-1);
00396   for(int j = 0; j < size ; j++) {    
00397     *arrayPtr++ = util.RandomDouble();  
00398   }
00399   
00400   return(0);
00401 }
00402 
00403 void Ifpack_SerialTriDiMatrix::Print(std::ostream& os) const {
00404     os <<" square format:"<<std::endl;
00405     if(! A_ ) {
00406       os <<" empty matrix "<<std::endl;
00407       return;
00408     }
00409     for(int i=0 ; i < N_ ; ++i)  {
00410     for(int j=0 ; j < N_ ; ++j)  {
00411       if ( j >= i-1  && j <= i+1) {
00412     os << (*this)(i,j)<<" ";
00413       }
00414       else 
00415     os <<". ";
00416     }
00417     os << std::endl;
00418     }
00419  }
 All Classes Files Functions Variables Enumerations Friends