Sandia Home

Nonlinear Solver Project: Anasazi_LOCA_Sort.H Source File

Anasazi_LOCA_Sort.H

00001 //@HEADER
00002 // ************************************************************************
00003 // 
00004 //                  LOCA Continuation Algorithm Package
00005 //                 Copyright (2005) 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 Tammy Kolda (tgkolda@sandia.gov) or Roger Pawlowski
00025 // (rppawlo@sandia.gov), Sandia National Laboratories.
00026 // 
00027 // ************************************************************************
00028 //@HEADER
00029 
00030 #ifndef ANASAZI_LOCA_SORT_HPP
00031 #define ANASAZI_LOCA_SORT_HPP
00032 
00038 #include "AnasaziSortManager.hpp"
00039 #include "Teuchos_LAPACK.hpp"
00040 
00041 namespace Anasazi {
00042     
00043   template<class ScalarType, class MV, class OP>
00044   class LOCASort : public SortManager<ScalarType,MV,OP> {
00045       
00046   public:
00047       
00049 
00061     LOCASort(const string which = "LM", 
00062              ScalarType cayleyPole = Teuchos::ScalarTraits<ScalarType>::zero(),
00063              ScalarType cayleyZero = Teuchos::ScalarTraits<ScalarType>::zero()
00064              ) 
00065     { _which = which; _sigma = cayleyPole; _mu = cayleyZero; };
00066       
00068     virtual ~LOCASort() {};
00069       
00070       
00072 
00083     ReturnType sort(Eigensolver<ScalarType,MV,OP>* solver, int n, ScalarType *evals, std::vector<int> *perm = 0) const;
00084       
00086 
00099     ReturnType sort(Eigensolver<ScalarType,MV,OP>* solver, int n, ScalarType *r_evals, ScalarType *i_evals, std::vector<int> *perm = 0) const;
00100       
00101   protected: 
00102       
00103     string _which;
00104     ScalarType _sigma, _mu;
00105       
00106   private:
00107       
00108     // Helper method for sorting cayley transform
00109     ScalarType realLambda(const ScalarType er, const ScalarType ei) const;      
00110       
00111   };
00112     
00113   template<class ScalarType, class MV, class OP>
00114   ReturnType LOCASort<ScalarType,MV,OP>::sort(Eigensolver<ScalarType,MV,OP>* solver, int n, ScalarType *evals, std::vector<int> *perm) const 
00115   {
00116     int i, j, tempord;
00117     ScalarType temp, temp2;
00118     Teuchos::LAPACK<int,ScalarType> lapack;
00119     //
00120     // Reset the permutation if it is required.
00121     //          
00122     if (perm) {
00123       for (i=0; i < n; i++) {
00124         (*perm)[i] = i;
00125       }
00126     }
00127     //
00128     // These methods use an insertion sort method to circument recursive calls.
00129     //---------------------------------------------------------------
00130     // Sort eigenvalues in increasing order of magnitude
00131     //---------------------------------------------------------------
00132     if (!_which.compare("SM")) {
00133       for (j=1; j < n; ++j) {
00134         temp = evals[j]; 
00135         if (perm)
00136           tempord = (*perm)[j];
00137         temp2 = evals[j]*evals[j];
00138         for (i=j-1; i>=0 && (evals[i]*evals[i])>temp2; --i) {
00139           evals[i+1]=evals[i];
00140           if (perm)
00141             (*perm)[i+1]=(*perm)[i];
00142         }
00143         evals[i+1] = temp; 
00144         if (perm) 
00145           (*perm)[i+1] = tempord;       
00146       }
00147       return Ok;
00148     }
00149     //---------------------------------------------------------------
00150     // Sort eigenvalues in increasing order of real part
00151     //---------------------------------------------------------------
00152     if (!_which.compare("SR")) {
00153       for (j=1; j < n; ++j) {
00154         temp = evals[j]; 
00155         if (perm)
00156           tempord = (*perm)[j];
00157         for (i=j-1; i>=0 && evals[i]>temp; --i) {
00158           evals[i+1]=evals[i];
00159           if (perm)
00160             (*perm)[i+1]=(*perm)[i];
00161         }
00162         evals[i+1] = temp; 
00163         if (perm)
00164           (*perm)[i+1] = tempord;       
00165       }
00166       return Ok;
00167     }
00168     //---------------------------------------------------------------
00169     // Sort eigenvalues in increasing order of imaginary part
00170     // NOTE:  There is no implementation for this since this sorting
00171     // method assumes only real eigenvalues.
00172     //---------------------------------------------------------------
00173     if (!_which.compare("SI")) {
00174       return Undefined;
00175     }
00176     //---------------------------------------------------------------
00177     // Sort eigenvalues in decreasing order of magnitude
00178     //---------------------------------------------------------------
00179     if (!_which.compare("LM")) {
00180       for (j=1; j < n; ++j) {
00181         temp = evals[j]; 
00182         if (perm)
00183           tempord = (*perm)[j];
00184         temp2 = evals[j]*evals[j];
00185         for (i=j-1; i>=0 && (evals[i]*evals[i])<temp2; --i) {
00186           evals[i+1]=evals[i];
00187           if (perm)
00188             (*perm)[i+1]=(*perm)[i];
00189         }
00190         evals[i+1] = temp; 
00191         if (perm)
00192           (*perm)[i+1] = tempord;       
00193       }
00194       return Ok;
00195     }
00196     //---------------------------------------------------------------
00197     // Sort eigenvalues in decreasing order of real part
00198     //---------------------------------------------------------------
00199     if (!_which.compare("LR")) {
00200       for (j=1; j < n; ++j) {
00201         temp = evals[j]; 
00202         if (perm)
00203           tempord = (*perm)[j];
00204         for (i=j-1; i>=0 && evals[i]<temp; --i) {
00205           evals[i+1]=evals[i];
00206           if (perm)
00207             (*perm)[i+1]=(*perm)[i];
00208         }
00209         evals[i+1] = temp; 
00210         if (perm)
00211           (*perm)[i+1] = tempord;       
00212       }
00213       return Ok;
00214     }
00215     //---------------------------------------------------------------
00216     // Sort eigenvalues in decreasing order of imaginary part
00217     // NOTE:  There is no implementation for this since this sorting
00218     // method assumes only real eigenvalues.
00219     //---------------------------------------------------------------
00220     if (!_which.compare("LI")) {
00221       return Undefined;
00222     }
00223     //---------------------------------------------------------------
00224     // Sort eigenvalues however Andy wants them ( which is always correct )
00225     //---------------------------------------------------------------
00226     if (!_which.compare("CA")) {
00227       // Sigma and mu are available here      
00228       // use _evalr and _evali and the ordering goes in _order
00229       // remember to actually sort the eigenvalues yourself
00230       //
00231       // LM code to start with....
00232       ScalarType templambda;
00233       for (j=1; j < n; ++j) {
00234         temp = evals[j]; 
00235         tempord = (*perm)[j];
00236         templambda=realLambda(evals[j],0);
00237         for (i=j-1; i>=0 && realLambda(evals[i],0)<templambda; --i) {
00238           evals[i+1]=evals[i]; 
00239           (*perm)[i+1]=(*perm)[i];
00240         }
00241         evals[i+1] = temp; (*perm)[i+1] = tempord;      
00242       } 
00243       return Ok;
00244     }
00245     
00246     // The character string held by this class is not valid.  
00247     return Undefined;    
00248   }
00249     
00250     
00251   template<class ScalarType, class MV, class OP>
00252   ReturnType LOCASort<ScalarType,MV,OP>::sort(Eigensolver<ScalarType,MV,OP>* solver, int n, ScalarType *r_evals, ScalarType *i_evals, std::vector<int> *perm) const {
00253     int i, j, tempord;
00254     ScalarType temp, tempr, tempi;
00255     Teuchos::LAPACK<int,ScalarType> lapack;
00256     //
00257     // Reset the index
00258     //          
00259     if (perm) {
00260       for (i=0; i < n; i++) {
00261         (*perm)[i] = i;
00262       }
00263     }
00264     //
00265     // These methods use an insertion sort method to circument recursive calls.
00266     //---------------------------------------------------------------
00267     // Sort eigenvalues in increasing order of magnitude
00268     //---------------------------------------------------------------
00269     if (!_which.compare("SM")) {
00270       for (j=1; j < n; ++j) {
00271         tempr = r_evals[j]; tempi = i_evals[j]; 
00272         if (perm)
00273           tempord = (*perm)[j];
00274         temp=lapack.LAPY2(r_evals[j],i_evals[j]);
00275         for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i])>temp; --i) {
00276           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00277           if (perm)
00278             (*perm)[i+1]=(*perm)[i];
00279         }
00280         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00281         if (perm)
00282           (*perm)[i+1] = tempord;       
00283       } 
00284       return Ok;
00285     }
00286     //---------------------------------------------------------------
00287     // Sort eigenvalues in increasing order of real part
00288     //---------------------------------------------------------------
00289     if (!_which.compare("SR")) {
00290       for (j=1; j < n; ++j) {
00291         tempr = r_evals[j]; tempi = i_evals[j]; 
00292         if (perm)
00293           tempord = (*perm)[j];
00294         for (i=j-1; i>=0 && r_evals[i]>tempr; --i) {
00295           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00296           if (perm)
00297             (*perm)[i+1]=(*perm)[i];
00298         }
00299         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00300         if (perm)
00301           (*perm)[i+1] = tempord;       
00302       } 
00303       return Ok;
00304     }
00305     //---------------------------------------------------------------
00306     // Sort eigenvalues in increasing order of imaginary part
00307     //---------------------------------------------------------------
00308     if (!_which.compare("SI")) {
00309       for (j=1; j < n; ++j) {
00310         tempr = r_evals[j]; tempi = i_evals[j]; 
00311         if (perm)
00312           tempord = (*perm)[j];
00313         for (i=j-1; i>=0 && i_evals[i]>tempi; --i) {
00314           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00315           if (perm)
00316             (*perm)[i+1]=(*perm)[i];
00317         }
00318         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00319         if (perm)
00320           (*perm)[i+1] = tempord;       
00321       }
00322       return Ok;
00323     }
00324     //---------------------------------------------------------------
00325     // Sort eigenvalues in decreasing order of magnitude
00326     //---------------------------------------------------------------
00327     if (!_which.compare("LM")) {
00328       for (j=1; j < n; ++j) {
00329         tempr = r_evals[j]; tempi = i_evals[j]; 
00330         if (perm)
00331           tempord = (*perm)[j];
00332         temp=lapack.LAPY2(r_evals[j],i_evals[j]);
00333         for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i])<temp; --i) {
00334           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00335           if (perm)
00336             (*perm)[i+1]=(*perm)[i];
00337         }
00338         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00339         if (perm)
00340           (*perm)[i+1] = tempord;       
00341       } 
00342       return Ok;
00343     }
00344     //---------------------------------------------------------------
00345     // Sort eigenvalues in decreasing order of real part
00346     //---------------------------------------------------------------
00347     if (!_which.compare("LR")) {
00348       for (j=1; j < n; ++j) {
00349         tempr = r_evals[j]; tempi = i_evals[j]; 
00350         if (perm)
00351           tempord = (*perm)[j];
00352         for (i=j-1; i>=0 && r_evals[i]<tempr; --i) {
00353           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00354           if (perm)
00355             (*perm)[i+1]=(*perm)[i];
00356         }
00357         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00358         if (perm)
00359           (*perm)[i+1] = tempord;       
00360       } 
00361       return Ok;
00362     }
00363     //---------------------------------------------------------------
00364     // Sort eigenvalues in decreasing order of imaginary part
00365     //---------------------------------------------------------------
00366     if (!_which.compare("LI")) {
00367       for (j=1; j < n; ++j) {
00368         tempr = r_evals[j]; tempi = i_evals[j]; 
00369         if (perm)
00370           tempord = (*perm)[j];
00371         for (i=j-1; i>=0 && i_evals[i]<tempi; --i) {
00372           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00373           if (perm)
00374             (*perm)[i+1]=(*perm)[i];
00375         }
00376         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00377         if (perm)
00378           (*perm)[i+1] = tempord;       
00379       }
00380       return Ok;
00381     }
00382     //---------------------------------------------------------------
00383     // Sort eigenvalues however Andy wants them ( which is always correct )
00384     //---------------------------------------------------------------
00385     if (!_which.compare("CA")) {
00386       // Sigma and mu are available here      
00387       // use _evalr and _evali and the ordering goes in _order
00388       // remember to actually sort the eigenvalues yourself
00389       //
00390       // LM code to start with....
00391       for (j=1; j < n; ++j) {
00392         tempr = r_evals[j]; tempi = i_evals[j]; 
00393         tempord = (*perm)[j];
00394         temp=realLambda(r_evals[j],i_evals[j]);
00395         for (i=j-1; i>=0 && realLambda(r_evals[i],i_evals[i])<temp; --i) {
00396           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00397           (*perm)[i+1]=(*perm)[i];
00398         }
00399         r_evals[i+1] = tempr; i_evals[i+1] = tempi; (*perm)[i+1] = tempord;     
00400       }
00401       return Ok;
00402     }      
00403     // The character string held by this class is not valid.  
00404     return Undefined;      
00405   }
00406     
00407   template<class ScalarType, class MV, class OP>
00408   ScalarType LOCASort<ScalarType, MV, OP>::realLambda(const ScalarType er, const ScalarType ei) const {
00409     // Utility that returns the real part of the un-Cayley-transformed eigenvalue for sorting
00410     // Reject if it is to the right of sigma --- these are junk
00411     // This is temporary, to be replaced by sorting class
00412     ScalarType reLambda =  (_sigma*(er*er+ei*ei) - (_sigma+_mu)*er + _mu)/ ( (er-1.0)*(er-1.0) + ei*ei);
00413     if (reLambda > _sigma) return -1.0e6;
00414     else                   return reLambda;
00415   }
00416   
00417 } // namespace Anasazi
00418 
00419 #endif // ANASAZI_LOCA_SORT_HPP
00420 

Generated on Thu Mar 3 01:00:44 2005 for Nonlinear Solver Project by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2002


© Sandia Corporation | Software.Sandia.Gov | Site Contact | Privacy and Security