Py.Cafe

jackparmer/

navier-stokes-animation

Animated 3D Navier-Stokes Equation Visualization with Plotly

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import numpy as np
import plotly.graph_objects as go
from scipy.ndimage import gaussian_filter

# Initialize the Dash app
app = dash.Dash(__name__)

# Function to generate initial fluid flow
def generate_initial_flow(shape=(20, 20, 20)):
    flow = np.random.rand(*shape, 3) * 2 - 1
    flow = gaussian_filter(flow, sigma=2)
    return flow

# Function to update the fluid flow
def update_flow(flow):
    perturbation = (np.random.rand(*flow.shape) * 2 - 1) * 0.1
    new_flow = flow + perturbation
    new_flow = gaussian_filter(new_flow, sigma=1)
    return new_flow

# Create initial fluid flow
initial_flow = generate_initial_flow()

# Initial camera position
initial_camera_angle = 0

# Create a 3D plot
def create_3d_plot(flow, angle):
    x, y, z = np.mgrid[0:1:20j, 0:1:20j, 0:1:20j]
    u, v, w = flow[..., 0], flow[..., 1], flow[..., 2]
    fig = go.Figure(data=go.Cone(x=x.flatten(), y=y.flatten(), z=z.flatten(),
                                  u=u.flatten(), v=v.flatten(), w=w.flatten(),
                                  colorscale='Viridis', sizemode='absolute',
                                  anchor="tip", showscale=False))

    # Calculate new camera position for rotation
    camera_x = 1.2 * np.cos(angle)
    camera_y = 1.2 * np.sin(angle)
    camera_z = 0.8  # Slightly zoomed in

    fig.update_layout(scene=dict(
        camera=dict(eye=dict(x=camera_x, y=camera_y, z=camera_z)),
        aspectratio=dict(x=1, y=1, z=1),
        aspectmode='cube'
    ))

    return fig

# Define the layout of the Dash app
app.layout = html.Div([
    html.H1("Navier-Stokes Equation Animation in 3D"),
    dcc.Interval(id='interval-component', interval=500, n_intervals=0),  # Slowed down to 500 ms
    dcc.Graph(id='3d-plot')
])

# Define the callback to update the 3D plot
@app.callback(
    Output('3d-plot', 'figure'),
    [Input('interval-component', 'n_intervals')]
)
def animate_flow(n):
    global initial_flow, initial_camera_angle
    initial_flow = update_flow(initial_flow)
    initial_camera_angle += 0.05  # Rotate the camera
    return create_3d_plot(initial_flow, initial_camera_angle)

# Run the app
if __name__ == '__main__':
    app.run_server(debug=True)