Close Menu
    Trending
    • Prompt Caching with the OpenAI API: A Full Hands-On Python tutorial
    • Building a Navier-Stokes Solver in Python from Scratch: Simulating Airflow
    • Escaping the SQL Jungle | Towards Data Science
    • A Gentle Introduction to Nonlinear Constrained Optimization with Piecewise Linear Approximations
    • The Math That’s Killing Your AI Agent
    • Building Robust Credit Scoring Models (Part 3)
    • How to Measure AI Value
    • What’s the right path for AI? | MIT News
    ProfitlyAI
    • Home
    • Latest News
    • AI Technology
    • Latest AI Innovations
    • AI Tools & Technologies
    • Artificial Intelligence
    ProfitlyAI
    Home » Building a Navier-Stokes Solver in Python from Scratch: Simulating Airflow
    Artificial Intelligence

    Building a Navier-Stokes Solver in Python from Scratch: Simulating Airflow

    ProfitlyAIBy ProfitlyAIMarch 22, 2026No Comments7 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Share
    Facebook Twitter LinkedIn Pinterest Email


    (CFD) is usually seen as a black field of advanced industrial software program. Nonetheless, implementing a solver “from scratch” is among the strongest methods to study the physics of fluid movement. I began this as a private mission, and as part of a course on Biophysics, I took it as a possibility to lastly perceive how these lovely simulations work.

    This information is designed for knowledge scientists and engineers who wish to transfer past high-level libraries and perceive the underlying mechanics of numerical simulations by translating partial differential equations into discretized Python code. We may even discover basic programming ideas like vectorized operations with NumPy and stochastic convergence, that are important abilities for everybody fascinated with broader scientific computing and machine studying architectures.

    We’ll stroll by way of the derivation and Python implementation of a easy incompressible Navier-Stokes (NS) solver. After which, we are going to then apply this solver to simulate airflow round a chicken’s wing profile.

    The Physics: Incompressible Navier-Stokes

    The basic equations of CFD are the Navier-Stokes equations, which describe how velocity and stress evolve in a fluid. For regular flight (like a chicken gliding), we assume the air is incompressible (fixed density) and laminar. They are often understood as simply Newton’s movement regulation, however for an infinitesimal aspect of fluid, with the forces that have an effect on it. That’s largely stress and viscosity, however relying on the context you could possibly add in gravity, mechanical stresses, and even electromagnetism should you’re feeling prefer it. The writer can attest to this being very a lot not suggest for a primary mission. 

    The equations in vector kind are:

    [
    frac{partial mathbf{v}}{partial t} + (mathbf{v} cdot nabla)mathbf{v} = -frac{1}{rho}nabla p + nu nabla^2 mathbf{v}
    nabla cdot mathbf{v} = 0
    ]

    The place:

    • v: Velocity area (u,v)
    • p: Stress
    • ρ: Fluid density
    • ν: Kinematic viscosity

    The primary equation (Momentum) balances inertia in opposition to stress gradients and viscous diffusion. The second equation (Continuity) enforces that the fluid density stays fixed.

    The Stress Coupling Drawback

    A serious problem in CFD is that stress and velocity are coupled: the stress area should regulate continually to make sure the fluid stays incompressible.

    To unravel this, we derive a Stress-Poisson equation by taking the divergence of the momentum equation. In a discretized solver, we clear up this Poisson equation at each single timestep to replace the stress, guaranteeing the rate area stays divergence-free.

    Discretization: From Math to Grid

    To unravel these equations on a pc, we use Finite Distinction schemes on a uniform grid.

    • Time: Ahead distinction (Express Euler).
    • Advection (Nonlinear phrases): Backward/Upwind distinction (for stability).
    • Diffusion & Stress: Central distinction.

    For instance, the replace system for the u (x-velocity) part appears to be like like this in finite-difference kind

    [
    u_{i,j}^n frac{u_{i,j}^n - u_{i-1,j}^n}{Delta x}
    ]

    In code, the advection time period u∂x∂u​ makes use of a backward distinction: 

    [
    u_{i,j}^n frac{u_{i,j}^n - u_{i-1,j}^n}{Delta x}
    ]

    The Python Implementation

    The implementation proceeds in 4 distinct steps utilizing NumPy arrays.

    1. Initialization

    We outline the grid dimension (nx, ny), time step (dt), and bodily parameters (rho, nu). We initialize velocity fields (u,v) and stress (p) to zeros or a uniform circulate.

    2. The Wing Geometry (Immersed Boundary)

    To simulate a wing on a Cartesian grid, we have to mark which grid factors lie inside the stable wing.

    • We load a wing mesh (e.g., from an STL file).
    • We create a Boolean masks array the place True signifies some extent contained in the wing.
    • Throughout the simulation, we pressure velocity to zero at these masked factors (no-slip/no-penetration situation).

    3. The Predominant Solver Loop

    The core loop repeats till the answer reaches a gentle state. The steps are:

    1. Construct the Supply Time period (b): Calculate the divergence of the rate phrases.
    2. Resolve Stress: Resolve the Poisson equation for p utilizing Jacobi iteration.
    3. Replace Velocity: Use the brand new stress to replace u and v.
    4. Apply Boundary Situations: Implement inlet velocity and nil velocities contained in the wing.

    The Code

    Right here is how the core mathematical updates look in Python (vectorized for efficiency).

    Step A: Constructing the Stress Supply Time period This represents the Proper-Hand Aspect (RHS) of the Poisson equation primarily based on present velocities.

    # b is the supply time period
    # u and v are present velocity arrays
    b[1:-1, 1:-1] = (rho * (
        1 / dt * ((u[1:-1, 2:] - u[1:-1, 0:-2]) / (2 * dx) +
                  (v[2:, 1:-1] - v[0:-2, 1:-1]) / (2 * dy)) -
        ((u[1:-1, 2:] - u[1:-1, 0:-2]) / (2 * dx))**2 -
        2 * ((u[2:, 1:-1] - u[0:-2, 1:-1]) / (2 * dy) *
             (v[1:-1, 2:] - v[1:-1, 0:-2]) / (2 * dx)) -
        ((v[2:, 1:-1] - v[0:-2, 1:-1]) / (2 * dy))**2
    ))

    Step B: Fixing for Stress (Jacobi Iteration) We iterate to easy out the stress area till it balances the supply time period.

    for _ in vary(nit):
        pn = p.copy()
        p[1:-1, 1:-1] = (
            (pn[1:-1, 2:] + pn[1:-1, 0:-2]) * dy**2 +
            (pn[2:, 1:-1] + pn[0:-2, 1:-1]) * dx**2 -
            b[1:-1, 1:-1] * dx**2 * dy**2
        ) / (2 * (dx**2 + dy**2))
    # Boundary situations: p=0 at edges (gauge stress)
        p[:, -1] = 0; p[:, 0] = 0; p[-1, :] = 0; p[0, :] = 0

    Step C: Updating Velocity Lastly, we replace the rate utilizing the express discretized momentum equations.

    un = u.copy()
    vn = v.copy() 
    # Replace u (x-velocity)
    u[1:-1, 1:-1] = (un[1:-1, 1:-1] -
                     un[1:-1, 1:-1] * dt / dx * (un[1:-1, 1:-1] - un[1:-1, 0:-2]) -
                     vn[1:-1, 1:-1] * dt / dy * (un[1:-1, 1:-1] - un[0:-2, 1:-1]) -
                     dt / (2 * rho * dx) * (p[1:-1, 2:] - p[1:-1, 0:-2]) +
                     nu * (dt / dx**2 * (un[1:-1, 2:] - 2 * un[1:-1, 1:-1] + un[1:-1, 0:-2]) +
                           dt / dy**2 * (un[2:, 1:-1] - 2 * un[1:-1, 1:-1] + un[0:-2, 1:-1])))
    # Replace v (y-velocity)
    v[1:-1, 1:-1] = (vn[1:-1, 1:-1] -
                     un[1:-1, 1:-1] * dt / dx * (vn[1:-1, 1:-1] - vn[1:-1, 0:-2]) -
                     vn[1:-1, 1:-1] * dt / dy * (vn[1:-1, 1:-1] - vn[0:-2, 1:-1]) -
                     dt / (2 * rho * dy) * (p[2:, 1:-1] - p[0:-2, 1:-1]) +
                     nu * (dt / dx**2 * (vn[1:-1, 2:] - 2 * vn[1:-1, 1:-1] + vn[1:-1, 0:-2]) +
                           dt / dy**2 * (vn[2:, 1:-1] - 2 * vn[1:-1, 1:-1] + vn[0:-2, 1:-1])))

    Outcomes: Does it Fly?

    We ran this solver on a inflexible wing profile with a continuing far-field influx.

    Qualitative Observations The outcomes align with bodily expectations. The simulations present excessive stress beneath the wing and low stress above it, which is strictly the mechanism that generates elevate. Velocity vectors present the airflow accelerating excessive floor (Bernoulli’s precept).

    Forces: Raise vs. Drag By integrating the stress area over the wing floor, we will calculate elevate.

    • The solver demonstrates that stress forces dominate viscous friction forces by an element of almost 1000x in air.
    • Because the angle of assault will increase (from 0∘ to −20∘), the lift-to-drag ratio rises, matching tendencies seen in wind tunnels {and professional} CFD packages like OpenFOAM.

    Limitations & Subsequent Steps

    Whereas making this solver was nice for studying, the device itself has its limitations:

    • Decision: 3D simulations on a Cartesian grid are computationally costly and require coarse grids, making quantitative outcomes much less dependable.
    • Turbulence: The solver is laminar; it lacks a turbulence mannequin (like ok−ϵ) required for high-speed or advanced flows.
    • Diffusion: Upwind differencing schemes are secure however numerically diffusive, doubtlessly “smearing” out superb circulate particulars.

    The place to go from right here? This mission serves as a place to begin. Future enhancements may embody implementing higher-order advection schemes (like WENO), including turbulence modeling, or transferring to Finite Quantity strategies (like OpenFOAM) for higher mesh dealing with round advanced geometries. There are many intelligent strategies to get across the plethora of situations that you could be wish to implement. That is only a first step on the path of actually understanding CFD!



    Source link

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleEscaping the SQL Jungle | Towards Data Science
    Next Article Prompt Caching with the OpenAI API: A Full Hands-On Python tutorial
    ProfitlyAI
    • Website

    Related Posts

    Artificial Intelligence

    Prompt Caching with the OpenAI API: A Full Hands-On Python tutorial

    March 22, 2026
    Artificial Intelligence

    Escaping the SQL Jungle | Towards Data Science

    March 21, 2026
    Artificial Intelligence

    A Gentle Introduction to Nonlinear Constrained Optimization with Piecewise Linear Approximations

    March 21, 2026
    Add A Comment
    Leave A Reply Cancel Reply

    Top Posts

    User-friendly system can help developers build more efficient simulations and AI models | MIT News

    April 6, 2025

    How to Effectively Review Claude Code Output

    March 17, 2026

    Microsoft’s AI Chief Says We’re Not Ready for ‘Seemingly Conscious’ AI

    August 26, 2025

    A Lawsuit Over AI Agents that Shop

    November 13, 2025

    Vilken AI-modell passar dig bäst? ChatGPT, Claude, Gemini, Perplexity

    July 3, 2025
    Categories
    • AI Technology
    • AI Tools & Technologies
    • Artificial Intelligence
    • Latest AI Innovations
    • Latest News
    Most Popular

    Evaluating Your RAG Solution | Towards Data Science

    September 17, 2025

    How to Protect Your Creativity in the Age of AI with Bridget McCormack [MAICON 2025 Speaker Series]

    October 9, 2025

    How to Implement Three Use Cases for the New Calendar-Based Time Intelligence

    November 25, 2025
    Our Picks

    Prompt Caching with the OpenAI API: A Full Hands-On Python tutorial

    March 22, 2026

    Building a Navier-Stokes Solver in Python from Scratch: Simulating Airflow

    March 22, 2026

    Escaping the SQL Jungle | Towards Data Science

    March 21, 2026
    Categories
    • AI Technology
    • AI Tools & Technologies
    • Artificial Intelligence
    • Latest AI Innovations
    • Latest News
    • Privacy Policy
    • Disclaimer
    • Terms and Conditions
    • About us
    • Contact us
    Copyright © 2025 ProfitlyAI All Rights Reserved.

    Type above and press Enter to search. Press Esc to cancel.