Compare commits

...

7 Commits

Author SHA1 Message Date
27fe40068e Minor changes to scripting style. 2021-07-16 16:14:11 +02:00
c19a514027 Added back the captured atom counting and the jackknife error estimation method as developed by Jianshun Gao, retained the bootstrap method and the counting that goes with it now corrected to prevent counting the same atoms repeatedly and also to reduce the atom count if they are lost. There is now an agreement between the two methods as to what the loading rate is with the bootstrap method giving a slightly lower estimate. 2021-07-16 15:57:16 +02:00
5407da354b Added results property to store the final results of a scan to later save the whole object along with its properties so as to have a way of going back and checking the values for the parameters used. 2021-07-16 15:53:19 +02:00
79b7a67c95 Cosmetic change of the name of the sideband beam flag. 2021-07-16 15:51:54 +02:00
2d7bc36fee Cosmetic changes only. 2021-07-16 15:51:00 +02:00
4051549b27 Increase of 5% was meant for cut-off velocity and not the capture velocity, correction was made accordingly. 2021-07-16 15:50:08 +02:00
0238e5d312 Added option to switch between Bootstrap and Jackknife error estimation methods, changed sideband beam flag name, removed zeeman slower beam flag which can be added later following development of the ThreeDimensionalMOT class and functionalities. 2021-07-16 15:49:02 +02:00
8 changed files with 152 additions and 47 deletions

View File

