Skip to content

Commit 65df055

Browse files
committedMar 19, 2018
- Switched to multi-bath version.
- Added many sample input files.
1 parent 8f47ee4 commit 65df055

10 files changed

+685
-17
lines changed
 

‎FeynDyn.m

+39-12
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
%% FEYN DYN, VERSION 2013.11.28
77
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88

9-
function [rho,elapsedTime]=FeynDyn(finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu)
9+
function [rho,elapsedTime]=FeynDyn(Nbath,finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu)
1010

1111
%% 1. Fundamental constansts
1212
kb=1.3806504*10^(-23); % Joules / Kelvin
1313
hbar=1.054571628*10^(-34); % Joules * seconds
1414
beta=1/(kb*temperature);
1515
%% 2. Setup arrays
16-
M=length(H);M2=M^2;Svector=eig(systemCouplingMatrix).';
16+
M=length(H);M2=M^2;
17+
Svector=eig(systemCouplingMatrix).';
18+
Svectors=diag(ones(Nbath,1));
1719
diagonals=diag(reshape(1:M2,M,M));
1820
upperTriangle=find(triu(reshape(1:M2,M,M)));
1921
initialPoint=0;
@@ -55,29 +57,55 @@
5557
K=repmat(K,1,length(gridOfTimeIndices)); % for time dependent OQS hamiltonians
5658

5759
[ia,ib] = ndgrid(1:M);
60+
5861
Sdiff=(kron(Svector,ones(1,M))-kron(ones(1,M),Svector))'; % would not need to transpose the things in the next three lines if Mvector was already a column vector (1:M)'
5962

