Py.Cafe

jackparmer/

dash-3d-diffusion-solver

3D Diffusion Equation Solver

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go

def solve_diffusion_equation(nx, ny, nz, nt, D, dt, initial_conditions):
    """
    Solve the diffusion equation using finite differences.

    Parameters:
    - nx, ny, nz: Number of grid points in the x, y, and z directions
    - nt: Number of time steps
    - D: Diffusion coefficient
    - dt: Time step size
    - initial_conditions: A function that takes x, y, z and returns the initial condition

    Returns:
    - A list of 3D arrays representing the solution at each time step
    """
    dx = 1.0 / (nx - 1)
    dy = 1.0 / (ny - 1)
    dz = 1.0 / (nz - 1)

    u = np.zeros((nx, ny, nz))
    u_new = np.zeros((nx, ny, nz))
    
    # Set initial conditions
    for i in range(nx):
        for j in range(ny):
            for k in range(nz):
                u[i, j, k] = initial_conditions(i * dx, j * dy, k * dz)
    
    results = [u.copy()]
    
    for n in range(nt):
        for i in range(1, nx-1):
            for j in range(1, ny-1):
                for k in range(1, nz-1):
                    u_new[i, j, k] = (
                        u[i, j, k]
                        + D * dt / dx**2 * (u[i+1, j, k] - 2 * u[i, j, k] + u[i-1, j, k])
                        + D * dt / dy**2 * (u[i, j+1, k] - 2 * u[i, j, k] + u[i, j-1, k])
                        + D * dt / dz**2 * (u[i, j, k+1] - 2 * u[i, j, k] + u[i, j, k-1])
                    )
        
        u[:] = u_new[:]
        results.append(u.copy())
    
    return results

# Parameters
nx, ny, nz = 20, 20, 20
nt = 50
D = 0.1
dt = 0.01

# Initial conditions function
def initial_conditions(x, y, z):
    return np.exp(-((x-0.5)**2 + (y-0.5)**2 + (z-0.5)**2) / 0.1)

# Solve the diffusion equation
results = solve_diffusion_equation(nx, ny, nz, nt, D, dt, initial_conditions)

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

app.layout = html.Div([
    dcc.Graph(id='diffusion-graph'),
    dcc.Slider(
        id='time-slider',
        min=0,
        max=nt-1,
        step=1,
        value=0,
        marks={i: str(i) for i in range(0, nt, nt//10)}
    )
])

@app.callback(
    dash.dependencies.Output('diffusion-graph', 'figure'),
    [dash.dependencies.Input('time-slider', 'value')]
)
def update_graph(time_step):
    data = results[time_step]
    
    trace = go.Volume(
        x=np.repeat(np.linspace(0, 1, nx), ny * nz),
        y=np.tile(np.repeat(np.linspace(0, 1, ny), nz), nx),
        z=np.tile(np.linspace(0, 1, nz), nx * ny),
        value=data.flatten(),
        isomin=0,
        isomax=1,
        opacity=0.1,
        surface_count=10,
    )
    
    layout = go.Layout(
        scene=dict(
            xaxis=dict(nticks=10, range=[0, 1]),
            yaxis=dict(nticks=10, range=[0, 1]),
            zaxis=dict(nticks=10, range=[0, 1]),
        ),
        margin=dict(r=0, l=0, b=0, t=0)
    )
    
    return go.Figure(data=[trace], layout=layout)

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