@ -5,12 +5,12 @@ classdef MOTCaptureProcess < handle & matlab.mixin.Copyable
TimeStep;
SimulationTime;
NumberOfAtoms;
ErrorEstimationMethod;
%Flags
SpontaneousEmission;
Sideband;
SidebandBeam;
PushBeam;
ZeemanSlowerBeam;
Gravity;
BackgroundCollision;
@ -34,6 +34,8 @@ classdef MOTCaptureProcess < handle & matlab.mixin.Copyable
p.KeepUnmatched = true;
addParameter(p, 'SimulationMode', '2D',...
@(x) any(strcmpi(x,{'2D','3D', 'Full'})));
addParameter(p, 'ErrorEstimationMethod', 'jackknife',...
@(x) any(strcmpi(x,{'jackknife','bootstrap'})));
addParameter(p, 'NumberOfAtoms', 5000,...
@(x) assert(isnumeric(x) && isscalar(x) && (x > 0)));
addParameter(p, 'TimeStep', 10e-06,...
@ -42,12 +44,10 @@ classdef MOTCaptureProcess < handle & matlab.mixin.Copyable
@(x) assert(isnumeric(x) && isscalar(x) && (x > 0)));
addParameter(p, 'SpontaneousEmission', false,...
@islogical);
addParameter(p, 'Sideband', false,...
addParameter(p, 'SidebandBeam', false,...
@islogical);
addParameter(p, 'PushBeam', false,...
@islogical);
addParameter(p, 'ZeemanSlowerBeam', false,...
@islogical);
addParameter(p, 'Gravity', false,...
@islogical);
addParameter(p, 'BackgroundCollision', false,...
@ -62,15 +62,15 @@ classdef MOTCaptureProcess < handle & matlab.mixin.Copyable
p.parse(varargin{:});
this.SimulationMode = p.Results.SimulationMode;
this.ErrorEstimationMethod= p.Results.ErrorEstimationMethod;
this.NumberOfAtoms = p.Results.NumberOfAtoms;
this.TimeStep = p.Results.TimeStep;
this.SimulationTime = p.Results.SimulationTime;
this.SpontaneousEmission = p.Results.SpontaneousEmission;
this.Sideband = p.Results.Sideband;
this.SidebandBeam = p.Results.SidebandBeam;
this.PushBeam = p.Results.PushBeam;
this.ZeemanSlowerBeam = p.Results.ZeemanSlowerBeam;
this.Gravity = p.Results.Gravity;
this.BackgroundCollision = p.Results.BackgroundCollision;

View File

@ -1,8 +1,8 @@
function ret = initialVelocitySampling(this, MOTObj)
n = this.NumberOfAtoms;
% Calculate Calculate Capture velocity --> Introduce velocity cutoff
MOTObj.CaptureVelocity = 1.05 * MOTObj.calculateCaptureVelocity(this, [-this.OvenDistance,0,0], [1,0,0]);
this.VelocityCutoff = MOTObj.CaptureVelocity(1); % Should be the magnitude of the 3-D velocity vector but since here the obtained capture
MOTObj.CaptureVelocity = MOTObj.calculateCaptureVelocity(this, [-this.OvenDistance,0,0], [1,0,0]);
this.VelocityCutoff = 1.05 * MOTObj.CaptureVelocity(1); % Should be the magnitude of the 3-D velocity vector but since here the obtained capture
% velocity is only along the x-axis, we take the first term which is the x-component of the velocity.
[ReducedClausingFactor, NormalizationConstantForAngularDistribution] = this.calculateReducedClausingFactor();

View File

@ -19,6 +19,7 @@ classdef TwoDimensionalMOT < Simulator.MOTCaptureProcess & matlab.mixin.Copyable
TimeSpentInInteractionRegion;
ParticleDynamicalQuantities;
InitialParameters;
Results;
end
methods
@ -130,6 +131,12 @@ classdef TwoDimensionalMOT < Simulator.MOTCaptureProcess & matlab.mixin.Copyable
function ret = get.InitialParameters(this)
ret = this.InitialParameters;
end
function set.Results(this, val)
this.Results = val;
end
function ret = get.Results(this)
ret = this.Results;
end
end % - setters and getters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View File

@ -9,17 +9,17 @@ function [LoadingRate, StandardError, ConfidenceInterval] = bootstrapErrorEstima
if ~isnan(CorrelationFactor)
SampleLength = floor(CorrelationFactor);
NumberOfBootsrapSamples = 1000;
MeanLoadingRatioInEachSample = zeros(1,NumberOfBootsrapSamples);
MeanCaptureRatioInEachSample = zeros(1,NumberOfBootsrapSamples);
for SampleNumber = 1:NumberOfBootsrapSamples
BoostrapSample = datasample(NumberOfLoadedAtoms, SampleLength); % Sample with replacement
MeanLoadingRatioInEachSample(SampleNumber) = mean(BoostrapSample) / n; % Empirical bootstrap distribution of sample means
MeanCaptureRatioInEachSample(SampleNumber) = mean(BoostrapSample) / n; % Empirical bootstrap distribution of sample means
end
LoadingRate = mean(MeanLoadingRatioInEachSample) * ovenObj.ReducedFlux;
LoadingRate = mean(MeanCaptureRatioInEachSample) * ovenObj.ReducedFlux;
Variance = 0; % Bootstrap Estimate of Variance
for SampleNumber = 1:NumberOfBootsrapSamples
Variance = Variance + (MeanLoadingRatioInEachSample(SampleNumber) - mean(MeanLoadingRatioInEachSample))^2;
Variance = Variance + (MeanCaptureRatioInEachSample(SampleNumber) - mean(MeanCaptureRatioInEachSample))^2;
end
StandardError = sqrt((1 / (NumberOfBootsrapSamples-1)) * Variance) * ovenObj.ReducedFlux;

View File

@ -1,9 +1,9 @@
function [LoadingRate, StandardError, ConfidenceInterval] = calculateLoadingRate(this, ovenObj)
n = this.NumberOfAtoms;
DynamicalQuantities = this.ParticleDynamicalQuantities;
NumberOfTimeSteps = int64(this.SimulationTime/this.TimeStep);
NumberOfLoadedAtoms = zeros(1, NumberOfTimeSteps);
CollisionEvents = zeros(1, n);
NumberOfLoadedAtoms = zeros(1, n);
% Include the stochastic process of background collisions
for AtomIndex = 1:n
@ -12,6 +12,12 @@ function [LoadingRate, StandardError, ConfidenceInterval] = calculateLoadingRate
end
% Count the number of loaded atoms subject to conditions
switch this.ErrorEstimationMethod
case 'bootstrap'
NumberOfTimeSteps = int64(this.SimulationTime/this.TimeStep);
NumberOfLoadedAtoms = zeros(1, NumberOfTimeSteps);
LoadedAtomIndices = [];
for TimeIndex = 1:NumberOfTimeSteps
if TimeIndex ~= 1
NumberOfLoadedAtoms(TimeIndex) = NumberOfLoadedAtoms(TimeIndex-1);
@ -19,10 +25,29 @@ function [LoadingRate, StandardError, ConfidenceInterval] = calculateLoadingRate
for AtomIndex = 1:n
Position = squeeze(DynamicalQuantities(AtomIndex, TimeIndex, 1:3))';
if this.exitCondition(Position, CollisionEvents(AtomIndex))
if ~ismember(AtomIndex, LoadedAtomIndices)
NumberOfLoadedAtoms(TimeIndex) = NumberOfLoadedAtoms(TimeIndex) + 1;
LoadedAtomIndices(end+1) = AtomIndex;
end
else
if ismember(AtomIndex, LoadedAtomIndices)
NumberOfLoadedAtoms(TimeIndex) = NumberOfLoadedAtoms(TimeIndex) - 1;
LoadedAtomIndices(LoadedAtomIndices==AtomIndex) = [];
end
end
end
end
[LoadingRate, StandardError, ConfidenceInterval] = this.bootstrapErrorEstimation(ovenObj, NumberOfLoadedAtoms);
case 'jackknife'
for AtomIndex = 1:n
if AtomIndex ~= 1
NumberOfLoadedAtoms(AtomIndex) = NumberOfLoadedAtoms(AtomIndex-1);
end
Position = squeeze(DynamicalQuantities(AtomIndex, end, 1:3))';
if this.exitCondition(Position, CollisionEvents(AtomIndex))
NumberOfLoadedAtoms(AtomIndex) = NumberOfLoadedAtoms(AtomIndex) + 1;
end
end
[LoadingRate, StandardError, ConfidenceInterval] = jackknifeErrorEstimation(this, ovenObj, NumberOfLoadedAtoms);
end
end

View File

@ -47,7 +47,7 @@ function ret = calculateTotalAcceleration(this, PositionVector, VelocityVector)
Delta_Cooling(i*2-1) = CoolingBeamDetuning + DopplerShift + (ZeemanShift * Sigma(i));
Delta_Cooling(i*2) = CoolingBeamDetuning - DopplerShift - (ZeemanShift * Sigma(i));
if this.Sideband
if this.SidebandBeam
Delta_Sideband(i*2-1) = SidebandDetuning + DopplerShift + (ZeemanShift * Sigma(i));
Delta_Sideband(i*2) = SidebandDetuning - DopplerShift - (ZeemanShift * Sigma(i));
end
@ -58,7 +58,7 @@ function ret = calculateTotalAcceleration(this, PositionVector, VelocityVector)
for i = 1:2
SaturationParameter(2*i-1) = CoolingBeamLocalSaturationIntensity(i) /(1 + 4 * (Delta_Cooling(2*i-1)/CoolingBeamLinewidth)^2);
SaturationParameter(2*i) = CoolingBeamLocalSaturationIntensity(i) /(1 + 4 * (Delta_Cooling(2*i) /CoolingBeamLinewidth)^2);
if this.Sideband
if this.SidebandBeam
SaturationParameter(2*i-1+4) = SidebandLocalSaturationIntensity(i) /(1 + 4 * (Delta_Sideband(2*i-1)/CoolingBeamLinewidth)^2);
SaturationParameter(2*i+4) = SidebandLocalSaturationIntensity(i) /(1 + 4 * (Delta_Sideband(2*i)/CoolingBeamLinewidth)^2);
end
@ -79,7 +79,7 @@ function ret = calculateTotalAcceleration(this, PositionVector, VelocityVector)
a_scattering = [0,0,0];
end
if this.Sideband
if this.SidebandBeam
a_1 = a_1 + a_sat .* (SaturationParameter(2*i-1+4)/(1 + TotalSaturationParameter));
a_2 = a_2 + a_sat .* (SaturationParameter(2*i+4) /(1 + TotalSaturationParameter));

View File

@ -0,0 +1,50 @@
function [LoadingRate, StandardError, ConfidenceInterval] = jackknifeErrorEstimation(this, ovenObj, NumberOfLoadedAtoms)
n = this.NumberOfAtoms;
Autocorrelation = zeros(1, n);
for i = 1:n-1
FirstTerm = 0;
SecondTerm = 0;
for j = 1:n-i
FirstTerm = FirstTerm + NumberOfLoadedAtoms(j) / j;
SecondTerm = SecondTerm + (NumberOfLoadedAtoms(i+j)) / (i+j);
Autocorrelation(i) = Autocorrelation(i) + ((NumberOfLoadedAtoms(j) / j) .*(NumberOfLoadedAtoms(i+j) / (i+j)));
end
Autocorrelation(i) = (1/(n-i)) * (Autocorrelation(i) - ((1/(n-i)) * FirstTerm * SecondTerm));
end
if Autocorrelation(1)~=0
Autocorrelation = Autocorrelation./Autocorrelation(1);
x = linspace(1,n,n);
[FitParams,~] = fit(x',Autocorrelation',"exp(-x/tau)", 'Startpoint', 100);
CorrelationFactor = FitParams.tau;
SampleLength = 2*CorrelationFactor+1;
NumberOfJackknifeSamples = floor(n/SampleLength);
CaptureRatioInEachSample = zeros(1,NumberOfJackknifeSamples);
SampleNumberLimit = min(NumberOfJackknifeSamples-1,5);
for i=1:NumberOfJackknifeSamples-SampleNumberLimit
CaptureRatioInEachSample(i) = NumberOfLoadedAtoms(n-ceil((i-1)*SampleLength))/(n-ceil((i-1)*SampleLength));
end
MeanCaptureRatio = sum(CaptureRatioInEachSample) / (NumberOfJackknifeSamples-SampleNumberLimit);
LoadingRate = MeanCaptureRatio * ovenObj.ReducedFlux;
Variance=0;
for i=1:NumberOfJackknifeSamples-SampleNumberLimit
Variance=Variance+(CaptureRatioInEachSample(i) - MeanCaptureRatio)^2;
end
StandardError = sqrt(Variance/(NumberOfJackknifeSamples-SampleNumberLimit));
ConfidenceInterval = LoadingRate + 1.96*StandardError; % 95% Confidence Intervals
else
LoadingRate = nan;
StandardError = nan;
ConfidenceInterval = [nan nan];
end
end

View File

@ -6,6 +6,7 @@
% - Create MOTCaptureProcess object with specified options
% - Automatically creates Beams objects
OptionsStruct = struct;
OptionsStruct.ErrorEstimationMethod = 'bootstrap'; % 'jackknife' | 'bootstrap'
OptionsStruct.NumberOfAtoms = 10000;
OptionsStruct.TimeStep = 50e-06; % in s
OptionsStruct.SimulationTime = 4e-03; % in s
@ -24,12 +25,8 @@ MOT2D = Simulator.TwoDimensionalMOT(options{:});
Beams = MOT2D.Beams;
%% - Run Simulation
% poolobj = gcp('nocreate'); % Check if pool is open
% if isempty(poolobj)
% parpool;
% end
MOT2D.NumberOfAtoms = 5000;
MOT2D.Sideband = false;
MOT2D.SidebandBeam = false;
CoolingBeam = Beams{cellfun(@(x) strcmpi(x.Alias, 'Blue'), Beams)};
CoolingBeam.Power = 0.4;
CoolingBeam.Waist = 13.3e-03;
@ -73,7 +70,7 @@ Plotter.plotAngularDistributionForDifferentBeta(Oven, Beta)
Plotter.plotCaptureVelocityVsAngle(Oven, MOT2D); % Takes a long time to plot!
%% - Plot Phase Space with Acceleration Field
MOT2D.Sideband = false;
MOT2D.SidebandBeam = false;
MOT2D.NumberOfAtoms = 50;
MinimumVelocity = 0;
MaximumVelocity = 150;
@ -128,13 +125,13 @@ QuantityOfInterestArray = LoadingRateArray;
OptionsStruct = struct;
OptionsStruct.RescalingFactorForParameter = 1000;
OptionsStruct.XLabelString = 'Cooling Beam Power (mW)';
OptionsStruct.RescalingFactorForYQuantity = 1e-11;
OptionsStruct.RescalingFactorForYQuantity = 1e-10;
OptionsStruct.ErrorsForYQuantity = true;
OptionsStruct.ErrorsArray = StandardErrorArray;
OptionsStruct.CIForYQuantity = true;
OptionsStruct.CIArray = ConfidenceIntervalArray;
OptionsStruct.RemoveOutliers = true;
OptionsStruct.YLabelString = 'Loading rate (x 10^{11} atoms/s)';
OptionsStruct.YLabelString = 'Loading rate (x 10^{10} atoms/s)';
OptionsStruct.TitleString = sprintf('Magnetic Gradient = %.0f (G/cm)', MOT2D.MagneticGradient * 100);
options = Helper.convertstruct2cell(OptionsStruct);
@ -143,11 +140,24 @@ Plotter.plotResultForOneParameterScan(ParameterArray, QuantityOfInterestArray, o
clear OptionsStruct
if MOT2D.DoSave
LoadingRate = struct;
LoadingRate.Values = LoadingRateArray;
LoadingRate.Errors = StandardErrorArray;
LoadingRate.CI = ConfidenceIntervalArray;
MOT2D.Results = LoadingRate;
SaveFolder = [MOT2D.SaveDirectory filesep 'Results'];
Filename = ['OneParameterScan_' datestr(now,'yyyymmdd_HHMM')];
eval([sprintf('%s_Object', Filename) ' = MOT2D;']);
mkdir(SaveFolder);
save([SaveFolder filesep Filename], sprintf('%s_Object', Filename));
end
%% - Scan parameters: Two-Parameter Scan
MOT2D.NumberOfAtoms = 50;
MOT2D.TotalPower = 0.6;
MOT2D.Sideband = false;
MOT2D.SidebandBeam = false;
SidebandBeam = Beams{cellfun(@(x) strcmpi(x.Alias, 'BlueSideband'), Beams)};
NumberOfPointsForFirstParam = 10; %iterations of the simulation
@ -197,3 +207,16 @@ options = Helper.convertstruct2cell(
Plotter.plotResultForTwoParameterScan(FirstParameterArray, SecondParameterArray, QuantityOfInterestArray, options{:})
clear OptionsStruct
if MOT2D.DoSave
LoadingRate = struct;
LoadingRate.Values = LoadingRateArray;
LoadingRate.Errors = StandardErrorArray;
LoadingRate.CI = ConfidenceIntervalArray;
MOT2D.Results = LoadingRate;
SaveFolder = [MOT2D.SaveDirectory filesep 'Results'];
Filename = ['TwoParameterScan_' datestr(now,'yyyymmdd_HHMM')];
eval([sprintf('%s_Object', Filename) ' = MOT2D;']);
mkdir(SaveFolder);
save([SaveFolder filesep Filename], sprintf('%s_Object', Filename));
end