void EigenProblemsTest::testGeev1() { std::cout << "--> Test: geev1." <<std::endl; // Compute only right eigenvectors. complex_matrix fake(1,1), rightV(size,size); complex_vector eigenval(size); Siconos::eigenproblems::geev(*A, eigenval, fake, rightV); complex_vector error(size); for( unsigned int i = 0; i < size; ++i ) error(i) = 0.0; for( unsigned int i = 0; i < size; ++i ) { error.plus_assign(ublas::prod(*A->dense(), column(rightV, i) )); error.minus_assign(eigenval(i)*column(rightV,i)); } // Check ... CPPUNIT_ASSERT_EQUAL_MESSAGE("testGeev1 1: ", norm_2(error) < 10 * std::numeric_limits< double >::epsilon() , true); // Check if A has not been modified CPPUNIT_ASSERT_EQUAL_MESSAGE("testGeev1 2: ", (*A) == (*Aref) , true); // Now compute only eigenvalues complex_vector RefEigenValues(size); RefEigenValues = eigenval; eigenval *= 0.0; Siconos::eigenproblems::geev(*A, eigenval, fake, fake, false, false); CPPUNIT_ASSERT_EQUAL_MESSAGE("testGeev1 3: ", norm_2(eigenval - RefEigenValues) < 10 * std::numeric_limits< double >::epsilon() , true); CPPUNIT_ASSERT_EQUAL_MESSAGE("testGeev1 4: ", (*A) == (*Aref) , true); std::cout << "--> geev1 test ended with success." <<std::endl; }
void EigenProblemsTest::testGeev3() { std::cout << "--> Test: geev3." <<std::endl; // Compute left and right eigenvectors. complex_matrix leftV(size,size), rightV(size,size); complex_vector eigenval(size); Siconos::eigenproblems::geev(*A, eigenval, leftV, rightV, true, true); complex_vector error(size); for( unsigned int i = 0; i < size; ++i ) error(i) = 0.0; for( unsigned int i = 0; i < size; ++i ) { error.plus_assign(ublas::prod(*A->dense(), column(rightV, i) )); error.minus_assign(eigenval(i)*column(rightV,i)); error.plus_assign(ublas::prod(conj(column(leftV, i)), *A->dense() )); error.minus_assign(eigenval(i)*conj(column(leftV,i))); } std::cout << norm_2(error) << std::endl; // Check ... CPPUNIT_ASSERT_EQUAL_MESSAGE("testGeev3 1: ", norm_2(error) < size * 10 * std::numeric_limits< double >::epsilon() , true); // Check if A has not been modified CPPUNIT_ASSERT_EQUAL_MESSAGE("testGeev3 2: ", (*A) == (*Aref) , true); std::cout << "--> geev3 test ended with success." <<std::endl; }
//------------------------------------------------------------------------------ void MfLowRankApproximation::integrate(const int q, const int r, const cx_mat &C, cx_vec &V2) { Vm.zeros(); V2.zeros(); for(int m=0; m<M; m++) { for(int j=0; j<nGrid; j++) { Vm(m) += std::conj(C(j,q))*U(j,m)*C(j,r); } } for(int i=0; i<nGrid; i++) { for(int m=0; m<M; m++) { V2(i) += eigenval(m)*U(i,m)*Vm(m); } } }
// eigen-decomposition of a symmetric matrix void Matrix::eig(Matrix& U, Matrix& lambda, unsigned int iter, bool ignoreError) const { ASSERT(isValid() && isSquare()); Matrix basic = *this; Matrix eigenval(m_rows); // 1-dim case if (m_rows == 1) { basic(0, 0) = 1.0; eigenval(0) = m_data[0]; return; } std::vector<double> oD(m_rows); unsigned int i, j, k, l, m; double b, c, f, g, h, hh, p, r, s, scale; // reduction to tridiagonal form for (i=m_rows; i-- > 1;) { h = 0.0; scale = 0.0; if (i > 1) for (k = 0; k < i; k++) scale += fabs(basic(i, k)); if (scale == 0.0) oD[i] = basic(i, i-1); else { for (k = 0; k < i; k++) { basic(i, k) /= scale; h += basic(i, k) * basic(i, k); } f = basic(i, i-1); g = (f > 0.0) ? -::sqrt(h) : ::sqrt(h); oD[i] = scale * g; h -= f * g; basic(i, i-1) = f - g; f = 0.0; for (j = 0; j < i; j++) { basic(j, i) = basic(i, j) / (scale * h); g = 0.0; for (k=0; k <= j; k++) g += basic(j, k) * basic(i, k); for (k=j+1; k < i; k++) g += basic(k, j) * basic(i, k); f += (oD[j] = g / h) * basic(i, j); } hh = f / (2.0 * h); for (j=0; j < i; j++) { f = basic(i, j); g = oD[j] - hh * f; oD[j] = g; for (k=0; k <= j; k++) basic(j, k) -= f * oD[k] + g * basic(i, k); } for (k=i; k--;) basic(i, k) *= scale; } eigenval(i) = h; } eigenval(0) = oD[0] = 0.0; // accumulation of transformation matrices for (i=0; i < m_rows; i++) { if (eigenval(i) != 0.0) { for (j=0; j < i; j++) { g = 0.0; for (k = 0; k < i; k++) g += basic(i, k) * basic(k, j); for (k = 0; k < i; k++) basic(k, j) -= g * basic(k, i); } } eigenval(i) = basic(i, i); basic(i, i) = 1.0; for (j=0; j < i; j++) basic(i, j) = basic(j, i) = 0.0; } // eigenvalues from tridiagonal form for (i=1; i < m_rows; i++) oD[i-1] = oD[i]; oD[m_rows - 1] = 0.0; for (l=0; l < m_rows; l++) { j = 0; do { // look for small sub-diagonal element for (m=l; m < m_rows - 1; m++) { s = fabs(eigenval(m)) + fabs(eigenval(m + 1)); if (fabs(oD[m]) + s == s) break; } p = eigenval(l); if (m != l) { if (j++ == iter) { // Too many iterations --> numerical instability! if (ignoreError) break; else throw("[Matrix::eig] numerical problems"); } // form shift g = (eigenval(l+1) - p) / (2.0 * oD[l]); r = ::sqrt(g * g + 1.0); g = eigenval(m) - p + oD[l] / (g + ((g > 0.0) ? fabs(r) : -fabs(r))); s = 1.0; c = 1.0; p = 0.0; for (i=m; i-- > l;) { f = s * oD[i]; b = c * oD[i]; if (fabs(f) >= fabs(g)) { c = g / f; r = ::sqrt(c * c + 1.0); oD[i+1] = f * r; s = 1.0 / r; c *= s; } else { s = f / g; r = ::sqrt(s * s + 1.0); oD[i+1] = g * r; c = 1.0 / r; s *= c; } g = eigenval(i+1) - p; r = (eigenval(i) - g) * s + 2.0 * c * b; p = s * r; eigenval(i+1) = g + p; g = c * r - b; for (k=0; k < m_rows; k++) { f = basic(k, i+1); basic(k, i+1) = s * basic(k, i) + c * f; basic(k, i) = c * basic(k, i) - s * f; } } eigenval(l) -= p; oD[l] = g; oD[m] = 0.0; } } while (m != l); } // normalize eigenvectors for (j=m_rows; j--;) { s = 0.0; for (i=m_rows; i--;) s += basic(i, j) * basic(i, j); s = ::sqrt(s); for (i=m_rows; i--;) basic(i, j) /= s; } // sort by eigenvalues std::vector<unsigned int> index(m_rows); for (i=0; i<m_rows; i++) index[i] = i; CmpIndex cmpidx(eigenval, index); std::sort(index.begin(), index.end(), cmpidx); U.resize(m_rows, m_rows); lambda.resize(m_rows); for (i=0; i<m_rows; i++) { j = index[i]; lambda(i) = eigenval(j); for (k=0; k<m_rows; k++) U(k, i) = basic(k, j); } }
//------------------------------------------------------------------------------ void MfLowRankApproximation::initialize() { double dx; double constValue; double endValue; double constEnd; double epsilon; dx = grid.DX; try { nOrbitals = cfg->lookup("spatialDiscretization.nSpatialOrbitals"); constEnd = cfg->lookup("meanFieldIntegrator.lowRankApproximation.constEnd"); constValue = cfg->lookup("meanFieldIntegrator.lowRankApproximation.constValue"); endValue = cfg->lookup("meanFieldIntegrator.lowRankApproximation.endValue"); epsilon = cfg->lookup("meanFieldIntegrator.lowRankApproximation.epsilon"); } catch (const SettingNotFoundException &nfex) { cerr << "MfLowRankApproximation::Error reading entry from config object." << endl; exit(EXIT_FAILURE); } int nConst = constEnd/dx; int constCenter = nGrid/2; Vxy = zeros(nGrid, nGrid); for(uint p=0; p<potential.size(); p++) { for(int i=0; i<nGrid; i++) { for(int j=0; j<nGrid; j++) { Vxy(i, j) += potential[p]->evaluate(i, j); } } } // Using a simple discretization equal to the discretization of // the system. mat h = hExactSpatial(); // mat h = hPiecewiseLinear(); mat Q = eye(nGrid,nGrid); // Using a consant weight in the center of the potential // and a linear decrease from the center. vec g = gLinear(nGrid, constCenter, nConst, constValue, endValue); mat C = cMatrix(g, h, dx); vec lambda; mat eigvec; eig_sym(lambda, eigvec, inv(C.t())*Vxy*inv(C)); mat Ut = C.t()*eigvec; mat QU = inv(Q)*Ut; // Sorting the eigenvalues by absoulte value and finding the number // of eigenvalues with abs(eigenval(i)) > epsilon uvec indices = sort_index(abs(lambda), 1); M = -1; for(uint m=0; m <lambda.n_rows; m++) { cout << abs(lambda(indices(m))) << endl; if(abs(lambda(indices(m))) < epsilon) { M = m; break; } } // cout << min(abs(lambda)) << endl; // cout << "hei" << endl; // cout << lambda << endl; // M = 63; if(M < 0) { cerr << "MfLowRankApproximation:: no eigenvalues < epsilon found." << " Try setting epsilon to a higher number" << endl; exit(EXIT_FAILURE); } eigenval = zeros(M); for(int m=0; m <M; m++) { eigenval(m) = lambda(indices(m)); } // Calculating the U matrix U = zeros(nGrid, M); for(int m=0; m < M; m++) { for(uint j=0; j<h.n_rows; j++) { U(j,m) = 0; for(uint i=0; i<h.n_cols; i++) { U(j,m) += h(j,i)*QU(i,indices(m)); } } } cout << "MfLowRankApproximation:: Trunction of eigenvalues at M = " << M << endl; #if 1 // For testing the low rank approximation's accuracy mat appV = zeros(nGrid, nGrid); for(int i=0; i<nGrid; i++) { for(int j=0; j<nGrid; j++) { appV(i,j) = 0; for(int m=0; m<M; m++) { appV(i,j) += eigenval(m)*U(i,m)*U(j,m); } } } mat diffV = abs(Vxy - appV); cout << "max_err = " << max(max(abs(Vxy - appV))) << endl; diffV.save("../DATA/diffV.mat"); appV.save("../DATA/Vapp.mat"); Vxy.save("../DATA/Vex.mat"); cout << nGrid << endl; // exit(EXIT_SUCCESS); #endif cout << "test" << endl; Vm = zeros<cx_vec>(M); Vqr = zeros<cx_vec>(nGrid); }