00001
00002
00003
00004
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(), 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 NULL, NULL, &eigenRank, &eigenRank,
00052 defaultTol,
00053 &eigenValueCount, &eigenValues[0], NULL, 1 , NULL,
00054 &workQueriedSize, query, &iworkQueriedSize, 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
00062
00063 const double v_workaround = 0.0;
00064
00065 Epetra_LAPACK().SYEVR(
00066 noVectors, range, uplo,
00067 matrixSize, matrix.A(), matrix.LDA(),
00068 &v_workaround, &v_workaround, &eigenRank, &eigenRank,
00069 defaultTol,
00070 &eigenValueCount, &eigenValues[0], NULL, 1 , NULL,
00071 &work[0], 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;
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 }
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 }