gas-sim.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. #
  4. #Stephen Stengel cs528 Final Project
  5. #Simulation of gas particles with partial wall
  6. #Simulation starts by putting all particles on the left side of a wall.
  7. #The wall is removed midway through? At start?
  8. import numpy
  9. import matplotlib.pyplot as plt
  10. import random
  11. import math
  12. import os
  13. def main(args):
  14. print("Hi!")
  15. print("Clearing old plots...")
  16. plotsFolder = "../frames/"
  17. videoFolder = "../video/"
  18. os.system("rm " + plotsFolder + "*.png")
  19. os.system("rm " + videoFolder + "output*")
  20. print("Done!")
  21. numpy.random.seed(3)
  22. # ~ xlow = -10000
  23. # ~ xhigh = 10000
  24. # ~ ylow = -10000
  25. # ~ yhigh = 10000
  26. # ~ xlow = -1000
  27. # ~ xhigh = 1000
  28. # ~ ylow = -1000
  29. # ~ yhigh = 1000
  30. xlow = -100
  31. xhigh = 100
  32. ylow = -100
  33. yhigh = 100
  34. # ~ xlow = -50
  35. # ~ xhigh = 50
  36. # ~ ylow = -100
  37. # ~ yhigh = 100
  38. # ~ xlow = -10
  39. # ~ xhigh = 10
  40. # ~ ylow = -10
  41. # ~ yhigh = 10
  42. # ~ xlow = -4
  43. # ~ xhigh = 4
  44. # ~ ylow = -4
  45. # ~ yhigh = 4
  46. xsize = abs( xhigh - xlow )
  47. ysize = abs( yhigh - ylow )
  48. # ~ numpoints = 10000
  49. numpoints = 5000 #This is good one
  50. # ~ numpoints = 1000
  51. # ~ numpoints = 100
  52. # ~ numpoints = 10
  53. # ~ numSteps = 100000
  54. # ~ numSteps = 50000
  55. numSteps = 30000
  56. numFrames = 30
  57. stepSizeGraphing = numSteps // numFrames + 1
  58. #Get xhigh up to wall
  59. wallstop = getxhighAbutment(xsize, xlow)
  60. # ~ print("wallstop: " + str(wallstop) + "\txlow: " + str(xlow) + "\txsize: " + str(xsize))
  61. #Create array to hold x and y positions of particles
  62. xpositions = numpy.random.randint(xlow, wallstop, numpoints)
  63. ypositions = numpy.random.randint(ylow, yhigh + 1, numpoints)
  64. xwallArray, ywallArray = createWallArray(xsize, ysize, xlow, xhigh, ylow, yhigh)
  65. print("Simulating...")
  66. simulate(numSteps, xpositions, ypositions, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, ysize, stepSizeGraphing, plotsFolder)
  67. print("Done")
  68. print("Creating videos...")
  69. createAnimations(plotsFolder, videoFolder)
  70. print("Done!")
  71. return 0
  72. #Gets position of the left side of wall
  73. def getxhighAbutment(xsize, xlow):
  74. wallxpos = xsize // 2
  75. #if xsize even, sub 1
  76. if xsize % 2 == 0:
  77. wallxpos -= 1
  78. return wallxpos + xlow
  79. #Create array that holds the position of wall obstacles.
  80. #Wall obstacles should always be at least 2x2 points!!!!!!!!!!!!!!!!
  81. #Ones are walls, zeroes are spaces.
  82. #There is a wall going down the middle with a hole in it in this version.
  83. def createWallArray(xsize, ysize, xlow, xhigh, ylow, yhigh):
  84. # ~ empty = []
  85. # ~ xwallArray = numpy.array(empty)
  86. # ~ ywallArray = numpy.array(empty)
  87. xwallArray = []
  88. ywallArray = []
  89. wallxpos = getxhighAbutment(xsize, xlow)
  90. # ~ print("wallxpos: " + str(wallxpos))
  91. # ~ yFirstThird = (ysize // 3) + ylow
  92. # ~ ySecondThird = ((ysize * 2) // 3) + ylow
  93. yFirstThird, ySecondThird = yPartitions(ysize, ylow)
  94. for i in range(ylow, yhigh + 1):
  95. if i <= yFirstThird or i >= ySecondThird:
  96. # ~ print("ysize // 3 = " + str(ysize // 3) + "\ti: " + str(i) + "\ti < (ysize // 3): " + str(i < (ysize // 3)) + "\ti > ((2 * ysize) // 3): " + str(i > ((2 * ysize) // 3)))
  97. xwallArray.append(wallxpos)
  98. ywallArray.append(i)
  99. xwallArray.append(wallxpos + 1)
  100. ywallArray.append(i)
  101. # ~ return xwallArray, ywallArray
  102. return numpy.array(xwallArray), numpy.array(ywallArray)
  103. #Returns the y partition points for the wall.
  104. def yPartitions(ysize, ylow):
  105. # ~ yFirstThird = (ysize // 3) + ylow
  106. # ~ ySecondThird = ((ysize * 2) // 3) + ylow
  107. # ~ yFirstThird = ((48 * ysize) // 100) + ylow
  108. # ~ ySecondThird = ((ysize * 52) // 100) + ylow
  109. yFirstThird = ((0 * ysize) // 100) + ylow
  110. ySecondThird = ((ysize * 10) // 100) + ylow
  111. return yFirstThird, ySecondThird
  112. #runs the simulation for some number of steps.
  113. def simulate(numSteps, xpositions, ypositions, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, ysize, stepSizeGraph, plotsFolder):
  114. #print initial condition
  115. printSimulation(xpositions, ypositions, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, 0, plotsFolder)
  116. movesArray = numpy.random.randint(1, 5, size=(numSteps, len(xpositions)))
  117. NORTH = 1
  118. EAST = 2
  119. SOUTH = 3
  120. WEST = 4
  121. for step in range(1, numSteps):
  122. #random walk the arrays.
  123. xpositions -= numpy.where(movesArray[step] == WEST, 1, 0)
  124. xpositions += numpy.where(movesArray[step] == EAST, 1, 0)
  125. ypositions += numpy.where(movesArray[step] == NORTH, 1, 0)
  126. ypositions -= numpy.where(movesArray[step] == SOUTH, 1, 0)
  127. #fix erroneous points.
  128. xpositions, ypositions = fixInWall(xpositions, ypositions, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, ysize)
  129. #print updated field
  130. if step % stepSizeGraph == 0:
  131. printSimulation(xpositions, ypositions, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, step, plotsFolder)
  132. #Moves points to a good position if they impact walls.
  133. def fixInWall(xpositions, ypositions, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, ysize):
  134. #Fix out of bounds
  135. for i in range(len(xpositions)):
  136. if xpositions[i] < xlow:
  137. xpositions[i] = xlow
  138. elif xpositions[i] > xhigh:
  139. xpositions[i] = xhigh
  140. if ypositions[i] < ylow:
  141. ypositions[i] = ylow
  142. elif ypositions[i] > yhigh:
  143. ypositions[i] = yhigh
  144. #get wall coords
  145. leftSideWall = math.inf
  146. rightSideWall = -math.inf
  147. yFirstThird, ySecondThird = yPartitions(ysize, ylow) #move up functions and pass?
  148. for i in range(len(xwallArray)):#move up functions loops
  149. if xwallArray[i] < leftSideWall:
  150. leftSideWall = xwallArray[i]
  151. if xwallArray[i] > rightSideWall:
  152. rightSideWall = xwallArray[i]
  153. #for each xy coord,
  154. for i in range(len(xpositions)):
  155. #left
  156. if xpositions[i] == leftSideWall:
  157. #if not in free middle third y section.
  158. if ypositions[i] <= yFirstThird or ypositions[i] >= ySecondThird:
  159. xpositions[i] -= 1
  160. #right
  161. elif xpositions[i] == rightSideWall:
  162. if ypositions[i] <= yFirstThird or ypositions[i] >= ySecondThird:
  163. xpositions[i] += 1
  164. return xpositions, ypositions
  165. def printSimulation(xArray, yArray, xwallArray, ywallArray, xlow, xhigh, ylow, yhigh, currentStep, plotsFolder):
  166. plt.title("Simulation of gas with wall: time = " + str(currentStep))
  167. plt.xlabel("x")
  168. plt.ylabel("y")
  169. plt.scatter(xArray, yArray, color="Red")
  170. plt.scatter(xwallArray, ywallArray, color="Black")
  171. plt.xlim(xlow, xhigh)
  172. plt.ylim(ylow, yhigh)
  173. # ~ plt.show()
  174. fileName = "{}plot{:05}.png".format(plotsFolder, currentStep)
  175. plt.savefig(fileName)
  176. plt.clf()
  177. #Creates the animation from the saved files.
  178. def createAnimations(plotsFolder, outputFolder):
  179. #This compresses the .pngs
  180. #os.system("optipng " + plotsFolder + "*.png")
  181. delay = 5
  182. print("Combining into an .mkv...")
  183. os.system("convert -delay " + str(delay) + " " + plotsFolder + "*.png " + outputFolder + "output.mkv")
  184. print("Combining into an .mp4...")
  185. os.system("convert -delay " + str(delay) + " " + plotsFolder + "*.png " + outputFolder + "output.mp4")
  186. print("Combining into a .gif...")
  187. os.system("convert -delay " + str(delay) + " " + plotsFolder + "*.png " + outputFolder + "output.gif")
  188. if __name__ == '__main__':
  189. import sys
  190. sys.exit(main(sys.argv))