├── .gitignore ├── Bilinear Interpolation ├── README.md ├── Sample Output.png └── bilinear_int.py ├── Evaluating Square Root ├── README.md └── sqrt.py ├── Feigenbaum Plot ├── FP_Comparison.py ├── FP_Iterations.py ├── Sample Output.png └── UNDOCUMENTED.md ├── Gradient Descent ├── UNDOCUMENTED.md ├── altitude.txt ├── max_alt.png ├── max_alt.py ├── min_STM.png ├── min_STM.py └── stm.txt ├── Lotka-Volterra Simulation ├── Lotka-Volterra.py └── Output Graphs │ ├── Function of N.png │ └── Function of Time │ ├── 1000 Diff.png │ ├── 1000 Euler.png │ ├── 1000 RK4.png │ ├── 10000 Diff.png │ ├── 10000 Euler.png │ ├── 10000 RK4.png │ ├── 100000 Diff.png │ ├── 100000 Euler.png │ ├── 100000 RK4.png │ ├── 1000000 Diff.png │ ├── 1000000 Euler.png │ └── 1000000 RK4.png ├── Numerical Differentiation and Integration ├── UNDOCUMENTED.md ├── derivatives_graph.py └── monte_carlo_and_riemann.py ├── Powers of Euler's Constant ├── README.md ├── exp ├── exp.cpp └── exp.py ├── Projectile Motion with Viscous Drag ├── Projectile_Motion.py ├── README.md ├── Speed vs Distance.png └── Speed vs Theta.png ├── README.md ├── Random Walk Simulation ├── README.md ├── Sample Outputs │ ├── M_vs._Time.png │ ├── RMS_vs._Time.png │ ├── Ratio_vs._Time.png │ └── Sim.png └── random_walk.py └── packet.c /.gitignore: -------------------------------------------------------------------------------- 1 | GitIgnored/ 2 | 3 | # Created by https://www.gitignore.io/api/vim,c++,java,xcode,macos,python,eclipse,sublimetext 4 | 5 | ### C++ ### 6 | # Prerequisites 7 | *.d 8 | 9 | # Compiled Object files 10 | *.slo 11 | *.lo 12 | *.o 13 | *.obj 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Compiled Dynamic libraries 20 | *.so 21 | *.dylib 22 | *.dll 23 | 24 | # Fortran module files 25 | *.mod 26 | *.smod 27 | 28 | # Compiled Static libraries 29 | *.lai 30 | *.la 31 | *.a 32 | *.lib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | 39 | ### Eclipse ### 40 | 41 | .metadata 42 | bin/ 43 | tmp/ 44 | *.tmp 45 | *.bak 46 | *.swp 47 | *~.nib 48 | local.properties 49 | .settings/ 50 | .loadpath 51 | .recommenders 52 | 53 | # External tool builders 54 | .externalToolBuilders/ 55 | 56 | # Locally stored "Eclipse launch configurations" 57 | *.launch 58 | 59 | # PyDev specific (Python IDE for Eclipse) 60 | *.pydevproject 61 | 62 | # CDT-specific (C/C++ Development Tooling) 63 | .cproject 64 | 65 | # Java annotation processor (APT) 66 | .factorypath 67 | 68 | # PDT-specific (PHP Development Tools) 69 | .buildpath 70 | 71 | # sbteclipse plugin 72 | .target 73 | 74 | # Tern plugin 75 | .tern-project 76 | 77 | # TeXlipse plugin 78 | .texlipse 79 | 80 | # STS (Spring Tool Suite) 81 | .springBeans 82 | 83 | # Code Recommenders 84 | .recommenders/ 85 | 86 | # Scala IDE specific (Scala & Java development for Eclipse) 87 | .cache-main 88 | .scala_dependencies 89 | .worksheet 90 | 91 | ### Eclipse Patch ### 92 | # Eclipse Core 93 | .project 94 | 95 | # JDT-specific (Eclipse Java Development Tools) 96 | .classpath 97 | 98 | ### Java ### 99 | # Compiled class file 100 | *.class 101 | 102 | # Log file 103 | *.log 104 | 105 | # BlueJ files 106 | *.ctxt 107 | 108 | # Mobile Tools for Java (J2ME) 109 | .mtj.tmp/ 110 | 111 | # Package Files # 112 | *.jar 113 | *.war 114 | *.ear 115 | *.zip 116 | *.tar.gz 117 | *.rar 118 | 119 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 120 | hs_err_pid* 121 | 122 | ### macOS ### 123 | *.DS_Store 124 | .AppleDouble 125 | .LSOverride 126 | 127 | # Icon must end with two \r 128 | Icon 129 | 130 | # Thumbnails 131 | ._* 132 | 133 | # Files that might appear in the root of a volume 134 | .DocumentRevisions-V100 135 | .fseventsd 136 | .Spotlight-V100 137 | .TemporaryItems 138 | .Trashes 139 | .VolumeIcon.icns 140 | .com.apple.timemachine.donotpresent 141 | 142 | # Directories potentially created on remote AFP share 143 | .AppleDB 144 | .AppleDesktop 145 | Network Trash Folder 146 | Temporary Items 147 | .apdisk 148 | 149 | ### Python ### 150 | # Byte-compiled / optimized / DLL files 151 | __pycache__/ 152 | *.py[cod] 153 | *$py.class 154 | 155 | # C extensions 156 | 157 | # Distribution / packaging 158 | .Python 159 | build/ 160 | develop-eggs/ 161 | dist/ 162 | downloads/ 163 | eggs/ 164 | .eggs/ 165 | lib/ 166 | lib64/ 167 | parts/ 168 | sdist/ 169 | var/ 170 | wheels/ 171 | *.egg-info/ 172 | .installed.cfg 173 | *.egg 174 | 175 | # PyInstaller 176 | # Usually these files are written by a python script from a template 177 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 178 | *.manifest 179 | *.spec 180 | 181 | # Installer logs 182 | pip-log.txt 183 | pip-delete-this-directory.txt 184 | 185 | # Unit test / coverage reports 186 | htmlcov/ 187 | .tox/ 188 | .coverage 189 | .coverage.* 190 | .cache 191 | nosetests.xml 192 | coverage.xml 193 | *.cover 194 | .hypothesis/ 195 | 196 | # Translations 197 | *.mo 198 | *.pot 199 | 200 | # Django stuff: 201 | local_settings.py 202 | 203 | # Flask stuff: 204 | instance/ 205 | .webassets-cache 206 | 207 | # Scrapy stuff: 208 | .scrapy 209 | 210 | # Sphinx documentation 211 | docs/_build/ 212 | 213 | # PyBuilder 214 | target/ 215 | 216 | # Jupyter Notebook 217 | .ipynb_checkpoints 218 | 219 | # pyenv 220 | .python-version 221 | 222 | # celery beat schedule file 223 | celerybeat-schedule 224 | 225 | # SageMath parsed files 226 | *.sage.py 227 | 228 | # Environments 229 | .env 230 | .venv 231 | env/ 232 | venv/ 233 | ENV/ 234 | env.bak/ 235 | venv.bak/ 236 | 237 | # Spyder project settings 238 | .spyderproject 239 | .spyproject 240 | 241 | # Rope project settings 242 | .ropeproject 243 | 244 | # mkdocs documentation 245 | /site 246 | 247 | # mypy 248 | .mypy_cache/ 249 | 250 | ### SublimeText ### 251 | # cache files for sublime text 252 | *.tmlanguage.cache 253 | *.tmPreferences.cache 254 | *.stTheme.cache 255 | 256 | # workspace files are user-specific 257 | *.sublime-workspace 258 | 259 | # project files should be checked into the repository, unless a significant 260 | # proportion of contributors will probably not be using SublimeText 261 | # *.sublime-project 262 | 263 | # sftp configuration file 264 | sftp-config.json 265 | 266 | # Package control specific files 267 | Package Control.last-run 268 | Package Control.ca-list 269 | Package Control.ca-bundle 270 | Package Control.system-ca-bundle 271 | Package Control.cache/ 272 | Package Control.ca-certs/ 273 | Package Control.merged-ca-bundle 274 | Package Control.user-ca-bundle 275 | oscrypto-ca-bundle.crt 276 | bh_unicode_properties.cache 277 | 278 | # Sublime-github package stores a github token in this file 279 | # https://packagecontrol.io/packages/sublime-github 280 | GitHub.sublime-settings 281 | 282 | ### Vim ### 283 | # swap 284 | [._]*.s[a-v][a-z] 285 | [._]*.sw[a-p] 286 | [._]s[a-v][a-z] 287 | [._]sw[a-p] 288 | # session 289 | Session.vim 290 | # temporary 291 | .netrwhist 292 | *~ 293 | # auto-generated tag files 294 | tags 295 | 296 | ### Xcode ### 297 | # Xcode 298 | # 299 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 300 | 301 | ## Build generated 302 | DerivedData/ 303 | 304 | ## Various settings 305 | *.pbxuser 306 | !default.pbxuser 307 | *.mode1v3 308 | !default.mode1v3 309 | *.mode2v3 310 | !default.mode2v3 311 | *.perspectivev3 312 | !default.perspectivev3 313 | xcuserdata/ 314 | 315 | ## Other 316 | *.moved-aside 317 | *.xccheckout 318 | *.xcscmblueprint 319 | 320 | ### Xcode Patch ### 321 | *.xcodeproj/* 322 | !*.xcodeproj/project.pbxproj 323 | !*.xcodeproj/xcshareddata/ 324 | !*.xcworkspace/contents.xcworkspacedata 325 | /*.gcno 326 | 327 | # End of https://www.gitignore.io/api/vim,c++,java,xcode,macos,python,eclipse,sublimetext 328 | -------------------------------------------------------------------------------- /Bilinear Interpolation/README.md: -------------------------------------------------------------------------------- 1 | ## Bilinear Interpolation 2 | 3 | ### Overview 4 | 5 | This project visualizes the bilinear interpolation of four corner values. 6 | 7 | ### Sample Output 8 | 9 | ![alt text](https://github.com/harvey2phase/CompPhysics/blob/master/Bilinear%20Interpolation/Sample%20Output.png) 10 | 11 | ### Details 12 | 13 | This project contains a single file `bilinear_int.py`, which does the following things: 14 | 15 | * Perform bilinear interpolation with four corner values and visualize using matplotlib's imshow 16 | 17 | * Plot the zero line(s) by finding points that are "close enough" to zero and scatter plotting them (this feature does not look perfect, but is sufficient for our purposes) 18 | 19 | ### Testing 20 | 21 | Download the project and run `bilinear_int.py`. 22 | 23 | Change the corner values on line 4 to any floating point values to visualize their bilinear interpolation. -------------------------------------------------------------------------------- /Bilinear Interpolation/Sample Output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Bilinear Interpolation/Sample Output.png -------------------------------------------------------------------------------- /Bilinear Interpolation/bilinear_int.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | # Setting the four corner values 5 | f00, f01, f10, f11 = 3.14, -6, -2, 4 6 | 7 | # Setting x0=y0=0 and x1=y1=1 yields u=x and v=y 8 | # Therefore, f can be simplified to: 9 | def f(x, y): 10 | F11 = x * y * f11 11 | F00 = (1 - x) * (1 - y) * f00 12 | F10 = x * (1 - y) * f10 13 | F01 = (1 - x) * y * f01 14 | return F11 + F00 + F10 + F01 15 | 16 | def annotate(): 17 | plt.annotate(s = f00, fontsize = 10, xy = (1, 1)) 18 | plt.annotate(s = f01, fontsize = 10, xy = (N-1, 1)) 19 | plt.annotate(s = f10, fontsize = 10, xy = (1, N-1)) 20 | plt.annotate(s = f11, fontsize = 10, xy = (N-1, N-1)) 21 | 22 | # Determine if the input is close enough to zero 23 | def close_to_zero(x): 24 | if abs(x) < 10 ** -3: 25 | return True 26 | return False 27 | 28 | # "Normal" binary search, where negative numbers are on the left side 29 | def n_to_p(L, l, m, h): 30 | if close_to_zero(L[m]): 31 | return m 32 | 33 | # If L has been searched through 34 | elif h <= l: 35 | return 0 36 | 37 | # Search right side 38 | elif L[m] < 0: 39 | if m == int((h-m)/2) + m: 40 | return 0 41 | return n_to_p(L, m, int((h-m)/2) + m, h) 42 | 43 | # Search left side 44 | else: 45 | if m == int((m-l)/2) + l: 46 | return 0 47 | return n_to_p(L, l, int((m-l)/2) + l, m) 48 | 49 | # Binary search with positive numbers on the left side 50 | def p_to_n(L, l, m, h): 51 | if close_to_zero(L[m]): 52 | return m 53 | 54 | # If L has been searched through 55 | elif h <= l: 56 | return 0 57 | 58 | # Search left side 59 | elif L[m] < 0: 60 | if m == int((m-l)/2) + m: 61 | return 0 62 | return p_to_n(L, l, int((m-l)/2) + l, m) 63 | else: 64 | if m == int((h-m)/2) + l: 65 | return 0 66 | return p_to_n(L, m, int((h-m)/2) + m, h) 67 | 68 | # Creating two arrays from x0=y0=0 to x1=y1=1 with N points 69 | N = 1000 70 | X, Y = np.linspace(0, 1, N), np.linspace(0, 1, N) 71 | inters, zero_line = np.empty([N, N]), [] 72 | 73 | x = 0 74 | for i in X: 75 | y = 0 76 | for j in Y: 77 | inters[x][y] = f(i, j) 78 | y += 1 79 | # List goes small to large 80 | if inters[x][N-1] > inters[x][0]: 81 | zero_line.append(n_to_p(inters[x], 0, int(N / 2), N)) 82 | else: 83 | zero_line.append(p_to_n(inters[x], 0, int(N / 2), N)) 84 | 85 | x += 1 86 | 87 | plt.imshow(inters) 88 | plt.jet() 89 | plt.scatter(zero_line, np.linspace(0, N-1, N), s = 0.1, c = 'k') 90 | plt.axis('off') 91 | annotate() 92 | plt.show() 93 | -------------------------------------------------------------------------------- /Evaluating Square Root/README.md: -------------------------------------------------------------------------------- 1 | ## Evaluating Square Root 2 | 3 | ### Overview 4 | 5 | This project explores numerical methods to evaluate the square root of a number without using existing math functions. 6 | 7 | ### Details 8 | 9 | `sqrt.py` defines the function `sqrt()`, which takes in a value `x` and finds its square root recursively using Binary Search up to `accuracy`. It then compares the evaluated square root to the square root found using the Python `math` library. 10 | 11 | ### Testing 12 | 13 | Download `sqrt.py` and simply change the `x` value to whatever you wish. 14 | -------------------------------------------------------------------------------- /Evaluating Square Root/sqrt.py: -------------------------------------------------------------------------------- 1 | # SQUARE ROOT 2 | # by Harvey Wang 3 | # Created September 2017 4 | 5 | import math as m 6 | 7 | # a recursive function to find the square root of x 8 | def sqrt_re(x, m, mid, M): 9 | # base case 10 | if M - m < accuracy: 11 | return mid 12 | if mid ** 2 == x: 13 | return mid 14 | # choose the left side of the range 15 | elif mid ** 2 > x: 16 | return sqrt_re(x, m, (mid - m) / 2 + m, mid) 17 | # choose the right side of the range 18 | else: 19 | return sqrt_re(x, mid, (M - mid) / 2 + mid, M) 20 | 21 | def sqrt(x): 22 | return sqrt_re(x, 1, x / 2, x) 23 | 24 | x = 5 25 | accuracy = 10 ** -6 26 | 27 | my_sqrt = sqrt(x) 28 | math_sqrt = m.sqrt(x) 29 | error = abs(my_sqrt - math_sqrt) 30 | 31 | print('x:\t\t', x) 32 | print('Accuracy:\t', accuracy) 33 | print('My sqrt:\t', my_sqrt) 34 | print('Math sqrt:\t', math_sqrt) 35 | print('Error:\t\t', error) -------------------------------------------------------------------------------- /Feigenbaum Plot/FP_Comparison.py: -------------------------------------------------------------------------------- 1 | from numpy import * 2 | from matplotlib.pyplot import * 3 | from time import * 4 | 5 | # Graph the Feigenbaum plot using the basic method in the textbook 6 | def basic(): 7 | r_list, x_list, r, x = [], [], 1, 0.5 8 | 9 | # Iterate through r = 1 to r = 4 10 | while r < 4: 11 | 12 | i = 0 13 | 14 | # First iterate the logistic map equation 1000 times 15 | while i < 1000: 16 | x = r * x * (1 - x) 17 | i += 1 18 | 19 | # Iterate the logistic map another 1000 times then plot 20 | while i < 2000: 21 | x = r * x * (1 - x) 22 | r_list.append(r) 23 | x_list.append(x) 24 | i += 1 25 | 26 | r += 0.01 27 | 28 | scatter(r_list, x_list, s = 0.1) 29 | 30 | # Graph the Feigenbaum plot using the approach described in footnote 10 31 | def footnote_10(): 32 | # Create two arrays of the same length, each containing r and x 33 | r = linspace(1.0, 4.0, 301) 34 | x = full(301, 0.5) 35 | 36 | # First iterate the logistic map equation 1000 times 37 | for i in range(1000): 38 | x = r * x * (1 - x) 39 | 40 | # Iterate the logistic map another 1000 times then plot 41 | for i in range(1000): 42 | x = r * x * (1 - x) 43 | scatter(r, x, s = 0.1) 44 | 45 | # Run both functions and print out the time it takes to compute each 46 | start_time = time() 47 | footnote_10() 48 | end_time_1 = time() 49 | basic() 50 | end_time_2 = time() 51 | print("The basic approach:", end_time_1 - start_time) 52 | print("The footnote approach:", end_time_2 - end_time_1) 53 | -------------------------------------------------------------------------------- /Feigenbaum Plot/FP_Iterations.py: -------------------------------------------------------------------------------- 1 | from numpy import * 2 | from matplotlib.pyplot import * 3 | from time import * 4 | 5 | # Graph the Feigenbaum plot using the approach described in footnote 10 6 | def footnote_10(n): 7 | 8 | # Create two arrays of the same length, each containing r and x 9 | r = linspace(1.0, 4.0, 301) 10 | x = full(301, 0.5) 11 | 12 | # First iterate the logistic map equation n times 13 | for i in range(n): 14 | x = r * x * (1 - x) 15 | 16 | # Iterate the logistic map another n times then plot 17 | for i in range(n * 2): 18 | x = r * x * (1 - x) 19 | scatter(r, x, s = 0.1) 20 | 21 | xlabel("r") 22 | ylabel("x") 23 | 24 | # Plot 100, 1000, 100000 iterations and print the time required 25 | 26 | time_0 = time() 27 | figure(1) 28 | footnote_10(100) 29 | title("Feigenbaum Plot - 100 Iterations") 30 | 31 | time_1 = time() 32 | figure(2) 33 | footnote_10(1000) 34 | title("Feigenbaum Plot - 1000 Iterations") 35 | 36 | time_2 = time() 37 | figure(3) 38 | footnote_10(10000) 39 | title("Feigenbaum Plot - 10000 Iterations") 40 | 41 | time_3 = time() 42 | 43 | print("100 Iterations: ", time_1 - time_0) 44 | print("1000 Iterations: ", time_2 - time_1) 45 | print("10000 Iterations:", time_3 - time_2) 46 | 47 | show() 48 | -------------------------------------------------------------------------------- /Feigenbaum Plot/Sample Output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Feigenbaum Plot/Sample Output.png -------------------------------------------------------------------------------- /Feigenbaum Plot/UNDOCUMENTED.md: -------------------------------------------------------------------------------- 1 | ## UNDOCUMENTED 2 | 3 | ### Overview 4 | 5 | ### Details 6 | 7 | ### Testing -------------------------------------------------------------------------------- /Gradient Descent/UNDOCUMENTED.md: -------------------------------------------------------------------------------- 1 | Data source (the txt files): http://www-personal.umich.edu/~mejn/cp/programs.html 2 | -------------------------------------------------------------------------------- /Gradient Descent/max_alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Gradient Descent/max_alt.png -------------------------------------------------------------------------------- /Gradient Descent/max_alt.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random as ran 3 | import matplotlib.pyplot as plt 4 | 5 | # Returns True if (x, y) is within bounds 6 | def inBounds(x, y): 7 | if x > 511 or x < 0 or y > 1023 or y < 0: 8 | return False 9 | return True 10 | 11 | # Returns True if (x, y) is a local max 12 | def localMax(x, y): 13 | for i in values: 14 | if alts[x, y] < values[i]: 15 | return False 16 | return True 17 | 18 | # Return a dict. of (x, y) containing surrounding points 19 | def adjacentCoors(x, y): 20 | s = { 21 | 0: (x, y + 1), 22 | 1: (x, y - 1), 23 | 2: (x + 1, y), 24 | 3: (x - 1, y), 25 | 4: (x + 1, y + 1), 26 | 5: (x + 1, y - 1), 27 | 6: (x - 1, y + 1), 28 | 7: (x - 1, y - 1) 29 | } 30 | rmKeys = [] 31 | for key in s: 32 | xx, yy = s[key] 33 | if not inBounds(xx, yy): 34 | rmKeys.append(key) 35 | for key in rmKeys: 36 | if key in s: 37 | del s[key] 38 | return s 39 | 40 | # Returns a dict. of floats containing surrounding alt. values 41 | def adjacentValues(x, y): 42 | s = adjacentCoors(x, y) 43 | for key in s: 44 | s[key] = alts[s[key]] 45 | 46 | return s 47 | 48 | # Returns (x, y) of the step to take 49 | # (A greedy algorithm to find the next step to take) 50 | def maxStep(x, y): 51 | step = max(values, key=values.get) 52 | return adjacentCoors(x, y)[step] 53 | 54 | alts = np.loadtxt('altitude.txt') 55 | width, height = len(alts[0]), len(alts) 56 | X, Y = [], [] 57 | N = 10 ** 4 58 | for i in range(N): 59 | x, y = ran.randint(0, height-1), ran.randint(0, width-1) 60 | values = adjacentValues(x, y) 61 | 62 | while not localMax(x, y): 63 | x, y = maxStep(x, y) 64 | values = adjacentValues(x, y) 65 | 66 | X.append(x) 67 | Y.append(y) 68 | 69 | plt.gray() 70 | plt.imshow(alts) 71 | plt.scatter(Y, X, c='g', s=1) 72 | plt.title('Local Maximums on World Map with 10,000 Random Points') 73 | plt.show() 74 | -------------------------------------------------------------------------------- /Gradient Descent/min_STM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Gradient Descent/min_STM.png -------------------------------------------------------------------------------- /Gradient Descent/min_STM.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random as ran 3 | import matplotlib.pyplot as plt 4 | 5 | # Returns True if (x, y) is within bounds 6 | def inBounds(x, y): 7 | if x > height-1 or x < 0 or y > width-1 or y < 0: 8 | return False 9 | return True 10 | 11 | # Returns True if (x, y) is a local max 12 | def localMin(x, y): 13 | for i in values: 14 | if stms[x, y] > values[i]: 15 | return False 16 | return True 17 | 18 | # Return a dict. of (x, y) containing surrounding points 19 | def adjacentCoors(x, y): 20 | s = { 21 | 0: (x, y + 1), 22 | 1: (x, y - 1), 23 | 2: (x + 1, y), 24 | 3: (x - 1, y), 25 | 4: (x + 1, y + 1), 26 | 5: (x + 1, y - 1), 27 | 6: (x - 1, y + 1), 28 | 7: (x - 1, y - 1) 29 | } 30 | rmKeys = [] 31 | for key in s: 32 | xx, yy = s[key] 33 | if not inBounds(xx, yy): 34 | rmKeys.append(key) 35 | for key in rmKeys: 36 | if key in s: 37 | del s[key] 38 | return s 39 | 40 | # Returns a dict. of floats containing surrounding alt. values 41 | def adjacentValues(x, y): 42 | s = adjacentCoors(x, y) 43 | for key in s: 44 | s[key] = stms[s[key]] 45 | return s 46 | 47 | # Returns (x, y) of the step to take 48 | # (A greedy algorithm to find the next step to take) 49 | def minStep(x, y): 50 | step = min(values, key=values.get) 51 | return adjacentCoors(x, y)[step] 52 | 53 | stms = np.loadtxt('stm.txt') 54 | width, height = len(stms[0]), len(stms) 55 | X, Y = [], [] 56 | N = 10 * 4 57 | for i in range(N): 58 | x, y = ran.randint(0, height-1), ran.randint(0, width-1) 59 | values = adjacentValues(x, y) 60 | 61 | while not localMin(x, y): 62 | x, y = minStep(x, y) 63 | values = adjacentValues(x, y) 64 | 65 | X.append(x) 66 | Y.append(y) 67 | 68 | plt.imshow(stms) 69 | plt.scatter(Y, X, c='r', s=1) 70 | plt.axis('off') 71 | plt.title('Minimums with 10,000 random points') 72 | plt.show() 73 | -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Lotka-Volterra.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | # The Lotka-Volterra 5 | def f(r, t): 6 | alpha, beta, gamma, delta = 1, 0.5, 0.5, 2 7 | x = r[0] 8 | y = r[1] 9 | fx = alpha * x - beta * x * y 10 | fy = gamma * x * y - delta * y 11 | return np.array([fx, fy], float) 12 | 13 | # Runge Kutta 4th Order 14 | def rk4(f, r, a, b, N): 15 | h = (b - a) / N 16 | t_points = np.arange(a, b, h) 17 | x_points, y_points = [], [] 18 | 19 | for t in t_points: 20 | x_points.append(r[0]) 21 | y_points.append(r[1]) 22 | k1 = h * f(r, t) 23 | k2 = h * f(r + k1/2, t + h/2) 24 | k3 = h * f(r + k2/2, t + h/2) 25 | k4 = h * f(r + k3, t + h) 26 | r += (k1 + 2*k2 + 2*k3 + k4) / 6 27 | 28 | return x_points, y_points, t_points 29 | 30 | # Euler's Method 31 | def euler(f, r, a, b, N): 32 | h = (b - a) / N 33 | t_points = np.arange(a, b, h) 34 | x_points, y_points = [], [] 35 | 36 | for t in t_points: 37 | x_points.append(r[0]) 38 | y_points.append(r[1]) 39 | r += h * f(r, t) 40 | 41 | return x_points, y_points, t_points 42 | 43 | def plot_function_of_time(): 44 | # Plotting with RK4 45 | R_X, R_Y, T = rk4(f, r, a, b, N) 46 | plt.figure(1) 47 | plt.title('Lotka-Volterra with RK4; N = ' + str(N)) 48 | plt.plot(T, R_X, label='Population of rabits') 49 | plt.plot(T, R_Y, label='Population of foxes') 50 | plt.xlabel('time') 51 | plt.legend() 52 | plt.savefig('Output Graphs/Function of Time/' + str(N) + ' RK4.png') 53 | plt.clf() 54 | 55 | # Plotting with Euler 56 | E_X, E_Y, T = euler(f, r, a, b, N) 57 | plt.figure(2) 58 | plt.title('Lotka-Volterra with Euler\'s Method; N = ' + str(N)) 59 | plt.plot(T, E_X, label='Population of rabits') 60 | plt.plot(T, E_Y, label='Population of foxes') 61 | plt.xlabel('time') 62 | plt.legend() 63 | plt.savefig('Output Graphs/Function of Time/' + str(N) + ' Euler.png') 64 | plt.clf() 65 | 66 | # Plotting the difference 67 | D_X, D_Y = [], [] 68 | for i in range(len(T)): 69 | D_X.append(abs(R_X[i] - E_X[i])) 70 | D_Y.append(abs(R_Y[i] - E_Y[i])) 71 | plt.figure(3) 72 | plt.title('Differeces between RK4 and Euler; N = ' + str(N)) 73 | plt.plot(T, D_X, label='Population of rabits') 74 | plt.plot(T, D_Y, label='Population of foxes') 75 | plt.xlabel('time') 76 | plt.legend() 77 | plt.savefig('Output Graphs/Function of Time/' + str(N) + ' Diff.png') 78 | plt.clf() 79 | x, y = 2, 2 80 | r = np.array([x, y], float) 81 | a, b = 0, 30 82 | 83 | for i in np.arange(3, 7): 84 | N = 10 ** i 85 | plot_function_of_time() 86 | 87 | # Plot as a function of timestep at t = 15 88 | b = 15 89 | N = 1000 90 | D_X, D_Y, D_N = [], [], [] 91 | while N < 100000: 92 | R_X, R_Y, T = rk4(f, r, a, b, N) 93 | E_X, E_Y, T = euler(f, r, a, b, N) 94 | D_X.append(abs(R_X[len(R_X)-1] - E_X[len(E_X)-1])) 95 | D_Y.append(abs(R_Y[len(R_Y)-1] - E_Y[len(E_Y)-1])) 96 | D_N.append(N) 97 | N *= 2 98 | 99 | plt.figure(4) 100 | plt.title('Differce between RK4 and Euler as function of time steps at t = 15') 101 | plt.plot(D_N, D_X, label='Population of rabits') 102 | plt.plot(D_N, D_Y, label='Population of foxes') 103 | plt.xlabel('N') 104 | plt.legend() 105 | plt.savefig('Output Graphs/Function of N.png') 106 | -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of N.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of N.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/1000 Diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/1000 Diff.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/1000 Euler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/1000 Euler.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/1000 RK4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/1000 RK4.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/10000 Diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/10000 Diff.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/10000 Euler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/10000 Euler.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/10000 RK4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/10000 RK4.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/100000 Diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/100000 Diff.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/100000 Euler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/100000 Euler.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/100000 RK4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/100000 RK4.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/1000000 Diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/1000000 Diff.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/1000000 Euler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/1000000 Euler.png -------------------------------------------------------------------------------- /Lotka-Volterra Simulation/Output Graphs/Function of Time/1000000 RK4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Lotka-Volterra Simulation/Output Graphs/Function of Time/1000000 RK4.png -------------------------------------------------------------------------------- /Numerical Differentiation and Integration/UNDOCUMENTED.md: -------------------------------------------------------------------------------- 1 | ## UNDOCUMENTED 2 | 3 | ### Overview 4 | 5 | ### Details 6 | 7 | ### Testing -------------------------------------------------------------------------------- /Numerical Differentiation and Integration/derivatives_graph.py: -------------------------------------------------------------------------------- 1 | # This program defines a function, 2 | # estimate the derivative of the function with various values of delta, 3 | # and plots the result 4 | 5 | import matplotlib.pyplot as plt 6 | 7 | # Define the function f(x) 8 | def f(x): 9 | return x * (x - 1) 10 | 11 | # Calculate the derivative of function f at x with delta 12 | def derivative(f, x, delta): 13 | return (f(x + delta) - f(x)) / delta 14 | 15 | # Estimate the derivative with delta 2 ** -1 to 2 ** -16 16 | p = -1 17 | while p > -16: 18 | plt.scatter(2 ** p, derivative(f, 1, 2 ** p) - 1, s = 5) 19 | p -= 1 20 | 21 | # Show results 22 | plt.title("delta vs. Derivative estimate error") 23 | plt.xlabel("Delta") 24 | plt.ylabel("Error") 25 | plt.xscale("log") 26 | plt.yscale("log") 27 | plt.show() 28 | -------------------------------------------------------------------------------- /Numerical Differentiation and Integration/monte_carlo_and_riemann.py: -------------------------------------------------------------------------------- 1 | # This program: 2 | # 1. Defines a function 3 | # 2. Estimates the integral with various values of N 4 | # 2.1 Using Riemann sum 5 | # 2.2 Using Monte Carlo Integration method 6 | # 3. Plots the result 7 | 8 | import math as m 9 | import time as t 10 | import matplotlib.pyplot as plt 11 | import random as r 12 | 13 | # Define the function g we're investigating 14 | def g(x): 15 | return m.sqrt(1 - x ** 2) 16 | 17 | # Calculate the integral of function f with N using Reimann sum 18 | def riemann(f, N): 19 | h = 2 / N 20 | s = 0 21 | 22 | # Loop through [k, N] to simulate the Sigma function 23 | for k in range(N): 24 | x = -1 + h * (k + 1) 25 | y = f(x) 26 | s += h * y 27 | 28 | return s 29 | 30 | # Configure graph settings and show it 31 | def configure_graph(): 32 | plt.title("N vs. Integral of f(x)") 33 | plt.xlabel("N") 34 | plt.ylabel("Integral of f(x)") 35 | plt.xscale("log", basex = 2) 36 | plt.yscale("log", basey = 2) 37 | plt.legend((a, b), ('Riemann', 'Monte Carlo')) 38 | plt.show() 39 | 40 | # Calculate the integral of g(x) using Monte Carlo method 41 | def monte_carlo(n): 42 | R = 1 43 | under = 0 44 | 45 | # Create n random points and append them to the list 46 | for j in range(n): 47 | x = r.uniform(-R, R) 48 | y = r.uniform(0, R) 49 | 50 | # check if the new point is under the function g(x) 51 | if g(x) >= y: 52 | under += 1 53 | 54 | f = under / n 55 | A = 2 * (R ** 2) * f 56 | 57 | return A 58 | 59 | # Evaluate the integral with N = 100 60 | print("N = 100:", riemann(g, 100)) 61 | 62 | # Increase N to as large as possible in one second 63 | end = t.time() + 1 64 | i = 1 65 | while t.time() < end: 66 | a = plt.scatter(i, riemann(g, i), s = 5, c = "g") 67 | i *= 2 68 | 69 | # Show results 70 | print("Most accurate value in one second:", riemann(g, int(i / 2))) 71 | 72 | # Increase the number of spheres to as large as possible in one second 73 | end = t.time() + 1 74 | i = 1 75 | while t.time() < end: 76 | b = plt.scatter(i, monte_carlo(i), s = 5, c = "b") 77 | i *= 2 78 | 79 | configure_graph() 80 | -------------------------------------------------------------------------------- /Powers of Euler's Constant/README.md: -------------------------------------------------------------------------------- 1 | ## Powers Of Euler's Constant 2 | 3 | ### Overview 4 | 5 | This project explores methods to evaluate e^x without using existing math functions or precomputed values of e. 6 | 7 | `exp.cpp` utilizes a simple Dynamic Programming technique to improve the time complexity while `exp.py` takes a more brute-force approach. 8 | 9 | ### Details 10 | 11 | `exp.py` defines the function `myexp()` which evaluates the value of e^x using the infinite power series e = ∑ 1n! as n goes from 0 to infinity. 12 | 13 | Accuracy is the difference the result of the power series up until N-1 and that of N. The program stops when increasing N no longer changes the result of the evaluated e, i.e. when the difference is less than accuracy. 14 | 15 | `exp.cpp` takes the same approach but improves on it with simple a Dynamic Programming technique. Instead of re-evaluating the summation of the series and n! every time n is increased, both values for n-1 are stored and readily available for the computation of n, and therefore saving time. 16 | 17 | ### Testing 18 | 19 | `exp` is the executable (object code) built from `exp.cpp`. Simply download the programs and run them. Both C++ and Python programs print out the value of e^x from x = 0 to x = 19. 20 | -------------------------------------------------------------------------------- /Powers of Euler's Constant/exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Powers of Euler's Constant/exp -------------------------------------------------------------------------------- /Powers of Euler's Constant/exp.cpp: -------------------------------------------------------------------------------- 1 | // EXP 2 | // by Harvey Wang 3 | // Created December 2017 4 | 5 | #include 6 | #include 7 | 8 | #define ACCURACY std::pow(10.0, -7) 9 | 10 | // Prototypes 11 | double myexp(double); 12 | double powSeries(double, double, double); 13 | 14 | 15 | 16 | int main() { 17 | for (int i = 0; i < 20; i++) 18 | std::cout << myexp(i) << "\n"; 19 | return 0; 20 | } 21 | 22 | // Evaluates e^x using the power seires 23 | // The function returns when the next item in the power series is less than ACCURACY (i.e. the improvment in accruacy is negligible) 24 | double myexp(double x) { 25 | double N = 1; 26 | double fact = 1; 27 | double sum = powSeries(x, N, fact) + 1; 28 | 29 | N++; 30 | fact *= N; 31 | double nextSeries = powSeries(x, N, fact); 32 | 33 | while (nextSeries > ACCURACY && N < 30) { 34 | sum += nextSeries; 35 | N++; 36 | fact *= N; 37 | nextSeries = powSeries(x, N, fact); 38 | } 39 | return sum; 40 | } 41 | 42 | // Returns the value of the Nth item in the power seires 43 | double powSeries(double x, double N, double fact) { 44 | return (std::pow(x, N) / fact); 45 | } 46 | -------------------------------------------------------------------------------- /Powers of Euler's Constant/exp.py: -------------------------------------------------------------------------------- 1 | # EXP 2 | # by Harvey Wang 3 | # Created September 2017 4 | 5 | # recursive function to find the factorial of x 6 | def fact(x): 7 | if x == 1: 8 | return 1 9 | return x * fact(x - 1) 10 | 11 | # recursive function to evaluate e^x using power series 12 | # the precision variable is the number of time the function will sum the series 13 | def powS(x, precision): 14 | if precision == 0: 15 | return 1 16 | return (x ** precision) / fact(precision) + powS(x, precision - 1) 17 | 18 | def close_enough(x1, x2): 19 | if abs(x1 - x2) < accuracy: 20 | return True 21 | return False 22 | 23 | def myexp(x): 24 | sum1 = powS(x, 1) 25 | sum2 = powS(x, 2) 26 | i = 3 27 | # "keep adding terms until they no longer change the result" 28 | while not close_enough(sum1, sum2): 29 | sum1 = sum2 30 | sum2 = powS(x, i) 31 | i += 1 32 | return sum2 33 | 34 | accuracy = 10 ** -7 35 | 36 | # print e^i where i is 0 to 20 37 | for i in range(20): 38 | print(myexp(i)) 39 | -------------------------------------------------------------------------------- /Projectile Motion with Viscous Drag/Projectile_Motion.py: -------------------------------------------------------------------------------- 1 | import math as m 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | 5 | # Function for projectile motion with viscous drag 6 | def f(r, t): 7 | vx = r[2] 8 | vz = r[3] 9 | 10 | dx = vx 11 | dz = vz 12 | dvx = -eta * vx 13 | dvz = -g - eta * vz 14 | return np.array([dx, dz, dvx, dvz], float) 15 | 16 | # Runge Kutta 4th Order 17 | def rk4(f, r, t): 18 | while r[1] > 0: 19 | x_points.append(r[0]) 20 | z_points.append(r[1]) 21 | k1 = h * f(r, t) 22 | k2 = h * f(r + k1/2, t + h/2) 23 | k3 = h * f(r + k2/2, t + h/2) 24 | k4 = h * f(r + k3, t + h) 25 | r += (k1 + 2*k2 + 2*k3 + k4) / 6 26 | t += h 27 | return t 28 | 29 | # Converts radients to degrees 30 | def r_to_d(x): 31 | return x * 180 / m.pi 32 | 33 | # Constants 34 | eta, g, t = 0.3, 9.81, 0 35 | h = 10 ** -2 36 | 37 | v = 10 38 | MAX_X, MAX_THETA, SPEED = [], [], [] 39 | # Varying the speed from 1 to 45 m/s 40 | while v < 70: 41 | theta = m.pi / 10 42 | X_HIT, THETA = [], [] 43 | 44 | # Varying theta from m.pi/10 to m.pi / 2 45 | while theta < m.pi / 2: 46 | vx, vz = v * m.cos(theta), v * m.sin(theta) 47 | r = np.array([1, 1, vx, vz], float) 48 | x_points, z_points = [], [] 49 | 50 | t_hit = rk4(f, r, t) 51 | x_hit = x_points[len(x_points)-1] 52 | X_HIT.append(x_hit) 53 | THETA.append(theta) 54 | 55 | theta += m.pi / 1000 56 | 57 | max_hit = max(X_HIT) 58 | # Find the corresponding theta for max_hit 59 | MAX_THETA.append(r_to_d(THETA[X_HIT.index(max_hit)])) 60 | MAX_X.append(max_hit) 61 | SPEED.append(v) 62 | 63 | v += 3 64 | 65 | plt.figure(1) 66 | plt.plot(SPEED, MAX_X) 67 | plt.xlabel('Speed (m/s)') 68 | plt.ylabel('Max Distance (m)') 69 | plt.title('Projectile motion with viscous drag') 70 | plt.savefig('Speed vs Distance') 71 | 72 | plt.figure(2) 73 | plt.plot(SPEED, MAX_THETA) 74 | plt.xlabel('Speed (m/s)') 75 | plt.ylabel('Max Theta (Degrees)') 76 | plt.title('Projectile motion with viscous drag') 77 | plt.savefig('Speed vs Theta') 78 | -------------------------------------------------------------------------------- /Projectile Motion with Viscous Drag/README.md: -------------------------------------------------------------------------------- 1 | # Newtonian Projectile Motion with Viscous Drag 2 | 3 | _More details to come. Project undocumented_ -------------------------------------------------------------------------------- /Projectile Motion with Viscous Drag/Speed vs Distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Projectile Motion with Viscous Drag/Speed vs Distance.png -------------------------------------------------------------------------------- /Projectile Motion with Viscous Drag/Speed vs Theta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Projectile Motion with Viscous Drag/Speed vs Theta.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Projects in Computational Physics 2 | 3 | This is project for me to investigate some topics in computational and theoretical physics, including numerical programming and quantum computing. 4 | 5 | I hope to experiment and bridge the knowledge gap between my two areas of study in university, computer science and physics. 6 | 7 | Some of these projects are based on assignments from the Computer Simulation in Science course (Fall 2017) at Dalhousie University. 8 | 9 | ## Goals 10 | 11 | My goals include the investigation of the following topics: 12 | * Methods and algorithms in numerical programming 13 | * Dynamic Programming 14 | * Differentiation and integration 15 | * System of linear equation 16 | * Ordinary Differential Equations 17 | * Partial Differential Equations 18 | * Comparison between different Programming languages in the context of physics and numerical programming 19 | * Python 20 | * C 21 | * C++ 22 | * Pascal 23 | * Quantum computing 24 | * Numerical solution of the Schrödinger equation 25 | * Simulation of wavepackets 26 | 27 | ## Sample Outputs 28 | 29 | ### Random Walk Simulation: 30 | ![alt text](https://github.com/harveytwoface/CompPhysics/blob/master/Random%20Walk%20Simulation/Sample%20Outputs/Sim.png) 31 | 32 | ### Bilinear Interpolation: 33 | ![alt text](https://github.com/harvey2phase/CompPhysics/blob/master/Bilinear%20Interpolation/Sample%20Output.png) 34 | 35 | ### Feigenbaum Plot: 36 | ![alt text](https://github.com/harvey2phase/CompPhysics/blob/master/Feigenbaum%20Plot/Sample%20Output.png) 37 | 38 | ### Lotka-Volterra Simulation: 39 | ![alt text](https://github.com/harvey2phase/CompPhysics/blob/master/Lotka-Volterra%20Simulation/Output%20Graphs/Function%20of%20Time/10000%20RK4.png) 40 | 41 | ## Installing and Testing 42 | 43 | To install, simply download the project as a zip file or clone the repository using the following Bash command: 44 | 45 | ``` 46 | $ git clone https://github.com/harveytwoface/CompPhysics.git 47 | ``` 48 | 49 | ## Author 50 | 51 | Harvey Wang
52 | Email: harvey@dal.ca
53 | 54 | ## Feedback 55 | 56 | I'm always looking for ideas for new projects! Please email me if you have an idea you want me to test out, or if you want to collaborate! I always love networking with new people. Also feel free to make pull requests. 😃 57 | 58 | ## Acknowledgements 59 | 60 | Big thanks to **Dr. Andrew Rutenberg**, who teaches the Computer Simulation in Science course at Dalhousie University. He inspired me to take the class material further. Please visit his website [here](http://fizz.phys.dal.ca/~adr/). 61 | -------------------------------------------------------------------------------- /Random Walk Simulation/README.md: -------------------------------------------------------------------------------- 1 | ## Random Walk 2 | 3 | ### Overview 4 | 5 | This Project simulates a random walk in 2 dimensional space. 6 | 7 | ### Sample Output 8 | 9 | ![alt text](https://github.com/harveytwoface/CompPhysics/blob/master/Random%20Walk%20Simulation/Sample%20Outputs/Sim.png) 10 | 11 | ### Details 12 | 13 | This project contains a single file `random_walk.py`, which does the following things: 14 | 15 | * Provides a visual simulation of 1,000 particles undergoing random walks in 2-D. 16 | 17 | * Graphs the root mean square (RMS) of the particles' distances from the origin vs. time. 18 | 19 | * Graphs the RMS of the particles' maximum distances from the origin vs. time. 20 | 21 | * Graphs the ratio of the maximum RMS and RMS of distances (M/R) vs. time. 22 | 23 | There are several objects in the visual simulation, each representing a different set of data: 24 | 25 | * *The red dots*: represent the particles in 2-D making the random walks. 26 | 27 | * *The green dots*: represent the maximum points of each particle when it is furthest away from the origin. 28 | 29 | * *The red circle*: represents the root mean square (RMS) of the particles' distances from the origin. 30 | 31 | * *The green circle*: represents the RMS of the maximum points' distances. 32 | 33 | ### Testing 34 | 35 | Download the project and run `random_walk.py`. 36 | 37 | The default value for `n` and `iterations` is 1000, which represent the number of particles and random steps taken, respectively. One can modify these to observe different behaviours, or change the `for` loop on line 41 to `while true`, running the simulation indefinitely. -------------------------------------------------------------------------------- /Random Walk Simulation/Sample Outputs/M_vs._Time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Random Walk Simulation/Sample Outputs/M_vs._Time.png -------------------------------------------------------------------------------- /Random Walk Simulation/Sample Outputs/RMS_vs._Time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Random Walk Simulation/Sample Outputs/RMS_vs._Time.png -------------------------------------------------------------------------------- /Random Walk Simulation/Sample Outputs/Ratio_vs._Time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Random Walk Simulation/Sample Outputs/Ratio_vs._Time.png -------------------------------------------------------------------------------- /Random Walk Simulation/Sample Outputs/Sim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harvey2phase/computational-physics/112ab8dabc25c1e522f4b5d4e14018c49efa90d6/Random Walk Simulation/Sample Outputs/Sim.png -------------------------------------------------------------------------------- /Random Walk Simulation/random_walk.py: -------------------------------------------------------------------------------- 1 | # RANDOM WALK 2 | # by Harvey Wang 3 | # Created October 2017 4 | 5 | import math as m 6 | import random as ran 7 | import numpy as np 8 | import vpython as vp 9 | import matplotlib.pyplot as plt 10 | import time as t 11 | 12 | # Define the constant parameters 13 | iterations = 1000 14 | n = 1000 15 | r = 0.1 16 | s = 0.1 17 | 18 | # Setup the canvas 19 | d = vp.canvas(x = 200, y = 200, width = 700, height = 700, center = vp.vector(0, 0, 5), background = vp.color.white) 20 | d.autoscale = False 21 | vp.rate(1000) 22 | 23 | # Create an array of 1000 spheres 24 | # Create another array of the same length to mark the maximums 25 | s_array = np.empty(n, vp.sphere) 26 | m_array = np.empty(n, vp.sphere) 27 | for i in range(n): 28 | s_array[i] = vp.sphere(radius = r, color = vp.color.red) 29 | m_array[i] = vp.sphere(radius = r, color = vp.color.green) 30 | 31 | # Create a black sphere to mark the origin 32 | origin = vp.sphere(radius = 0.15, color = vp.color.black) 33 | 34 | # Create rings to represent the RMS of spheres and maxes 35 | sph_rin = vp.ring(axis = vp.vector(0, 0, 1), thickness = 0.1, color = vp.color.red) 36 | max_rin = vp.ring(axis = vp.vector(0, 0, 1), thickness = 0.1, color = vp.color.green) 37 | 38 | start = t.time() 39 | 40 | # Move the n spheres randomly 41 | for j in range(iterations): 42 | r_sum = 0 43 | m_sum = 0 44 | 45 | for i in range(n): 46 | dx = (2 * ran.random() - 1) * s 47 | dy = (2 * ran.random() - 1) * s 48 | s_array[i].pos += vp.vector(dx, dy, 0) 49 | 50 | # Calculate distances and sums from origin 51 | d_sph = m.sqrt(s_array[i].pos.x ** 2 + s_array[i].pos.y ** 2) 52 | d_max = m.sqrt(m_array[i].pos.x ** 2 + m_array[i].pos.y ** 2) 53 | r_sum += d_sph ** 2 54 | m_sum += d_max ** 2 55 | 56 | # Check for the max point 57 | if d_sph > d_max: 58 | m_array[i].pos = s_array[i].pos 59 | 60 | # Calculate and plot the RMS of the spheres and the maximums 61 | r_RMS = m.sqrt(r_sum / n) 62 | m_RMS = m.sqrt(m_sum / n) 63 | sph_rin.radius = r_RMS 64 | max_rin.radius = m_RMS 65 | plt.figure(1) 66 | plt.scatter(t.time() - start, r_RMS) 67 | plt.figure(2) 68 | plt.scatter(t.time() - start, m_RMS) 69 | plt.figure(3) 70 | plt.scatter(t.time() - start, m_RMS / r_RMS) 71 | 72 | # Configure the graphs 73 | plt.figure(1) 74 | plt.ylabel("RMS of the spheres") 75 | plt.title("RMS of the Spheres vs. Time") 76 | plt.xlabel("Time (s)") 77 | plt.figure(2) 78 | plt.ylabel("RMS of the maximums") 79 | plt.title("RMS of the Maximums vs. Time") 80 | plt.xlabel("Time (s)") 81 | plt.figure(3) 82 | plt.title("RMS of Spheres over Maximums vs. Time") 83 | plt.ylabel("RMS of Spheres over Maximums") 84 | plt.xlabel("Time (s)") 85 | plt.show() 86 | -------------------------------------------------------------------------------- /packet.c: -------------------------------------------------------------------------------- 1 | // Based on http://physics.oregonstate.edu/~landaur/nacphy/ComPhys/PACKETS/packets.c 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define xDim 501 // number space pts, must be odd for simpson 8 | 9 | FILE *out1, *out2, *out3a, *out3b, *out3c, *out7a, *out7b, *out7c; 10 | FILE *out8, *out10, *out11, *out12, *out13, *out14, *input; 11 | 12 | // Prototypes 13 | void potential(); 14 | void initialize(void); 15 | void solveSE(void); 16 | void output(); 17 | void probability(); 18 | 19 | // Global variables 20 | double rePsi[xDim][xDim][2], imPsi[xDim][xDim][2], v[xDim][xDim]; 21 | double rho[xDim][xDim], j[xDim][xDim]; 22 | double rho1[xDim], rho2[xDim], sumRho[xDim], corr[xDim]; 23 | double w[3]; 24 | double a1, a2, a3, a4, alpha, dx, dt, er, ei, eri, eii; 25 | double k1, k2, m1, m2, dm1, dm2, dm12, dm22, dxx2, dtx, con, con2; 26 | double ptot, ptotI; 27 | double sol, sig, vmax, x01, x02, y; 28 | int choice, nt, n1, n2, nprint; 29 | time_t timei, timef; 30 | 31 | int main() { 32 | int i, j; 33 | time_t timeF; 34 | time_t timeI = time(NULL); 35 | 36 | // Inititialzation of variables 37 | input = fopen("in.dat", "r"); 38 | 39 | } 40 | --------------------------------------------------------------------------------