A sequence of Jupyter notebooks featuring the 12 Steps to Navier-Stokes

Overview

CFD Python

Please cite as: Barba, Lorena A., and Forsyth, Gilbert F. (2018). CFD Python: the 12 steps to Navier-Stokes equations. Journal of Open Source Education, 1(9), 21, https://doi.org/10.21105/jose.00021

DOI

CFD Python, a.k.a. the 12 steps to Navier-Stokes, is a practical module for learning the foundations of Computational Fluid Dynamics (CFD) by coding solutions to the basic partial differential equations that describe the physics of fluid flow. The module was part of a course taught by Prof. Lorena Barba between 2009 and 2013 in the Mechanical Engineering department at Boston University (Prof. Barba since moved to the George Washington University).

The module assumes only basic programming knowledge (in any language) and some background in partial differential equations and fluid mechanics. The "steps" were inspired by ideas of Dr. Rio Yokota, who was a post-doc in Prof. Barba's lab until 2011, and the lessons were refined by Prof. Barba and her students over several semesters teaching the CFD course. We wrote this set of Jupyter notebooks in 2013 to teach an intensive two-day course in Mendoza, Argentina.

Guiding students through these steps (without skipping any!), they learn many valuable lessons. The incremental nature of the exercises means they get a sense of achievement at the end of each assignment, and they feel they are learning with low effort. As they progress, they naturally practice code re-use and they incrementally learn programming and plotting techniques. As they analyze their results, they learn about numerical diffusion, accuracy and convergence. In about four weeks of a regularly scheduled course, they become moderately proficient programmers and are motivated to start discussing more theoretical matters.

How to use this module

In a regular-session university course, students can complete the CFD Python lessons in 4 to 5 weeks. As an intensive tutorial, the module can be completed in two or three full days, depending on the learner's prior experience. The lessons can also be used for self study. In all cases, learners should follow along the worked examples in each lesson by re-typing the code in a fresh Jupyter notebook, maybe taking original notes as they try things out.

Lessons

Launch an interactive session with this module using the Binder service: Binder

Steps 1–4 are in one spatial dimension. Steps 5–10 are in two dimensions (2D). Steps 11–12 solve the Navier-Stokes equation in 2D. Three "bonus" notebooks cover the CFL condition for numerical stability, array operations with NumPy, and defining functions in Python.

  • Quick Python Intro —For Python novices, this lesson introduces the numerical libraries (NumPy and Matplotlib), Python variables, use of whitespace, and slicing arrays.
  • Step 1 —Linear convection with a step-function initial condition (IC) and appropriate boundary conditions (BCs).
  • Step 2 —With the same IC/BCs, nonlinear convection.
  • CFL Condition —Exploring numerical stability and the Courant-Friedrichs-Lewy (CFL) condition.
  • Step 3 —With the same IC/BCs, diffusion only.
  • Step 4 —Burgers’ equation, with a saw-tooth IC and periodic BCs (with an introduction to Sympy).
  • Array Operations with NumPy
  • Step 5 —Linear convection in 2D with a square-function IC and appropriate BCs.
  • Step 6 —With the same IC/BCs, nonlinear convection in 2D.
  • Step 7 —With the same IC/BCs, diffusion in 2D.
  • Step 8 —Burgers’ equation in 2D
  • Defining Functions in Python
  • Step 9 —Laplace equation with zero IC and both Neumann and Dirichlet BCs.
  • Step 10 —Poisson equation in 2D.
  • Step 11 —Solves the Navier-Stokes equation for 2D cavity flow.
  • Step 12 —Solves the Navier-Stokes equation for 2D channel flow.

Dependencies

To use these lessons, you need Python 3, and the standard stack of scientific Python: NumPy, Matplotlib, SciPy, Sympy. And of course, you need Jupyter—an interactive computational environment that runs on a web browser.

