function [psi] = propagateWavefunction(this,psi,Params,Transf,VDk,V,t_idx,Observ) switch this.SimulationMode case 'ImaginaryTimeEvolution' dt = -1j*abs(this.TimeStepSize); % Imaginary Time KEop = 0.5*(Transf.KX.^2+Transf.KY.^2+Transf.KZ.^2); Observ.residual = 1; Observ.res = 1; muchem = this.Calculator.calculateChemicalPotential(psi,Params,Transf,VDk,V); if this.PlotLive Plotter.plotLive(psi,Params,Transf,Observ) drawnow end AdaptIdx = 0; while t_idx < Params.sim_time_cut_off % kin psi = fftn(psi); psi = psi.*exp(-0.5*1i*dt*KEop); psi = ifftn(psi); % DDI frho = fftn(abs(psi).^2); Phi = real(ifftn(frho.*VDk)); % Real-space psi = psi.*exp(-1i*dt*(V + Params.gs*abs(psi).^2 + Params.gammaQF*abs(psi).^3 + Params.gdd*Phi - muchem)); % kin psi = fftn(psi); psi = psi.*exp(-0.5*1i*dt*KEop); psi = ifftn(psi); % Renorm Norm = sum(abs(psi(:)).^2)*Transf.dx*Transf.dy*Transf.dz; psi = sqrt(Params.N)*psi/sqrt(Norm); muchem = this.Calculator.calculateChemicalPotential(psi,Params,Transf,VDk,V); if mod(t_idx,1000) == 0 % Change in Energy E = this.Calculator.calculateTotalEnergy(psi,Params,Transf,VDk,V); E = E/Norm; Observ.EVec = [Observ.EVec E]; % Chemical potential Observ.mucVec = [Observ.mucVec muchem]; % Normalized residuals res = this.Calculator.calculateNormalizedResiduals(psi,Params,Transf,VDk,V,muchem); Observ.residual = [Observ.residual res]; Observ.res_idx = Observ.res_idx + 1; if this.PlotLive Plotter.plotLive(psi,Params,Transf,Observ) drawnow end save(sprintf(strcat(this.SaveDirectory, '/Run_%03i/psi_gs.mat'),Params.njob),'psi','muchem','Observ','t_idx','Transf','Params','VDk','V'); %Adaptive time step -- Careful, this can quickly get out of control relres = abs(Observ.residual(Observ.res_idx)-Observ.residual(Observ.res_idx-1))/Observ.residual(Observ.res_idx); if relres < 1e-5 if AdaptIdx > 4 && abs(dt) > Params.mindt dt = dt / 2; fprintf('Time step changed to '); disp(dt); AdaptIdx = 0; elseif AdaptIdx > 4 && abs(dt) < Params.mindt break else AdaptIdx = AdaptIdx + 1; end else AdaptIdx = 0; end end if any(isnan(psi(:))) disp('NaNs encountered!') break end t_idx=t_idx+1; end % Change in Energy E = this.Calculator.calculateTotalEnergy(psi,Params,Transf,VDk,V); E = E/Norm; Observ.EVec = [Observ.EVec E]; Observ.res_idx = Observ.res_idx + 1; disp('Run completed!'); disp('Saving data...'); save(sprintf(strcat(this.SaveDirectory, '/Run_%03i/psi_gs.mat'),Params.njob),'psi','muchem','Observ','t_idx','Transf','Params','VDk','V'); disp('Save complete!'); case 'RealTimeEvolution' dt = abs(this.TimeStepSize); KEop= 0.5*(Transf.KX.^2+Transf.KY.^2+Transf.KZ.^2); muchem = this.Calculator.calculateChemicalPotential(psi,Params,Transf,VDk,V); while t_idx < Params.sim_time_cut_off % Parameters at time t %kin psi = fftn(psi); psi = psi.*exp(-0.5*1i*dt*KEop); psi = ifftn(psi); %DDI frho = fftn(abs(psi).^2); Phi = real(ifftn(frho.*VDk)); %Real-space psi = psi.*exp(-1i*dt*(V + Params.gs*abs(psi).^2 + Params.gammaQF*abs(psi).^3 + Params.gdd*Phi - muchem)); %kin psi = fftn(psi); psi = psi.*exp(-0.5*1i*dt*KEop); psi = ifftn(psi); muchem = this.Calculator.calculateChemicalPotential(psi,Params,Transf,VDk,V); if mod(t_idx,1000)==0 %Change in Normalization Norm = sum(abs(psi(:)).^2)*Transf.dx*Transf.dy*Transf.dz; % normalisation Observ.NormVec = [Observ.NormVec Norm]; %Change in Energy E = this.Calculator.calculateTotalEnergy(psi,Params,Transf,VDk,V); E = E/Norm; Observ.EVec = [Observ.EVec E]; Observ.tVecPlot = [Observ.tVecPlot tVal]; Observ.res_idx = Observ.res_idx + 1; save(sprintf('./Data/Run_%03i/TimeEvolution/psi_%i.mat',Params.njob,Observ.res_idx),'psi','muchem','Observ','t_idx'); end if any(isnan(psi(:))) disp('NaNs encountered!') break end t_idx=t_idx+1; end %Change in Normalization Norm = sum(abs(psi(:)).^2)*Transf.dx*Transf.dy*Transf.dz; % normalisation Observ.NormVec = [Observ.NormVec Norm]; %Change in Energy E = this.Calculator.calculateTotalEnergy(psi,Params,Transf,VDk,V); E = E/Norm; Observ.EVec = [Observ.EVec E]; % Phase coherence [PhaseC] = this.Calculator.calculatePhaseCoherence(psi,Transf); Observ.PCVec = [Observ.PCVec PhaseC]; Observ.tVecPlot = [Observ.tVecPlot tVal]; Observ.res_idx = Observ.res_idx + 1; disp('Run completed!'); disp('Saving data...'); save(sprintf('./Data/Run_%03i/TimeEvolution/psi_%i.mat',Params.njob,Observ.res_idx),'psi','muchem','Observ','t_idx'); disp('Save complete!'); otherwise disp('Choose a valid DDI cutoff type!') return end end