Possible fully functional gradient descent code for further modification, testing.
This commit is contained in:
parent
f88ebc298d
commit
7e5aa3df23
@ -8,9 +8,9 @@ function [psi] = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ)
|
|||||||
switch this.GradientDescentMethod
|
switch this.GradientDescentMethod
|
||||||
case 'HeavyBall'
|
case 'HeavyBall'
|
||||||
% Convergence Criteria:
|
% Convergence Criteria:
|
||||||
epsilon = 1E-6;
|
alpha = 1E-6;
|
||||||
alpha = 1E-3;
|
|
||||||
beta = 0.9;
|
beta = 0.9;
|
||||||
|
epsilon = 1E-8;
|
||||||
|
|
||||||
Observ.residual = 1;
|
Observ.residual = 1;
|
||||||
Observ.res = 1;
|
Observ.res = 1;
|
||||||
@ -46,7 +46,7 @@ function [psi] = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ)
|
|||||||
|
|
||||||
% Normalize psi
|
% Normalize psi
|
||||||
Norm = inner_product(psi_new, psi_new, Transf);
|
Norm = inner_product(psi_new, psi_new, Transf);
|
||||||
psi = sqrt(Params.N) * psi_new / sqrt(Norm);
|
psi = psi_new / sqrt(Norm);
|
||||||
|
|
||||||
% Write output at specified intervals
|
% Write output at specified intervals
|
||||||
if mod(idx,100) == 0
|
if mod(idx,100) == 0
|
||||||
@ -156,7 +156,7 @@ function [psi] = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ)
|
|||||||
|
|
||||||
% Normalize psi
|
% Normalize psi
|
||||||
Norm = abs(inner_product(psi, psi, Transf));
|
Norm = abs(inner_product(psi, psi, Transf));
|
||||||
psi = sqrt(Params.N) * psi / sqrt(Norm);
|
psi = psi / sqrt(Norm);
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
|
|
||||||
% Calculate chemical potential with new psi
|
% Calculate chemical potential with new psi
|
||||||
@ -208,59 +208,67 @@ end
|
|||||||
%% Modules
|
%% Modules
|
||||||
|
|
||||||
function J = compute_gradient(psi, Params, Transf, VDk, V)
|
function J = compute_gradient(psi, Params, Transf, VDk, V)
|
||||||
|
% === Precompute quantities ===
|
||||||
|
absPsi2 = abs(psi).^2; % Density |ψ|^2
|
||||||
|
absPsi3 = abs(psi).^3; % |ψ|^3
|
||||||
|
N = Params.N;
|
||||||
|
|
||||||
% Operators
|
% === Kinetic energy operator: -∇²/2 ===
|
||||||
|
KEop = 0.5 * (Transf.KX.^2 + Transf.KY.^2 + Transf.KZ.^2);
|
||||||
% Kinetic energy
|
HKin = @(w) ifftn(KEop .* fftn(w));
|
||||||
KEop = 0.5 * (Transf.KX.^2+Transf.KY.^2+Transf.KZ.^2);
|
|
||||||
HKin = @(w) ifft(KEop.*fft(w));
|
|
||||||
|
|
||||||
% Trap Potential
|
% === External potential (already scaled by ℏω₀) ===
|
||||||
HV = @(w) V.*w;
|
HV = @(w) V .* w;
|
||||||
|
|
||||||
% Contact interactions
|
% === Contact interaction: C|ψ|² ===
|
||||||
Hint = @(w) (Params.gs*abs(psi).^2).*w;
|
C = Params.gs * N;
|
||||||
|
Hint = @(w) (C * absPsi2) .* w;
|
||||||
% DDIs
|
|
||||||
frho = fftn(abs(psi).^2);
|
|
||||||
Phi = ifftn(frho.*VDk);
|
|
||||||
Hddi = @(w) (Params.gdd*Phi).*w;
|
|
||||||
|
|
||||||
% Quantum fluctuations
|
% === Dipole-dipole interaction: D U_dd * |ψ|² ===
|
||||||
Hqf = @(w) (Params.gammaQF*abs(psi).^3).*w;
|
frho = fftn(absPsi2);
|
||||||
|
Phi_dd = ifftn(frho .* VDk);
|
||||||
H = @(w) HKin(w) + HV(w) + Hint(w) + Hddi(w) + Hqf(w);
|
D = Params.gdd * N;
|
||||||
|
Hddi = @(w) (D * Phi_dd) .* w;
|
||||||
|
|
||||||
J = H(psi);
|
% === Quantum fluctuations: Q|ψ|³ ===
|
||||||
|
Q = Params.gammaQF * N^(3/2);
|
||||||
|
Hqf = @(w) (Q * absPsi3) .* w;
|
||||||
|
|
||||||
|
% === Total Hamiltonian operator ===
|
||||||
|
H = @(w) HKin(w) + HV(w) + Hint(w) + Hddi(w) + Hqf(w);
|
||||||
|
|
||||||
|
% === Compute gradient ===
|
||||||
|
J = H(psi);
|
||||||
end
|
end
|
||||||
|
|
||||||
function g = compute_g(psi, p, Params, VDk)
|
function g = compute_g(psi, p, Params, VDk)
|
||||||
|
% === Precompute necessary quantities ===
|
||||||
rho = real(psi.*conj(p));
|
rho = real(psi .* conj(p)); % Mixed density
|
||||||
|
absPsi = abs(psi); % Magnitude of wavefunction
|
||||||
|
N = Params.N;
|
||||||
|
|
||||||
% Contact interactions
|
% === Contact interaction term ===
|
||||||
C = Params.gs*Params.N;
|
C = Params.gs * N;
|
||||||
gint = @(w)(C.*rho).*w;
|
g_contact = @(w) (C * rho) .* w;
|
||||||
|
|
||||||
% DDIs
|
|
||||||
D = Params.gdd*Params.N;
|
|
||||||
rhotilde = fftn(rho);
|
|
||||||
Phi = ifftn(rhotilde.*VDk);
|
|
||||||
gaddi = @(w)(D.*Phi).*w;
|
|
||||||
|
|
||||||
% Quantum fluctuations
|
% === Dipole-dipole interaction term ===
|
||||||
eps_dd = Params.add/Params.as;
|
rhotilde = fftn(rho);
|
||||||
Q = (4/(3*pi^2)) * (C^(5/2)/Params.N) * (1 + ((3*eps_dd^2)/2));
|
Phi_dd = ifftn(rhotilde .* VDk); % Convolution with DDI kernel
|
||||||
gqf = @(w)(((3/2)*Q).*abs(psi).*rho).*w;
|
D = Params.gdd * N;
|
||||||
|
g_ddi = @(w) (D * Phi_dd) .* w;
|
||||||
gop = @(w) gint(w) + gaddi(w) + gqf(w);
|
|
||||||
|
|
||||||
g = gop(psi);
|
% === Quantum fluctuation (LHY) correction ===
|
||||||
|
Q = Params.gammaQF * N^(3/2); % LHY prefactor
|
||||||
|
g_qf = @(w) ((3/2) * Q * absPsi .* rho) .* w;
|
||||||
|
|
||||||
|
% === Total effective operator applied to psi ===
|
||||||
|
g_total = @(w) g_contact(w) + g_ddi(w) + g_qf(w);
|
||||||
|
|
||||||
|
% === Multiply by factor of 2, as per gradient expression ===
|
||||||
|
g = 2 * g_total(psi);
|
||||||
end
|
end
|
||||||
|
|
||||||
% Optimal direction via line search
|
% Optimal direction
|
||||||
function theta = compute_optimal_theta(p, muchem, psi, Params, Transf, VDk, V)
|
function theta = compute_optimal_theta(p, muchem, psi, Params, Transf, VDk, V)
|
||||||
|
|
||||||
Hpsi = compute_gradient(psi, Params, Transf, VDk, V);
|
Hpsi = compute_gradient(psi, Params, Transf, VDk, V);
|
||||||
|
Loading…
Reference in New Issue
Block a user