/* SCHI2: Applies my belated realization that my direct original discretization of the Schroedinger equation could be interpreted as a second-order difference equation, which could be implemented reversibly using integers, without going through the whole development of the successive additional approximations employed in SCH, SCHU, SCHD, and SCHI. Moreover, SCHI2 can also be seen as a direct first-order approximation of SCHI. Thus you can proceed all the way around the circle SCHI2->SCH->SCHU->SCHD->SCHI->SCHI2 by considering each program to be a direct first-order approximation of the previous program. */ #include #include #include #include /* Physical constants. We'll use MKS (m,kg,s,nt,J,coul...) units. */ #define planck_h (6.626e-34) /* Planck's constant, in Joule-seconds */ #define light_c (2.998e8) /* Speed of light in meters/second */ static const double hbar = planck_h/(2*M_PI), /* h/2*pi, also in J-sec */ elec_m = 9.109e-31, /* Electron rest mass, in kg */ elec_q = 1.602e-19, /* Electron charge (abs.value) in Coulombs */ coul_const = 8.988e9; /* 1/4*pi*epsilon_0 (Coulomb's law constant) in nt-m^2/coul^2. */ /* Parameters of simulation. o */ #define space_width (1e-10) /* Width of sim space in meters: 1 A. */ #define num_pts (100) /* Number of discrete space points in sim. */ static const double sim_dx = space_width/num_pts, /* delta btw. pts, in meters. */ sim_dt = 5e-22, /* Simulated time per step, in secs. */ init_vel = light_c*0.0, /* Initial velocity in m/s */ initial_mu = -space_width/4, /* initial mean electron pos, rel. to ctr. */ initial_sigma = space_width/20; /* width of initial hump. */ /* For holding some arrays of size num_pts, in real/imaginary pairs. */ static double *energies, /* Real potential energies at points. */ *on_real,*on_imag, *off_real,*off_imag, /* On/off diagonal matrix elements, real/imag */ *Psi_real,*Psi_imag; /* Real at t, imag at t+1/2. */ /* Now, we will use Psi_real and Psi_imag only for translation between the internal, integer form, and how it is used externally. Here is the real wave function: */ static int *psiR,*psiI; /* Real and imaginary integer wave function. */ static double scaleFactor; /* The value, in the integer range, that a real value of 1.0 translates to. */ static int n_steps = 0; /* Number of iterations done so far. */ static double total_t = 0; /* Total simulated time so far. */ static int max_steps = 100000; /* go a million iterations before reversing */ static int direction = 0; /* forwards */ #define STEPS_PER_SHOT 20 typedef enum energ_funcs { neg_gaus=0, pos_gaus, inv_cutoff, parabolic, const_nonzero, const_zero, step_barrier } energ_func_id; static energ_func_id which_potential = step_barrier; static const char *energ_func_strs[] = { "Negative Gaussian potential well", "Positive Gaussian potential bump", "Inverse distance well with cutoff", "Parabolic well for harmonic oscillator", "Constant, non-zero energy level", "Constant, zero energy", "A step barrier to tunnel through" }; void print_sim_params() { printf("\n"); printf("SCHROEDINGER SIMULATOR PARAMETERS\n"); printf("---------------------------------\n"); printf("\n"); printf("Width of simulated space is %g meters (%g light-seconds).\n", space_width, space_width/light_c); printf("Simulating %d discrete points in space.\n", num_pts); printf("Distance between points: %g m (%g ls).\n",sim_dx, sim_dx/light_c); printf("Time per simulation step: %g secs (light dist: %g m)\n", sim_dt, sim_dt*light_c); printf("Initial electron position: mu=%g m, sigma=%g m.\n", initial_mu, initial_sigma); printf("Using potential energy function %d: %s.\n", which_potential, energ_func_strs[which_potential]); printf("Initial electron velocity = %g m/s (%g c).\n", init_vel, init_vel/light_c); printf("Number of steps to go before reversing: %d.\n",max_steps); printf("\n"); } static double *init_real,*init_imag; void print_stats() { /* Calculate and print some stats of the wavefunction. */ int this = n_steps&1; int i; double total_p = 0; double mom_real = 0, mom_imag = 0, potential = 0, kin_real = 0, kin_imag = 0, energ_real = 0, energ_imag = 0; double dPsi2_real, dPsi2_imag; double diff=0; for(i=0;i -4e-14) { return p; } else { return -4e-14; } } case parabolic: /* Parabolic well for harmonic oscillator. */ return x*x*1e+6; case const_nonzero: /* Constant, nonzero energy. Apparent wave rotation rate differs from zero-energy case.*/ return -24e-15; case const_zero: /* Constant, zero energy. */ return 0; case step_barrier: /* A step barrier through which to tunnel. */ if (x < space_width * 0.15) { return 0; } else if (x < space_width * 0.18) { return 1e-15; } else { return 0; } } return 0; } static double epsilon; static double *alphas; static int *alphasi; static int epsiloni; void cache_energies() { int i; /* epsilon: an angle that roughly indicates how much of a point's amplitude gets spread to its neighboring points per time step. A function of sim dt and dx parameters only. */ epsilon = hbar*sim_dt/(elec_m*sim_dx*sim_dx); epsiloni = (int)((unsigned)(0x80000000) * epsilon); printf("Sim epsilon angle: %g radians (%g of a circle).\n", epsilon, epsilon/(2*M_PI)); printf("Integer epsilon: %d\n",epsiloni); energies = malloc_doubles(); on_real = malloc_doubles(); on_imag = malloc_doubles(); off_real = malloc_doubles(); off_imag = malloc_doubles(); alphas = malloc_doubles(); alphasi = malloc_ints(); printf("Alphas:\n"); for(i=0;imaxval) maxval=absval; absval = Psi_imag[i]; absval = (absval<0)?-absval:absval; if (absval>maxval) maxval=absval; } printf("The maximum absolute value initially is: %g.\n",maxval); /* We'll scale our integers so that they can hold values up to almost twice the largest initial value before they incur an overflow. */ scaleFactor = (1<<30)/maxval; printf("Therefore the scale factor will be: %g.\n",scaleFactor); } /* Convert to integers. */ printf("Integer psis:\n"); for(i=0;i>= 1; if (m1p&mask) prod += m2p>>pos; } if (m1<0) prod = -prod; if (m2<0) prod = -prod; return prod; } double function(int *vec,int i){ int j,k; j = i+1; if (j==-1) j=num_pts-1; else if (j==num_pts) j=0; k = i-1; if (k==-1) k=num_pts-1; else if (k==num_pts) k=0; /* This first minus was needed because Atheta in the program is the negative of the alpha_i used in my calculations. */ return 2*alphas[i]*vec[i] - epsilon*vec[j] - epsilon*vec[k]; } void step_forwards() { int i; for(i=0;i #include #include #include "icon.bitmap" #define BITMAPDEPTH 1 static Display *display; static int screen; static double *prev_real, *prev_imag; static double maxv; static double maxp; void init_graphics() { int i; int this = n_steps&1; prev_real = malloc_doubles(); prev_imag = malloc_doubles(); maxv = 0; maxp = 0; for(i=0;i maxv) maxv = absv; absv = Psi_imag[i]; absv = (absv<0)?-absv:absv; if (absv > maxv) maxv = absv; absv = Psi_real[i]*Psi_real[i] + Psi_imag[i]*Psi_imag[i]; if (absv > maxp) maxp = absv; } } void draw_graphics(win,gc,window_width,window_height,gce,gcreal,gcimag) Window win; GC gc; unsigned window_width, window_height; GC gce,gcreal,gcimag; { double ght = window_height/2; /* How much Y space per graph */ unsigned c1 = ght/2; /* origin y for top graph */ unsigned c2 = window_height; /* origin y for bottom graph */ int this = n_steps&1; /* which Psi is current */ int i; for(i=0;ifid); { XColor sdr,edr; if (foo == 1) { XSetForeground(display,*gc,WhitePixel(display,screen)); } else if (foo == 0) { XSetForeground(display,*gc,BlackPixel(display,screen)); } else if (foo == 2) { XAllocNamedColor(display,DefaultColormap(display,screen),"cyan", &sdr,&edr); XSetForeground(display,*gc,edr.pixel); } else if (foo == 3) { XAllocNamedColor(display,DefaultColormap(display,screen),"yellow", &sdr,&edr); XSetForeground(display,*gc,edr.pixel); }} /* set line attributes */ XSetLineAttributes(display,*gc,line_width,line_style,cap_style, join_style); /* set dashes to be line_width in length */ XSetDashes(display,*gc,dash_offset,dash_list,list_length); } load_font(XFontStruct **font_info) { char *fontname = "9x15"; /* Access font */ if ((*font_info = XLoadQueryFont(display,fontname)) == NULL) { fprintf(stderr,"Basic: Cannot open 9x15 font\n"); exit(-1); } } int main(argc,argv) int argc; char **argv; { Window win; unsigned width, height; /* window size */ int x = 0, y = 0; /* window position */ unsigned border_width = 4; /* border four pixels wide */ unsigned display_width, display_height; char *window_name = "Schroedinger Wave Simulator"; char *icon_name = "schroed"; Pixmap icon_pixmap; XSizeHints size_hints; XEvent report; GC gc,gce,gcreal,gcimag; XFontStruct *font_info; char *display_name = NULL; int i; /* connect to X server */ if ( (display=XOpenDisplay(display_name)) == NULL ) { fprintf(stderr, "cannot connect to X server %s\n", XDisplayName(display_name)); exit(-1); } sim_init(); init_graphics(); /* get screen size from display structure macro */ screen = DefaultScreen(display); display_width = DisplayWidth(display,screen); display_height = DisplayHeight(display,screen); /* size window with enough room for text */ width = display_width/3, height = display_height/3; /* create opaque window */ win = XCreateSimpleWindow(display,RootWindow(display,screen), x,y,width,height,border_width, WhitePixel(display,screen), BlackPixel(display,screen)); /* Create pixmap of depth 1 (bitmap) for icon */ icon_pixmap = XCreateBitmapFromData(display, win, icon_bitmap_bits, icon_bitmap_width, icon_bitmap_height); /* initialize size hint property for window manager */ size_hints.flags = PPosition | PSize | PMinSize; size_hints.x = x; size_hints.y = y; size_hints.width = width; size_hints.height = height; size_hints.min_width = 175; size_hints.min_height = 125; /* set properties for window manager (always before mapping) */ XSetStandardProperties(display,win,window_name,icon_name, icon_pixmap,argv,argc,&size_hints); /* Select event types wanted */ XSelectInput(display,win, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask); load_font(&font_info); /* create GC for text and drawing */ get_GC(win, &gc, font_info, 1); get_GC(win, &gce, font_info, 0); get_GC(win, &gcreal, font_info, 2); get_GC(win, &gcimag, font_info, 3); /* Display window */ XMapWindow(display,win); while (1) { /* Event loop. */ int i; XNextEvent(display,&report); switch(report.type) { case Expose: /* get rid of all other Expose events on the queue */ while (XCheckTypedEvent(display, Expose, &report)); draw_graphics(win, gc, width, height, gce, gcreal, gcimag); for(i=0;ifid); XFreeGC(display,gc); XFreeGC(display,gce); XFreeGC(display,gcreal); XFreeGC(display,gcimag); XCloseDisplay(display); exit(1); default: break; } } return 0; }