#include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> #include <string.h> /* --------------------------------------------------------------------------------------------------- ! The Monte-Carlo Simulation of the Stern-Gerlach Experiment (ROOT Version) ! ! In quantum mechanics, the Stern.Gerlach experiment is a celebrated experiment (performed in 1921) ! on the deflection of particles, often used to illustrate basic principles of quantum mechanics. ! It can be used to demonstrate that electrons and atoms have intrinsically quantum properties, and ! how measurement in quantum mechanics affects the system being measured. ! This is a basic simulation of an "ideal" Stern-Gerlach experiment to spatially ! separate the electrons (spin-1/2) particles. ! ! Experimental set up ! ! +--------------------------------------------------------------+ ! | | ! | Ag Slit Magnetic field Region Photographic Plate | ! | Source | ! | | ! | | | S | || | ! | | |__________________| || | ! | \|/ | || | ! | --O--------> || | ! | /|\ | __________________ || | ! | | | | || | ! | T | | N | || | ! | . . . | ! | .<------- L ------>.<-- D -->. | ! | | ! +--------------------------------------------------------------+ ! ! The program can be executed on the root terminal as follows: ! ! .x spin.C(field, quantum) [default: field=1 and quantum=1] ! ! Examples: ! ! .x spin.C(0) field = 0 --> dB/dz = 0 (uniform magnetic field) ! .x spin.C(1) field = 1 --> dB/dZ > 0 (non-uniform magnetic field along z axis) ! .x spin.C(2) field = 2 --> dB/dZ > 0 (non-uniform magnetic field along z axis) ! .x spin.C(1,0) field = 1 & quantum=0 --> dB/dZ > 0 and do not consider quantum effect ! ! See for details: http://www1.gantep.edu.tr/~bingul/seminar/spin/ ! ! All versions : http://www1.gantep.edu.tr/~bingul/seminar/spin/spin.f90 (Fortran 90) ! http://www1.gantep.edu.tr/~bingul/seminar/spin/spin.c (ANSI C) ! http://www1.gantep.edu.tr/~bingul/seminar/spin/spin.C (ROOT) ! ! Author : Dr. Ahmet Bingul <Ahmet.Bingul (at) gantep.edu.tr>, <Ahmet.Bingul (at) cern.ch> ! ! Date : Mar 2008 ! --------------------------------------------------------------------------------------------------- */ #define XMAX 0.05 // Slit width in x direction in m #define ZMAX 0.005 // Slit width in z direction in m #define kB 1.38E-23 // Bolzman constant in J/K #define PI 3.14159265359 // Number PI #define GS 2.0023 // Gyromagnetic ratio for the electron #define EoM 1.759E+11 // e/m ratio for the electron in C/kg #define HBAR 1.055E-34 // Plank constant in J.s #define L 1.000E+0 // Length in m of the region containing magnetic filed along y axis #define D 0.100E+0 // Distance in m between the end of magnetic filed and Photograhic plate #define MAg 1.792E-25 // Mass of the silver atom kg #define DBZ 100.0 // Field gradient, dB/dz, in T/m void spin(Int_t field=1, Int_t quantum=1) { const Int_t N = 100000; // Number of Silver, Ag(47), atoms Double_t T = 2000.0; // Temperature in Kelvin Double_t X[N],Z[N]; Double_t sz, muz, phi, theta; Double_t s,sm,x0,z,z0,v,a,dBdz; Int_t i; sm = HBAR*sqrt(3.0)/2.0; // Magnitude of the spin vector srand(time(NULL)); // initilize the random number generator // Loop over Silver atoms for(i=0; i<N; i++) { // A random angle on the x-y plane in the range [0,2pi] //phi = 2.0*PI*Rnd(); if(quantum){ s = +1.0; if(Rnd() < 0.5) s = -1.0; theta = acos(1.0/sqrt(3.0)); // angle and Sz sz = sm*cos(theta)*s; // are quantized } else{ theta = acos(2.0*Rnd()-1.0); // angle and Sz sz = sm*cos(theta); // are not quantized } // magnetic moment muz = -sz*GS*EoM/2.0; // Velocity of a Silver atom taken from a Maxwell-Boltzman distribution v = Maxwell_Boltzman(MAg,T); // Populate uniformly Silver atoms in x-z plane at y=0 x0 = -XMAX/2.0 + Rnd()*XMAX; z0 = -ZMAX/2.0 + Rnd()*ZMAX; // Get the field gradient dBdz = Field_Grad(field,x0); // Acceceleration and final position along z axis a = muz*dBdz/MAg; z = z0 + 0.5*a*(L/v)*(L/v) + sign(a)*D*sqrt(2.0*fabs(a)*L)/v; X[i] = x0*100; // in cm Z[i] = z*100; // in cm // print the final results to the user screen // printf("%12.4e %12.4e\n",x0,z); } TGraph *gr = new TGraph(N,X,Z); TCanvas *c1 = new TCanvas("c1","Stern-Gerlach Experiment",10,10,400,400); c1->SetFillColor(0); //gr->SetMaximum(10); //gr->SetMinimum(-10); gr->GetXaxis()->SetTitle("X (cm)"); gr->GetYaxis()->SetTitle("Z (cm)"); gr->GetXaxis()->CenterTitle(); gr->GetYaxis()->CenterTitle(); gr->SetMarkerSize(0.15); gr->SetMarkerStyle(21); gr->SetMarkerColor(2); gr->Draw("AP"); if(!field && !quantum) gr->SetTitle("SGE: dB/dz = 0, Sz is not quantized."); if(!field && quantum) gr->SetTitle("SGE: dB/dz = 0, Sz is quantized"); if( field && !quantum) gr->SetTitle("SGE: dB/dz > 0, Sz is not quantized"); if( field && quantum) gr->SetTitle("SGE: dB/dz > 0, Sz is quantized"); } /* main */ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Double_t Maxwell_Boltzman(Double_t m, Double_t T){ //-------------------------------------------------------------- // Returns, for an atom of mass m (kg) and temperature T (K), // a velocity in m/s which is randomly selected from // a Maxwell-Boltzman Distribution function, Fmb, around the // most probable velocity, vp. To do this, // the Monte-Carlo Rejection method is used. //-------------------------------------------------------------- Double_t r,v,vmax,vmin,vp,Ptest,fmb,fmax,kT,C; kT = kB*T; C = PI*sqrt(2.0) * pow(m/(PI*kT),1.5); vp = sqrt(2.0*kT/m); vmin = vp-vp/8.0; vmax = vp+vp/8.0; fmax = C * vp*vp * exp(-1.0); // Rejection algorithm while(1) { r = Rnd(); v = Rnd(); Ptest = fmax*r; v = vmin + (vmax-vmin)*v; fmb = C * v*v * exp(-0.5*m*v*v/kT); if (fmb > Ptest) return v; } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Double_t Field_Grad(Int_t op, Double_t x){ //------------------------------------------------------------ // Returns the components of the magnetic field // gradient (in Tesla/meter) along the z direction. //------------------------------------------------------------ Double_t Field_Grad; if(op==0) Field_Grad = 0.0; // uniform magnetic field in z axis else if(op==1) Field_Grad = DBZ; // non-uniform in z but uniform in x direction else Field_Grad = DBZ*exp(-25*x*x/XMAX/XMAX); // Field_Grad = DBZ*(1-4*x*x/XMAX/XMAX); return Field_Grad; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Double_t Rnd(void){ //-------------------------------------------------------------- // Returns an random number uniformly distributed between [0,1]. //-------------------------------------------------------------- return (Double_t) gRandom->Rndm(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Double_t sign(Double_t x){ //-------------------------------------------------------------- // Returns sign of x (-1 or +1) //-------------------------------------------------------------- if(x>0.0) return +1.0; else return -1.0; }