void EigsGen::findMatchedIndex(const Eigen::VectorXcd &target, const Eigen::VectorXcd &collection, Eigen::VectorXi &result) { int nfound = 0; int maxn = target.size(); if(result.size() < maxn) result.resize(maxn); for(int i = 0; i < collection.size(); i++) { int j; for(j = 0; j < maxn; j++) { if(abs(collection[i] - target[j]) < 1e-8 * abs(target[j])) break; } if(j < maxn) { result[nfound] = i; nfound++; if(collection[i].imag() != 0) { i++; result[nfound] = i; nfound++; } } if(nfound >= maxn) break; } if(result.size() > nfound) result.conservativeResize(nfound); }
//Main-Function int main () { double xiMax = 10; double xiMin = -10; double deltaXi = 0.1; double deltaT = 0.05; double mittelWert = 0, mittelWert2 = 0; double impuls = 0, impuls2 = 0; int cn = floor(10./deltaT+0.5); int iN = 0; std::complex<double> c_i = (0,1); Eigen::MatrixXcd Sh = S_H(deltaT, &H, deltaXi, xiMax, xiMin); Eigen::VectorXcd xi = init(xiMax, xiMin, deltaXi); Eigen::VectorXcd xi_n = xi; Eigen::VectorXcd xi_temp; //Dateistreams für geforderte Ausgabe-Plots std::ofstream datei("A1d_Normierung.dat"); std::ofstream datei2("A1f.dat"); //Anwenden des Zeitentwicklungsoperators bis t=10 for (int i = 0; i < cn; i++) { xi_n = Sh*xi_n; datei << i*deltaT << " " << Norm(xi_n) << std::endl; //Animationssequenz //if (i%2 == 0) { // SchreibeZustand(xi_n, "A1d_Animation_"+convertInt(i/2)); //} //Mittelwert des Ortes und des Impulses for (int j = 0; j < xi.size(); j++) { iN = j - floor(xi.size()/2); mittelWert += iN*deltaXi*abs(xi_n(j))*abs(xi_n(j)); mittelWert2 += (iN*deltaXi)*(iN*deltaXi)*abs(xi_n(j))*abs(xi_n(j)); impuls += abs(xi_n(j)*(-c_i)*Ableitung(xi_n, j, deltaXi)); impuls2 += abs(xi_n(j)*(-1.)*Ableitung2(xi_n, j, deltaXi)); } datei2 << i*deltaT << " " << mittelWert << " " << (mittelWert2 - mittelWert*mittelWert) << " " << impuls << " " << impuls2 << std::endl; mittelWert = 0; mittelWert2 = 0; impuls = 0; impuls2 = 0; } datei.close(); datei2.close(); SchreibeZustand(xi_n, "A1d_Zustand"); return 0; }
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- void LapH::OperatorsForMesons::build_vdaggerv(const std::string& filename) { clock_t t2 = clock(); const size_t dim_row = 3*Lx*Ly*Lz; const size_t id_unity = operator_lookuptable.index_of_unity; // resizing each matrix in vdaggerv // TODO: check if it is better to use for_each and resize instead of std::fill std::fill(vdaggerv.origin(), vdaggerv.origin() + vdaggerv.num_elements(), Eigen::MatrixXcd::Zero(nb_ev, nb_ev)); #pragma omp parallel { Eigen::VectorXcd mom = Eigen::VectorXcd::Zero(dim_row); LapH::EigenVector V_t(1, dim_row, nb_ev);// each thread needs its own copy #pragma omp for schedule(dynamic) for(size_t t = 0; t < Lt; ++t){ // creating full filename for eigenvectors and reading them in char inter_name[200]; sprintf(inter_name, "%s%03d", filename.c_str(), (int) t); //avoid reading eigenvectors for now, since no displacement or momentum is //used //V_t.read_eigen_vector(inter_name, 0, 0); // reading eigenvectors // VdaggerV is independent of the gamma structure and momenta connected by // sign flip are related by adjoining VdaggerV. Thus the expensive // calculation must only be performed for a subset of quantum numbers given // in op_VdaggerV. for(const auto& op : operator_lookuptable.vdaggerv_lookup){ // For zero momentum and displacement VdaggerV is the unit matrix, thus // the calculation is not performed if(op.id != id_unity){ // momentum vector contains exp(-i p x). Divisor 3 for colour index. // All three colours on same lattice site get the same momentum. for(size_t x = 0; x < dim_row; ++x) { mom(x) = momentum[op.id][x/3]; } vdaggerv[op.id][t] = V_t[0].adjoint() * mom.asDiagonal() * V_t[0]; } else // zero momentum vdaggerv[op.id][t] = Eigen::MatrixXcd::Identity(nb_ev, nb_ev); } } // loop over time }// pragma omp parallel ends here t2 = clock() - t2; std::cout << std::setprecision(1) << "\t\t\tSUCCESS - " << std::fixed << ((float) t2)/CLOCKS_PER_SEC << " seconds" << std::endl; is_vdaggerv_set = true; }
//Norm eines Zustands double Norm(Eigen::VectorXcd xi) { double summe = 0; int n_max = xi.size(); for (int i = 0; i < n_max; i++) { summe += abs(xi(i))*abs(xi(i)); } return summe; }
//Zustandsvektor in Datei schreiben void SchreibeZustand(Eigen::VectorXcd xi, std::string name) { int n_max = xi.size(); std::ofstream datei(name + ".dat"); for (int i = 0; i < n_max; i++) { datei << (i - floor(n_max/2)) << " " << abs(xi(i))*abs(xi(i)) << std::endl; } datei.close(); }
// Calculates U_mu^dagger(x-\hat{mu})V(x-\hat{\mu}) Eigen::MatrixXcd GaugeField::backward_uv(const Eigen::VectorXcd &v, const ssize_t t, const int spatial_ind, const int direction) const { int down_ind = idown[spatial_ind][direction]; return (tslices.at(t))[down_ind][direction].adjoint() * v.segment(3 * down_ind, 3); }
// Calculates U_mu(x)V(x+\hat{\mu}) Eigen::MatrixXcd GaugeField::forward_uv(const Eigen::VectorXcd &v, const ssize_t t, const int spatial_ind, const int direction) const { int up_ind = iup[spatial_ind][direction]; return (tslices.at(t))[spatial_ind][direction] * v.segment(3 * up_ind, 3); }
//Ableitung der Wellenfunktion an der Stelle n std::complex<double> Ableitung(Eigen::VectorXcd xi, int n, double deltaXi) { int laenge = xi.size(); if (n == 0) { return (xi(1)-xi(0))/(deltaXi); } else if (n == (laenge-1)) { return (xi(laenge-1) - xi(laenge-2))/(deltaXi); } else { return (xi(n+1)-xi(n-1))/(2.*deltaXi); } }
unsigned int Model::check_feedback_matrix(Eigen::MatrixXd &S) { Eigen::VectorXcd eigenvalues = S.eigenvalues(); Eigen::VectorXd real = eigenvalues.real(); Eigen::VectorXd imag = eigenvalues.imag(); double magnitude, max_magnitude = 0; for (unsigned int i = 0; i < n_alternatives; i++) { magnitude = sqrt(real(i) * real(i) + imag(i) * imag(i)); if (magnitude > max_magnitude) { max_magnitude = magnitude; } } // unsigned int res = 1; unsigned int res = 0; if (max_magnitude < 1) { res = 0; } return res; }
// partial reorthogonalization double EigenTriangle::solve(int maxIter, double tol) { int n = graph -> VertexCount(); srand(time(0)); if (maxIter > n) maxIter = n; double na = adjMatrix.norm(); double phi = tol * na; double delta = tol * sqrt(na); vector<Triplet<double> > omega_vector; //MatrixXd omega = MatrixXd::Zero(n + 2, n + 2); for (int i = 0; i < n + 2; i ++) { //omega(i, i - 1) = phi; if (i > 0) omega_vector.push_back(Triplet<double>(i, i - 1, phi)); omega_vector.push_back(Triplet<double>(i, i, 1)); } omega.resize(n + 2, n + 2); omega.setFromTriplets(omega_vector.begin(), omega_vector.end()); //std::cout << omega << std::endl; vector<SparseVector<double> > v; //v.push_back(SparseVector::Random(n)); SparseVector<double> firstV(n); for (int i = 0; i < 100; i ++) firstV.coeffRef(i % n) = i; v.push_back(firstV); v[0] /= v[0].norm(); VectorXd alpha(n); VectorXd beta(n + 1); beta[0] = 0; SparseVector<double> w; bool flag = false; int num = 0; // reorthogonalization times int last = -1; for (int i = 0; i < maxIter; i ++) { if ((i + 1) * 100 / maxIter > last) { last = (i + 1) * 100 / maxIter; std::cout << "\r" << "[EigenTriangle] Processing " << last << "% ..." << std::flush; } //printf("== Iter %d ===\n", i); w = adjMatrix * v[i]; alpha.coeffRef(i) = w.dot(v[i]); if (i == maxIter - 1) break; w -= alpha[i] * v[i]; if (i > 0) w -= beta[i] * v[i - 1]; beta[i + 1] = w.norm(); v.push_back(w / beta[i + 1]); if (flag) { flag = false; for (int j = 0; j <= i; j ++) v[i + 1] -= v[j].dot(v[i + 1]) * v[j]; for (int j = 0; j <= i; j ++) omega.coeffRef(i + 1, j) = phi; //for (int j = 0; j <= i; j ++) // printf("%.5lf\n", v[i + 1].dot(v[j])); } else { omega.coeffRef(i + 1, 0) = 0.0; if (i > 0) { omega.coeffRef(i + 1, 0) = 1.0 / beta(i) * ((alpha(0) - alpha(i)) * omega.coeffRef(i, 0) - beta(i - 1) * omega.coeffRef(i - 1, 0)) + delta; } for (int j = 1; j <= i; j ++) { omega.coeffRef(i + 1, j) = 1.0 / beta(i) * (beta(j) * omega.coeffRef(i, j + 1) + (alpha(j) - alpha(i)) * omega.coeffRef(i, j) - beta(j - 1) * omega.coeffRef(i, j - 1) - beta(i - 1) * omega.coeffRef(i - 1, j)) + delta; } } double mx = 0.0; for (int j = 0; j <= i; j ++) if (mx < fabs(omega.coeffRef(i + 1, j))) mx = fabs(omega.coeffRef(i + 1, j)); if (mx > sqrt(tol)) { for (int j = 0; j <= i; j ++) omega.coeffRef(i + 1, j) = phi; num ++; for (int j = 0; j <= i; j ++) v[i + 1] -= v[i + 1].dot(v[j]) * v[j]; flag = true; } } printf("\n"); int k = maxIter; MatrixXd T = MatrixXd::Zero(k, k); for (int i = 0; i < k; i ++) { T(i, i) = alpha[i]; if (i < k - 1) T(i, i + 1) = beta[i + 1]; if (i > 0) T(i, i - 1) = beta[i]; } //std::cout << T << std::endl; Eigen::EigenSolver<MatrixXd> eigenSolver; eigenSolver.compute(T, false); Eigen::VectorXcd eigens = eigenSolver.eigenvalues(); double res = 0; for (int i = 0; i < eigens.size(); i ++) { std::complex<double> tmp = eigens[i]; res += pow(tmp.real(), 3) / 6; std::cout << i << ": " << tmp << std::endl; } //res /= 6; return res; }
// full reorthogonalization double EigenTriangle::solve(int maxIter) { int n = graph -> VertexCount(); srand(time(0)); // check if rows == cols() if (maxIter > n) maxIter = n; vector<VectorXd> v; v.push_back(VectorXd::Random(n)); v[0] = v[0] / v[0].norm(); VectorXd alpha(n); VectorXd beta(n + 1); beta[0] = 0; VectorXd w; int last = 0; printf("%d\n", maxIter); for (int i = 0; i < maxIter; i ++) { if (i * 100 / maxIter > last + 10 || i == maxIter - 1) { last = (i + 1) * 100 / maxIter; std::cout << "\r" << "[EigenTriangle] Processing " << last << "% ..." << std::flush; } w = adjMatrix * v[i]; alpha[i] = w.dot(v[i]); if (i == maxIter - 1) break; w -= alpha[i] * v[i]; if (i > 0) w -= beta[i] * v[i - 1]; beta[i + 1] = w.norm(); v.push_back(w / beta[i + 1]); for (int j = 0; j <= i; j ++) { v[i + 1] = v[i + 1] - v[i + 1].dot(v[j]) * v[j]; } } printf("\n"); int k = maxIter; MatrixXd T = MatrixXd::Zero(k, k); for (int i = 0; i < k; i ++) { T(i, i) = alpha[i]; if (i < k - 1) T(i, i + 1) = beta[i + 1]; if (i > 0) T(i, i - 1) = beta[i]; } //std::cout << T << std::endl; Eigen::EigenSolver<MatrixXd> eigenSolver; eigenSolver.compute(T, /* computeEigenvectors = */ false); Eigen::VectorXcd eigens = eigenSolver.eigenvalues(); double res = 0; for (int i = 0; i < eigens.size(); i ++) { std::complex<double> tmp = eigens[i]; res += pow(tmp.real(), 3); printf("%.5lf\n", tmp.real()); } res /= 6; return res; }
inline int size_zeta() const { return zeta_iz.rows(); }
void propa_2d() { trace.beginBlock("2d propagation"); typedef DiscreteExteriorCalculus<2, 2, EigenLinearAlgebraBackend> Calculus; typedef DiscreteExteriorCalculusFactory<EigenLinearAlgebraBackend> CalculusFactory; { trace.beginBlock("solving time dependent equation"); const Calculus::Scalar cc = 8; // px/s trace.info() << "cc = " << cc << endl; const Z2i::Domain domain(Z2i::Point(0,0), Z2i::Point(29,29)); const Calculus calculus = CalculusFactory::createFromDigitalSet(generateDiskSet(domain), false); //! [time_laplace] const Calculus::DualIdentity0 laplace = calculus.laplace<DUAL>() + 1e-8 * calculus.identity<0, DUAL>(); //! [time_laplace] trace.info() << "laplace = " << laplace << endl; trace.beginBlock("finding eigen pairs"); //! [time_eigen] typedef Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> EigenSolverMatrix; const EigenSolverMatrix eigen_solver(laplace.myContainer); const Eigen::VectorXd eigen_values = eigen_solver.eigenvalues(); const Eigen::MatrixXd eigen_vectors = eigen_solver.eigenvectors(); //! [time_eigen] trace.info() << "eigen_values_range = " << eigen_values.minCoeff() << "/" << eigen_values.maxCoeff() << endl; trace.endBlock(); //! [time_omega] const Eigen::VectorXd angular_frequencies = cc * eigen_values.array().sqrt(); //! [time_omega] Eigen::VectorXcd initial_wave = Eigen::VectorXcd::Zero(calculus.kFormLength(0, DUAL)); //set_initial_phase_null(calculus, initial_wave); set_initial_phase_dir_yy(calculus, initial_wave); { Board2D board; board << domain; board << CustomStyle("KForm", new KFormStyle2D(-1, 1)); board << Calculus::DualForm0(calculus, initial_wave.real()); board.saveSVG("propagation_time_wave_initial_coarse.svg"); } //! [time_init_proj] Eigen::VectorXcd initial_projections = eigen_vectors.transpose() * initial_wave; //! [time_init_proj] // low pass //! [time_low_pass] const Calculus::Scalar lambda_cutoff = 4.5; const Calculus::Scalar angular_frequency_cutoff = 2*M_PI * cc / lambda_cutoff; int cutted = 0; for (int kk=0; kk<initial_projections.rows(); kk++) { const Calculus::Scalar angular_frequency = angular_frequencies(kk); if (angular_frequency < angular_frequency_cutoff) continue; initial_projections(kk) = 0; cutted ++; } //! [time_low_pass] trace.info() << "cutted = " << cutted << "/" << initial_projections.rows() << endl; { const Eigen::VectorXcd wave = eigen_vectors * initial_projections; Board2D board; board << domain; board << CustomStyle("KForm", new KFormStyle2D(-1, 1)); board << Calculus::DualForm0(calculus, wave.real()); board.saveSVG("propagation_time_wave_initial_smoothed.svg"); } const int kk_max = 60; trace.progressBar(0,kk_max); for (int kk=0; kk<kk_max; kk++) { //! [time_solve_time] const Calculus::Scalar time = kk/20.; const Eigen::VectorXcd current_projections = (angular_frequencies * std::complex<double>(0,time)).array().exp() * initial_projections.array(); const Eigen::VectorXcd current_wave = eigen_vectors * current_projections; //! [time_solve_time] std::stringstream ss; ss << "propagation_time_wave_solution_" << std::setfill('0') << std::setw(3) << kk << ".svg"; Board2D board; board << domain; board << CustomStyle("KForm", new KFormStyle2D(-1, 1)); board << Calculus::DualForm0(calculus, current_wave.real()); board.saveSVG(ss.str().c_str()); trace.progressBar(kk+1,kk_max); } trace.info() << endl; trace.endBlock(); } { trace.beginBlock("forced oscillations"); const Z2i::Domain domain(Z2i::Point(0,0), Z2i::Point(50,50)); const Calculus calculus = CalculusFactory::createFromDigitalSet(generateDiskSet(domain), false); const Calculus::DualIdentity0 laplace = calculus.laplace<DUAL>(); trace.info() << "laplace = " << laplace << endl; trace.beginBlock("finding eigen pairs"); typedef Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> EigenSolverMatrix; const EigenSolverMatrix eigen_solver(laplace.myContainer); const Eigen::VectorXd laplace_eigen_values = eigen_solver.eigenvalues(); const Eigen::MatrixXd laplace_eigen_vectors = eigen_solver.eigenvectors(); trace.info() << "eigen_values_range = " << laplace_eigen_values.minCoeff() << "/" << laplace_eigen_values.maxCoeff() << endl; trace.endBlock(); Calculus::DualForm0 concentration(calculus); { const Z2i::Point point(25,25); const Calculus::Cell cell = calculus.myKSpace.uSpel(point); const Calculus::Index index = calculus.getCellIndex(cell); concentration.myContainer(index) = 1; } { Board2D board; board << domain; board << concentration; board.saveSVG("propagation_forced_concentration.svg"); } for (int ll=0; ll<6; ll++) { //! [forced_lambda] const Calculus::Scalar lambda = 4*20.75/(1+2*ll); //! [forced_lambda] trace.info() << "lambda = " << lambda << endl; //! [forced_dalembert_eigen] const Eigen::VectorXd dalembert_eigen_values = (laplace_eigen_values.array() - (2*M_PI/lambda)*(2*M_PI/lambda)).array().inverse(); const Eigen::MatrixXd concentration_to_wave = laplace_eigen_vectors * dalembert_eigen_values.asDiagonal() * laplace_eigen_vectors.transpose(); //! [forced_dalembert_eigen] //! [forced_wave] Calculus::DualForm0 wave(calculus, concentration_to_wave * concentration.myContainer); //! [forced_wave] wave.myContainer /= wave.myContainer(calculus.getCellIndex(calculus.myKSpace.uSpel(Z2i::Point(25,25)))); { trace.info() << "saving samples" << endl; const Calculus::Properties properties = calculus.getProperties(); { std::stringstream ss; ss << "propagation_forced_samples_hv_" << ll << ".dat"; std::ofstream handle(ss.str().c_str()); for (int kk=0; kk<=50; kk++) { const Z2i::Point point_horizontal(kk,25); const Z2i::Point point_vertical(25,kk); const Calculus::Scalar xx = 2 * (kk/50. - .5); handle << xx << " "; handle << sample_dual_0_form<Calculus>(properties, wave, point_horizontal) << " "; handle << sample_dual_0_form<Calculus>(properties, wave, point_vertical) << endl; } } { std::stringstream ss; ss << "propagation_forced_samples_diag_" << ll << ".dat"; std::ofstream handle(ss.str().c_str()); for (int kk=0; kk<=50; kk++) { const Z2i::Point point_diag_pos(kk,kk); const Z2i::Point point_diag_neg(kk,50-kk); const Calculus::Scalar xx = 2 * sqrt(2) * (kk/50. - .5); handle << xx << " "; handle << sample_dual_0_form<Calculus>(properties, wave, point_diag_pos) << " "; handle << sample_dual_0_form<Calculus>(properties, wave, point_diag_neg) << endl; } } } { std::stringstream ss; ss << "propagation_forced_wave_" << ll << ".svg"; Board2D board; board << domain; board << CustomStyle("KForm", new KFormStyle2D(-.5, 1)); board << wave; board.saveSVG(ss.str().c_str()); } } trace.endBlock(); } trace.endBlock(); }
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- void LapH::OperatorsForMesons::build_vdaggerv(const std::string& filename, const int config) { clock_t t2 = clock(); const size_t dim_row = 3*Lx*Ly*Lz; const int id_unity = operator_lookuptable.index_of_unity; // prepare full path for writing char dummy_path[200]; sprintf(dummy_path, "/%s/cnfg%04d/", path_vdaggerv.c_str(), config); const std::string full_path(dummy_path); // check if directory exists if(handling_vdaggerv == "write" && access(full_path.c_str(), 0 ) != 0) { std::cout << "\tdirectory " << full_path.c_str() << " does not exist and will be created"; boost::filesystem::path dir(full_path.c_str()); if(!boost::filesystem::create_directories(dir)) std::cout << "\tSuccess" << std::endl; else std::cout << "\tFailure" << std::endl; } // resizing each matrix in vdaggerv // TODO: check if it is better to use for_each and resize instead of std::fill std::fill(vdaggerv.origin(), vdaggerv.origin() + vdaggerv.num_elements(), Eigen::MatrixXcd::Zero(nb_ev, nb_ev)); #pragma omp parallel { Eigen::VectorXcd mom = Eigen::VectorXcd::Zero(dim_row); LapH::EigenVector V_t(1, dim_row, nb_ev);// each thread needs its own copy #pragma omp for schedule(dynamic) for(size_t t = 0; t < Lt; ++t){ // creating full filename for eigenvectors and reading them in if(!(operator_lookuptable.vdaggerv_lookup.size() == 1 && operator_lookuptable.vdaggerv_lookup[0].id == id_unity)){ char inter_name[200]; sprintf(inter_name, "%s%03d", filename.c_str(), (int) t); V_t.read_eigen_vector(inter_name, 0, 0); // reading eigenvectors } // VdaggerV is independent of the gamma structure and momenta connected by // sign flip are related by adjoining VdaggerV. Thus the expensive // calculation must only be performed for a subset of quantum numbers given // in op_VdaggerV. for(const auto& op : operator_lookuptable.vdaggerv_lookup){ // For zero momentum and displacement VdaggerV is the unit matrix, thus // the calculation is not performed if(op.id != id_unity){ // momentum vector contains exp(-i p x). Divisor 3 for colour index. // All three colours on same lattice site get the same momentum. for(size_t x = 0; x < dim_row; ++x) { mom(x) = momentum[op.id][x/3]; } vdaggerv[op.id][t] = V_t[0].adjoint() * mom.asDiagonal() * V_t[0]; // writing vdaggerv to disk if(handling_vdaggerv == "write"){ char dummy2[200]; sprintf(dummy2, "operators.%04d.p_", config); std::string dummy = std::string(dummy2) + std::to_string(op.momentum[0]) + std::to_string(op.momentum[1]) + std::to_string(op.momentum[2]); char outfile[200]; sprintf(outfile, "%s_.t_%03d", dummy.c_str(), (int) t); write_vdaggerv(full_path, std::string(outfile), vdaggerv[op.id][t]); } } else // zero momentum vdaggerv[op.id][t] = Eigen::MatrixXcd::Identity(nb_ev, nb_ev); } } // loop over time }// pragma omp parallel ends here t2 = clock() - t2; std::cout << std::setprecision(1) << "\t\t\tSUCCESS - " << std::fixed << ((float) t2)/CLOCKS_PER_SEC << " seconds" << std::endl; is_vdaggerv_set = true; }