Created
January 20, 2021 19:15
-
-
Save bencbartlett/744c581d4022a2a72459fa213e3c66b1 to your computer and use it in GitHub Desktop.
Code to make the animation for https://twitter.com/bencbartlett/status/1351967463609491458
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SetDirectory[NotebookDirectory[]]; | |
\[Theta]0 = -.1 \[Pi]; \[Phi]0 = .35*\[Pi]; | |
\[Psi]0 = {Cos[\[Theta]0] Cos[\[Phi]0], Sin[\[Theta]0] Cos[\[Phi]0], | |
Sin[\[Phi]0]}; | |
Clear[BlochSphereVector]; | |
BlochSphereVector[\[Psi]_, imSize_ : 1000, color_ : Gray, | |
opacity_ : 1, \[Phi]view_ : \[Pi]/4, viewdist_ : 100] := Module[{ | |
tubeball, pointline, | |
blochSphereEmpty, | |
lineLen = 1, | |
mag = 4 | |
}, | |
tubeball[pt_, r_] := | |
Sequence[Sphere[pt, 3 r],(*Opacity[.5],*)Tube[{{0, 0, 0}, pt}, r]]; | |
pointline[pt_, r_] := | |
Sequence[Point[pt],(*Opacity[.5],*)Line[{{0, 0, 0}, pt}]]; | |
Show[ | |
Graphics3D[{Blue, [email protected], | |
Specularity[Blue, 10], | |
Sphere[{0, 0, 0}, 1], | |
Lighting -> "Neutral", | |
[email protected], Arrowheads[.03], | |
Opacity[.2], Gray, | |
Line[lineLen*{{0, 0, 0}, {0, 0, 1}}], | |
Line[lineLen*{{0, 0, 0}, {1, 0, 0}}], | |
Line[lineLen*{{0, 0, 0}, {0, 1, 0}}], | |
Opacity[.03], Gray, EdgeForm[{Transparent}], | |
Polygon[ | |
Table[{Cos[\[Theta]\[Prime]], Sin[\[Theta]\[Prime]], | |
0}, {\[Theta]\[Prime], 0, 2 \[Pi], .01}]] | |
}, | |
Boxed -> False, PlotRange -> ConstantArray[1*{-1, 1}, 3]], | |
Graphics3D[{Opacity[1], GrayLevel[.9], [email protected], | |
Point[{1, 0, 0}], | |
Point[{0, 1, 0}], | |
Point[{0, 0, 1}] | |
}], | |
Graphics3D[{ | |
Lighting -> "Neutral", | |
Thickness[0.005], | |
Arrowheads[0.025], | |
PointSize[0.02], | |
Opacity[opacity], color, tubeball[\[Psi], 0.01], | |
PointSize[0.02], | |
Opacity@1, Black, Sphere[{0, 0, 0}, 0.025] | |
}], | |
ImageSize -> imSize, | |
ImagePadding -> 0, | |
ViewVertical -> {0, 0, 1}, | |
ViewPoint -> | |
viewdist*{1 Cos[\[Phi]view], 1 Cos[\[Phi]view], 1 Sin[\[Phi]view]} | |
] | |
]; | |
BlochSphereVectorOnly[\[Psi]_, imSize_ : 1000, color_ : Gray, | |
opacity_ : 1] := Module[{tubeball}, | |
tubeball[pt_, r_] := | |
Sequence[Sphere[pt, 3 r],(*Opacity[.5],*)Tube[{{0, 0, 0}, pt}, r]]; | |
Graphics3D[{Opacity[opacity], color, tubeball[\[Psi], 0.01]}] | |
]; | |
BlochSphereVectorFromAngles[\[Theta]_, \[Phi]_, imSize_ : 1000, | |
color_ : Gray, \[Phi]view_ : \[Pi]/4, viewdist_ : 100] := | |
BlochSphereVector[{Cos[\[Theta]] Cos[\[Phi]], | |
Sin[\[Theta]] Cos[\[Phi]], Sin[\[Phi]]}, imSize, | |
color, \[Phi]view, viewdist]; | |
Clear[BlochSphereRotation]; | |
BlochSphereRotation[\[Psi]0_, \[Theta]_, ax_, tmax_ : 1, | |
imSize_ : 1000, color_ : Gray, opacityScale_ : 1, | |
tubeOpacity_ : 1] := Module[{ | |
\[Psi]1, | |
arc, arcpts, | |
thickness = 0.006}, | |
If[tmax == 0, Return[BlochSphereVector[\[Psi]0, imSize]]]; | |
\[Psi]1 = RotationMatrix[tmax*\[Theta], ax] . \[Psi]0; | |
arc = ParametricPlot3D[ | |
RotationMatrix[t \[Theta], ax] . \[Psi]0, {t, 0, tmax}, | |
PlotStyle -> Directive[Gray, Thickness[thickness]], | |
ColorFunction -> (Opacity[opacityScale*(#4 + .1), color] &)]; | |
arcpts = | |
Table[RotationMatrix[t \[Theta], ax] . \[Psi]0, {t, 0, tmax, | |
0.01}]; | |
Show[ | |
BlochSphereVector[\[Psi]1, imSize, Gray, tubeOpacity], | |
arc, | |
Graphics3D[{ | |
Opacity[0.1*opacityScale], color, | |
Thickness[0.003], | |
Arrowheads[0.02], | |
EdgeForm[{Transparent, Thickness[0.001], Dotted, color}], | |
Polygon[Join[ | |
arcpts, {Normalize[ax]*Dot[Last[arcpts], Normalize[ax]]}]] | |
}] | |
] | |
]; | |
BlochSphereRotationSequence[\[Psi]0_, \[Theta]List_, axList_, | |
animTime_ : 1, imSize_ : 1000, colorList\[Prime]_ : Null, | |
opacityList\[Prime]_ : Null] := Module[{ | |
\[Psi] = \[Psi]0, | |
i = 0, | |
colorList = colorList\[Prime], | |
opacityList = opacityList\[Prime], | |
\[Theta], ax, tmax, opacity, color, | |
displayList = {}, | |
arc, arcpts, | |
thickness = 0.006}, | |
If[colorList == Null, | |
colorList = ConstantArray[Gray, Length[\[Theta]List]]]; | |
If[opacityList == Null, | |
opacityList = ConstantArray[0.1, Length[\[Theta]List]]]; | |
If[animTime == 0, Return[BlochSphereVector[\[Psi]0, imSize]]]; | |
While[i < Length[\[Theta]List]*animTime , | |
\[Theta] = \[Theta]List[[i + 1]]; (*1-indexed*) | |
ax = axList[[i + 1]]; | |
color = colorList[[i + 1]]; | |
opacity = opacityList[[i + 1]]; | |
tmax = Clip[Length[\[Theta]List]*animTime - i, {0, 1}]; | |
arc = | |
ParametricPlot3D[ | |
RotationMatrix[t \[Theta], ax] . \[Psi], {t, 0, tmax}, | |
PlotStyle -> Directive[Gray, Thickness[thickness]], | |
ColorFunction -> (Opacity[#4 + .1, color] &)]; | |
arcpts = | |
Table[RotationMatrix[t \[Theta], ax] . \[Psi], {t, 0, tmax, | |
0.01}]; | |
\[Psi] = RotationMatrix[tmax*\[Theta], ax] . \[Psi]; | |
AppendTo[displayList, arc]; | |
AppendTo[displayList, | |
Graphics3D[{ | |
Opacity[opacity], color, | |
Thickness[0.003], | |
Arrowheads[0.02], | |
EdgeForm[{Transparent, Thickness[0.001], Dotted, color}], | |
Polygon[ | |
Join[arcpts, {Normalize[ax]*Dot[Last[arcpts], Normalize[ax]]}]] | |
}] | |
]; | |
++i; | |
]; | |
Show[BlochSphereVector[\[Psi], imSize], displayList] | |
]; | |
baseSwitchClosed = | |
Import["/Users/ben/Dropbox/Research/qpgav2/animation/switches_\ | |
closed_2.png"]; | |
baseSwitchOpen = | |
Import["/Users/ben/Dropbox/Research/qpgav2/animation/switches_open_\ | |
2.png"]; | |
base = baseSwitchClosed; | |
(*these coordinates were chosen by clicking points on the images to \ | |
trace the photon path*) | |
coordsRingToBeamsplitterTop = \ | |
{{3213.8305999348113`, 1059.3037483813007`}, {3166.0119817800314`, | |
1106.6882343267484`}, {3125.583593903153`, | |
1147.1165061254958`}, {3086.4594599043658`, | |
1186.67535272427`}, {3043.4227964275683`, | |
1229.27718752295`}, {2987.779583629292`, | |
1271.009597121657`}, {2905.619018309969`, | |
1274.9220105215356`}, {2810.8516715129053`, | |
1275.7914357215086`}, {2726.5174271155183`, | |
1276.6608609214818`}, {2650.008009517889`, | |
1275.7914357215086`}, {2563.934914720556`, | |
1275.7914357215086`}, {2471.3400862202475`, | |
1288.398101121118`}, {2384.3975662229414`, | |
1321.870971320081`}, {2303.1298738860205`, | |
1367.5585691098804`}, {2225.3164345665623`, | |
1424.505919708116`}, {2153.588739490654`, | |
1485.36568370623`}, {2088.3818494926745`, | |
1550.137861104223`}, {2029.260935894506`, | |
1610.5629125023506`}, {1969.2705970963648`, | |
1681.8557789001418`}, {1903.4672057829514`, | |
1751.2574705894`}, {1783.5966424593155`, | |
1804.267902358066`}}; coordsRingToBeamsplitterBottom = \ | |
{{3213.8027411834105`, 1058.23640996825`}, {3182.50343398438`, | |
1028.2412405691794`}, {3149.8998729072596`, | |
998.2460711701087`}, {3115.5574614301927`, | |
963.4690631711865`}, {3079.911260387559`, | |
928.2573425722774`}, {3040.78689423251`, | |
888.2637833735166`}, {2990.360232634072`, | |
847.8355115747693`}, {2923.414724392408`, | |
845.2272359748501`}, {2853.8607083945635`, | |
844.7925233748635`}, {2786.4801393185203`, | |
844.7925233748635`}, {2716.9261233206753`, | |
843.9230981748906`}, {2651.7190011664343`, | |
845.2272359748501`}, {2583.903835568535`, | |
844.7925233748635`}, {2514.3498195706907`, | |
842.1842477749444`}, {2434.7975298512865`, | |
828.2734445753754`}, {2355.6796044974762`, | |
806.537814576049`}, {2280.909037299793`, | |
774.3690821770456`}, {2214.397893423723`, | |
734.8102355782714`}, {2152.668704225636`, | |
689.1654125796856`}, {2102.2420426271983`, | |
640.9123139811809`}, {2060.944229550347`, | |
591.789790182703`}, {2013.9952687518016`, | |
538.7547369062154`}, {1951.3966543537413`, | |
490.50163830771044`}, {1901.8394179552768`, | |
433.11957510948855`}, {1850.1085024787487`, | |
372.6945237113607`}, {1784.032303358927`, 309.66119671331376`}}; | |
coordsBeamsplitterToMirrorTop = {{4397.265782207965`, | |
1275.59}, {4341.867493152422`, 1275.59}, {4277.8731729089595`, | |
1275.59}, {4212.9234547059095`, 1275.59}, {4147.9737365028595`, | |
1275.59}, {4089.2323197232695`, 1275.59}, {4027.148030264472`, | |
1275.59}, {3963.63089891113`, 1275.59}, {3892.472879284618`, | |
1274.770400099958`}, {3819.4043187837683`, | |
1275.59}, {3746.8129471730385`, 1275.59}, {3683.295815819696`, | |
1275.59}, {3611.182653278434`, 1275.59}, {3531.428092374329`, | |
1275.7255430147088`}, {3443.55417908275`, | |
1272.382542813081`}, {3382.425032538703`, | |
1228.92290257983`}, {3326.0716005684094`, | |
1172.0918991521612`}, {3269.718168598116`, | |
1113.8281813523663`}, {3214.3198795425733`, 1058.907463754199`}}; | |
coordsBeamsplitterToAtomBottom = {{4222.067322203811`, | |
842.69}, {4206.785035567799`, 842.69}, {4193.89098878592`, | |
842.69}, {4173.355288596361`, 842.69}, {4155.68527219589`, | |
842.69}, {4134.672128071375`, 842.69}, {4115.091315751729`, | |
842.69}, {4091.606022021691`, | |
846.1683803338327`}, {4068.6825920676724`, | |
842.69}, {4047.6694479431567`, 842.69}, {4006.5983026088747`, | |
842.69}, {3955.498284192129`, 842.69}, {3892.4588518185806`, | |
842.69}, {3827.5091336155306`, 842.69}, {3767.812573921191`, | |
842.69}, {3701.90771280339`, 842.69}, {3639.3459794096357`, | |
842.69}, {3575.828848056293`, 842.69}, {3511.8342727679938`, | |
842.69}, {3437.810059262719`, | |
848.5562376207095`}, {3385.7548979312223`, | |
887.2395256681143`}, {3348.5043242559436`, | |
925.9228137155192`}, {3303.134908282865`, | |
969.859387794053`}, {3259.1983342043313`, | |
1014.7511047873376`}, {3214.784316190841`, 1059.1652503232467`}}; | |
ringXY = {1125, 1060}; (* approx center of ring in pixels *) | |
ringRadius = 995; | |
(*Manipulate[Show[base,Graphics[{Magenta,Circle[{x,y}, r]}],ImageSize\ | |
\[Rule]1500],{x,1100,1200},{y,1000,1200},{r,950,1100}]*) | |
\ | |
(*Show[base,Graphics[{Magenta,Circle[ringXY, ringRadius]}],ImageSize\ | |
\[Rule]1500]*) | |
coordsRing = | |
Table[ringXY - ringRadius*{Cos[2 \[Pi] t], Sin[2 \[Pi] t]}, {t, 0, | |
1, 0.01}]; | |
(*pathRingCCW[t_]:= ringXY-ringRadius*{Cos[2\[Pi] t], Sin[2\[Pi] t]}; | |
pathRingCW[t_] := ringXY-ringRadius*{Cos[-2\[Pi] t], Sin[-2\[Pi] \ | |
t]}; | |
(*Manipulate[Show[base,Graphics[{PointSize[0.05],Red,Point[pathRingCW[\ | |
t]], Blue,Point[ pathRingCCW[t]]}],ImageSize\[Rule]1500],{t,0,1}]*)*) | |
ymax = 1.2* | |
ImageAspectRatio[ | |
base]; (*stretch the image vertically a little to make it look \ | |
less distorted when viewed from an angle*) | |
p = {{0, 0}, {1, 0}, {1, ymax}, {0, ymax}}; | |
plane = Graphics3D[{ | |
EdgeForm[Opacity[0.2]], | |
Texture[base], | |
Polygon[(Join[#1, {0.002}] &) /@ p, | |
VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}] | |
}]; | |
(*Show[ | |
plane, | |
PlotRange\[Rule]{{0,1},{0,ymax},{-.1,.1}}, | |
ViewPoint\[Rule] 1*{0,-1.5,2}, ViewVertical\[Rule]{0,0,1}, | |
ImageSize\[Rule]1500,ImagePadding\[Rule]5,Boxed\[Rule]False,Lighting\ | |
\[Rule]"Neutral"]*) | |
coordsRingNormalized = | |
Map[((#/ ImageDimensions[base])*{1, ymax}) &, coordsRing]; | |
coordsRingToBeamsplitterTopNormalized = | |
Map[((#/ ImageDimensions[base])*{1, ymax}) &, | |
coordsRingToBeamsplitterTop]; | |
coordsRingToBeamsplitterBottomNormalized = | |
Map[((#/ ImageDimensions[base])*{1, ymax}) &, | |
coordsRingToBeamsplitterBottom]; | |
coordsBeamsplitterToMirrorTopNormalized = | |
Map[((#/ ImageDimensions[base])*{1, ymax}) &, | |
coordsBeamsplitterToMirrorTop]; | |
coordsBeamsplitterToAtomBottomNormalized = | |
Map[((#/ ImageDimensions[base])*{1, ymax}) &, | |
coordsBeamsplitterToAtomBottom]; | |
tspecTop1 = | |
Rescale[Prepend[ | |
Accumulate[ | |
Map[Norm, Differences[coordsRingToBeamsplitterTopNormalized]]], | |
0]]; | |
tspecTop2 = | |
Rescale[Prepend[ | |
Accumulate[ | |
Map[Norm, Differences[coordsBeamsplitterToMirrorTopNormalized]]], | |
0]]; | |
tspecBot1 = | |
Rescale[Prepend[ | |
Accumulate[ | |
Map[Norm, | |
Differences[coordsRingToBeamsplitterBottomNormalized]]], 0]]; | |
(*no tspecBot2 because we want photon to seem like it's moving slower \ | |
in chamber*) | |
zValueForPath = 0.0; | |
pathRingCCW = | |
Interpolation[ | |
TimeSeries[ | |
Join[#1, {zValueForPath}] & /@ coordsRingNormalized, {0, 1}]]; | |
pathRingCW = | |
Interpolation[ | |
TimeSeries[ | |
Reverse[Join[#1, {zValueForPath}] & /@ coordsRingNormalized], {0, | |
1}]]; | |
pathTop1 = | |
Interpolation[ | |
TimeSeries[ | |
Reverse[Join[#1, {zValueForPath}] & /@ | |
coordsRingToBeamsplitterTopNormalized], {tspecTop1}]]; | |
pathTop2 = | |
Interpolation[ | |
TimeSeries[ | |
Reverse[Join[#1, {zValueForPath}] & /@ | |
coordsBeamsplitterToMirrorTopNormalized], {tspecTop2}]]; | |
pathBot1 = | |
Interpolation[ | |
TimeSeries[ | |
Reverse[Join[#1, {zValueForPath}] & /@ | |
coordsRingToBeamsplitterBottomNormalized], {tspecBot1}]]; | |
pathBot2 = | |
Interpolation[ | |
TimeSeries[ | |
Reverse[Join[#1, {zValueForPath}] & /@ | |
coordsBeamsplitterToAtomBottomNormalized], {0, 1}]]; | |
(*define functions to show the pulses*) | |
dt = 0.001;(*0.0005;*) | |
rfunc = | |
Function[{x, y, z}, Abs[z] > 0.001]; | |
opac = 0.3; | |
A0 = 0.05; | |
vg = 1.3; | |
\[Omega] = 70; | |
\[Delta]\[Omega] = 250; | |
Clear[pulse, ringPulse, reflectedPulse]; | |
pulse[path_, A_, \[Tau]_, color_, op_ : opac] := ListPointPlot3D[ | |
Table[path[t] + {0, 0, | |
A*A0 Cos[\[Omega] (\[Tau]/vg - | |
t)] Exp[-\[Delta]\[Omega] (\[Tau] - t)^2]}, {t, 0, 1, | |
dt}], | |
PlotStyle -> {color, PointSize[Small]}, Filling -> 0, | |
FillingStyle -> {color, Opacity[op]}, RegionFunction -> rfunc, | |
RegionBoundaryStyle -> None]; | |
ringPulse[path_, A_, \[Tau]_, color_, pointOp_ : 1, op_ : opac, | |
numRotations_ : 1] := ListPointPlot3D[ | |
Table[path[Mod[t/4, 1]] + {0, 0, | |
A*A0 Cos[\[Omega] (\[Tau]/vg - | |
t)] Exp[-\[Delta]\[Omega] ((\[Tau] - t)^2)]}, {t, 0, | |
4*numRotations, dt}], | |
PlotStyle -> {color, Opacity[pointOp], PointSize[Small]}, | |
Filling -> 0, FillingStyle -> {color, Opacity[op]}, | |
RegionFunction -> rfunc, RegionBoundaryStyle -> None]; | |
reflectedPulse[path_, A_, \[Tau]_, color_, \[Phi]_ : -1] := | |
ListPointPlot3D[ | |
Table[path[t] + {0, 0, | |
A*A0 Cos[\[Omega] (\[Tau]/vg - | |
t)] Exp[-\[Delta]\[Omega] (\[Tau] - t)^2] + \[Phi]*A* | |
A0 Cos[\[Omega] ((\[Tau] - 1)/ | |
vg + (t - 1))] Exp[-\[Delta]\[Omega] ((\[Tau] - | |
1) + (t - 1))^2] | |
}, {t, 0, 1, dt}], | |
PlotStyle -> {color, PointSize[Small]}, Filling -> 0, | |
FillingStyle -> {color, Opacity[opac]}, RegionFunction -> rfunc, | |
RegionBoundaryStyle -> None]; | |
BS = 1/Sqrt[2] ({ | |
{1, I}, | |
{I, 1} | |
}); | |
\[Phi]ringDelay = 1.465(*1.462*); | |
createPulses[\[Alpha]_, \[Beta]_, t_] := | |
Module[{A, B, \[Alpha]\[Prime], \[Beta]\[Prime]}, | |
{A, B} = Abs[BS . {\[Alpha], \[Beta]}]; | |
{\[Alpha]\[Prime], \[Beta]\[Prime]} = Abs[BS . {A, -B}]; | |
Show[ | |
pulse[pathTop1, \[Alpha], t, Red], | |
pulse[pathBot1, \[Beta], t, Blue], | |
reflectedPulse[pathTop2, A, t - 1, Purple, 1], | |
reflectedPulse[pathBot2, B, t - 1, Magenta, -1], | |
pulse[pathTop1, \[Alpha], 3 - (t - 1), Blue], | |
pulse[pathBot1, \[Beta], 3 - (t - 1), Red] | |
] | |
]; | |
createRingPulses[\[Alpha]_, \[Beta]_, t_] := | |
Module[{CWpath, CCWpath}, | |
CWpath[\[Tau]_] := pathRingCW[Mod[\[Tau] + \[Phi]ringDelay/4, 1]]; | |
CCWpath[\[Tau]_] := pathRingCCW[Mod[\[Tau] + \[Phi]ringDelay/4, 1]]; | |
Show[ | |
ringPulse[CWpath, \[Alpha], t, Red], | |
ringPulse[CCWpath, \[Beta], t, Blue] | |
] | |
]; | |
createRingPulsesReturn[\[Alpha]_, \[Beta]_, t_] := | |
Module[{CWpath, CCWpath}, | |
CWpath[\[Tau]_] := pathRingCW[Mod[\[Tau] - \[Phi]ringDelay/4, 1]]; | |
CCWpath[\[Tau]_] := pathRingCCW[Mod[\[Tau] - \[Phi]ringDelay/4, 1]]; | |
Show[ | |
ringPulse[CWpath, \[Alpha], t, Red, 1, opac, 2], | |
ringPulse[CCWpath, \[Beta], t, Blue, 1, opac, 2] | |
] | |
]; | |
createOtherRingPulses[t_, nPulses_ : 4 - 1] := | |
Module[{t\[Prime] = t + \[Phi]ringDelay, pointOp = .1, op = .07}, | |
Show[ | |
ringPulse[pathRingCW, 1, Mod[t\[Prime] - 1*4/6, 4], Red, pointOp, | |
op], | |
ringPulse[pathRingCW, 1, Mod[t\[Prime] - 2*4/6, 4], Red, pointOp, | |
op], | |
ringPulse[pathRingCW, 1, Mod[t\[Prime] - 3*4/6, 4], Red, pointOp, | |
op], | |
ringPulse[pathRingCW, 1, Mod[t\[Prime] - 4*4/6, 4], Red, pointOp, | |
op], | |
ringPulse[pathRingCW, 1, Mod[t\[Prime] - 5*4/6, 4], Red, pointOp, | |
op], | |
ringPulse[pathRingCCW, 1, Mod[t\[Prime] - 1*4/6, 4], Blue, pointOp, | |
op], | |
ringPulse[pathRingCCW, 1, Mod[t\[Prime] - 2*4/6, 4], Blue, pointOp, | |
op], | |
ringPulse[pathRingCCW, 1, Mod[t\[Prime] - 3*4/6, 4], Blue, pointOp, | |
op], | |
ringPulse[pathRingCCW, 1, Mod[t\[Prime] - 4*4/6, 4], Blue, pointOp, | |
op], | |
ringPulse[pathRingCCW, 1, Mod[t\[Prime] - 5*4/6, 4], Blue, pointOp, | |
op] | |
] | |
] | |
ringSpeed = 1 + 2*(1/2 - \[Phi]ringDelay/4); | |
(*"retroactive" Bloch sphere rotation to show teleportation action*) | |
customBlochSphereRotationSequence[\[Psi]0_, \[Theta]List_, axList_, | |
animTime_ : 1, imSize_ : 1000, colorList\[Prime]_ : Null, | |
opacityList\[Prime]_ : Null, auxTime_ : 1] := Module[{ | |
\[Psi] = \[Psi]0, | |
i = 0, | |
colorList = colorList\[Prime], | |
opacityList = opacityList\[Prime], | |
\[Theta], ax, tmax, opacity, color, | |
displayList = {}, | |
arc, arcpts, | |
thickness = 0.006, | |
aux\[Theta] = 0.7 \[Pi], auxAx = {0, 1, 0}, auxInsertionPos = 1, | |
auxColor = Magenta, auxOp = 0.1 | |
}, | |
If[colorList == Null, | |
colorList = ConstantArray[Gray, Length[\[Theta]List]]]; | |
If[opacityList == Null, | |
opacityList = ConstantArray[0.1, Length[\[Theta]List]]]; | |
If[animTime == 0.0, Return[BlochSphereVector[\[Psi]0, imSize]]]; | |
While[i < Length[\[Theta]List]*animTime , | |
(*retroactively insert a rotation here*) | |
If[i == auxInsertionPos && auxTime > 0.0, | |
arc = | |
ParametricPlot3D[ | |
RotationMatrix[t aux\[Theta], auxAx] . \[Psi], {t, 0, | |
auxTime}, | |
PlotStyle -> Directive[auxColor, Thickness[thickness]], | |
ColorFunction -> (Opacity[#4 + .1, auxColor] &)]; | |
arcpts = | |
Table[ | |
RotationMatrix[t aux\[Theta], auxAx] . \[Psi], {t, 0, auxTime, | |
0.01}]; | |
\[Psi] = RotationMatrix[auxTime*aux\[Theta], auxAx] . \[Psi]; | |
AppendTo[displayList, arc]; | |
AppendTo[displayList, | |
Graphics3D[{ | |
Opacity[auxOp], auxColor, | |
Thickness[0.003], | |
Arrowheads[0.02], | |
EdgeForm[{Transparent, Thickness[0.001], Dotted, auxColor}], | |
Polygon[Join[ | |
arcpts, {Normalize[auxAx]* | |
Dot[Last[arcpts], Normalize[auxAx]]}]] | |
}] | |
]; | |
]; | |
\[Theta] = \[Theta]List[[i + 1]]; (*1-indexed*) | |
ax = axList[[i + 1]]; | |
color = colorList[[i + 1]]; | |
opacity = opacityList[[i + 1]]; | |
tmax = Clip[Length[\[Theta]List]*animTime - i, {0, 1}]; | |
arc = | |
ParametricPlot3D[ | |
RotationMatrix[t \[Theta], ax] . \[Psi], {t, 0, tmax}, | |
PlotStyle -> Directive[Gray, Thickness[thickness]], | |
ColorFunction -> (Opacity[#4 + .1, color] &)]; | |
arcpts = | |
Table[RotationMatrix[t \[Theta], ax] . \[Psi], {t, 0, tmax, | |
0.01}]; | |
\[Psi] = RotationMatrix[tmax*\[Theta], ax] . \[Psi]; | |
AppendTo[displayList, arc]; | |
AppendTo[displayList, | |
Graphics3D[{ | |
Opacity[opacity], color, | |
Thickness[0.003], | |
Arrowheads[0.02], | |
EdgeForm[{Transparent, Thickness[0.001], Dotted, color}], | |
Polygon[Join[ | |
arcpts, {Normalize[ax]*Dot[Last[arcpts], Normalize[ax]]}]] | |
}] | |
]; | |
++i; | |
]; | |
Show[BlochSphereVector[\[Psi], imSize], displayList] | |
]; | |
(* | |
Timings: | |
t~0-0.1:red photon enters scattering unit | |
t~0.1-0.2:blue photon enters scattering unit | |
t~0.4-0.6 photon passes phase shifter | |
t=1:photon passes beamsplitter | |
t=2:photon hits atom/mirror | |
t=3:photon passes beamsplitter (return) | |
t~3.4:photon passes phase shifter | |
t=4:photon re-injected into ring | |
t=4-4.75:atom state rotated | |
t=5.25-5.75:atom measured,teleportation animation shown | |
*) | |
\[Theta]0atom = \[Pi]/2; \[Phi]0atom = 0; | |
\[Psi]0atom = {Cos[\[Theta]0atom] Cos[\[Phi]0atom], | |
Sin[\[Theta]0atom] Cos[\[Phi]0atom], Sin[\[Phi]0atom]}; | |
\[Psi]1atom = {0, 0, -1}; | |
scaleTime01[t_, min_, | |
max_] := (Clip[t, {min, max}] - min)/(max - | |
min); (*scales a time range between min and max to run from 0 to \ | |
1*) | |
laserImg = | |
Import["/Users/ben/Dropbox/Research/qpgav2/animation/laser_pulse.\ | |
png"]; | |
baseSwitchClosedLaserOn = | |
Import["/Users/ben/Dropbox/Research/qpgav2/animation/switches_\ | |
closed_laser_on.png"]; | |
baseSwitchClosedMeterOn = | |
Import["/Users/ben/Dropbox/Research/qpgav2/animation/switches_\ | |
closed_meter_on_laser_on_labeled.png"]; | |
laserPlane = Graphics3D[{ | |
EdgeForm[Opacity[0.0]], Texture[laserImg], | |
Polygon[(Join[#1, {0.003}] &) /@ p, | |
VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}] | |
}]; | |
Clear[showBase]; | |
showBase[t_, imSize_ : 1500, debug_ : False] := | |
Module[{texture, blochPhoton, blochAtom, tAtomRotate, tPhotonZ, | |
tMeas, ballSize, imScale, meterAngle, meterPivot, meterEnd, meter}, | |
ballSize = imSize/5; | |
imScale = imSize/1500; | |
(* set up progress of different events of animation *) | |
tPhotonZ = 0; | |
tPhotonZ += 1/2*scaleTime01[t, 0.4, 0.6]; | |
tPhotonZ += 1/2*2/3*scaleTime01[t, 1.9, 2.1]; | |
tPhotonZ += 1/2*1/3*scaleTime01[t, 3.4, 3.6]; | |
tAtomRotate = scaleTime01[t, 4, 4.75]; | |
tMeas = scaleTime01[t, 5.25, 5.65]; | |
If[debug, | |
Print[tPhotonZ]; | |
Print[tAtomRotate]; | |
Print[tMeas]; | |
]; | |
meterAngle = 80 Degree *(Sin[\[Pi] tMeas] - .5); | |
meterPivot = {0.9235, ymax*.5, 0}; | |
meterEnd = | |
meterPivot + | |
RotationMatrix[meterAngle, {0, 0, -1}] . {0, .03, 0}; | |
meter = Line[{meterPivot, meterEnd}]; | |
blochPhoton = | |
customBlochSphereRotationSequence[\[Psi]0, {\[Pi]/ | |
4, \[Pi]/2 + \[Pi]/4}, {{0, 0, 1}, {0, 0, 1}}, tPhotonZ, | |
ballSize, {Gray, Gray}, Null, tMeas]; | |
blochAtom = Show[ | |
BlochSphereRotation[\[Psi]0atom, 0.7 \[Pi], {1, 0, 0}, | |
tAtomRotate, ballSize, Magenta, 1 - tMeas, 1 - tMeas], | |
BlochSphereVectorOnly[\[Psi]1atom, ballSize, Magenta, tMeas] | |
]; | |
texture = If[0 <= t <= 0.2 || 3.8 <= t <= 4.0, baseSwitchOpen, | |
If[0 < tAtomRotate < 1, baseSwitchClosedLaserOn, | |
If[0 < tMeas < 1, baseSwitchClosedMeterOn, | |
baseSwitchClosed] | |
] | |
]; | |
Show[ | |
Graphics3D[{ | |
Inset[blochPhoton, {.58, 1.07*ymax, -.12}], | |
Inset[blochAtom, {.88, 1.07*ymax, -.12}], | |
EdgeForm[Opacity[0.0]], | |
Texture[texture], | |
Polygon[(Join[#1, {0.002}] &) /@ p, | |
VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}], | |
Text[ | |
Style["|photon\[RightAngleBracket]", 25*imScale, | |
Gray], {0.58 - .12, 1.07*ymax + .02, -.00}], | |
Text[ | |
Style["|atom\[RightAngleBracket]", 25*imScale, | |
Gray], {0.88 - .12, 1.07*ymax + .02, -.00}], | |
If[tAtomRotate > 0, Text[Style["Subscript[R, x](\[Theta])", 18*imScale, Magenta, | |
Opacity[tAtomRotate - tMeas]], {0.89, .90*ymax, -.00}]], | |
If[tMeas > 0, Text[Style["Subscript[R, y](-\[Theta])", 18*imScale, Magenta, Opacity[tMeas]], {0.55, .86*ymax, -.00}]], | |
Thick, Black, meter, | |
If[debug, | |
Text[Style["t=" <> ToString[N[t, 3]], 25*imScale, Gray], {0.1, | |
1.07*ymax + .02, -.00}]] | |
}], | |
PlotRange -> {{0, 1}, {0, ymax}, {-.1, .1}}, | |
ViewPoint -> 1*{0, -1.5, 2}, ViewVertical -> {0, 0, 1}, | |
ImageSize -> imSize, ImagePadding -> 5, Boxed -> False, | |
Lighting -> "Neutral"] | |
]; | |
Clear[renderFrame]; | |
renderFrame[t_, imSize_ : 1000, debug_ : False] := Quiet@Show[ | |
showBase[t, imSize, debug], | |
createRingPulses[1, 1 , ringSpeed (t) + 4], | |
createRingPulsesReturn[-1, -1, ringSpeed (t - 4)], | |
createOtherRingPulses[t ringSpeed], | |
createPulses[-1, -1, t], | |
PlotRange -> {{0, 1}, {0, ymax}, {-.1, .1}}, | |
ViewPoint -> 1*{0, -1.5, 2}, ViewVertical -> {0, 0, 1}, | |
ImageSize -> imSize, ImagePadding -> 5, Boxed -> False, | |
Lighting -> "Neutral"] | |
saveFrame[t_] := Module[{frame, title}, | |
frame = Quiet[renderFrame[t, 2000]]; | |
title = IntegerString[Floor[10^4 * (t + 2)], 10, 6] <> ".png"; | |
Export["frames/" <> title, frame]; | |
Print["rendered frame: " <> title] | |
] | |
start = -1; stop = 8.5; | |
simTimescale = (stop - start); | |
animationTime = 15; | |
framesPerSec = 60; | |
frameStep = simTimescale /(animationTime*framesPerSec); | |
ParallelDo[saveFrame[t], {t, start, stop, frameStep}] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment