// @HEADER // *********************************************************************** // // Anasazi: Block Eigensolvers Package // Copyright (2004) Sandia Corporation // // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive // license for use of this work by or on behalf of the U.S. Government. // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA // Questions? Contact Michael A. Heroux (maherou@sandia.gov) // // *********************************************************************** // @HEADER /*! \file AnasaziBasicSort.hpp \brief Basic implementation of the Anasazi::SortManager class */ #ifndef ANASAZI_BASIC_SORT_HPP #define ANASAZI_BASIC_SORT_HPP /*! \class Anasazi::BasicSort \brief An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques. \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist */ #include "AnasaziConfigDefs.hpp" #include "AnasaziSortManager.hpp" #include "Teuchos_LAPACK.hpp" #include "Teuchos_ScalarTraits.hpp" namespace Anasazi { template class BasicSort : public SortManager { public: //! Constructor /** @param which [in] The eigenvalues of interest for this eigenproblem. */ BasicSort( const std::string which = "LM" ) { setSortType(which); } //! Destructor virtual ~BasicSort() {}; //! Set sort type /** @param which [in] The eigenvalues of interest for this eigenproblem. */ void setSortType( const std::string which ) { which_ = which; TEST_FOR_EXCEPTION(which_.compare("LM") && which_.compare("SM") && which_.compare("LR") && which_.compare("SR") && which_.compare("LI") && which_.compare("SI"), std::invalid_argument, "Anasazi::BasicSort::sort(): sorting order is not valid"); }; //! Sort the vector of eigenvalues, optionally returning the permutation vector. /** @param solver [in] Eigensolver that is calling the sorting routine @param n [in] Number of values in evals to be sorted. @param evals [in/out] Vector of length n containing the eigenvalues to be sorted @param perm [out] Vector of length n to store the permutation index (optional) */ void sort(Eigensolver* solver, const int n, std::vector::magnitudeType> &evals, std::vector *perm = 0) const; /*! \brief Sort the vectors of eigenpairs, optionally returning the permutation vector. This routine takes two vectors, one for each part of a complex eigenvalue. This is helpful for solving real, non-symmetric eigenvalue problems. @param solver [in] Eigensolver that is calling the sorting routine @param n [in] Number of values in r_evals,i_evals to be sorted. @param r_evals [in/out] Vector of length n containing the real part of the eigenvalues to be sorted @param i_evals [in/out] Vector of length n containing the imaginary part of the eigenvalues to be sorted @param perm [out] Vector of length n to store the permutation index (optional) */ void sort(Eigensolver* solver, const int n, std::vector::magnitudeType> &r_evals, std::vector::magnitudeType> &i_evals, std::vector *perm = 0) const; protected: //! Sorting type /*! \note Sorting choices:
  • "LM" - Largest Magnitude [ default ]
  • "SM" - Smallest Magnitude
  • "LR" - Largest Real
  • "SR" - Smallest Real
  • "LI" - Largest Imaginary
  • "SI" - Smallest Imaginary
