• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

MOR_CollocationMetricCriterion.cpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 #include "MOR_CollocationMetricCriterion.hpp"
00007 
00008 #include "MOR_ExtendedEpetraLapack.hpp"
00009 
00010 #include "Teuchos_TestForException.hpp"
00011 
00012 #include <vector>
00013 #include <algorithm>
00014 #include <cmath>
00015 #include <cstddef>
00016 
00017 namespace MOR {
00018 
00019 namespace Detail {
00020 
00021 double frobeniusNorm(const Epetra_SerialSymDenseMatrix &matrix) {
00022   const char norm = 'F';
00023   const char uplo = matrix.Upper() ? 'U' : 'L';
00024 
00025   return Extended_Epetra_LAPACK().LANSY(norm, uplo, matrix.N(), matrix.A(), matrix.LDA(), /*WORK = */ NULL);
00026 }
00027 
00028 double selectedEigenvalue(const Epetra_SerialSymDenseMatrix &m, int rank) {
00029   Epetra_SerialSymDenseMatrix matrix(m);
00030   const int matrixSize = matrix.N();
00031 
00032   if (matrixSize > 0) {
00033     const char noVectors = 'N';
00034     const char range = 'I';
00035     const char uplo = matrix.Upper() ? 'U' : 'L';
00036     const int eigenRank = rank + 1;
00037     const double defaultTol = 0.0;
00038 
00039     int eigenValueCount;
00040     std::vector<double> eigenValues(matrixSize);
00041 
00042     int info;
00043 
00044     const int query = -1;
00045     double workQueriedSize;
00046     int iworkQueriedSize;
00047 
00048     Extended_Epetra_LAPACK().SYEVR(
00049         noVectors, range, uplo,
00050         matrixSize, matrix.A(), matrix.LDA(),
00051         /* vl = */ NULL, /* vu = */ NULL, &eigenRank, &eigenRank,
00052         defaultTol,
00053         &eigenValueCount, &eigenValues[0], /* z = */ NULL, /* ldz = */ 1 /* (dummy) */, /* isuppz = */ NULL,
00054         &workQueriedSize, /* lwork = */ query, &iworkQueriedSize, /* liwork = */ query,
00055         &info);
00056     TEUCHOS_TEST_FOR_EXCEPT(info != 0);
00057 
00058     std::vector<double> work(static_cast<int>(workQueriedSize));
00059     std::vector<int> iwork(iworkQueriedSize);
00060 
00061     // Workaround for bug in DSYEVR in early releases of the Lapack 3 reference implementation:
00062     // The input arguments VU and VL are accessed even when RANGE != 'V'
00063     const double v_workaround = 0.0;
00064 
00065     Epetra_LAPACK().SYEVR(
00066         noVectors, range, uplo,
00067         matrixSize, matrix.A(), matrix.LDA(),
00068         /* vl = */ &v_workaround, /* vu = */ &v_workaround, &eigenRank, &eigenRank,
00069         defaultTol,
00070         &eigenValueCount, &eigenValues[0], /* z = */ NULL, /* ldz = */ 1 /* (dummy) */, /* isuppz = */ NULL,
00071         &work[0], /* lwork = */ work.size(), &iwork[0], iwork.size(),
00072         &info);
00073     TEUCHOS_TEST_FOR_EXCEPT(info != 0);
00074 
00075     return eigenValues[0];
00076   } else {
00077     return 0.0; // Dummy value
00078   }
00079 }
00080 
00081 double largestEigenvalue(const Epetra_SerialSymDenseMatrix &m) {
00082   return selectedEigenvalue(m, m.N() - 1);
00083 }
00084 
00085 double smallestEigenvalue(const Epetra_SerialSymDenseMatrix &m) {
00086   return selectedEigenvalue(m, 0);
00087 }
00088 
00089 } // end namespace Detail
00090 
00091 
00092 double
00093 FrobeniusNormCriterion::fitness(const Epetra_SerialSymDenseMatrix &discrepancy) const {
00094   return normalizedFrobeniusNorm(discrepancy);
00095 }
00096 
00097 double
00098 FrobeniusNormCriterion::partialFitness(const Epetra_SerialSymDenseMatrix &discrepancy, int contributionCount) const {
00099   return normalizedFrobeniusNorm(discrepancy);
00100 }
00101 
00102 double FrobeniusNormCriterion::normalizedFrobeniusNorm(const Epetra_SerialSymDenseMatrix &discrepancy) {
00103   return Detail::frobeniusNorm(discrepancy) / std::sqrt(static_cast<double>(discrepancy.N()));
00104 }
00105 
00106 
00107 TwoNormCriterion::TwoNormCriterion(int eigenRankStride) :
00108   eigenRankStride_(eigenRankStride)
00109 {}
00110 
00111 double
00112 TwoNormCriterion::fitness(const Epetra_SerialSymDenseMatrix &discrepancy) const {
00113   return -Detail::smallestEigenvalue(discrepancy);
00114 }
00115 
00116 double
00117 TwoNormCriterion::partialFitness(const Epetra_SerialSymDenseMatrix &discrepancy, int contributionCount) const {
00118   const int eigenRank = std::min(discrepancy.N(), contributionCount * eigenRankStride_);
00119   return -Detail::selectedEigenvalue(discrepancy, discrepancy.N() - eigenRank);
00120 }
00121 
00122 } // end namespace MOR

Generated on Wed Mar 26 2014 18:36:40 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1