Eine Wasseranimation mit Geschwindigkeits -Hitzemap und sich wechselnder Oberflächenniveau in Python
Posted: 18 Apr 2025, 00:58
Ich versuche, eine Animation von Wasser aus Daten zu erstellen, die ich aus einer Simulation generiert habe. Das Uraw enthält auch horizontale Geschwindigkeiten, die an äquidistanten Stellen zwischen 0 und der Oberflächenhöhe des Wassers und dem anderen Datensatz (HRAW) die y-Koordinaten enthält, bei denen die Geschwindigkeiten gemessen werden. Ich habe es geschafft, nur die Oberfläche zu simulieren, aber die Wärme erscheinen nicht: < /p>
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# uraw and hraw have shape (t,x,y) say (174, 200, 50)
# Create grid coordinates
x_coords = np.arange(200)
X = np.tile(x_coords[:, np.newaxis], (1, 50))
# Calculate visualization parameters
max_h = np.max(hraw[:, :, -1]) # Maximum surface height
vmin, vmax = np.min(uraw), np.max(uraw) # Velocity color limits
# Set up figure
fig, ax = plt.subplots(figsize=(12, 7))
ax.set_xlabel('X Position')
ax.set_ylabel('Elevation')
ax.set_ylim(0, max_h * 1.05) # Add 5% padding
ax.set_title('Surface Elevation and Velocity Profile')
# Initial plot
pc = ax.pcolormesh(X, hraw[0], uraw[0],
shading='auto', cmap='viridis',
vmin=vmin, vmax=vmax)
line, = ax.plot(x_coords, hraw[0, :, -1], 'r-', lw=2, label='Surface')
cbar = fig.colorbar(pc, ax=ax)
cbar.set_label('Velocity Magnitude')
def animate(t):
"""Update plot for each timestep"""
# Update velocity heatmap
pc.set_array(uraw[t].ravel())
pc.set_offsets(np.column_stack([X.ravel(), hraw[t].ravel()]))
# Update surface line
line.set_ydata(hraw[t, :, -1])
ax.set_title(f'Time Step: {t}/{hraw.shape[0]-1}')
return pc, line
ani = FuncAnimation(fig, animate, frames=hraw.shape[0], interval=100, blit=False)
plt.show()
< /code>
Versuch 1 < /p>
Ich habe auch einen anderen gemacht, in dem ich es geschafft habe, die Hitzemap zu arbeiten, aber die Höhen werden konstant gehalten: < /p>
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
timesteps, nx, ny = hraw.shape
x = np.linspace(0, 1, nx) # arbitrary horizontal scale
y_base = np.linspace(0, 1, ny) # normalized vertical positions
X, Y_base = np.meshgrid(x, y_base)
# Determine the global max absolute velocity for symmetric color scaling
abs_max_vel = np.max(np.abs(uraw))
# Initial setup
fig, ax = plt.subplots(figsize=(10, 6))
U0 = uraw[0].T # shape (50, 200)
H0 = hraw[0, :, -1] # surface heights at timestep 0
# Create the velocity heatmap with symmetric colormap and limits
velocity_mesh = ax.pcolormesh(
x, y_base, U0,
shading='auto',
cmap='seismic',
vmin=-abs_max_vel,
vmax=abs_max_vel
)
surface_line, = ax.plot(x, H0, color='white', lw=2, label='Surface')
colorbar = fig.colorbar(velocity_mesh, ax=ax, label='Velocity (u)')
# Set axis limits
ax.set_xlim(x[0], x[-1])
ax.set_ylim(0, np.max(hraw))
ax.set_xlabel('x')
ax.set_ylabel('Height')
ax.set_title('Water surface and horizontal velocity')
ax.legend()
def update(t):
h = hraw[t] # shape (200, 50)
u = uraw[t] # shape (200, 50)
# Construct dynamic Y grid
Y_dynamic = np.array([np.linspace(0, h[i, -1], ny) for i in range(nx)]).T
# Update pcolormesh values and offsets
velocity_mesh.set_array(u.T.ravel())
velocity_mesh.set_offsets(np.c_[X.ravel(), Y_dynamic.ravel()])
# Update surface line
surface_line.set_ydata(h[:, -1])
ax.set_title(f"Timestep {t}")
return velocity_mesh, surface_line
ani = animation.FuncAnimation(fig, update, frames=timesteps, interval=100, blit=False)
plt.show()
< /code>
Versuch 2 < /p>
Grundsätzlich möchte ich, dass es eine dynamische Oberfläche und eine Wärmemap hat. Ich habe es geschafft, sie getrennt, aber nicht zusammen zu bekommen.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# uraw and hraw have shape (t,x,y) say (174, 200, 50)
# Create grid coordinates
x_coords = np.arange(200)
X = np.tile(x_coords[:, np.newaxis], (1, 50))
# Calculate visualization parameters
max_h = np.max(hraw[:, :, -1]) # Maximum surface height
vmin, vmax = np.min(uraw), np.max(uraw) # Velocity color limits
# Set up figure
fig, ax = plt.subplots(figsize=(12, 7))
ax.set_xlabel('X Position')
ax.set_ylabel('Elevation')
ax.set_ylim(0, max_h * 1.05) # Add 5% padding
ax.set_title('Surface Elevation and Velocity Profile')
# Initial plot
pc = ax.pcolormesh(X, hraw[0], uraw[0],
shading='auto', cmap='viridis',
vmin=vmin, vmax=vmax)
line, = ax.plot(x_coords, hraw[0, :, -1], 'r-', lw=2, label='Surface')
cbar = fig.colorbar(pc, ax=ax)
cbar.set_label('Velocity Magnitude')
def animate(t):
"""Update plot for each timestep"""
# Update velocity heatmap
pc.set_array(uraw[t].ravel())
pc.set_offsets(np.column_stack([X.ravel(), hraw[t].ravel()]))
# Update surface line
line.set_ydata(hraw[t, :, -1])
ax.set_title(f'Time Step: {t}/{hraw.shape[0]-1}')
return pc, line
ani = FuncAnimation(fig, animate, frames=hraw.shape[0], interval=100, blit=False)
plt.show()
< /code>
Versuch 1 < /p>
Ich habe auch einen anderen gemacht, in dem ich es geschafft habe, die Hitzemap zu arbeiten, aber die Höhen werden konstant gehalten: < /p>
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
timesteps, nx, ny = hraw.shape
x = np.linspace(0, 1, nx) # arbitrary horizontal scale
y_base = np.linspace(0, 1, ny) # normalized vertical positions
X, Y_base = np.meshgrid(x, y_base)
# Determine the global max absolute velocity for symmetric color scaling
abs_max_vel = np.max(np.abs(uraw))
# Initial setup
fig, ax = plt.subplots(figsize=(10, 6))
U0 = uraw[0].T # shape (50, 200)
H0 = hraw[0, :, -1] # surface heights at timestep 0
# Create the velocity heatmap with symmetric colormap and limits
velocity_mesh = ax.pcolormesh(
x, y_base, U0,
shading='auto',
cmap='seismic',
vmin=-abs_max_vel,
vmax=abs_max_vel
)
surface_line, = ax.plot(x, H0, color='white', lw=2, label='Surface')
colorbar = fig.colorbar(velocity_mesh, ax=ax, label='Velocity (u)')
# Set axis limits
ax.set_xlim(x[0], x[-1])
ax.set_ylim(0, np.max(hraw))
ax.set_xlabel('x')
ax.set_ylabel('Height')
ax.set_title('Water surface and horizontal velocity')
ax.legend()
def update(t):
h = hraw[t] # shape (200, 50)
u = uraw[t] # shape (200, 50)
# Construct dynamic Y grid
Y_dynamic = np.array([np.linspace(0, h[i, -1], ny) for i in range(nx)]).T
# Update pcolormesh values and offsets
velocity_mesh.set_array(u.T.ravel())
velocity_mesh.set_offsets(np.c_[X.ravel(), Y_dynamic.ravel()])
# Update surface line
surface_line.set_ydata(h[:, -1])
ax.set_title(f"Timestep {t}")
return velocity_mesh, surface_line
ani = animation.FuncAnimation(fig, update, frames=timesteps, interval=100, blit=False)
plt.show()
< /code>
Versuch 2 < /p>
Grundsätzlich möchte ich, dass es eine dynamische Oberfläche und eine Wärmemap hat. Ich habe es geschafft, sie getrennt, aber nicht zusammen zu bekommen.