Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import matplotlib.pyplot as plt
- import time
- class ReactionDiffusionModel:
- def __init__(self, Nx=128, Ny=128, P=0.06):
- self.Nx = Nx
- self.Ny = Ny
- self.dx = 1.0
- self.dy = 1.0
- self.epsilon = 4.0
- self.beta = 0.9
- self.rho = 0.25
- self.T = 1.0
- self.D_par = 0.1
- self.P = P
- self.dt = 0.01
- self.t_max = 2000
- self.steps = int(self.t_max / self.dt)
- np.random.seed(42)
- self.x = 0.5 + 0.1 * (np.random.rand(self.Nx, self.Ny) - 0.5)
- self.time_points = []
- self.mean_history = []
- self.variance_history = []
- self.snapshots = {}
- if abs(self.P - 0.12) < 1e-5:
- self.snapshot_times = [20, 40, 60, 80, 100, 500, 1000, 2000]
- else:
- self.snapshot_times = [20, 100, 120, 160, 200, 500, 1000, 2000]
- def laplacian(self, field):
- top = np.roll(field, 1, axis=0)
- bottom = np.roll(field, -1, axis=0)
- left = np.roll(field, 1, axis=1)
- right = np.roll(field, -1, axis=1)
- return (top + bottom + left + right - 4 * field) / (self.dx ** 2)
- def nonlinear_flux_divergence(self, M, field):
- M_ip1 = np.roll(M, -1, axis=0)
- M_im1 = np.roll(M, 1, axis=0)
- M_jp1 = np.roll(M, -1, axis=1)
- M_jm1 = np.roll(M, 1, axis=1)
- f_ip1 = np.roll(field, -1, axis=0)
- f_im1 = np.roll(field, 1, axis=0)
- f_jp1 = np.roll(field, -1, axis=1)
- f_jm1 = np.roll(field, 1, axis=1)
- term_x = ( (M_ip1 + M)/2.0 * (f_ip1 - field) -
- (M + M_im1)/2.0 * (field - f_im1) ) / (self.dx**2)
- term_y = ( (M_jp1 + M)/2.0 * (f_jp1 - field) -
- (M + M_jm1)/2.0 * (field - f_jm1) ) / (self.dy**2)
- return term_x + term_y
- def reaction_term(self, x):
- term1 = self.P * (1 - x) * (1 - self.beta * x)
- term2 = x * (1 - self.beta * x) * np.exp(- (2 * self.epsilon / self.T) * x)
- term3 = self.D_par * x * (1 - self.beta)
- return term1 - term2 - term3
- def run(self):
- print(f"Початок симуляції для P={self.P}...")
- print(f" Цільові знімки на t: {self.snapshot_times}")
- start_time = time.time()
- for step in range(self.steps + 1):
- t = step * self.dt
- if step % 100 == 0:
- mean_val = np.mean(self.x)
- sq_mean = np.mean(self.x**2)
- variance = sq_mean - mean_val**2
- self.time_points.append(t)
- self.mean_history.append(mean_val)
- self.variance_history.append(variance)
- for st in self.snapshot_times:
- if abs(t - st) < self.dt / 1.5:
- if st not in self.snapshots:
- self.snapshots[st] = self.x.copy()
- M = self.x * (1 - self.x)
- lap_x = self.laplacian(self.x)
- factor = 2 * self.epsilon / self.T
- term_nabla_M_nabla_x = self.nonlinear_flux_divergence(M, self.x)
- term_nabla_M_nabla_lapX = self.nonlinear_flux_divergence(M, lap_x)
- Diffusion_total = lap_x - factor * term_nabla_M_nabla_x - factor * (self.rho**2) * term_nabla_M_nabla_lapX
- Reaction = self.reaction_term(self.x)
- self.x += self.dt * (Reaction + Diffusion_total)
- self.x = np.clip(self.x, 0, 1)
- if step % 50000 == 0 and step > 0:
- print(f" Прогрес: {t:.0f}/{self.t_max} a.u.")
- print(f"Симуляцію завершено за {time.time() - start_time:.2f} с.")
- def main():
- sim1 = ReactionDiffusionModel(P=0.06)
- sim1.run()
- sim2 = ReactionDiffusionModel(P=0.12)
- sim2.run()
- print("Виведення графіків...")
- plt.figure(figsize=(8, 6))
- plt.plot(sim1.time_points, sim1.mean_history, 'k-', label='P = 0.06')
- plt.plot(sim2.time_points, sim2.mean_history, 'r-', label='P = 0.12')
- plt.xlabel('time [a.u.]')
- plt.ylabel('<x>')
- plt.title('Середня концентрація')
- plt.legend()
- plt.grid(True, linestyle=':', alpha=0.6)
- plt.figure(figsize=(8, 6))
- plt.plot(sim1.time_points, sim1.variance_history, 'k-', label='P = 0.06')
- plt.plot(sim2.time_points, sim2.variance_history, 'r-', label='P = 0.12')
- plt.xlabel('time [a.u.]')
- plt.ylabel('<($\delta$x)$^2$>')
- plt.title('Дисперсія')
- plt.legend()
- plt.grid(True, linestyle=':', alpha=0.6)
- def show_8_snapshots(sim_obj, title):
- times = sorted(sim_obj.snapshots.keys())
- fig, axes = plt.subplots(2, 4, figsize=(16, 8))
- fig.suptitle(title, fontsize=16)
- ax_flat = axes.flatten()
- last_im = None
- for i, ax in enumerate(ax_flat):
- if i < len(times):
- t = times[i]
- last_im = ax.imshow(sim_obj.snapshots[t], cmap='hot', origin='lower', interpolation='bilinear', vmin=0, vmax=1)
- ax.set_title(f"t = {t}")
- ax.axis('off')
- else:
- ax.axis('off')
- if last_im:
- cbar = fig.colorbar(last_im, ax=axes, orientation='vertical', fraction=0.025, pad=0.04)
- cbar.set_label('x(r)', fontsize=12)
- show_8_snapshots(sim2, f"Еволюція для P=0.12")
- show_8_snapshots(sim1, f"Еволюція для P=0.06")
- plt.show()
- if __name__ == "__main__":
- main()
Advertisement