1. #include <iostream>
  2. #include <cmath>
  3. #include <cstdio>
  4. #include <fstream>
  5. #include <string>
  6. #include <assert.h>
  7. #include <GLUT/glut.h>
  8.  
  9. using namespace std;
  10.  
  11. //Global constants
  12. const double PI = 4*atan(1.0);
  13. double* xArray_ptr;
  14. double* yArray_ptr;
  15. GLuint circle;
  16. string DIRECTORY = "/Users/rj/Desktop/";
  17.  
  18. //Math section
  19.  
  20. //Generate random trajectories
  21. /***********************************************************************/
  22. double linearCongruence(long int scale, unsigned long int& seed, unsigned long int offSet, unsigned long int modulo)
  23. {
  24. double randomNum = 0;
  25. seed = (scale*seed+offSet)%modulo;
  26. randomNum = (double)seed/(double)(modulo-1);
  27. return(randomNum);
  28. }
  29.  
  30. void genRandNum(double rand1[], double rand2[], int numRandomNums)
  31. {
  32. //Constants for random number generator, choices from Numerical Recipes
  33. const unsigned long int modulo = pow(2.0, 32.0);
  34. const long int scale = 1664525;
  35. const unsigned long int offSet = 1013904223;
  36.  
  37. //Random number generator seed and pointer
  38. unsigned long int seed1 = 1024;
  39. unsigned long int seed2 = 512;
  40.  
  41. for(int i = 0; numRandomNums > i; i++)
  42. {
  43. rand1[i] = (linearCongruence(scale,seed1,offSet,modulo));
  44. rand2[i] = (linearCongruence(scale,seed2,offSet,modulo));
  45. }
  46. }
  47.  
  48. void boxMuller(double gauss1[], double gauss2[], double rand1[], double rand2[])
  49. {
  50. for(int i = 0; 10000 > i; i++)
  51. {
  52. gauss1[i] = sqrt(-2*log(rand1[i]))*cos(2.0*PI*rand2[i]);
  53. gauss2[i] = sqrt(-2*log(rand1[i]))*sin(2*PI*rand2[i]);
  54. }
  55. }
  56. /***********************************************************************/
  57.  
  58. //Calculate classical dynamics
  59. /***********************************************************************/
  60. void posClassical( double posArray[], double gauss1[], double gauss2[], const double FIELD, double currentTime)
  61. {
  62. //mass is 1
  63.  
  64. for(int i = 0; 10000 > i; i++)
  65. {
  66. posArray[i] = (gauss1[i] + gauss2[i] * currentTime - 0.5 * FIELD * pow(currentTime, 2));
  67. }
  68. }
  69.  
  70. void momentumClassical(double momArray[], double gauss2[], const double FIELD, double currentTime)
  71. {
  72.  
  73. //mass is 1
  74.  
  75. for(int i = 0; 10000 > i; i++)
  76. {
  77. momArray[i] = (gauss2[i] - FIELD * currentTime);
  78. }
  79. }
  80. /***********************************************************************/
  81.  
  82. //Calculate probability densities analitically
  83. /***********************************************************************/
  84.  
  85. //Spatial probability density
  86. double rho_X_T(double pos, double spatialWidth0, double momWidth0, double atomicTime, double potential)
  87. {
  88. double spatialWidthT = sqrt(pow(spatialWidth0,2.0)+pow(momWidth0,2.0)*pow(atomicTime,2.0));
  89. double exponent = (-0.5)*pow(((pos+(potential/2.0)*pow(atomicTime,2.0))/spatialWidthT),2.0);
  90.  
  91. return((1/(sqrt(2.0)*PI))*(1/spatialWidthT)*exp(exponent));
  92. }
  93. /***********************************************************************/
  94.  
  95. //Statistics
  96. /***********************************************************************/
  97.  
  98.  
  99. double arrayAverage(double array[], int arraySize)
  100. {
  101. double sum = 0;
  102.  
  103. for(int i = 0; arraySize > i; i++)
  104. {
  105. sum = sum + array[i];
  106. }
  107. //cout << sum << endl;
  108. return(sum/(double)arraySize);
  109. }
  110.  
  111. double calculateAvgPosition(double posArray[], double arraySize)
  112. {
  113. return(arrayAverage(posArray, arraySize));
  114. }
  115.  
  116. double calculateAvgMomentum(double momArray[], double arraySize)
  117. {
  118. return(arrayAverage(momArray, arraySize));
  119. }
  120.  
  121. void writePhaseSpacePointToFile(double avgPosition, double avgMomentum, double currentTime)
  122. {
  123. string filename = DIRECTORY + "phaseSpaceData.txt";
  124. ofstream fout;
  125. fout.open(filename.c_str(), ios_base::app);
  126.  
  127. fout << avgPosition << ";" << avgMomentum << ";" << currentTime << endl;
  128.  
  129. fout.close();
  130. }
  131.  
  132.  
  133. //If I switch to vectors I can get rid of all this arraySize crap...
  134. void calculatAvgPhaseSpace(double totalTime, double numTimeSteps,
  135. double posArray[], double momArray[],
  136. int arraySize, const double FIELD, double gauss1[], double gauss2[])
  137. {
  138.  
  139. const double deltaT = totalTime/(double)numTimeSteps;
  140.  
  141. double currentTime = 0;
  142. double avgPosition = 0; //These two seem to be a waste of memory
  143. double avgMomentum = 0;
  144.  
  145. for(int i = 0; numTimeSteps > i; i++)
  146. {
  147. currentTime = deltaT * i;
  148.  
  149. //load the position and momentum values for each particle
  150. posClassical(posArray, gauss1, gauss2, FIELD, currentTime);
  151. momentumClassical(momArray, gauss2, FIELD, currentTime);
  152.  
  153. //calculate the averages
  154. avgPosition = calculateAvgPosition(posArray, arraySize);
  155. avgMomentum = calculateAvgMomentum(momArray, arraySize);
  156.  
  157. //Write data to file
  158. writePhaseSpacePointToFile(avgPosition, avgMomentum, currentTime);
  159. }
  160. }
  161.  
  162.  
  163. /***********************************************************************/
  164.  
  165. //Bookkeeping
  166. /***********************************************************************/
  167. void writeArrayToFile(double xArray[], double yArray[], ofstream* filePtr)
  168. {
  169. //Arrays must be same size, should add an assert here at some point.
  170. for(int i = 0; 10000 > i; i++)
  171. {
  172. *filePtr << xArray[i] << ";" << yArray[i] << endl;
  173. }
  174. }
  175.  
  176. /***********************************************************************/
  177.  
  178. //Graphics part
  179. /***********************************************************************/
  180. void createCircle()
  181. {
  182. float theta;
  183. int i;
  184. int div = 50;
  185.  
  186.  
  187. circle = glGenLists(1);
  188.  
  189. glNewList(circle,GL_COMPILE);
  190. glBegin(GL_TRIANGLE_FAN);
  191. glVertex2f(0,0);
  192. for (i=0;i<div;i++)
  193. {
  194. theta = (float)i*2*3.14159/div;
  195. glVertex2f(cos(theta),sin(theta));
  196. }
  197. glVertex2f(1,0);
  198. glEnd();
  199. glEndList();
  200. }
  201.  
  202. void drawAxis(int xSize, int ySize)
  203. {
  204. glBegin(GL_LINES);
  205. //x-axis
  206. glColor3f(0,0,0);
  207. glVertex3f(-xSize,0,0);
  208. glVertex3f(xSize,0,0);
  209.  
  210. //y-axis
  211. glColor3f(0,0,0);
  212. glVertex3f(0,-ySize,0);
  213. glVertex3f(0,ySize,0);
  214. glEnd();
  215. }
  216.  
  217. void drawBaorder(int xSize, int ySize)
  218. {
  219. glBegin(GL_LINES);
  220.  
  221. //Left boarder
  222. glColor3f(0,0,0);
  223. glVertex3f(-xSize,-ySize,0);
  224. glVertex3f(-xSize,ySize,0);
  225.  
  226. //Botom boarder
  227. glColor3f(0,0,0);
  228. glVertex3f(-xSize,-ySize,0);
  229. glVertex3f(xSize,-ySize,0);
  230.  
  231. //Right boarder
  232. glColor3f(0,0,0);
  233. glVertex3f(xSize,-ySize,0);
  234. glVertex3f(xSize,ySize,0);
  235.  
  236. //top boarder
  237. glColor3f(0,0,0);
  238. glVertex3f(-xSize,ySize,0);
  239. glVertex3f(xSize,ySize,0);
  240. glEnd();
  241. }
  242.  
  243. void display(void)
  244. {
  245. glClear(GL_COLOR_BUFFER_BIT);
  246. glMatrixMode(GL_MODELVIEW);
  247. glLoadIdentity();
  248.  
  249. glColor3f(1,0,0); //pure red
  250. glPointSize(2.0);
  251.  
  252. glBegin(GL_POINTS);
  253. for (int i=0; i < 10000; i++)
  254. {
  255. glVertex2f(xArray_ptr[i],yArray_ptr[i]);
  256. }
  257. glEnd();
  258.  
  259. drawAxis(35,35);
  260. drawBaorder(35,35);
  261.  
  262. /*
  263.   glColor3f(1,0,0);
  264.   for (int i=0; i < 10000; i++)
  265.   {
  266.   glPushMatrix();
  267.   glTranslatef(xArray_ptr[i],yArray_ptr[i],0);
  268.   glScalef(.025,.025,1);
  269.   glCallList(circle);
  270.   glPopMatrix();
  271.   }
  272. */
  273. glutSwapBuffers();
  274. }
  275.  
  276. void reshape(int width, int height)
  277. {
  278. glMatrixMode(GL_PROJECTION);
  279. glClearColor(1,1,1,1);
  280. glLoadIdentity();
  281. gluOrtho2D(-40,40,-40,40); //you need to get these
  282. glViewport(0,0,width,height);
  283.  
  284. createCircle();
  285. }
  286.  
  287. void idle(void)
  288. {
  289. //Need to generate x and y
  290.  
  291. glutPostRedisplay();
  292. }
  293.  
  294.  
  295. /***********************************************************************/
  296.  
  297. //main program
  298. /***********************************************************************/
  299. int main(int argc, char *argv[])
  300. {
  301. //OpenGL stuff
  302. glutInit(&argc, argv);
  303.  
  304. glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  305. glutInitWindowSize(1024, 768);
  306.  
  307. glutCreateWindow("Classical Statistical Dynamics");
  308.  
  309. glutDisplayFunc(display);
  310. glutReshapeFunc(reshape);
  311. //glutIdleFunc(idle);
  312.  
  313. //Problem specific constants
  314. const int numRandomNums = 10000;
  315. const double EFIELD = 1.0;
  316. const double spatialWidth0 = 1.0;
  317. const double momWidth0 = 0.5;
  318. const double numTimeSteps = 100;
  319. double atomicTime_t0 = 0;
  320. double atomicTime_t1 = 2;
  321. double atomicTime_t2 = 4;
  322. string filename_t0 = DIRECTORY + "data_t0.txt";
  323. string filename_t1 = DIRECTORY + "data_t1.txt";
  324. string filename_t2 = DIRECTORY + "data_t2.txt";
  325.  
  326. //Stream variables for classical trajectories
  327. ofstream fout0(filename_t0.c_str());
  328. ofstream fout1(filename_t1.c_str());
  329. ofstream fout2(filename_t2.c_str());
  330.  
  331. //temp arrays for storing uniformly distributed random numbers
  332. double rand1[numRandomNums];
  333. double rand2[numRandomNums];
  334.  
  335. //temp arrays for storing gaussian distributed random numbers
  336. double gauss1[numRandomNums];
  337. double gauss2[numRandomNums];
  338.  
  339. //Arrays to hold classical position and momentum
  340. double posArray[numRandomNums];
  341. double momArray[numRandomNums];
  342.  
  343. //Array pointers
  344. xArray_ptr = &posArray[0];
  345. yArray_ptr = &momArray[0];
  346.  
  347. //Generate 10000 uniformly distributed random numbers
  348. genRandNum(rand1, rand2, numRandomNums);
  349.  
  350. //Convert to Gaussian distributed random numbers
  351. boxMuller(gauss1, gauss2, rand1, rand2);
  352.  
  353. //PROBLEM 1.2F
  354. /***********************************************************************/
  355. calculatAvgPhaseSpace(atomicTime_t2, numTimeSteps, posArray, momArray, numRandomNums, EFIELD, gauss1, gauss2);
  356.  
  357. /***********************************************************************/
  358.  
  359. //PROBLEM 1.2D T0
  360. /***********************************************************************/
  361.  
  362. //Calculate first itteration of classical position and momentum for t = 0
  363. posClassical(posArray, gauss1, gauss2, EFIELD, atomicTime_t0);
  364. momentumClassical(momArray, gauss2, EFIELD, atomicTime_t0);
  365.  
  366. writeArrayToFile(posArray, momArray, &fout0);
  367. /***********************************************************************/
  368.  
  369. //Problem 1.2D T1
  370. /***********************************************************************/
  371. //Calculate first itteration of classical position and momentum for t = 2
  372. posClassical(posArray, gauss1, gauss2, EFIELD, atomicTime_t1);
  373. momentumClassical(momArray, gauss2, EFIELD, atomicTime_t1);
  374.  
  375. writeArrayToFile(posArray, momArray, &fout1);
  376. /***********************************************************************/
  377.  
  378. //Problem 1.2D T2
  379. /***********************************************************************/
  380. //Calculate first itteration of classical position and momentum for t = 4
  381. posClassical(posArray, gauss1, gauss2, EFIELD, atomicTime_t2);
  382. momentumClassical(momArray, gauss2, EFIELD, atomicTime_t2);
  383.  
  384. writeArrayToFile(posArray, momArray, &fout2);
  385. /***********************************************************************/
  386.  
  387. //Need to make sure arrays are assigned and changing correctly before this function is called.
  388. glutMainLoop();
  389.  
  390. return 0;
  391. }
  392.