/* SCHII: Like SCHI2 except uses only integer multiplication in the main loop. SCHI2 kept its state in integers but calculating amounts to add using floating-point math. This will be the model for my Pendulum implementation. */ #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 (128) /* 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, /* Initial velocity in m/s */ initial_mu = -space_width/4, /* initial mean electron pos, rel. to ctr. */ initial_sigma = space_width/30; /* 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 = 10000; /* go a million iterations before reversing */ static int direction = 0; /* forwards */ #define STEPS_PER_SHOT 20 #define BITS_PER_N 30 /* Max in a 32-bit int is 30 */ 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 = parabolic; 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.0) { return 0; } else if (x < space_width * 0.03) { return 5e-16; } 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("Integer 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;*/ /* Max for a 32-bit int. */ /* Below I'm experimenting to see how little precision we can get by with. */ scaleFactor = (1<>= 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; return signed_mult_frac(alphasi[i],vec[i]) - signed_mult_frac(epsiloni,vec[j]) - signed_mult_frac(epsiloni,vec[k]); } #define SHIFT_FACTOR 0 /* unsigned add(unsigned a,unsigned b, int nbits){ int i; unsigned sum=0; unsigned carry = 0; for(i=0;i>SHIFT_FACTOR; } for(i=0;i>SHIFT_FACTOR; } psiR[0] = psiR[num_pts-1] = psiI[0] = psiI[num_pts-1] = 0; for(i=0;i>SHIFT_FACTOR; } for(i=0;i>SHIFT_FACTOR; } psiR[0] = psiR[num_pts-1] = psiI[0] = psiI[num_pts-1] = 0; 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; } maxp = 1.0; } 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 = 90; size_hints.min_height = 60; /* 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); //if (n_steps == 0) sleep(1); for(i=0;ifid); XFreeGC(display,gc); XFreeGC(display,gce); XFreeGC(display,gcreal); XFreeGC(display,gcimag); XCloseDisplay(display); exit(1); default: break; } } return 0; }