Guest User

Untitled

a guest
Jan 18th, 2025
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.89 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import numpy as np
  4. from scipy.integrate import solve_ivp
  5. from PIL import Image
  6. import colorsys
  7. import math
  8. from concurrent.futures import ProcessPoolExecutor
  9. import json
  10.  
  11. # this function was made by GPT because I am way too fucking stupid to know how to code double pendulum physics
  12. def double_pendulum_simulation(theta1_start, theta2_start, sim_time) -> tuple[float]:
  13.     """
  14.    Simulates a double pendulum and returns the final angles of both pendulums.
  15.  
  16.    Parameters:
  17.        theta1_start (float): Initial angle of the first pendulum in radians. Angle 0 is downwards and + goes counter clockwise.
  18.        theta2_start (float): Initial angle of the second pendulum (in radians). Angle 0 is downwards and + goes counter clockwise.
  19.        sim_time (float): Time to simulate the system (in seconds).
  20.  
  21.    Returns:
  22.        tuple: Final angles (theta1, theta2) in radians. Angle is in the range [0 - 2pi)
  23.    """
  24.     # Constants (fixed values)
  25.     g = 9.81  # gravitational acceleration (m/s^2)
  26.  
  27.     # Equations of motion
  28.     def equations(t, y):
  29.         theta1, omega1, theta2, omega2 = y
  30.  
  31.         delta_theta = theta1 - theta2
  32.         denom1 = 2 - np.cos(delta_theta)**2
  33.         denom2 = denom1
  34.  
  35.         alpha1 = (-g * (2) * np.sin(theta1)
  36.                   - g * np.sin(theta1 - 2*theta2)
  37.                   - 2 * np.sin(delta_theta) * (omega2**2 + omega1**2 * np.cos(delta_theta))) / denom1
  38.  
  39.         alpha2 = (2 * np.sin(delta_theta) * (omega1**2
  40.                                              + g * np.cos(theta1)
  41.                                              + omega2**2 * np.cos(delta_theta))) / denom2
  42.  
  43.         return [omega1, alpha1, omega2, alpha2]
  44.  
  45.     # Initial conditions
  46.     theta1_0 = theta1_start  # initial angle of first pendulum (radians)
  47.     omega1_0 = 0.0           # initial angular velocity of first pendulum
  48.     theta2_0 = theta2_start  # initial angle of second pendulum (radians)
  49.     omega2_0 = 0.0           # initial angular velocity of second pendulum
  50.  
  51.     y0 = [theta1_0, omega1_0, theta2_0, omega2_0]
  52.  
  53.     # Time span
  54.     t_span = (0, sim_time)
  55.  
  56.     # Solve using Runge-Kutta method
  57.     solution = solve_ivp(equations, t_span, y0, method='RK45')
  58.  
  59.     # Final angles
  60.     theta1_final = solution.y[0, -1]
  61.     theta2_final = solution.y[2, -1]
  62.  
  63.     return float(theta1_final % (2 * np.pi)), float(theta2_final % (2 * np.pi))
  64.  
  65.  
  66. RESOLUTION: int = 4000
  67.  
  68. def process_column(x):
  69.     column_pixels = []
  70.     for y in range(RESOLUTION):
  71.         angle1, angle2 = double_pendulum_simulation(2 * np.pi / RESOLUTION * x, 2 * np.pi / RESOLUTION * y, 2)
  72.  
  73.         angle1Norm: float = float(angle1 / (2 * np.pi))
  74.         angle2Norm: float = float(angle2 / (2 * np.pi))
  75.  
  76.         # normalize angle one
  77.         if angle1Norm <= 0.5:
  78.             angle1Norm *= 2
  79.         else:
  80.             angle1Norm = 1 - ((angle1Norm - 0.5) * 2)
  81.  
  82.         # make image brighter
  83.         angle1Norm **= (1 / 3)
  84.  
  85.         color = colorsys.hsv_to_rgb(angle2Norm, 1, angle1Norm)
  86.  
  87.         # Store pixel data for this column
  88.         column_pixels.append((x, y, round(color[0] * 255), round(color[1] * 255), round(color[2] * 255)))
  89.  
  90.     with open(f"row_data/row_{x}", "w") as f:
  91.         json.dump(column_pixels, f)
  92.     print(x)
  93.  
  94.  
  95. choice = input("press enter to start generating image. Write anything and then press enter to combine row data into one image file.")
  96. if choice == "":
  97.     # Use ProcessPoolExecutor to parallelize the task
  98.     with ProcessPoolExecutor(max_workers=8) as executor:
  99.         executor.map(process_column, range(RESOLUTION))
  100. else:
  101.     image = Image.new("RGB", (RESOLUTION, RESOLUTION))
  102.     pixels = image.load()
  103.  
  104.     for row in range(RESOLUTION):
  105.         with open(f"row_data/row_{row}") as f:
  106.             columnPixels = json.load(f)
  107.  
  108.         for x, y, r, g, b in columnPixels:
  109.             pixels[x, y] = (r, g, b)
  110.  
  111.     image.save("output.png")
Add Comment
Please, Sign In to add comment