6063
I_00=expand(exp(-Sdiff.*(kernelEnd(1)*Svector(1,ib)-kernelEndConj(1)*Svector(1,ia)).'),[M2,1]); %eq(14) on pg 4601 of tensor prop. I. repeated values are for n=1, changing values are for n=0
6164
I_mk=zeros(M2^2,deltaKmax+1);I_mkEnd=I_mk;I_mkTD=I_mk;I_mkTDend=I_mk; %I_00 means I0(sk), I_mk means I(sk,s minus k) ?
6265
I_mk(:,1)=kron(ones(M2,1),exp(-Sdiff.*(kernel(1)*Svector(1,ib)-kernelConj(1)*Svector(1,ia)).')); %eq(14) on pg 4601 of tensor prop. I. repeated values are for 0 (or just n-1?), changing values are for n %might be better to rearrange stuff so that you can use kron if repmat is slow in fortran, %is it better computationally to do this in one line or separate calcs ? This is delatK=0, ie, eq 14 on pg 4604 of Tensor Prop. I, the diff btwn this and the line above is that this is for sk>=1 while line above is for sk=0 ? eta+kk ?
6366
I_mkEnd(:,1)=kron(ones(M2,1),exp(-Sdiff.*(kernelEnd(1)*Svector(1,ib)-kernelEndConj(1)*Svector(1,ia)).')); %repeated values are for 0, changing values are for n %might be better to rearrange stuff so that you can use kron if repmat is slow in fortran, %is it better computationally to do this in one line or separate calcs ? This is delatK=0, eta_NN ?
67+
6468
for deltaK=1:deltaKmax %should go up to deltaKmax-1 and deltaKmax should be treated separately
6569
I_mk(:,1+deltaK)=exp(-kron((kernel(1+deltaK)*Svector(1,ib)-kernelConj(1+deltaK)*Svector(1,ia)).',Sdiff)); %can't we just make kernel a vector and use kernel(deltaK) ? , %saving kernelConj reduces number of times 'conj.m' has to be called, but adds another variable, which is worse ? %is it bad to have such a big argument in kron ? or should i save it and make 2 lines, depending on your units for kernel, you might need to factor the argument by 1/hbar. The reshaping afterwards must be redundant, we must be able to use kron in such a way that the answer ends up in matrix form ,
6670
I_mkTD(:,1+deltaK)=exp(-kron((kernelTD(1+deltaK)*Svector(1,ib)-kernelTDConj(1+deltaK)*Svector(1,ia)).',Sdiff)); %can't we just make kernel a vector and use kernel(deltaK) ? , %saving kernelConj reduces number of times 'conj.m' has to be called, but adds another variable, which is worse ? %is it bad to have such a big argument in kron ? or should i save it and make 2 lines, depending on your units for kernel, you might need to factor the argument by 1/hbar. The reshaping afterwards must be redundant, we must be able to use kron in such a way that the answer ends up in matrix form ,
6771
I_mkEnd(:,1+deltaK)=exp(-kron((kernelEnd(1+deltaK)*Svector(1,ib)-kernelEndConj(1+deltaK)*Svector(1,ia)).',Sdiff)); %can't we just make kernel a vector and use kernel(deltaK) ? , %saving kernelConj reduces number of times 'conj.m' has to be called, but adds another variable, which is worse ? %is it bad to have such a big argument in kron ? or should i save it and make 2 lines, depending on your units for kernel, you might need to factor the argument by 1/hbar. The reshaping afterwards must be redundant, we must be able to use kron in such a way that the answer ends up in matrix form ,
6872
I_mkTDend(:,1+deltaK)=exp(-kron((kernelTDend(1+deltaK)*Svector(1,ib)-kernelTDendConj(1+deltaK)*Svector(1,ia)).',Sdiff)); %can't we just make kernel a vector and use kernel(deltaK) ? , %saving kernelConj reduces number of times 'conj.m' has to be called, but adds another variable, which is worse ? %is it bad to have such a big argument in kron ? or should i save it and make 2 lines, depending on your units for kernel, you might need to factor the argument by 1/hbar. The reshaping afterwards must be redundant, we must be able to use kron in such a way that the answer ends up in matrix form ,
6973
end %kernel(1)=eta_kk, kernel(2)=eta_{k+1,k}
74+
75+
%% 4.1 Calculation of I tensors with N identical baths
76+
for jj=2:Nbath
77+
Svector2=Svectors(Nbath+1-jj,:); %relationship between Svector and Svector2
78+
Sdiff2=(kron(Svector2,ones(1,M))-kron(ones(1,M),Svector2))';
79+
80+
Ij_00=expand(exp(-Sdiff2.*(kernelEnd(1)*Svector2(1,ib)-kernelEndConj(1)*Svector2(1,ia)).'),[M2,1]);
81+
Ij_mk=zeros(M2^2,deltaKmax+1);Ij_mkEnd=Ij_mk;Ij_mkTD=Ij_mk;Ij_mkTDend=Ij_mk;
82+
Ij_mk(:,1)=kron(ones(M2,1),exp(-Sdiff2.*(kernel(1)*Svector2(1,ib)-kernelConj(1)*Svector2(1,ia)).'));
83+
Ij_mkEnd(:,1)=kron(ones(M2,1),exp(-Sdiff2.*(kernelEnd(1)*Svector2(1,ib)-kernelEndConj(1)*Svector2(1,ia)).'));
84+
85+
for deltaK=1:deltaKmax
86+
Ij_mk(:,1+deltaK)=exp(-kron((kernel(1+deltaK)*Svector2(1,ib)-kernelConj(1+deltaK)*Svector2(1,ia)).',Sdiff2));
87+
Ij_mkTD(:,1+deltaK)=exp(-kron((kernelTD(1+deltaK)*Svector2(1,ib)-kernelTDConj(1+deltaK)*Svector2(1,ia)).',Sdiff2));
88+
Ij_mkEnd(:,1+deltaK)=exp(-kron((kernelEnd(1+deltaK)*Svector2(1,ib)-kernelEndConj(1+deltaK)*Svector2(1,ia)).',Sdiff2));
89+
Ij_mkTDend(:,1+deltaK)=exp(-kron((kernelTDend(1+deltaK)*Svector2(1,ib)-kernelTDendConj(1+deltaK)*Svector2(1,ia)).',Sdiff2));
90+
end %kernel(1)=eta_kk, kernel(2)=eta_{k+1,k}
91+
92+
I_00=I_00.*Ij_00;
93+
I_mk=I_mk.*Ij_mk;
94+
I_mkTD=I_mkTD.*Ij_mkTD;
95+
I_mkEnd(:,1)=I_mkEnd(:,1).*Ij_mkEnd(:,1);
96+
I_mkTDend=I_mkTDend.*Ij_mkTDend;
97+
end
98+
7099
%% 5. Propagation of rho for the first deltaKmax timesteps
71100
A=K(:,1).*I_mkTD(:,1+1).*I_mk(:,1).*I_00.*expand(rho(:,1),[M2,1]); %I_mkTD=I_k0,k=1 I_mk=I_kk, k=1 , I_00=I_NN,k=0
72-
73101
Aend=K(:,1).*I_mkTDend(:,1+1).*I_mkEnd(:,1).*I_00.*expand(rho(:,1),[M2,1]); %I_mkTD=I_N0,N=1 I_mkEnd=I_NN, k=1 , I_00=I_NN,N=0
74-
%K(:,1)=[]; %why is this here ?
102+
%K(:,1)=[]; % only for time-dependent system Hamiltonians
75103

76104
rho(:,2)=sum(reshape(Aend,M2,M2).'); Aend=[];
77105

78-
indices=uint64(npermutek(cast(1:M2,'single'),1+1)); %makes 1:4 single precision. One can make them int(8) but then you'd have to use Jan simons's thing (or you could use Matt Fig's MEX, since you're storing it anyway)
106+
indices=uint32(npermutek(cast(1:M2,'single'),1+1)); %makes 1:4 single precision. One can make them int(8) but then you'd have to use Jan simons's thing (or you could use Matt Fig's MEX, since you're storing it anyway)
79107

80-
for J=2:deltaKmax %could go to deltaKmax-1 and incorporate the deltaKmax case into the next forloop, but the former way uses I_mkTD and the latter does not.
108+
for J=2:deltaKmax %could go to deltaKmax-1 and incorporate the deltaKmax case into the next forloop, but the former way uses I_mkTD and the latter does not.
81109

82110
indices=horzcat(expand(indices,[M2,1]),repmat((1:M2)',size(indices,1),1));% Making 1:M single precision might help
83111
A=(expand(A,[M2,1]));
@@ -91,8 +119,8 @@
91119
end
92120
A=A.*I_mkTD((indices(:,end-J)-1)*M2+indices(:,end),J+1); %the k=J case for forloop above. uses eta_k0
93121
Aend=Aend.*I_mkTDend((indices(:,end-J)-1)*M2+indices(:,end),J+1); %the k=J case for forloop above. uses eta_N0
94-
%whos('A','Aend','indices')
95-
122+
%whos('A','Aend','indices')
123+
96124
%weakPaths=find(abs(A)<tol); %in 2001 Sim, it's <=
97125
%A(weakPaths)=0;indices(weakPaths,:)=0; % might be better to just remove these rows completely, and then calculate rho using information in the leftover INDICES array. If you remove rows of A, you have to also remove rows of indices to allow A.*I_mk(indices) to work
98126
%A=sparse(A);indices=sparse(indices); %now there's a problem with indices=horzcat.... above. Not only does size(indices,1) have to be changed into length(find(indices(:,1)), but expand will also expand the 0's even though you don't want that.
@@ -108,7 +136,7 @@
108136
if strcmpi(cpuORgpu,'GPU');gpuIndex=gpuDevice(1);end
109137
KtimesIpermanent=K((indices(:,end-1)-1)*M2+indices(:,end),1); %predefine ?
110138
KtimesIpermanentEnd=KtimesIpermanent;
111-
%whos
139+
%whos
112140
for k=0:deltaKmax % it's probably faster if this tensor is just built as A is in the above forloop ... in fact it seems reading indices is slow, so perhaps even the previous iterations should be done like the tensor propagator below:
113141
KtimesIpermanent=KtimesIpermanent.*I_mk((indices(:,end-k)-1)*M2+indices(:,end),k+1); %when k=deltaKmax, we're using I_mk(:,1+deltaKmax) which used kernel(1+deltaK) which uses eta 5
114142
KtimesIpermanentEnd=KtimesIpermanentEnd.*I_mkEnd((indices(:,end-k)-1)*M2+indices(:,end),k+1);%when k=deltaKmax, we're using I_mkEnd(:,1+deltaKmax) which used kernelEnd(1+deltaK) which uses eta 3
@@ -127,7 +155,7 @@
127155
A=reshape(bsxfun(@times,reshape(sum(reshape(A,[],M2),2),1,[]),KtimesIpermanent),[],1); %could be sped up by using some of the calculations in line above
128156

129157
Aend=reshape(Aend,M2,[]); % for some reason, switching the M2 and [] and removing the ,2 in the line below alters the beginning
130-
if or(strcmp(allPointsORjustFinalPoint,'allPoints'),and(strcmp(allPointsORjustFinalPoint,'justFinalPoint'),J==finalPoint));
158+
if or(strcmpi(allPointsORjustFinalPoint,'allPoints'),and(strcmpi(allPointsORjustFinalPoint,'justFinalPoint'),J==finalPoint));
131159
switch wholeDensityMatrixOrJustDiagonals
132160
case 'justDiagonals'
133161
rho(diagonals(1:M-1),J+1)=sum(Aend(diagonals(1:M-1),:),2); % all diagonals but the last
@@ -140,7 +168,6 @@
140168
end
141169
end
142170
end
143-
144171
elapsedTime=toc;
145172
if strcmpi(cpuORgpu,'GPU')
146173
rho=gather(rho);reset(gpuIndex);
@@ -150,7 +177,7 @@
150177
function B = expand(A,S) % Compact version of: http://www.mathworks.co.uk/matlabcentral/fileexchange/24536-expand
151178

152179
SA = size(A); % Get the size (and number of dimensions) of input.
153-
if length(SA)~=length(S);error('Length of size vector must equal ndims(A). See help.');
180+
if length(SA)~=length(S);error('Length of size vector must equal ndims(A). See help.')
154181
elseif any(S~=floor(S));error('The size vector must contain integers only. See help.')
155182
end
156183
for ii = length(SA):-1:1

‎sampleInput.m

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
rhoInitial=[0 0; 0 1];
1818

1919
%% 5. system coupling matrix
20+
Nbaths=1; % Number of baths
2021
systemCouplingMatrix=[0 0;0 1]; % The system is coupled to the bath via |1X1|
2122
%systemCouplingMatrix=[1 0;0 -1]; % The system is coupled to the bath via sigma_z
2223

@@ -47,7 +48,7 @@
4748
%% 9. run the program and plot only <0|rho|0> and <1|rho|1> as a function of time
4849
wholeDensityMatrixOrJustDiagonals='justDiagonals';
4950

50-
[rho_onlyDiagonals,elapsedTime_onlyDiagonals]=FeynDyn(finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu);
51+
[rho_onlyDiagonals,elapsedTime_onlyDiagonals]=FeynDyn(Nbaths,finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu);
5152

5253
figure(1);hold('on')
5354
plot(0:totalT/finalPoint:totalT,real(rho_onlyDiagonals(1,:)));
@@ -57,11 +58,11 @@
5758
%% 10. run the program and plot all elements of the density matrix as a function of time
5859
wholeDensityMatrixOrJustDiagonals='wholeDensityMatrix';
5960

60-
[rho_allElements,elapsedTime_allElements]=FeynDyn(finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu);
61+
[rho_allElements,elapsedTime_allElements]=FeynDyn(Nbaths,finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu);
6162

6263
figure(2);hold('on')
6364
plot(0:totalT/finalPoint:totalT,real(rho_allElements(1,:)));
6465
plot(0:totalT/finalPoint:totalT,real(rho_allElements(3,:)),'r');plot(0:totalT/finalPoint:totalT,imag(rho_allElements(3,:)),'--r');
6566
plot(0:totalT/finalPoint:totalT,real(rho_allElements(3,:)),'r');plot(0:totalT/finalPoint:totalT,-imag(rho_allElements(3,:)),'--r');
6667
plot(0:totalT/finalPoint:totalT,real(rho_allElements(4,:)));
67-
xlabel('time (seconds)');
68+
xlabel('time (seconds)');
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
%% Press F5. A figure from Nancy Makri's 1995 JCP paper will be plotted.
2+
3+
%% 1. fundamental constants
4+
kb=1.3806504*10^(-23); % Joules / Kelvin
5+
hbar=1.054571628*10^(-34); % Joule * seconds
6+
7+
%% 2. temperature
8+
temperature=1/5/kb;
9+
beta=1/(kb*temperature);
10+
11+
%% 3. system hamiltonian
12+
Omega=1/hbar;%hbar*1e12*pi/8; % Rabi frequency in Joules %bho
13+
H=hbar*[0 Omega; Omega 0]; % System hamiltonian in Joules
14+
%H=hbar*[Omega Omega; Omega -Omega];
15+
16+
%% 4. initial denisty matrix
17+
rhoInitial=[1 0; 0 0];
18+
19+
%% 5. system coupling matrix
20+
Nbaths=1;
21+
%systemCouplingMatrix=[0 0;0 1]; % The system is coupled to the bath via |1X1|
22+
systemCouplingMatrix=[1 0;0 -1]; % The system is coupled to the bath via sigma_z
23+
24+
%% 6. spectral distribution function
25+
alpha=0.05*pi*hbar; % prefactor. In ps^2 / rad^2
26+
wc=7.5*Omega; % cutoff frequency. In rad/ps
27+
dw=0.01*Omega; % stepsize for w in J(w). In rad/ps
28+
w=dw:dw:10*wc; % must start with dw because coth(0)=infinity. In rad/ps
29+
J=alpha*exp(-(w/wc)).*w;% spectral density. In rad/ps
30+
31+
%J=J*1e12*hbar; % spectral distribution function. In Joules
32+
33+
%w=w*1e12; % w in s-1
34+
%dw=dw*1e12; % dw in s-1
35+
36+
%% 7. numerical parameters for Feynman integral
37+
deltaKmax=1; % number of time steps before memory kernel dies
38+
totalT=25/Omega;%10/1e12; % total time for the simulation, in seconds
39+
%totalT=15/Omega;
40+
dt=totalT/100; % size of time step (delta t)
41+
finalPoint=round(totalT/dt); % number of timesteps in total
42+
allPointsORjustFinalPoint='allPoints'; % do you just want the density matrix at time=totalT ? or do you want it at every point until then
43+
cpuORgpu='cpu';
44+
45+
%% 8. build input array that represents the densitry matrix (flattened to a column vector) as a function of time (where the columns represent the time steps)
46+
rho=zeros(numel(H),finalPoint+1);
47+
rho(:,1)=reshape(rhoInitial.',[],1); % I'm not sure about the transpose, since I'm not sure about labeling of the states in the column vector for the purposes of the final sum function.
48+
49+
%% 9. run the program and plot only <0|rho|0> and <1|rho|1> as a function of time
50+
% wholeDensityMatrixOrJustDiagonals='JustDiagonals';
51+
%
52+
% [rho_onlyDiagonals,elapsedTime_onlyDiagonals]=FeynDyn(Nbaths,finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu);
53+
%
54+
% figure(1);hold('on')
55+
% plot(0:totalT/finalPoint:totalT,real(rho_onlyDiagonals(1,:)));
56+
% plot(0:totalT/finalPoint:totalT,real(rho_onlyDiagonals(4,:)));
57+
% xlabel('time (seconds)');
58+
%% 10. run the program and plot all elements of the density matrix as a function of time
59+
wholeDensityMatrixOrJustDiagonals='wholeDensityMatrix';
60+
61+
[rho_allElements,elapsedTime_allElements]=FeynDyn(Nbaths,finalPoint,deltaKmax,totalT,rho,H,systemCouplingMatrix,w,dw,J,temperature,wholeDensityMatrixOrJustDiagonals,allPointsORjustFinalPoint,cpuORgpu);
62+
totalT=totalT*Omega;
63+
figure(2);hold('on')
64+
plot(0:totalT/finalPoint:totalT,(real(rho_allElements(1,:))-real(rho_allElements(4,:))),'k');
65+
% plot(0:totalT/finalPoint:totalT,real(rho_allElements(1,:)));
66+
% plot(0:totalT/finalPoint:totalT,real(rho_allElements(3,:)),'r');plot(0:totalT/finalPoint:totalT,imag(rho_allElements(3,:)),'--r');
67+
% plot(0:totalT/finalPoint:totalT,real(rho_allElements(3,:)),'r');plot(0:totalT/finalPoint:totalT,-imag(rho_allElements(3,:)),'--r');
68+
% plot(0:totalT/finalPoint:totalT,real(rho_allElements(4,:)));
69+
xlabel('time (seconds)');
70+

0 commit comments

Comments
 (0)
Please sign in to comment.