This mini-course is built as a set of Jupyter notebooks containing the written materials and worked-out solutions on Python code. To work with the material, we recommend that you start each lesson with a fresh new notebook, and follow along, typing each line of code (don't copy-and-paste!), and exploring by changing parameters and seeing what happens.

Installing via Anaconda

We highly recommend that you install the Anaconda Python Distribution. It will make your life so much easier. You can download and install Anaconda on Windows, OSX and Linux.

After installing, to ensure that your packages are up to date, run the following commands in a terminal:

conda update conda
conda update jupyter numpy sympy scipy matplotlib

If you prefer Miniconda (a mini version of Anaconda that saves you disk space), install all the necessary libraries to follow this course by running the following commands in a terminal:

conda update conda
conda install jupyter
conda install numpy scipy sympy matplotlib

Without Anaconda

If you already have Python installed on your machine, you can install Jupyter using pip:

pip install jupyter

Please also make sure that you have the necessary libraries installed by running

pip install numpy scipy sympy matplotlib

Running the notebook server

Once Jupyter is installed, open up a terminal and then run

jupyter notebook

This will start up a Jupyter session in your browser!

How to contribute to CFD Python

We accept contributions via pull request—in fact, several users have already submitted pull requests making corrections or small improvements. You can also open an issue if you find a bug, or have a suggestion.

Copyright and License

(c) 2017 Lorena A. Barba, Gilbert F. Forsyth. All content is under Creative Commons Attribution CC-BY 4.0, and all code is under BSD-3 clause (previously under MIT, and changed on March 8, 2018).

We are happy if you re-use the content in any way!

License License: CC BY 4.0

Comments
  • Added a top level license file

    Added a top level license file

    The course is offered under CC-BY, which is fantastic. This is not obvious from the repository (unless you dig into the iPython notebooks). A top-level license file makes this obvious both to people browsing and to search engines.

    opened by pmitros 11
  • Display equations correctly

    Display equations correctly

    Fix #40

    Use Latex split environment. Remove line breaks to display equation correctly.

    You can view the modified notebooks with Nbviewer to check the equations:

    opened by mesnardo 6
  • Division by zero on 01_Step_1.ipynb

    Division by zero on 01_Step_1.ipynb

    Running 01_Step_1.ipynb I get a division by zero error. The error goes away by setting dx = 2.0/(nx-1) instead of dx = 2/(nx-1). I am using anaconda Python 2.7.11 :: Anaconda 2.5.0 (x86_64).

    Thanks!

    opened by xocd 5
  • Fixed a typo in the Step4 notebook

    Fixed a typo in the Step4 notebook

    The u[0] calculation had terms that were un[-2] in both spatial derivatives. Those should be un[-1].

    Additionally it is worth noting that the periodic conditions can all be handled correctly by the u[i] calculation as written by simply changing the range to for i in range(-1, nx-1) as below. This makes use of python negative indexing which wraps to the end of the array, effectively computing u[-1] and u[0] first.

    for n in range(nt):
        un = u.copy()
        for i in range(-1, nx-1):
            u[i] = un[i] - un[i] * dt/dx *(un[i] - un[i-1]) + nu*dt/dx**2*\
                    (un[i+1]-2*un[i]+un[i-1])
    
    opened by amcdawes 4
  • Maybe there is a bug in code of Array Operations with NumPy

    Maybe there is a bug in code of Array Operations with NumPy

    In . There is a little bug in sentence: u[1:, 1:] = un[1:, 1:] - ((c * dt / dx * (un[1:, 1:] - un[1:, 0:-1])) - (c * dt / dy * (un[1:, 1:] - un[0:-1, 1:])))

    The bold left bracket "(" is in a wrong place. It should follow "=" . Correct code should be: u[1:, 1:] = ( un[1:, 1:] -(c * dt / dx * (un[1:, 1:] - un[1:, 0:-1])) - (c * dt / dy * (un[1:, 1:] - un[0:-1, 1:]))) This little bug make cell5 and cell6 show a different result which suppose to be same.

    bug 
    opened by fidle 3
  • Step4: Error in periodic boundary condition ?

    Step4: Error in periodic boundary condition ?

    Hey, when handling the periodic boundary conditions in Step 4, after the second for loop of code snippet #10, you have u[-1] = un[-1] - un[-1] * dt / dx * (un[-1] - un[-2]) + nu * dt / dx**2 * (un[0] - 2 * un[-1] + un[-2]) where in the last set of parentheses you obtained un[i + 1] = un[-1 + 1] = un[0].

    Given the boundary u(0) = u(2*pi), shouldn't it be un[i + 1] = un[0 + 1] = un[1] instead of un[0] ?

    Thanks in advance!

    opened by ghost 3
  • Use of ipython widgets

    Use of ipython widgets

    Looking at one of the early notebooks, you have a call to action: What do you observe about the evolution of the hat function under the non-linear convection equation? What happens when you change the numerical parameters and run again?

    I wondered if you had considered making an interactive out of this using ipywidgets? (Or maybe you did and discounted it because it can detract from purposeful exploration and engagement with the code in favour of letting students just play with the interactive shiny bits?!)

    opened by psychemedia 3
  • 2D PDE solving: x-y index of u arrays might be mistaken

    2D PDE solving: x-y index of u arrays might be mistaken

    Dear BarbaGroud,

    Thank you for sharing your work, it's awesome. But I'm having a hard time understanding your 2D implementation. In every of the notebooks I can see that the u is initialised as:

    u = np.ones((ny,nx))

    This means that the rows of the u array are related to the y direction and the columns are related to the x direction.

    Furthermore when (for example) the 2D linear burger equation is solved you are using the following expression:

    c_dt/dx_(un[i,j] - un[i-1,j])

    To evaluate the derivative in the x-direction. As far as I'm concerned the rows of un, do have the information of the y axis, and thus you should be using dy instead of dx. This problem is not raised up because you are using the same dimensions and subdivisions for the x and y axis, but whenever this is changed there will be some errors.

    The problem could be solved changing the u initialisation to:

    u = np.ones((nx,ny))

    Although the plots should be using the transposed of u in order to get the right axis.

    Hope I'm wrong with my comments, but I've been thinking about this for a long time and I just cannot see if I'm making a mistake.

    Thank you very much.

    opened by GonzaloSaez 3
  • definition of L1 norm on Step 9: 2D Laplace Equation

    definition of L1 norm on Step 9: 2D Laplace Equation

    According to the link below, the L1 norm of a matrix is calculated by summing up absolute values in each column, and then taking the maximum https://en.wikipedia.org/wiki/Matrix_norm

    The notebook for Step 9 calculates the norm by summing up the absolute values of all the elements in the matrix. Also the link provided to read up further on the L1 norm leads to the wiki page for L1 norm of a vector (which I understand is different from the L1 norm of a matrix)

    question 
    opened by bharath-kamath705 2
  • No pressure gradient in step 12?

    No pressure gradient in step 12?

    If you plot the pressure profile after convergence of the Navier-Stokes equations coupled with the pressure-poisson equation there is no pressure gradient, is this an artifact of the periodic boundary conditions?

    The pressure field does not change at all during iteration...

    opened by Beramos 2
  • Typo in the Poisson equation discretization in Step 11

    Typo in the Poisson equation discretization in Step 11

    There is a strange (1 / Delta t) term in the discretized Poisson equation that is present in the written equation, the Python code (in the build_up_b function), and the corresponding Youtube video. This seems to make the solution unstable for small time steps. I think this may be due to a misapplication of discretization to a time derivative of div v. For an incompressible fluid, div v = 0 so this term should vanish. In any case, just tacking on a (1 / Delta t) is not the correct way to discretize a time derivative.

    opened by peterparity 2
  • Outdated dependencies

    Outdated dependencies

    The Python module versions in requirements.txt are a bit outdated.

    I installed all the dependencies using my system's package manager, and while those packages aren't all at the latest version, some of them are quite far ahead of those in requirements.txt. These are the versions I have tested: numpy: 1.21.5 matplotlib: 3.5.2 scipy: 1.8.1 sympy: 1.10.1

    There weren't any issues, except for a deprecation in matplotlib 3.6 (changelog is here):

    MatplotlibDeprecationWarning: Calling gca() with keyword arguments was deprecated in Matplotlib 3.4. Starting two minor releases later, gca() will take no keyword arguments. The gca() function should only be used to get the current axes, or if no axes exist, create new axes with default keyword arguments. To create a new axes with non-default arguments, use plt.axes() or plt.subplot().
      ax = fig.gca(projection='3d')
    

    The fix for this actually quite easy: Replace

    ax = fig.gca(projection='3d')
    

    with

    ax = fig.add_subplot(projection='3d')
    

    Also, when I checked the matplotlib 2.2.x documentation, it didn't even mention the projection argument on the gca() function.

    Please update the dependency list to more recent versions.

    You could also use compatible versions instead of exact versions. For example:

    # requirements.txt
    ipywidgets ~=8.0
    jupyter ~=1.0.0
    numpy ~=1.23
    matplotlib ~=3.6.0
    scipy ~=1.9
    sympy ~=1.11
    
    opened by onitake 1
  • Fixed constant typo in the periodic boundary conditions

    Fixed constant typo in the periodic boundary conditions

    Previously, there has been a typo throughout the code implementation in Step 12 in the periodic boundary conditions. As a quick example, If u_{i,j} was at the right boundary, then u_{i+1,j} was took to be at the left boundary i.e u_{0,j} (instead of u_{1,j}). This PR fixes those issues, although hardly changes the results.

    opened by michaeldavidjohnson 1
  • Bump numpy from 1.14.3 to 1.22.0

    Bump numpy from 1.14.3 to 1.22.0

    Bumps numpy from 1.14.3 to 1.22.0.

    Release notes

    Sourced from numpy's releases.

    v1.22.0

    NumPy 1.22.0 Release Notes

    NumPy 1.22.0 is a big release featuring the work of 153 contributors spread over 609 pull requests. There have been many improvements, highlights are:

    • Annotations of the main namespace are essentially complete. Upstream is a moving target, so there will likely be further improvements, but the major work is done. This is probably the most user visible enhancement in this release.
    • A preliminary version of the proposed Array-API is provided. This is a step in creating a standard collection of functions that can be used across application such as CuPy and JAX.
    • NumPy now has a DLPack backend. DLPack provides a common interchange format for array (tensor) data.
    • New methods for quantile, percentile, and related functions. The new methods provide a complete set of the methods commonly found in the literature.
    • A new configurable allocator for use by downstream projects.

    These are in addition to the ongoing work to provide SIMD support for commonly used functions, improvements to F2PY, and better documentation.

    The Python versions supported in this release are 3.8-3.10, Python 3.7 has been dropped. Note that 32 bit wheels are only provided for Python 3.8 and 3.9 on Windows, all other wheels are 64 bits on account of Ubuntu, Fedora, and other Linux distributions dropping 32 bit support. All 64 bit wheels are also linked with 64 bit integer OpenBLAS, which should fix the occasional problems encountered by folks using truly huge arrays.

    Expired deprecations

    Deprecated numeric style dtype strings have been removed

    Using the strings "Bytes0", "Datetime64", "Str0", "Uint32", and "Uint64" as a dtype will now raise a TypeError.

    (gh-19539)

    Expired deprecations for loads, ndfromtxt, and mafromtxt in npyio

    numpy.loads was deprecated in v1.15, with the recommendation that users use pickle.loads instead. ndfromtxt and mafromtxt were both deprecated in v1.17 - users should use numpy.genfromtxt instead with the appropriate value for the usemask parameter.

    (gh-19615)

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • Initialization error in Step 9

    Initialization error in Step 9

    In the fourth code cell in 12_Step_9.ipynb, dy is set to 2 / (ny - 1). To be consistent with the y array, this should be 1 / (ny - 1).

    Correcting this has several effects. First, convergence slows. With the current version, laplace2d() stops iterating at 1,133 steps; after applying the correction, it takes 2,043 steps. Second, the revision affects how close laplace2d() comes to the analytic solution. I use sum(p) as a rough comparison among different results from laplace2d(). The current version (2/(ny - 1)) produces a sum of 231.8 when iteration stops at 1,133 steps. The corrected initialization (1/(ny - 1)) produces 220.2 at 2,043 steps. Compare these with the analytic solution sum of 240.25.

    I'm translating to Julia as I work through the Steps. My Julia versions of Step 9 come up with the same results as the revised Python version. In addition, it shows that if you iterate the Julia version of laplace2d() for 5,000 steps, you come up pretty close the analytic solution (sum of 239.5 vs. the 240.25 noted above).

    Hope this helps. Thanks again for all your work on this. In addition, thank you for keeping it current.

    On to Step 10!

    bug 
    opened by Bob-McCrory 1
  • Disappearing viscosity term in the discrete version of Poisson-pressure equation

    Disappearing viscosity term in the discrete version of Poisson-pressure equation

    Thank you for this great course! I have been using this course to teach CFD-concepts in Belgium.

    I'm stuck with the following question. In video lecture 11, a poisson equation is obtained to correct for the divergence in the velocity.

    image

    However in notebook 14 the discretised pressure-Poisson equation looks completely different than the one obtained in the video lecture: https://youtu.be/ZjfxA3qq2Lg?t=1647

    My question is: what happened in between the curved brackets in the video lecture and equation 13 in the notebook.

    evergreen 
    opened by Beramos 10
Releases(v1.0)
Owner
Barba group
Barba group
Code for the paper "Learning-Augmented Algorithms for Online Steiner Tree"

Learning-Augmented Algorithms for Online Steiner Tree This is the code for the paper "Learning-Augmented Algorithms for Online Steiner Tree". Requirem

0 Dec 09, 2021
Distributed Deep learning with Keras & Spark

Elephas: Distributed Deep Learning with Keras & Spark Elephas is an extension of Keras, which allows you to run distributed deep learning models at sc

Max Pumperla 1.6k Jan 05, 2023
python library for invisible image watermark (blind image watermark)

invisible-watermark invisible-watermark is a python library and command line tool for creating invisible watermark over image.(aka. blink image waterm

Shield Mountain 572 Jan 07, 2023
Code for "FGR: Frustum-Aware Geometric Reasoning for Weakly Supervised 3D Vehicle Detection", ICRA 2021

FGR This repository contains the python implementation for paper "FGR: Frustum-Aware Geometric Reasoning for Weakly Supervised 3D Vehicle Detection"(I

Yi Wei 31 Dec 08, 2022
Repository for the paper "Exploring the Sensory Spaces of English Perceptual Verbs in Natural Language Data"

Sensory Spaces of English Perceptual Verbs This repository contains the code and collocational data described in the paper "Exploring the Sensory Spac

David Peng 0 Sep 07, 2021
Automatic tool focused on deriving metallicities of open clusters

metalcode Automatic tool focused on deriving metallicities of open clusters. Based on the method described in Pöhnl & Paunzen (2010, https://ui.adsabs

2 Dec 13, 2021
The official implementation of NeurIPS 2021 paper: Finding Optimal Tangent Points for Reducing Distortions of Hard-label Attacks

Introduction This repository includes the source code for "Finding Optimal Tangent Points for Reducing Distortions of Hard-label Attacks", which is pu

machen 11 Nov 27, 2022
Pytorch Performace Tuning, WandB, AMP, Multi-GPU, TensorRT, Triton

Plant Pathology 2020 FGVC7 Introduction A deep learning model pipeline for training, experimentaiton and deployment for the Kaggle Competition, Plant

Bharat Giddwani 0 Feb 25, 2022
Data-Uncertainty Guided Multi-Phase Learning for Semi-supervised Object Detection

An official implementation of paper Data-Uncertainty Guided Multi-Phase Learning for Semi-supervised Object Detection

11 Nov 23, 2022
Bayesian Inference Tools in Python

BayesPy Bayesian Inference Tools in Python Our goal is, given the discrete outcomes of events, estimate the distribution of categories. Using gradient

Max Sklar 99 Dec 14, 2022
This Repostory contains the pretrained DTLN-aec model for real-time acoustic echo cancellation.

This Repostory contains the pretrained DTLN-aec model for real-time acoustic echo cancellation.

Nils L. Westhausen 182 Jan 07, 2023
[CVPR 21] Vectorization and Rasterization: Self-Supervised Learning for Sketch and Handwriting, IEEE Conf. on Computer Vision and Pattern Recognition (CVPR), 2021.

Vectorization and Rasterization: Self-Supervised Learning for Sketch and Handwriting, CVPR 2021. Ayan Kumar Bhunia, Pinaki nath Chowdhury, Yongxin Yan

Ayan Kumar Bhunia 44 Dec 12, 2022
利用yolov5和TensorRT从0到1实现目标检测的模型训练到模型部署全过程

写在前面 利用TensorRT加速推理速度是以时间换取精度的做法,意味着在推理速度上升的同时将会有精度的下降,不过不用太担心,精度下降微乎其微。此外,要有NVIDIA显卡,经测试,CUDA10.2可以支持20系列显卡及以下,30系列显卡需要CUDA11.x的支持,并且目前有bug。 默认你已经完成了

Helium 6 Jul 28, 2022
Website for D2C paper

D2C This is the repository that contains source code for the D2C Website. If you find D2C useful for your work please cite: @article{sinha2021d2c au

1 Oct 21, 2021
Deep deconfounded recommender (Deep-Deconf) for paper "Deep causal reasoning for recommendations"

Deep Causal Reasoning for Recommender Systems The codes are associated with the following paper: Deep Causal Reasoning for Recommendations, Yaochen Zh

Yaochen Zhu 22 Oct 15, 2022
This repo provides the source code & data of our paper "GreaseLM: Graph REASoning Enhanced Language Models"

GreaseLM: Graph REASoning Enhanced Language Models This repo provides the source code & data of our paper "GreaseLM: Graph REASoning Enhanced Language

137 Jan 02, 2023
Cross-platform CLI tool to generate your Github profile's stats and summary.

ghs Cross-platform CLI tool to generate your Github profile's stats and summary. Preview Hop on to examples for other usecases. Jump to: Installation

HackerRank 134 Dec 20, 2022
[CIKM 2019] Code and dataset for "Fi-GNN: Modeling Feature Interactions via Graph Neural Networks for CTR Prediction"

FiGNN for CTR prediction The code and data for our paper in CIKM2019: Fi-GNN: Modeling Feature Interactions via Graph Neural Networks for CTR Predicti

Big Data and Multi-modal Computing Group, CRIPAC 75 Dec 30, 2022
TensorFlow implementation of "A Simple Baseline for Bayesian Uncertainty in Deep Learning"

TensorFlow implementation of "A Simple Baseline for Bayesian Uncertainty in Deep Learning"

YeongHyeon Park 7 Aug 28, 2022
Learning Multiresolution Matrix Factorization and its Wavelet Networks on Graphs

Project Learning Multiresolution Matrix Factorization and its Wavelet Networks on Graphs, https://arxiv.org/pdf/2111.01940.pdf. Authors Truong Son Hy

5 Jun 28, 2022