Added functionality to load a initial wavefunction if necessary to bias the solver, modified the conjugate gradient descent algorithm.
This commit is contained in:
		
							parent
							
								
									e0991a9a29
								
							
						
					
					
						commit
						6566f53559
					
				| @ -20,7 +20,7 @@ OptionsStruct.UseApproximationForLHY  = true; | ||||
| OptionsStruct.IncludeDDICutOff        = true; | ||||
| OptionsStruct.CutoffType              = 'Cylindrical'; | ||||
| OptionsStruct.SimulationMode          = 'EnergyMinimization'; % 'ImaginaryTimeEvolution' | 'RealTimeEvolution' | 'EnergyMinimization' | ||||
| OptionsStruct.GradientDescentMethod   = 'HeavyBall'; % 'HeavyBall' | 'NonLinearCGD'  | ||||
| OptionsStruct.GradientDescentMethod   = 'NonLinearCGD'; % 'HeavyBall' | 'NonLinearCGD'  | ||||
| OptionsStruct.MaxIterationsForGD      = 2E5; | ||||
| OptionsStruct.TimeStepSize            = 1E-4;            % in s | ||||
| OptionsStruct.MinimumTimeStepSize     = 2E-10;           % in s | ||||
| @ -50,35 +50,6 @@ sim.Potential                         = pot.trap(); % + pot.repulsive_chopstick( | ||||
| Plotter.visualizeTrapPotential(sim.Potential,Params,Transf) | ||||
| %% - Plot initial wavefunction | ||||
| Plotter.visualizeWavefunction(psi,Params,Transf) | ||||
| %% - Plot GS wavefunction | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/AspectRatio2_8'; | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/AspectRatio3_7'; | ||||
| SaveDirectory = './Results/Data_3D/CompleteLHY/AspectRatio3_8'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/BeyondSSD_SSD'; | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/BeyondSSD_Labyrinth'; | ||||
| SaveDirectory = './Results/Data_3D/CompleteLHY/BeyondSSD_Honeycomb'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% - Plot GS wavefunction | ||||
| SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio2_8'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio3_7'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio3_8'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio3_9'; | ||||
| JobNumber     = 3; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/BeyondSSD_SSD'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/BeyondSSD_Labyrinth'; | ||||
| SaveDirectory = './Results/Data_3D/ApproximateLHY/BeyondSSD_Honeycomb'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| SaveDirectory = './Results/Data_3D/GradientDescent'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| 
 | ||||
| % To reproduce results from the Blair Blakie paper: | ||||
| @ -438,4 +409,40 @@ JobNumber     = 2; % 82 | ||||
| % JobNumber     = 3; % 83 | ||||
| Plotter.visualizeGSWavefunction2D(SaveDirectory, JobNumber) | ||||
| [contrast, period_X, period_Y] = Scripts.analyzeGSWavefunction_in_plane_trap(SaveDirectory, JobNumber); | ||||
| 
 | ||||
| %% - Plot GS wavefunction | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/AspectRatio2_8'; | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/AspectRatio3_7'; | ||||
| SaveDirectory = './Results/Data_3D/CompleteLHY/AspectRatio3_8'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/BeyondSSD_SSD'; | ||||
| % SaveDirectory = './Results/Data_3D/CompleteLHY/BeyondSSD_Labyrinth'; | ||||
| SaveDirectory = './Results/Data_3D/CompleteLHY/BeyondSSD_Honeycomb'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% - Plot GS wavefunction | ||||
| SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio2_8'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio3_7'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio3_8'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/AspectRatio3_9'; | ||||
| JobNumber     = 3; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/BeyondSSD_SSD'; | ||||
| % SaveDirectory = './Results/Data_3D/ApproximateLHY/BeyondSSD_Labyrinth'; | ||||
| SaveDirectory = './Results/Data_3D/ApproximateLHY/BeyondSSD_Honeycomb'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| SaveDirectory = './Results/Data_3D/TiltedDipoles15'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| SaveDirectory = './Results/Data_3D/TiltedDipoles30'; | ||||
| JobNumber     = 0; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
| %% | ||||
| SaveDirectory = './Results/Data_3D/TiltedDipoles45'; | ||||
| JobNumber     = 1; | ||||
| Plotter.visualizeGSWavefunction(SaveDirectory, JobNumber) | ||||
|  | ||||
| @ -1,18 +1,20 @@ | ||||
| %% Scaled parameters | ||||
| theta = 0; | ||||
| phi   = 0; | ||||
| 
 | ||||
| ScalingFactor                         = (4/5)^2; | ||||
| % - SSD: N = 1E5, as = 86ao | ||||
| 
 | ||||
| OptionsStruct = struct; | ||||
| 
 | ||||
| OptionsStruct.NumberOfAtoms           = sqrt(ScalingFactor) * 5E5; | ||||
| OptionsStruct.DipolarPolarAngle       = deg2rad(0); | ||||
| OptionsStruct.DipolarAzimuthAngle     = 0; | ||||
| OptionsStruct.ScatteringLength        = 75; | ||||
| OptionsStruct.NumberOfAtoms           = 1E5; | ||||
| OptionsStruct.DipolarPolarAngle       = deg2rad(theta); | ||||
| OptionsStruct.DipolarAzimuthAngle     = deg2rad(phi); | ||||
| OptionsStruct.ScatteringLength        = 86; | ||||
| 
 | ||||
| AspectRatio                           = 2.8; | ||||
| HorizontalTrapFrequency               = 125/ScalingFactor; | ||||
| VerticalTrapFrequency                 = AspectRatio * HorizontalTrapFrequency; | ||||
| OptionsStruct.TrapFrequencies         = [HorizontalTrapFrequency, HorizontalTrapFrequency, VerticalTrapFrequency]; | ||||
| % AspectRatio                           = 2.0; | ||||
| % HorizontalTrapFrequency               = 125; | ||||
| % VerticalTrapFrequency                 = AspectRatio * HorizontalTrapFrequency; | ||||
| % OptionsStruct.TrapFrequencies         = [HorizontalTrapFrequency, HorizontalTrapFrequency, VerticalTrapFrequency]; | ||||
| OptionsStruct.TrapFrequencies         = [150, 150, 300]; | ||||
| OptionsStruct.TrapPotentialType       = 'Harmonic'; | ||||
| 
 | ||||
| OptionsStruct.NumberOfGridPoints      = [128, 128, 64]; | ||||
| @ -21,18 +23,18 @@ OptionsStruct.UseApproximationForLHY  = true; | ||||
| OptionsStruct.IncludeDDICutOff        = true; | ||||
| OptionsStruct.CutoffType              = 'Cylindrical'; | ||||
| OptionsStruct.SimulationMode          = 'ImaginaryTimeEvolution'; % 'ImaginaryTimeEvolution' | 'RealTimeEvolution' | ||||
| OptionsStruct.TimeStepSize            = 1E-4;            % in s | ||||
| OptionsStruct.MinimumTimeStepSize     = 2E-6;           % in s | ||||
| OptionsStruct.TimeStepSize            = 1E-3;            % in s | ||||
| OptionsStruct.MinimumTimeStepSize     = 2E-6;            % in s | ||||
| OptionsStruct.TimeCutOff              = 2E6;             % in s | ||||
| OptionsStruct.EnergyTolerance         = 5E-10; | ||||
| OptionsStruct.ResidualTolerance       = 1E-08; | ||||
| OptionsStruct.NoiseScaleFactor        = 0.01; | ||||
| 
 | ||||
| OptionsStruct.PlotLive                = false; | ||||
| OptionsStruct.JobNumber               = 2; | ||||
| OptionsStruct.RunOnGPU                = true; | ||||
| OptionsStruct.PlotLive                = true; | ||||
| OptionsStruct.JobNumber               = 0; | ||||
| OptionsStruct.RunOnGPU                = false; | ||||
| OptionsStruct.SaveData                = true; | ||||
| OptionsStruct.SaveDirectory           = sprintf('./Results/Data_3D/ApproximateLHY/AspectRatio%s', strrep(num2str(AspectRatio), '.', '_')); | ||||
| OptionsStruct.SaveDirectory           = './Results/Data_3D/TiltedDipoles0'; | ||||
| options                               = Helper.convertstruct2cell(OptionsStruct); | ||||
| clear OptionsStruct | ||||
| 
 | ||||
| @ -43,46 +45,3 @@ sim.Potential                         = pot.trap(); | ||||
| %-% Run Simulation %-% | ||||
| [Params, Transf, psi, V, VDk]         = sim.run(); | ||||
| 
 | ||||
| 
 | ||||
| %{ | ||||
| %% - Gradient Descent Test | ||||
| 
 | ||||
| OptionsStruct = struct; | ||||
| 
 | ||||
| OptionsStruct.NumberOfAtoms           = 8E4; | ||||
| OptionsStruct.DipolarPolarAngle       = deg2rad(0); | ||||
| OptionsStruct.DipolarAzimuthAngle     = 0; | ||||
| OptionsStruct.ScatteringLength        = 95; | ||||
| 
 | ||||
| OptionsStruct.TrapFrequencies         = [30, 60, 90]; | ||||
| OptionsStruct.TrapPotentialType       = 'Harmonic'; | ||||
| 
 | ||||
| OptionsStruct.NumberOfGridPoints      = [256, 128, 128]; | ||||
| OptionsStruct.Dimensions              = [30, 20, 20]; | ||||
| OptionsStruct.UseApproximationForLHY  = true; | ||||
| OptionsStruct.IncludeDDICutOff        = true; | ||||
| OptionsStruct.CutoffType              = 'Cylindrical'; | ||||
| OptionsStruct.SimulationMode          = 'EnergyMinimization'; % 'ImaginaryTimeEvolution' | 'RealTimeEvolution' | 'EnergyMinimization' | ||||
| OptionsStruct.MaxIterationsForGD      = 2E4; | ||||
| % OptionsStruct.TimeStepSize            = 1E-4;            % in s | ||||
| % OptionsStruct.MinimumTimeStepSize     = 2E-10;           % in s | ||||
| % OptionsStruct.TimeCutOff              = 2E6;             % in s | ||||
| % OptionsStruct.EnergyTolerance         = 5E-10; | ||||
| % OptionsStruct.ResidualTolerance       = 1E-08; | ||||
| OptionsStruct.NoiseScaleFactor        = 0.01; | ||||
| 
 | ||||
| OptionsStruct.PlotLive                = true; | ||||
| OptionsStruct.JobNumber               = 0; | ||||
| OptionsStruct.RunOnGPU                = false; | ||||
| OptionsStruct.SaveData                = true; | ||||
| OptionsStruct.SaveDirectory           = './Results/Data_3D/GradientDescent'; | ||||
| options                               = Helper.convertstruct2cell(OptionsStruct); | ||||
| clear OptionsStruct | ||||
| 
 | ||||
| sim                                   = Simulator.DipolarGas(options{:}); | ||||
| pot                                   = Simulator.Potentials(options{:}); | ||||
| sim.Potential                         = pot.trap(); % + pot.repulsive_chopstick(); | ||||
| 
 | ||||
| %-% Run Simulation %-% | ||||
| [Params, Transf, psi, V, VDk]         = sim.run(); | ||||
| %} | ||||
| @ -41,8 +41,19 @@ function [psi,V,VDk] = initialize(this,Params,Transf,TransfRad) | ||||
|     end | ||||
| 
 | ||||
|     % == Setting up the initial wavefunction == % | ||||
|     psi = this.setupWavefunction(Params,Transf); | ||||
|     WavefunctionFile  = fullfile(this.SaveDirectory, 'psi_init.mat'); | ||||
|      | ||||
|     if isfile(WavefunctionFile) | ||||
|         loadedData = load(WavefunctionFile); | ||||
|         if isgpuarray(loadedData.psi) | ||||
|             psi    = gather(loadedData.psi);  | ||||
|         else | ||||
|             psi    = loadedData.psi; | ||||
|         end | ||||
|     else | ||||
|         psi = this.setupWavefunction(Params,Transf); | ||||
|     end | ||||
| 
 | ||||
|     if this.RunOnGPU | ||||
|         psi = gpuArray(psi); | ||||
|     end | ||||
|  | ||||
| @ -12,6 +12,7 @@ function [psi]  = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ) | ||||
|             Observ.res      = 1; | ||||
|             psi_old         = psi;         % Previous psi value (for heavy-ball method) | ||||
|              | ||||
|             % Live Plotter | ||||
|             if this.PlotLive | ||||
|                 Plotter.plotLive(psi,Params,Transf,Observ) | ||||
|                 drawnow | ||||
| @ -24,7 +25,6 @@ function [psi]  = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ) | ||||
|                 J        = compute_gradient(psi, Params, Transf, VDk, V); | ||||
|          | ||||
|                 % Calculate chemical potential and norm | ||||
|                 % Can also be calculated as  --> muchem   = this.Calculator.calculateChemicalPotential(psi,Params,Transf,VDk,V); | ||||
|                 muchem   = sum(real(conj(psi(:)) .* J(:))) / sum(abs(psi(:)).^2); | ||||
|                  | ||||
|                 % Calculate residual and check convergence | ||||
| @ -83,12 +83,11 @@ function [psi]  = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ) | ||||
|             disp('Saving data...'); | ||||
|             save(sprintf(strcat(this.SaveDirectory, '/Run_%03i/psi_gs.mat'),Params.njob),'psi','muchem','Observ','Transf','Params','VDk','V'); | ||||
|             disp('Save complete!'); | ||||
|         case 'NonLinearCGD' | ||||
|             % Define the function handle | ||||
|             f                 = @(X) this.Calculator.calculateTotalEnergy(X, Params, Transf, VDk, V)/Params.N; | ||||
|          | ||||
|         case 'NonLinearCGD' | ||||
|              | ||||
|             % Convergence Criteria: | ||||
|             Epsilon           = 1E-5; | ||||
|             epsilon           = 1E-13; | ||||
|              | ||||
|             % Iteration Counter: | ||||
|             i                 = 1; | ||||
| @ -98,65 +97,80 @@ function [psi]  = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ) | ||||
|             % Initialize the PrematureExitFlag to false | ||||
|             PrematureExitFlag = false; | ||||
|              | ||||
|             % Live plotter | ||||
|             if this.PlotLive | ||||
|                 Plotter.plotLive(psi,Params,Transf,Observ) | ||||
|                 drawnow | ||||
|             end | ||||
|          | ||||
|              | ||||
|             % Minimization Loop | ||||
|             while true | ||||
|                 % Compute gradient | ||||
|                 J       = compute_gradient(psi, Params, Transf, VDk, V); | ||||
|          | ||||
|                 % Check stopping criterion (Gradient norm) | ||||
|                 if norm(J(:)) < Epsilon | ||||
|                     disp('Tolerance reached: Gradient norm is below the specified epsilon.'); | ||||
|                 J                = compute_gradient(psi, Params, Transf, VDk, V); | ||||
|                 % Calculate chemical potential | ||||
|                 muchem           = real(conj(psi(:))' * J(:)) / norm(psi(:))^2; | ||||
|                 % Calculate residual | ||||
|                 residual         = J - (muchem * psi); | ||||
|                  | ||||
|                 % Compute energy difference between the last two saved energy values | ||||
|                 if i == 1 | ||||
|                     energydifference = NaN; | ||||
|                 elseif mod(i,100) == 0 && length(Observ.EVec) > 1 | ||||
|                     energydifference = abs(Observ.EVec(end) - Observ.EVec(end-1)); | ||||
|                 end | ||||
|                 % Convergence check - if energy difference is below set tolerance, then exit | ||||
|                 if energydifference <= epsilon | ||||
|                     disp('Tolerance reached: Energy difference is below the specified epsilon.'); | ||||
|                     PrematureExitFlag = true;  % Set flag to indicate premature exit | ||||
|                     break; | ||||
|                 elseif i >= this.MaxIterationsForCGD | ||||
|                 elseif i >= this.MaxIterationsForGD % If set maximum number of iterations reached, then exit | ||||
|                     disp('Maximum number of iterations for CGD reached.'); | ||||
|                     PrematureExitFlag = true;  % Set flag to indicate premature exit | ||||
|                     break; | ||||
|                 end | ||||
|          | ||||
|                  | ||||
|                 % Initialize search direction if first iteration | ||||
|                 if i == 1 | ||||
|                     S   = -J; | ||||
|                 else | ||||
|                     % Update search direction | ||||
|                     S   = update_search_direction(S, J, J_old); | ||||
|                     d            = -residual; | ||||
|                 else % Compute beta via Polak-Ribiere and create new direction | ||||
|                     residual_new = residual; | ||||
|                     beta         = compute_beta(residual_new, residual_old); | ||||
|                     d            = -residual_new + beta * p_old; | ||||
|                 end | ||||
|          | ||||
|                 % Step Size Optimization (Line Search) | ||||
|                 alpha   = optimize_step_size(f, psi, S, Params, Transf, VDk, V); | ||||
|          | ||||
|                  | ||||
|                 residual_old     = residual; | ||||
|                 p                = d - (real(conj(d(:))' * psi(:)) .* psi); | ||||
|                 p_old            = p; | ||||
|                  | ||||
|                 % Compute optimal theta to generate psi in the direction of minimum in the energy landscape | ||||
|                 theta            = compute_optimal_theta(p, muchem, psi, Params, Transf, VDk, V); | ||||
|                  | ||||
|                 % Update solution | ||||
|                 psi     = psi + alpha * S; | ||||
|          | ||||
|                 psi              = (cos(theta).*psi) + (sin(theta).*(p / norm(p(:)))); | ||||
|                 % Normalize psi | ||||
|                 Norm    = sum(abs(psi(:)).^2) * Transf.dx * Transf.dy * Transf.dz; | ||||
|                 psi     = sqrt(Params.N) * psi / sqrt(Norm); | ||||
|          | ||||
|                 % Store old gradient | ||||
|                 J_old   = J; | ||||
|                 i       = i + 1; | ||||
|                 muchem = this.Calculator.calculateChemicalPotential(psi,Params,Transf,VDk,V); | ||||
|                          | ||||
|                 if mod(i,500) == 0         | ||||
|                 Norm             = sum(abs(psi(:)).^2) * Transf.dx * Transf.dy * Transf.dz; | ||||
|                 psi              = sqrt(Params.N) * psi / sqrt(Norm); | ||||
|                 i                = i + 1; | ||||
| 
 | ||||
|                 % Calculate chemical potential with new psi | ||||
|                 muchem           = real(conj(psi(:))' * J(:)) / norm(psi(:))^2; | ||||
|                  | ||||
|                 if mod(i,100) == 0         | ||||
|              | ||||
|                     % Change in Energy | ||||
|                     % Collect Energy value | ||||
|                     E               = this.Calculator.calculateTotalEnergy(psi,Params,Transf,VDk,V); | ||||
|                     E               = E/Norm; | ||||
|                     Observ.EVec     = [Observ.EVec E]; | ||||
|              | ||||
|                     % Chemical potential | ||||
|                     % Collect Chemical potential value | ||||
|                     Observ.mucVec   = [Observ.mucVec muchem]; | ||||
|              | ||||
|                     % Normalized residuals | ||||
|                     % Collect Normalized residuals | ||||
|                     res             = this.Calculator.calculateNormalizedResiduals(psi,Params,Transf,VDk,V,muchem); | ||||
|                     Observ.residual = [Observ.residual res]; | ||||
|                     Observ.res_idx  = Observ.res_idx + 1; | ||||
|                      | ||||
|                     % Live plotter | ||||
|                     if this.PlotLive | ||||
|                         Plotter.plotLive(psi,Params,Transf,Observ) | ||||
|                         drawnow | ||||
| @ -185,7 +199,7 @@ function [psi]  = runGradientDescent(this,psi,Params,Transf,VDk,V,Observ) | ||||
| end | ||||
| 
 | ||||
| %% Modules | ||||
| % Numerical Gradient Calculation using the finite differences method | ||||
| 
 | ||||
| function J      = compute_gradient(psi, Params, Transf, VDk, V) | ||||
| 
 | ||||
|     % Operators | ||||
| @ -210,44 +224,48 @@ function J      = compute_gradient(psi, Params, Transf, VDk, V) | ||||
|      | ||||
|     H       = @(w) HKin(w) + HV(w) + Hint(w) + Hddi(w) + Hqf(w); | ||||
| 
 | ||||
|     J = H(psi); | ||||
|     J       = H(psi); | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
| % Backtracking Line Search (Step Size Optimization) | ||||
| function alpha  = optimize_step_size(f, X, S, Params, Transf, VDk, V) | ||||
|     alpha       = 1;        % Initial step size | ||||
|     rho         = 0.5;      % Step size reduction factor | ||||
|     c           = 1E-4;     % Armijo condition constant | ||||
|     max_iter    = 100;      % Max iterations for backtracking | ||||
|     tol         = 1E-4;     % Tolerance for stopping | ||||
| function g      = compute_g(psi, p, Params, VDk) | ||||
|      | ||||
|     rho      = real(psi.*conj(p)); | ||||
| 
 | ||||
|     grad        = compute_gradient(X, Params, Transf, VDk, V);  % Compute gradient once | ||||
|     f_X         = f(X);                                         % Evaluate f(X) once | ||||
|     % Contact interactions | ||||
|     C        = Params.gs*Params.N; | ||||
|     gint     = @(w)(C.*rho).*w; | ||||
|      | ||||
|     % DDIs | ||||
|     D        = Params.gdd*Params.N; | ||||
|     rhotilde = fftn(rho); | ||||
|     Phi      = real(ifftn(rhotilde.*VDk)); | ||||
|     gaddi    = @(w)(D.*Phi).*w; | ||||
| 
 | ||||
|     for k = 1:max_iter | ||||
|         % Evaluate Armijo condition with precomputed f(X) and grad | ||||
|         if f(X + alpha * S) <= f_X + c * alpha * (S(:)' * grad(:)) | ||||
|             break; | ||||
|         else | ||||
|             alpha = rho * alpha;  % Reduce the step size | ||||
|         end | ||||
|          | ||||
|         % Early stopping if step size becomes too small | ||||
|         if alpha < tol | ||||
|             break; | ||||
|         end | ||||
|     end | ||||
|     % Quantum fluctuations | ||||
|     eps_dd   = Params.add/Params.as; | ||||
|     Q        = (4/(3*pi^2)) * (C^(5/2)/Params.N) * (1 + ((3*eps_dd^2)/2)); | ||||
|     gqf      = @(w)(((3/2)*Q).*abs(psi).*rho).*w; | ||||
|      | ||||
|     gop      = @(w) gint(w) + gaddi(w) + gqf(w); | ||||
| 
 | ||||
|     g        = gop(psi); | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
| % Update Search Direction  | ||||
| function S_new  = update_search_direction(S, J_new, J_old) | ||||
|     % (Fletcher-Reeves method) | ||||
|     % beta        = (norm(J_new(:))^2) / (norm(J_old(:))^2); | ||||
|     % S_new       = -J_new + beta * S; | ||||
| % Optimal direction via line search | ||||
| function theta  = compute_optimal_theta(p, muchem, psi, Params, Transf, VDk, V) | ||||
|      | ||||
|     Hpsi        = compute_gradient(psi, Params, Transf, VDk, V); | ||||
|     Hp          = compute_gradient(p, Params, Transf, VDk, V); | ||||
|     g           = compute_g(psi, p, Params, VDk); | ||||
|     numerator   = real(conj(p(:))' * Hpsi(:))/norm(p(:)); | ||||
|     denominator = muchem - ((conj(p(:))' * Hp(:)) + real(conj(g(:))' * p(:)))/norm(p(:))^2;  | ||||
| 
 | ||||
|     % (Polak-Ribiere method) | ||||
|     beta        = max(0, (J_new(:)' * (J_new(:) - J_old(:))) / (norm(J_old(:))^2)); | ||||
|     S_new       = -J_new + beta * S; | ||||
|     theta       = numerator / denominator; | ||||
| end | ||||
| 
 | ||||
| % Optimal step size via Polak-Ribiere | ||||
| function beta   = compute_beta(residual_new, residual_old) | ||||
|     beta       = max(0, (residual_new(:)' * (residual_new(:) - residual_old(:))) / (norm(residual_old(:))^2)); | ||||
| end | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user