Advertisement
mirosh111000

Мірошниченко_Артем_ПМ-11_Лр№4_Мет_комп_експ

Mar 29th, 2024
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.28 KB | None | 0 0
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import time
  4. from IPython.display import Latex
  5.  
  6.  
  7.  
  8. def my_time_(s):
  9.     h = s // 3600
  10.     time = s % 3600
  11.     m = time // 60
  12.     s = time % 60
  13.     if h < 10:
  14.         h = '0' + str(int(h))
  15.     if m < 10:
  16.         m = '0' + str(int(m))
  17.     if s < 10:
  18.         s = '0' + str(int(s))
  19.    
  20.     return fr'{h}:{m}:{s}'
  21.  
  22.  
  23. def phi(r, sigma=SIGMA, epsilon=EPSILON):
  24.     sigma_r_pow_6 = (sigma / r) ** 6
  25.     return 4 * epsilon * (sigma_r_pow_6 ** 2 - sigma_r_pow_6)
  26. def init_state(number_of_pieces=NUMBER_OF_PIECES, mass=1):
  27.     pieces = np.zeros((number_of_pieces, 5))
  28.     pieces[:, MASS] = np.full(number_of_pieces, mass)  # mass
  29.     pieces[:, X] = np.random.rand(number_of_pieces) * BOX_WIDTH  # x
  30.     pieces[:, Y] = np.random.rand(number_of_pieces) * BOX_HEIGHT  # y
  31.     pieces[:, VX] = (2 * np.random.rand(number_of_pieces) - 1) * V_MAX  # vx
  32.     pieces[:, VY] = (2 * np.random.rand(number_of_pieces) - 1) * V_MAX  # vy
  33.  
  34.     pieces[:, VX] -= np.mean(pieces[:, VX])
  35.     pieces[:, VY] -= np.mean(pieces[:, VY])
  36.  
  37.     while True:
  38.         flag = False
  39.         for i in range(0, number_of_pieces):
  40.             for j in range(i + 1, number_of_pieces):
  41.                 rx = pieces[i, X] - pieces[j, X]
  42.                 ry = pieces[i, Y] - pieces[j, Y]
  43.                 r = (rx ** 2 + ry ** 2) ** 0.5
  44.                 if r < 1:
  45.                     pieces[j, X] = np.random.rand(1)[0] * BOX_WIDTH
  46.                     flag = True
  47.         if not flag:
  48.             break
  49.  
  50.     return pieces
  51. class FCalc:
  52.     def __init__(self, number_of_pieces=NUMBER_OF_PIECES, epsilon=EPSILON, sigma=SIGMA):
  53.         self.number_of_pieces = number_of_pieces
  54.         self.epsilon = epsilon
  55.         self.sigma = sigma
  56.         self.cache = np.full((number_of_pieces, number_of_pieces), None)
  57.  
  58.     def get_from_cache(self, i, j):
  59.         return self.cache[i][j]
  60.  
  61.     def save_to_cache(self, Fr, i, j):
  62.         self.cache[i][j] = Fr
  63.  
  64.  
  65.     def f(self, r):
  66.         sigma_r = self.sigma / r
  67.         sigma_r_pow_6 = sigma_r ** 6
  68.         return 24 * self.epsilon * sigma_r * sigma_r_pow_6 * (2 * sigma_r_pow_6 - 1)
  69.  
  70.     def fi(self, i, state, axis):
  71.         forces = np.zeros(self.number_of_pieces)
  72.         for j in range(0, self.number_of_pieces):
  73.             if i == j:
  74.                 Fr = 0
  75.             else:
  76.                 x = state[i, X] - state[j, X]
  77.                 y = state[i, Y] - state[j, Y]
  78.                 r = (y ** 2 + x ** 2) ** 0.5
  79.  
  80.                 Fr_from_cache = self.get_from_cache(i, j)
  81.                 if Fr_from_cache is not None:
  82.                     Fr = Fr_from_cache
  83.                 else:
  84.                     Fr = self.f(r)
  85.                     self.save_to_cache(Fr, i, j)
  86.  
  87.                 if axis == X:
  88.                     Fr = x / r * Fr
  89.                 elif axis == Y:
  90.                     Fr = y / r * Fr
  91.  
  92.             forces[j] = Fr
  93.  
  94.         return np.sum(forces)
  95.  
  96.  
  97. def mean_kinetic_energy(state):
  98.     mass = state[:, MASS]
  99.     vx = state[:, VX]
  100.     vy = state[:, VY]
  101.     v2 = vx ** 2 + vy ** 2
  102.     kinetic_energy = 0.5 * mass * v2
  103.     return np.mean(kinetic_energy)
  104.  
  105.  
  106. def rt(t0_state, t_state):
  107.     xt0 = t0_state[:, X]
  108.     yt0 = t0_state[:, Y]
  109.     xt = t_state[:, X]
  110.     yt = t_state[:, Y]
  111.     return np.hypot((xt - xt0), (yt - yt0))
  112.  
  113.  
  114. def mean_potential_energy(state):
  115.     number_of_pieces = state.shape[0]
  116.  
  117.     counter = 0
  118.     phis_count = int(number_of_pieces * (number_of_pieces + 1) / 2)
  119.     phis = np.zeros(phis_count)
  120.     for i in range(0, number_of_pieces):
  121.         for j in range(i + 1, number_of_pieces):
  122.             x = state[i, X] - state[j, X]
  123.             y = state[i, Y] - state[j, Y]
  124.             r = (y ** 2 + x ** 2) ** 0.5
  125.             phis[counter] = phi(abs(r))
  126.             counter += 1
  127.  
  128.     return np.sum(phis) / number_of_pieces
  129.  
  130.  
  131. def Rt2(state, t0_state):
  132.     return np.mean(rt(state, t0_state) ** 2)
  133.  
  134.  
  135. def handle_corner_cases(x, y, vx, vy):
  136.     if x < 0:
  137.         x = -x
  138.         vx = -vx
  139.     elif x > BOX_WIDTH:
  140.         x = BOX_WIDTH - (x - BOX_WIDTH)
  141.         vx = -vx
  142.     if y < 0:
  143.         y = -y
  144.         vy = -vy
  145.     elif y > BOX_HEIGHT:
  146.         y = BOX_HEIGHT - (y - BOX_HEIGHT)
  147.         vy = -vy
  148.     return x, y, vx, vy
  149.  
  150.  
  151. # Ейлер
  152. def calc_next_state(state, epsilon=EPSILON, sigma=SIGMA):
  153.     next_state = np.copy(state)
  154.     f_calc = FCalc(NUMBER_OF_PIECES, epsilon, sigma)
  155.  
  156.     for i, piece_state in enumerate(state):
  157.         Fix = f_calc.fi(i, state, X)
  158.         Fiy = f_calc.fi(i, state, Y)
  159.         axi = Fix / piece_state[MASS]
  160.         ayi = Fiy / piece_state[MASS]
  161.         vxi = piece_state[VX] + axi * DELTA_T
  162.         vyi = piece_state[VY] + ayi * DELTA_T
  163.  
  164.         xi = piece_state[X] + vxi * DELTA_T
  165.         yi = piece_state[Y] + vyi * DELTA_T
  166.         xi, yi, vxi, vyi = handle_corner_cases(xi, yi, vxi, vyi)
  167.  
  168.         next_state[i][X] = xi
  169.         next_state[i][Y] = yi
  170.         next_state[i][VX] = vxi
  171.         next_state[i][VY] = vyi
  172.  
  173.     return next_state
  174.  
  175.  
  176.  
  177.  
  178.  
  179. NUMBER_OF_PIECES = 100  
  180. EPSILON = 1  
  181. SIGMA = 1  
  182. BOX_WIDTH = 20  
  183. BOX_HEIGHT = 20
  184. WEGHT = 1
  185. DELTA_T = 0.001  
  186. V_MAX = 1
  187.  
  188. MASS, X, Y, VX, VY = [0, 1, 2, 3, 4]
  189.  
  190.  
  191. start_time = time.time()
  192.  
  193. initial_state = init_state()
  194. x_values = [initial_state[-1, X]]
  195. y_values = [initial_state[-1, Y]]
  196.  
  197. current_state = initial_state
  198. current_time = 0
  199. total_time = 100
  200.  
  201. while current_time < total_time:
  202.     current_state = calc_next_state(current_state)
  203.     print(f'current_time={current_time}\n')
  204.     x_values.append(current_state[-1, X])
  205.     y_values.append(current_state[-1, Y])
  206.     current_time += DELTA_T
  207.  
  208. plt.plot(x_values, y_values)
  209. plt.scatter(x_values[0], y_values[0], c='red', label=r'$start$')
  210. plt.scatter(x_values[-1], y_values[-1], c='blue', label=r'$finish$')
  211. plt.xlabel(r'$x$')
  212. plt.ylabel(r'$y$')
  213. plt.title(r'$Фазовий\ портрет\ частинки$')
  214. plt.legend()
  215. plt.grid(True)
  216. plt.show()
  217.  
  218. end_time = time.time()
  219. my_time = end_time - start_time
  220.  
  221. display(Latex(fr'$Час\ моделювання: \quad {my_time_(round(my_time))}.$'))
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230. start_time = time.time()
  231.  
  232. initial_state = init_state()
  233. current_state = initial_state
  234. kinetic_energies = []
  235. potential_energies = []
  236. total_energies = []
  237.  
  238. plt.figure(figsize=(10, 6))
  239.  
  240. current_time = 0
  241. while current_time < total_time:
  242.     print(f'current_time={current_time}\n')
  243.     kinetic_energy_value = mean_kinetic_energy(current_state)
  244.     potential_energy_value = mean_potential_energy(current_state)
  245.     total_energy_value = kinetic_energy_value + potential_energy_value
  246.     kinetic_energies.append(kinetic_energy_value)
  247.     potential_energies.append(potential_energy_value)
  248.     total_energies.append(total_energy_value)
  249.     current_state = calc_next_state(current_state)
  250.     current_time += DELTA_T
  251.  
  252.  
  253. time_points = np.linspace(0, 100, len(kinetic_energies))
  254.  
  255. plt.plot(time_points, kinetic_energies, label=r'$Kinetic\ Energy$')
  256. plt.plot(time_points, potential_energies, label=r'$Potential\ Energy$')
  257. plt.plot(time_points, total_energies, label=r'$Total\ Energy$')
  258. plt.xlabel(r'$Time$')
  259. plt.ylabel(r'$Energy$')
  260. plt.title(r'$Залежність\ середніх\ значень\ енергій\ від\ часу$')
  261. plt.legend()
  262. plt.grid(True)
  263. plt.show()
  264.  
  265. end_time = time.time()
  266. my_time = end_time - start_time
  267.  
  268. display(Latex(fr'$Час\ моделювання: \quad {my_time_(round(my_time))}.$'))
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275. start_time = time.time()
  276.  
  277.  
  278. initial_state = init_state()
  279. current_state = initial_state
  280. displacements = []
  281. time_points = []
  282.  
  283. current_time = 0
  284. while current_time < total_time:
  285.     print(f'current_time={current_time}\n')
  286.     rt2_value = Rt2(current_state, initial_state)
  287.     displacements.append(rt2_value)
  288.     time_points.append(current_time)
  289.    
  290.     current_state = calc_next_state(current_state)
  291.     current_time += DELTA_T
  292.  
  293.  
  294. plt.figure(figsize=(10, 6))
  295. plt.loglog(time_points, displacements, c='red', marker='o', linestyle='', markersize=5)
  296. plt.xlabel(r'$Time$')
  297. plt.ylabel(r'$Mean\ Square\ Displacement$')
  298. plt.title(r'$Середньоквадратичне\ зміщення\ для\ всіх\ частинок$')
  299. plt.grid(True)
  300. plt.show()
  301.  
  302. end_time = time.time()
  303. my_time = end_time - start_time
  304.  
  305. display(Latex(fr'$Час\ моделювання: \quad {my_time_(round(my_time))}.$'))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement