Code Example7: Comprehensive Project
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class ComprehensiveProject:
"""Comprehensive Exercise Project: Advanced Sampling Methods practical application"""
def __init__(self, Nx=150, Ny=150):
self.Nx = Nx
self.Ny = Ny
self.x = np.linspace(0, 10, Nx)
self.y = np.linspace(0, 10, Ny)
self.X, self.Y = np.meshgrid(self.x, self.y)
self.dx = self.x[1] - self.x[0]
self.dy = self.y[1] - self.y[0]
# State variables
self.field = np.zeros((Nx, Ny))
self.auxiliary = np.zeros((Nx, Ny))
def initialize_complex_condition(self):
"""Complex initial condition"""
# Superposition of multiple Gaussian distributions
centers = [(2, 2), (5, 5), (8, 8), (2, 8), (8, 2)]
for (cx, cy) in centers:
self.field += np.exp(-((self.X - cx)**2 + (self.Y - cy)**2) / 0.3)
# Adding noise
self.field += 0.1 * np.random.randn(self.Nx, self.Ny)
def coupled_evolution(self, dt):
"""Coupled evolution equation"""
# Laplacian calculation
lap_field = np.zeros_like(self.field)
lap_field[1:-1, 1:-1] = (
(self.field[2:, 1:-1] - 2*self.field[1:-1, 1:-1] +
self.field[:-2, 1:-1]) / self.dx**2 +
(self.field[1:-1, 2:] - 2*self.field[1:-1, 1:-1] +
self.field[1:-1, :-2]) / self.dy**2
)
# Nonlinear term
nonlinear_term = self.field**2 - self.field**3
# Time evolution
self.field += dt * (lap_field + nonlinear_term)
# Boundary conditions(Neumann)
self.field[0, :] = self.field[1, :]
self.field[-1, :] = self.field[-2, :]
self.field[:, 0] = self.field[:, 1]
self.field[:, -1] = self.field[:, -2]
def compute_statistics(self):
"""Calculate statistics"""
mean = np.mean(self.field)
std = np.std(self.field)
total_energy = np.sum(self.field**2) * self.dx * self.dy
return {
'mean': mean,
'std': std,
'energy': total_energy,
'min': np.min(self.field),
'max': np.max(self.field)
}
def run_simulation(self, T=5.0, dt=0.01):
"""Run simulation"""
steps = int(T / dt)
# Recording statistical information
stats_history = []
for n in range(steps):
self.coupled_evolution(dt)
if n % 10 == 0:
stats = self.compute_statistics()
stats['time'] = n * dt
stats_history.append(stats)
print(f"Step {n}/{steps}: Energy={stats['energy']:.4f}")
return stats_history
def plot_final_results(self, stats_history):
"""Comprehensive plot of final results"""
fig = plt.figure(figsize=(16, 12))
gs = fig.add_gridspec(3, 3, hspace=0.3, wspace=0.3)
# Final field (contour)
ax1 = fig.add_subplot(gs[0, :2])
im1 = ax1.contourf(self.X, self.Y, self.field, levels=30, cmap='RdBu_r')
ax1.set_xlabel('x', fontsize=12)
ax1.set_ylabel('y', fontsize=12)
ax1.set_title('Final field distribution', fontsize=14, fontweight='bold')
plt.colorbar(im1, ax=ax1)
# 3D surface
ax2 = fig.add_subplot(gs[0, 2], projection='3d')
surf = ax2.plot_surface(self.X[::3, ::3], self.Y[::3, ::3],
self.field[::3, ::3], cmap='viridis')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_zlabel('field')
ax2.set_title('3D visualization', fontsize=12, fontweight='bold')
# Energy time evolution
ax3 = fig.add_subplot(gs[1, 0])
times = [s['time'] for s in stats_history]
energies = [s['energy'] for s in stats_history]
ax3.plot(times, energies, 'b-', linewidth=2)
ax3.set_xlabel('Time t', fontsize=12)
ax3.set_ylabel('Total energy', fontsize=12)
ax3.set_title('Energy conservation', fontsize=12, fontweight='bold')
ax3.grid(True, alpha=0.3)
# Time evolution of statistics
ax4 = fig.add_subplot(gs[1, 1])
means = [s['mean'] for s in stats_history]
stds = [s['std'] for s in stats_history]
ax4.plot(times, means, 'r-', linewidth=2, label='Mean')
ax4.plot(times, stds, 'g-', linewidth=2, label='Standard deviation')
ax4.set_xlabel('Time t', fontsize=12)
ax4.set_ylabel('Statistics', fontsize=12)
ax4.set_title('Statistical properties', fontsize=12, fontweight='bold')
ax4.legend()
ax4.grid(True, alpha=0.3)
# Minimum/maximum values
ax5 = fig.add_subplot(gs[1, 2])
mins = [s['min'] for s in stats_history]
maxs = [s['max'] for s in stats_history]
ax5.plot(times, mins, 'b-', linewidth=2, label='Minimum')
ax5.plot(times, maxs, 'r-', linewidth=2, label='Maximum')
ax5.set_xlabel('Time t', fontsize=12)
ax5.set_ylabel('Value', fontsize=12)
ax5.set_title('Minimum/maximum values', fontsize=12, fontweight='bold')
ax5.legend()
ax5.grid(True, alpha=0.3)
# Histogram
ax6 = fig.add_subplot(gs[2, 0])
ax6.hist(self.field.flatten(), bins=50, alpha=0.7, color='blue')
ax6.set_xlabel('ーValue', fontsize=12)
ax6.set_ylabel('Frequency', fontsize=12)
ax6.set_title('Value distribution', fontsize=12, fontweight='bold')
ax6.grid(True, alpha=0.3, axis='y')
# cross-sectionprofile
ax7 = fig.add_subplot(gs[2, 1])
mid_y = self.Ny // 2
ax7.plot(self.x, self.field[:, mid_y], 'b-', linewidth=2)
ax7.set_xlabel('x', fontsize=12)
ax7.set_ylabel('field(x, y=5)', fontsize=12)
ax7.set_title('Central cross-section', fontsize=12, fontweight='bold')
ax7.grid(True, alpha=0.3)
# Power spectrum
ax8 = fig.add_subplot(gs[2, 2])
fft_field = np.fft.fft2(self.field)
power_spectrum = np.abs(fft_field)**2
power_spectrum_1d = np.mean(power_spectrum, axis=0)
freq = np.fft.fftfreq(self.Nx, self.dx)
ax8.loglog(freq[1:self.Nx//2], power_spectrum_1d[1:self.Nx//2], 'b-')
ax8.set_xlabel('Wave number', fontsize=12)
ax8.set_ylabel('Power', fontsize=12)
ax8.set_title('Power spectrum', fontsize=12, fontweight='bold')
ax8.grid(True, alpha=0.3)
return fig
# Main execution
project = ComprehensiveProject(Nx=150, Ny=150)
project.initialize_complex_condition()
print("Starting comprehensive simulation...")
stats_history = project.run_simulation(T=5.0, dt=0.01)
fig = project.plot_final_results(stats_history)
plt.show()
print("\n=== Simulation completed ===")
print(f"Final energy: {stats_history[-1]['energy']:.4f}")
print(f"Final mean: {stats_history[-1]['mean']:.4f}")
print(f"FinalStandard deviation: {stats_history[-1]['std']:.4f}")