*/ std::string which_; }; template void BasicSort::sort(Eigensolver* solver, const int n, std::vector::magnitudeType> &evals, std::vector *perm) const { int i=0,j=0; TEST_FOR_EXCEPTION(evals.size() < (unsigned int) n, std::invalid_argument, "Anasazi::BasicSort:sort(): eigenvalue vector size isn't consistent with n."); if (perm) { TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n, std::invalid_argument, "Anasazi::BasicSort:sort(): permutation vector size isn't consistent with n."); } // Temp integer for swapping the index of the permutation, used in all sorting types. int tempord=0; typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; typedef Teuchos::ScalarTraits MT; // Temp variable for swapping the eigenvalue used in all sorting types. MagnitudeType temp; Teuchos::LAPACK lapack; // // Reset the permutation if it is required. // if (perm) { for (i=0; i < n; i++) { (*perm)[i] = i; } } // // These methods use an insertion sort method to circumvent recursive calls. //--------------------------------------------------------------- // Sort eigenvalues in increasing order of magnitude //--------------------------------------------------------------- if (!which_.compare("SM")) { for (j=1; j < n; j++) { temp = evals[j]; if (perm) { tempord = (*perm)[j]; } MagnitudeType temp2 = MT::magnitude(evals[j]); for (i=j-1; i >=0 && MT::magnitude(evals[i]) > temp2; i--) { evals[i+1] = evals[i]; if (perm) { (*perm)[i+1]=(*perm)[i]; } } evals[i+1] = temp; if (perm) { (*perm)[i+1] = tempord; } } return; } //--------------------------------------------------------------- // Sort eigenvalues in increasing order of real part //--------------------------------------------------------------- if (!which_.compare("SR")) { for (j=1; j < n; j++) { temp = evals[j]; if (perm) { tempord = (*perm)[j]; } for (i=j-1; i >= 0 && evals[i] > temp; i--) { evals[i+1]=evals[i]; if (perm) { (*perm)[i+1]=(*perm)[i]; } } evals[i+1] = temp; if (perm) { (*perm)[i+1] = tempord; } } return; } //--------------------------------------------------------------- // Sort eigenvalues in increasing order of imaginary part // NOTE: There is no implementation for this since this sorting // method assumes only real eigenvalues. //--------------------------------------------------------------- TEST_FOR_EXCEPTION(!which_.compare("SI"), SortManagerError, "Anasazi::BasicSort::sort() with one arg assumes real eigenvalues"); //--------------------------------------------------------------- // Sort eigenvalues in decreasing order of magnitude //--------------------------------------------------------------- if (!which_.compare("LM")) { for (j=1; j < n; j++) { temp = evals[j]; if (perm) { tempord = (*perm)[j]; } MagnitudeType temp2 = MT::magnitude(evals[j]); for (i=j-1; i >= 0 && MT::magnitude(evals[i]) < temp2; i--) { evals[i+1]=evals[i]; if (perm) { (*perm)[i+1]=(*perm)[i]; } } evals[i+1] = temp; if (perm) { (*perm)[i+1] = tempord; } } return; } //--------------------------------------------------------------- // Sort eigenvalues in decreasing order of real part //--------------------------------------------------------------- if (!which_.compare("LR")) { for (j=1; j < n; j++) { temp = evals[j]; if (perm) { tempord = (*perm)[j]; } for (i=j-1; i >= 0 && evals[i] void BasicSort::sort(Eigensolver* solver, const int n, std::vector::magnitudeType> &r_evals, std::vector::magnitudeType> &i_evals, std::vector *perm) const { typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; typedef Teuchos::ScalarTraits MT; TEST_FOR_EXCEPTION(r_evals.size() < (unsigned int) n || i_evals.size() < (unsigned int) n, std::invalid_argument, "Anasazi::BasicSort:sort(): real and imaginary vector sizes aren't consistent with n."); if (perm) { TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n, std::invalid_argument, "Anasazi::BasicSort:sort(): permutation vector size isn't consistent with n."); } int i=0,j=0; int tempord=0; MagnitudeType temp, tempr, tempi; Teuchos::LAPACK lapack; // // Reset the index // if (perm) { for (i=0; i < n; i++) { (*perm)[i] = i; } } // // These methods use an insertion sort method to circumvent recursive calls. //--------------------------------------------------------------- // Sort eigenvalues in increasing order of magnitude //--------------------------------------------------------------- if (!which_.compare("SM")) { for (j=1; j < n; j++) { tempr = r_evals[j]; tempi = i_evals[j]; if (perm) { tempord = (*perm)[j]; } temp=lapack.LAPY2(r_evals[j],i_evals[j]); for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i]) > temp; i--) { r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; if (perm) { (*perm)[i+1]=(*perm)[i]; } } r_evals[i+1] = tempr; i_evals[i+1] = tempi; if (perm) { (*perm)[i+1] = tempord; } } return; } //--------------------------------------------------------------- // Sort eigenvalues in increasing order of real part //--------------------------------------------------------------- if (!which_.compare("SR")) { for (j=1; j < n; j++) { tempr = r_evals[j]; tempi = i_evals[j]; if (perm) { tempord = (*perm)[j]; } for (i=j-1; i>=0 && r_evals[i]>tempr; i--) { r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; if (perm) { (*perm)[i+1]=(*perm)[i]; } } r_evals[i+1] = tempr; i_evals[i+1] = tempi; if (perm) { (*perm)[i+1] = tempord; } } return; } //--------------------------------------------------------------- // Sort eigenvalues in increasing order of imaginary part //--------------------------------------------------------------- if (!which_.compare("SI")) { for (j=1; j < n; j++) { tempr = r_evals[j]; tempi = i_evals[j]; if (perm) { tempord = (*perm)[j]; } for (i=j-1; i>=0 && i_evals[i]>tempi; i--) { r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; if (perm) { (*perm)[i+1]=(*perm)[i]; } } r_evals[i+1] = tempr; i_evals[i+1] = tempi; if (perm) { (*perm)[i+1] = tempord; } } return; } //--------------------------------------------------------------- // Sort eigenvalues in decreasing order of magnitude //--------------------------------------------------------------- if (!which_.compare("LM")) { for (j=1; j < n; j++) { tempr = r_evals[j]; tempi = i_evals[j]; if (perm) { tempord = (*perm)[j]; } temp=lapack.LAPY2(r_evals[j],i_evals[j]); for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i])=0 && r_evals[i]=0 && i_evals[i]