Untitled
Anonymous
plain_text
02/20/2026 5:17 AM
13.6 KB
10
Indexable
//#include "/home/lipegal/Documents/OIST/code/Modular/kp_lib.h"
#include "/flash/BuschU/andres/Transfer_protocol/kp_lib.h"
#include <vector>
#include <functional>
#include <iostream>
#include <fstream>
#include <cmath>
#include <boost/numeric/odeint.hpp>
using namespace boost::numeric::odeint;
using namespace std;
int in_trunc_dim = 1600;
double d_tol = 1e-7;
using HamKernel = std::function<double(int, int)>;
// ------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------
// Diagonalize hamiltonian with given parameters and store data
Ham_data H_diag_spec (const std::function<double(int, int)>& H, int trunc_d_init, const double tol_overlap, const int num_comp) {
int trunc_d = trunc_d_init, last_trunc_d = 0;
std::vector<double> converged_eigvals, current_eigvals;
std::vector<double> last_eigvecs;
std::vector<double> A; // Flattened hamiltonian matrix
bool converged = false;
// Check for convergence in diagonalization
while (!converged) {
A.resize (trunc_d * trunc_d);
current_eigvals.resize(trunc_d);
// Flatten Hamiltonian matrix
for(int n = 0; n < trunc_d; n++) {
for(int m = 0; m < trunc_d; m++) {
A [n * trunc_d + m] = H (n + 1,m + 1);
// There is a distintion between physical (n,m) and array index
}
}
// Define working variables
int n = trunc_d, lda = trunc_d, info, lwork = -1;
double work_test;
char jobz = 'V', uplo = 'U';
// Diagonalization (is not being done twice, first just assigns workspace sizes)
dsyev_(&jobz, &uplo, &n, A.data(), &lda, current_eigvals.data(), &work_test, &lwork, &info);
lwork = static_cast<int>(work_test);
std::vector<double> work_opt(lwork);
dsyev_(&jobz, &uplo, &n, A.data(), &lda, current_eigvals.data(), work_opt.data(), &lwork, &info);
//if (info != 0) {
// throw std::runtime_error("Diagonalization failed : " + std::to_string(info));
//}
// Convergence check (similar to old version)
if (last_eigvecs.empty()) {
last_eigvecs = A;
last_trunc_d = trunc_d;
trunc_d += 20;
continue; // Skip convergence check on first iteration
}
converged = true;
int max_check = std::min(num_comp, last_trunc_d);
for (int i = 0; i < max_check; i++) {
double overlap = 0.0;
// Eigenvectors are column-wise in LAPACK
for (int k = 0; k < last_trunc_d; k++) {
overlap += last_eigvecs[k + i * (last_trunc_d)]
* A[k + i * trunc_d];
}
overlap = std::abs(overlap);
//std::cout << std::setprecision(16) << std::scientific;
//std::cout << "1 - ovlp = " << 1 - overlap << endl;
if (1.0 - overlap > tol_overlap) {
converged = false;
break;
}
}
if (!converged) {
last_eigvecs = A;
last_trunc_d = trunc_d;
trunc_d += 500;
}
}
// Convert to output format
RealVector eigenvals(trunc_d);
for(int i = 0; i < trunc_d; i++) {
eigenvals(i) = current_eigvals[i];
}
ComplexVector eigenvecs(trunc_d * trunc_d);
for(int i = 0; i < trunc_d * trunc_d; i++) {
eigenvecs(i) = A[i];
}
return {eigenvals, eigenvecs, trunc_d};
}
// Derivative of Hamiltonian
double Ham_dd(int n, int m, double d_2,
const std::vector<Domain>& domains, const RealVector& offsets, double L_total) {
double sum = 0.;
double k = PI / L_total;
const Domain &d = domains[1]; // second domain
for (int i = 1; i <= d.M; i++) { // BARRIER POSITION GOES FROM 1 TO M
double ym = y_(1, i, d_2, domains, offsets, L_total) - xc + ( L_total / 2.) ;
sum += k * (n + m) * sin( k * (n + m) * ym) - k * (n - m) * sin( k * (n - m) * ym);
}
return sum * ( (d.h * d.L ) / (2 * L_total * d.M) ) ;
}
double Ham_dd_num (int n, int m, double dd,
const vector<Domain>& domains, const RealVector& offsets, double L) {
vector<Domain> domains_p = domains;
vector<Domain> domains_m = domains;
// Only vary the height parameter
domains_p[1].D += dd;
domains_m[1].D -= dd;
double Lp = syst_L(domains_p);
double Lm = syst_L(domains_m);
RealVector offsets_p = offsets_(domains_p);
RealVector offsets_m = offsets_(domains_m);
double Hp = Ham_uni(n, m, domains_p, offsets_p, Lp);
double Hm = Ham_uni(n, m, domains_m, offsets_m, Lm);
return (Hp - Hm) / (2.0 * dd);
}
// ------------------------------------------------------------------
// FAQUAD single-Delta computation
// ------------------------------------------------------------------
void d_FAQUAD(const RealVector& d_vals, int d_idx, double d_sep, double h,
int idx_1, int idx_2, ofstream& out) {
double d = d_vals(d_idx);
double E1 = 0., E2 = 0.;
Complex M_an = 0., M_num = 0.;
int doms_num = 2;
std::vector<Domain> domains;
double L_[] = {20., 20.};
int M_[] = {20, 20};
double B_[] = {10., 0.};
double W_[] = {1., 0.};
double D_[] = {0., d};
double h_[] = {h, h};
dom_load(domains, L_, M_, B_, W_, D_, h_, doms_num);
double L = syst_L(domains);
RealVector offsets = offsets_(domains);
// Construct Hamiltonian
auto H_in = [&](int n, int m) {
return Ham_uni(n, m, domains, offsets, L);
};
auto H_dh_fun_an = [&](int n, int m) {
return Ham_dd(n, m, d, domains, offsets, L);
};
auto H_dh_fun_num = [&](int n, int m) {
return Ham_dd_num(n, m, 1e-5, domains, offsets, L);
};
Ham_data h_data = H_diag_spec(H_in, 4000, 1e-06, 6000);
E1 = h_data.eigvals(idx_1);
E2 = h_data.eigvals(idx_2);
//static ComplexVector v1_prev, v2_prev;
//static bool first = true;
ComplexVector v1 = eigen_extract(h_data, idx_1);
ComplexVector v2 = eigen_extract(h_data, idx_2);
// Compute derivative matrix element M
M_an = 0.0;
M_num = 0.0;
int N = v1.size();
for (int n = 0; n < N; ++n) {
for (int m = 0; m < N; ++m) {
M_an += std::conj(v1(n)) * H_dh_fun_an(n, m) * v2(m);
M_num += std::conj(v1(n)) * H_dh_fun_num(n, m) * v2(m);
}
}
out << d << " " << E1 << " " << E2 << " "
<< real(M_an) << " " << imag(M_an) << " "
<< real(M_num) << " " << imag(M_num) << endl;
}
void d_FAQUAD_conv(const RealVector& d_vals, int d_idx, double d_sep, double h,
int idx_1, int idx_2, ofstream& out) {
double d = d_vals(d_idx);
int num_comp_local = 2000;
int step = 500;
double eps_abs = 1e-10;
double eps_rel = 1e-6;
Complex M_prev = 0.0;
Complex M_curr = 0.0;
double E1 = 0., E2 = 0.;
Complex M_an = 0., M_num = 0.;
int doms_num = 2;
std::vector<Domain> domains;
double L_[] = {20., 20.};
int M_[] = {20, 20};
double B_[] = {10., 0.};
double W_[] = {1., 0.};
double D_[] = {0., d};
double h_[] = {h, h};
dom_load(domains, L_, M_, B_, W_, D_, h_, doms_num);
double L = syst_L(domains);
RealVector offsets = offsets_(domains);
// Construct Hamiltonian
auto H_in = [&](int n, int m) {
return Ham_uni(n, m, domains, offsets, L);
};
auto H_dh_fun_an = [&](int n, int m) {
return Ham_dd(n, m, d, domains, offsets, L);
};
auto H_dh_fun_num = [&](int n, int m) {
return Ham_dd_num(n, m, 1e-5, domains, offsets, L);
};
bool first = true;
while (true) {
Ham_data h_data = H_diag_spec(H_in, in_trunc_dim, d_tol, num_comp_local);
E1 = h_data.eigvals(idx_1);
E2 = h_data.eigvals(idx_2);
//static ComplexVector v1_prev, v2_prev;
//static bool first = true;
ComplexVector v1 = eigen_extract(h_data, idx_1);
ComplexVector v2 = eigen_extract(h_data, idx_2);
// Compute derivative matrix element M
M_an = 0.0;
M_num = 0.0;
int N = v1.size();
for (int n = 0; n < N; ++n) {
for (int m = 0; m < N; ++m) {
M_an += std::conj(v1(n)) * H_dh_fun_an(n, m) * v2(m);
M_num += std::conj(v1(n)) * H_dh_fun_num(n, m) * v2(m);
}
}
cout << std::setprecision(16) << "M = " << real(M_an) << " - " << real(M_num) << endl;
if (!first) {
double diff = abs(M_an - M_prev);
double scale = max(abs(M_an), abs(M_prev));
if (diff < eps_abs || diff / scale < eps_rel) {
M_curr = M_an;
break;
}
}
M_prev = M_an;
first = false;
num_comp_local += step;
if (num_comp_local > 7000) {
cout << "WARNING: did not converge up to max num_comp\n";
M_curr = M_an;
break;
}
}
out << d << " " << E1 << " " << E2 << " "
<< real(M_curr) << " " << imag(M_curr) << " "
<< real(M_num) << " " << imag(M_num) << endl;
}
// ------------------------------------------------------------------
// Main
// ------------------------------------------------------------------
int main(int argc, char* argv[]) {
if (argc < 5) {
cerr << "Usage: ./run [d_in][d_f][d_sep][d_idx][JOB_ID]" << endl;
return 1;
}
double d_sep = stod(argv[3]);
int d_idx = stoi(argv[4]);
int job_id = stoi(argv[5]);
// -------------------- System setup ------------------------------
double d_i = stod(argv[1]), d_f = stod(argv[2]), h = 1.6;
int N_steps = static_cast<int>((d_f - d_i) / d_sep) + 1;
RealVector d_vals(N_steps);
for (int i = 0; i < N_steps; ++i)
d_vals(i) = d_i + i * d_sep;
// Output file for this specific index
string fname = "data/gen_data_" + to_string(job_id) + ".dat";
// can change job_id -> d_idx if single d per job and ios::trunc -> ios::app
ofstream gen_File(fname, ios::app);
//for(int d_idx_i = 0; d_idx_i <= N_steps; d_idx_i++) {
d_FAQUAD(d_vals, d_idx, d_sep, h, 38, 39, gen_File);
cout << " completed d = " << d_idx << endl;
//}
//cout << "FLAG: completed d_idx = " << d_idx << endl;
return 0;
}
Editor is loading...
Leave a Comment