Close Menu
SkytikSkytik

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    At Least 32 People Dead After a Mine Bridge Collapsed Due to Overcrowding

    November 17, 2025

    Here’s how I turned a Raspberry Pi into an in-car media server

    November 17, 2025

    Beloved SF cat’s death fuels Waymo criticism

    November 17, 2025
    Facebook X (Twitter) Instagram
    • About Us
    • Contact Us
    SkytikSkytik
    • Home
    • AI Tools
    • Online Tools
    • Tech News
    • Guides
    • Reviews
    • SEO & Marketing
    • Social Media Tools
    SkytikSkytik
    Home»AI Tools»Building a Navier-Stokes Solver in Python from Scratch: Simulating Airflow
    AI Tools

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

    AwaisBy AwaisMarch 22, 2026No Comments7 Mins Read0 Views
    Facebook Twitter Pinterest LinkedIn Telegram Tumblr Email
    Building a Navier-Stokes Solver in Python from Scratch: Simulating Airflow
    Share
    Facebook Twitter LinkedIn Pinterest Email

    (CFD) is often seen as a black box of complex commercial software. However, implementing a solver “from scratch” is one of the most powerful ways to learn the physics of fluid motion. I started this as a personal project, and as a part of a course on Biophysics, I took it as an opportunity to finally understand how these beautiful simulations work.

    This guide is designed for data scientists and engineers who want to move beyond high-level libraries and understand the underlying mechanics of numerical simulations by translating partial differential equations into discretized Python code. We will also explore fundamental programming concepts like vectorized operations with NumPy and stochastic convergence, which are essential skills for everyone interested in broader scientific computing and machine learning architectures.

    We will walk through the derivation and Python implementation of a simple incompressible Navier-Stokes (NS) solver. And then, we will then apply this solver to simulate airflow around a bird’s wing profile.

    The Physics: Incompressible Navier-Stokes

    The fundamental equations of CFD are the Navier-Stokes equations, which describe how velocity and pressure evolve in a fluid. For steady flight (like a bird gliding), we assume the air is incompressible (constant density) and laminar. They can be understood as just Newton’s motion law, but for an infinitesimal element of fluid, with the forces that affect it. That’s mostly pressure and viscosity, but depending on the context you could add in gravity, mechanical stresses, or even electromagnetism if you’re feeling like it. The author can attest to this being very much not recommend for a first project. 

    The equations in vector form 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
    \]

    Where:

    • v: Velocity field (u,v)
    • p: Pressure
    • ρ: Fluid density
    • ν: Kinematic viscosity

    The first equation (Momentum) balances inertia against pressure gradients and viscous diffusion. The second equation (Continuity) enforces that the fluid density remains constant.

    The Pressure Coupling Problem

    A major challenge in CFD is that pressure and velocity are coupled: the pressure field must adjust constantly to ensure the fluid remains incompressible.

    To solve this, we derive a Pressure-Poisson equation by taking the divergence of the momentum equation. In a discretized solver, we solve this Poisson equation at every single timestep to update the pressure, ensuring the velocity field remains divergence-free.

    Discretization: From Math to Grid

    To solve these equations on a computer, we use Finite Difference schemes on a uniform grid.

    • Time: Forward difference (Explicit Euler).
    • Advection (Nonlinear terms): Backward/Upwind difference (for stability).
    • Diffusion & Pressure: Central difference.

    For example, the update formula for the u (x-velocity) component looks like this in finite-difference form

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

    In code, the advection term u∂x∂u​ uses a backward difference: 

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

    The Python Implementation

    The implementation proceeds in four distinct steps using NumPy arrays.

    1. Initialization

    We define the grid size (nx, ny), time step (dt), and physical parameters (rho, nu). We initialize velocity fields (u,v) and pressure (p) to zeros or a uniform flow.

    2. The Wing Geometry (Immersed Boundary)

    To simulate a wing on a Cartesian grid, we need to mark which grid points lie inside the solid wing.

    • We load a wing mesh (e.g., from an STL file).
    • We create a Boolean mask array where True indicates a point inside the wing.
    • During the simulation, we force velocity to zero at these masked points (no-slip/no-penetration condition).

    3. The Main Solver Loop

    The core loop repeats until the solution reaches a steady state. The steps are:

    1. Build the Source Term (b): Calculate the divergence of the velocity terms.
    2. Solve Pressure: Solve the Poisson equation for p using Jacobi iteration.
    3. Update Velocity: Use the new pressure to update u and v.
    4. Apply Boundary Conditions: Enforce inlet velocity and zero velocities inside the wing.

    The Code

    Here is how the core mathematical updates look in Python (vectorized for performance).

    Step A: Building the Pressure Source Term This represents the Right-Hand Side (RHS) of the Poisson equation based on current velocities.

    # b is the source term
    # u and v are current 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: Solving for Pressure (Jacobi Iteration) We iterate to smooth out the pressure field until it balances the source term.

    for _ in range(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 conditions: p=0 at edges (gauge pressure)
        p[:, -1] = 0; p[:, 0] = 0; p[-1, :] = 0; p[0, :] = 0

    Step C: Updating Velocity Finally, we update the velocity using the explicit discretized momentum equations.

    un = u.copy()
    vn = v.copy() 
    # Update 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])))
    # Update 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])))

    Results: Does it Fly?

    We ran this solver on a rigid wing profile with a constant far-field inflow.

    Qualitative Observations The results align with physical expectations. The simulations show high pressure beneath the wing and low pressure above it, which is exactly the mechanism that generates lift. Velocity vectors show the airflow accelerating over the top surface (Bernoulli’s principle).

    Forces: Lift vs. Drag By integrating the pressure field over the wing surface, we can calculate lift.

    • The solver demonstrates that pressure forces dominate viscous friction forces by a factor of nearly 1000x in air.
    • As the angle of attack increases (from 0∘ to −20∘), the lift-to-drag ratio rises, matching trends seen in wind tunnels and professional CFD packages like OpenFOAM.

    Limitations & Next Steps

    While making this solver was great for learning, the tool itself has its limitations:

    • Resolution: 3D simulations on a Cartesian grid are computationally expensive and require coarse grids, making quantitative results less reliable.
    • Turbulence: The solver is laminar; it lacks a turbulence model (like k−ϵ) required for high-speed or complex flows.
    • Diffusion: Upwind differencing schemes are stable but numerically diffusive, potentially “smearing” out fine flow details.

    Where to go from here? This project serves as a starting point. Future improvements could include implementing higher-order advection schemes (like WENO), adding turbulence modeling, or moving to Finite Volume methods (like OpenFOAM) for better mesh handling around complex geometries. There are lots of clever techniques to get around the plethora of scenarios that you may want to implement. This is just a first step on the direction of really understanding CFD!

    Airflow building NavierStokes Python Scratch Simulating Solver
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Awais
    • Website

    Related Posts

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

    March 22, 2026

    Escaping the SQL Jungle | Towards Data Science

    March 21, 2026

    A Gentle Introduction to Nonlinear Constrained Optimization with Piecewise Linear Approximations

    March 21, 2026

    Agentic RAG Failure Modes: Retrieval Thrash, Tool Storms, and Context Bloat (and How to Spot Them Early)

    March 21, 2026

    Multi-Hop Data Synthesis for Generalizable Vision-Language Reasoning

    March 21, 2026

    How to Measure AI Value

    March 20, 2026
    Leave A Reply Cancel Reply

    Top Posts

    At Least 32 People Dead After a Mine Bridge Collapsed Due to Overcrowding

    November 17, 20250 Views

    Here’s how I turned a Raspberry Pi into an in-car media server

    November 17, 20250 Views

    Beloved SF cat’s death fuels Waymo criticism

    November 17, 20250 Views
    Don't Miss

    47 Easter Dinner Ideas: Mains, Sides, and Salads for Your Holiday Feast

    March 22, 2026

    Easter dinner isn’t as fixed as other food-centric holidays (looking at you, Thanksgiving). You can…

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

    March 22, 2026

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

    March 22, 2026

    Bake Pasta on a Sheet Pan for Maximum Crisp

    March 22, 2026
    Stay In Touch
    • Facebook
    • YouTube
    • TikTok
    • WhatsApp
    • Twitter
    • Instagram
    Latest Reviews

    What Is Buttermilk? How It’s Made and Used

    March 22, 2026

    Why your law firm’s best leads don’t convert after research

    March 22, 2026
    Most Popular

    13 Trending Songs on TikTok in Nov 2025 (+ How to Use Them)

    November 18, 20257 Views

    How to watch the 2026 GRAMMY Awards online from anywhere

    February 1, 20263 Views

    Corporate Reputation Management Strategies | Sprout Social

    November 19, 20252 Views
    Our Picks

    At Least 32 People Dead After a Mine Bridge Collapsed Due to Overcrowding

    November 17, 2025

    Here’s how I turned a Raspberry Pi into an in-car media server

    November 17, 2025

    Beloved SF cat’s death fuels Waymo criticism

    November 17, 2025

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    Facebook X (Twitter) Instagram Pinterest YouTube Dribbble
    • About Us
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    • Disclaimer

    © 2025 skytik.cc. All rights reserved.

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